mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
ID3: Fix end-of-string detection for UTF-16
The current detection logic checks that the two byte terminator starts at an even position in the ID3 data, where-as it should check that it starts at an even position relative to the start of the string. Issue: #9087 PiperOrigin-RevId: 395274934
This commit is contained in:
parent
a1d376fae1
commit
1bd96fbaf7
@ -12,6 +12,8 @@
|
|||||||
* Extractors:
|
* Extractors:
|
||||||
* Support TS packets without PTS flag
|
* Support TS packets without PTS flag
|
||||||
([#9294](https://github.com/google/ExoPlayer/issues/9294)).
|
([#9294](https://github.com/google/ExoPlayer/issues/9294)).
|
||||||
|
* ID3: Fix issue decoding ID3 tags containing UTF-16 encoded strings
|
||||||
|
([#9087](https://github.com/google/ExoPlayer/issues/9087)).
|
||||||
* Video:
|
* Video:
|
||||||
* Request smaller decoder input buffers for Dolby Vision. This fixes an
|
* Request smaller decoder input buffers for Dolby Vision. This fixes an
|
||||||
issue that could cause UHD Dolby Vision playbacks to fail on some
|
issue that could cause UHD Dolby Vision playbacks to fail on some
|
||||||
|
@ -806,9 +806,9 @@ public final class Id3Decoder extends SimpleMetadataDecoder {
|
|||||||
return terminationPos;
|
return terminationPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise ensure an even index and look for a second zero byte.
|
// Otherwise ensure an even offset from the start, and look for a second zero byte.
|
||||||
while (terminationPos < data.length - 1) {
|
while (terminationPos < data.length - 1) {
|
||||||
if (terminationPos % 2 == 0 && data[terminationPos + 1] == (byte) 0) {
|
if ((terminationPos - fromIndex) % 2 == 0 && data[terminationPos + 1] == (byte) 0) {
|
||||||
return terminationPos;
|
return terminationPos;
|
||||||
}
|
}
|
||||||
terminationPos = indexOfZeroByte(data, terminationPos + 1);
|
terminationPos = indexOfZeroByte(data, terminationPos + 1);
|
||||||
|
@ -38,6 +38,7 @@ public final class Id3DecoderTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void decodeTxxxFrame() {
|
public void decodeTxxxFrame() {
|
||||||
|
// Test UTF-8.
|
||||||
byte[] rawId3 =
|
byte[] rawId3 =
|
||||||
buildSingleFrameTag(
|
buildSingleFrameTag(
|
||||||
"TXXX",
|
"TXXX",
|
||||||
@ -53,6 +54,21 @@ public final class Id3DecoderTest {
|
|||||||
assertThat(textInformationFrame.description).isEmpty();
|
assertThat(textInformationFrame.description).isEmpty();
|
||||||
assertThat(textInformationFrame.value).isEqualTo("mdialog_VINDICO1527664_start");
|
assertThat(textInformationFrame.value).isEqualTo("mdialog_VINDICO1527664_start");
|
||||||
|
|
||||||
|
// Test UTF-16.
|
||||||
|
rawId3 =
|
||||||
|
buildSingleFrameTag(
|
||||||
|
"TXXX",
|
||||||
|
new byte[] {
|
||||||
|
1, 0, 72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 32, 0, 87, 0, 111, 0, 114, 0, 108, 0,
|
||||||
|
100, 0, 0
|
||||||
|
});
|
||||||
|
metadata = decoder.decode(rawId3, rawId3.length);
|
||||||
|
assertThat(metadata.length()).isEqualTo(1);
|
||||||
|
textInformationFrame = (TextInformationFrame) metadata.get(0);
|
||||||
|
assertThat(textInformationFrame.id).isEqualTo("TXXX");
|
||||||
|
assertThat(textInformationFrame.description).isEqualTo("Hello World");
|
||||||
|
assertThat(textInformationFrame.value).isEmpty();
|
||||||
|
|
||||||
// Test empty.
|
// Test empty.
|
||||||
rawId3 = buildSingleFrameTag("TXXX", new byte[0]);
|
rawId3 = buildSingleFrameTag("TXXX", new byte[0]);
|
||||||
metadata = decoder.decode(rawId3, rawId3.length);
|
metadata = decoder.decode(rawId3, rawId3.length);
|
||||||
@ -220,6 +236,43 @@ public final class Id3DecoderTest {
|
|||||||
assertThat(apicFrame.description).isEqualTo("Hello World");
|
assertThat(apicFrame.description).isEqualTo("Hello World");
|
||||||
assertThat(apicFrame.pictureData).hasLength(10);
|
assertThat(apicFrame.pictureData).hasLength(10);
|
||||||
assertThat(apicFrame.pictureData).isEqualTo(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0});
|
assertThat(apicFrame.pictureData).isEqualTo(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0});
|
||||||
|
|
||||||
|
// Test with UTF-16 description at even offset.
|
||||||
|
rawId3 =
|
||||||
|
buildSingleFrameTag(
|
||||||
|
"APIC",
|
||||||
|
new byte[] {
|
||||||
|
1, 105, 109, 97, 103, 101, 47, 106, 112, 101, 103, 0, 16, 0, 72, 0, 101, 0, 108, 0,
|
||||||
|
108, 0, 111, 0, 32, 0, 87, 0, 111, 0, 114, 0, 108, 0, 100, 0, 0, 1, 2, 3, 4, 5, 6, 7,
|
||||||
|
8, 9, 0
|
||||||
|
});
|
||||||
|
decoder = new Id3Decoder();
|
||||||
|
metadata = decoder.decode(rawId3, rawId3.length);
|
||||||
|
assertThat(metadata.length()).isEqualTo(1);
|
||||||
|
apicFrame = (ApicFrame) metadata.get(0);
|
||||||
|
assertThat(apicFrame.mimeType).isEqualTo("image/jpeg");
|
||||||
|
assertThat(apicFrame.pictureType).isEqualTo(16);
|
||||||
|
assertThat(apicFrame.description).isEqualTo("Hello World");
|
||||||
|
assertThat(apicFrame.pictureData).hasLength(10);
|
||||||
|
assertThat(apicFrame.pictureData).isEqualTo(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0});
|
||||||
|
|
||||||
|
// Test with UTF-16 description at odd offset.
|
||||||
|
rawId3 =
|
||||||
|
buildSingleFrameTag(
|
||||||
|
"APIC",
|
||||||
|
new byte[] {
|
||||||
|
1, 105, 109, 97, 103, 101, 47, 112, 110, 103, 0, 16, 0, 72, 0, 101, 0, 108, 0, 108, 0,
|
||||||
|
111, 0, 32, 0, 87, 0, 111, 0, 114, 0, 108, 0, 100, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0
|
||||||
|
});
|
||||||
|
decoder = new Id3Decoder();
|
||||||
|
metadata = decoder.decode(rawId3, rawId3.length);
|
||||||
|
assertThat(metadata.length()).isEqualTo(1);
|
||||||
|
apicFrame = (ApicFrame) metadata.get(0);
|
||||||
|
assertThat(apicFrame.mimeType).isEqualTo("image/png");
|
||||||
|
assertThat(apicFrame.pictureType).isEqualTo(16);
|
||||||
|
assertThat(apicFrame.description).isEqualTo("Hello World");
|
||||||
|
assertThat(apicFrame.pictureData).hasLength(10);
|
||||||
|
assertThat(apicFrame.pictureData).isEqualTo(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
x
Reference in New Issue
Block a user