Skip to content

Commit 2a4cbc3

Browse files
rohitjoinscopybara-github
authored andcommitted
Fix parsing of language code in mdhd box
Language codes in the `mdhd` box are stored as three 5-bit values, each representing a letter ('a' to 'z') using an offset of `0x60`. If the decoded characters are not in this range, the language should be treated as undefined. PiperOrigin-RevId: 738470544
1 parent 2d1bcc7 commit 2a4cbc3

23 files changed

+39
-38
lines changed

libraries/extractor/src/main/java/androidx/media3/extractor/Ac3Util.java

+10-4
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,15 @@ private SyncFrameInfo(
169169
*
170170
* @param data The AC3SpecificBox to parse.
171171
* @param trackId The track identifier to set on the format.
172-
* @param language The language to set on the format.
172+
* @param language The language to set on the format, or {@code null} if unset.
173173
* @param drmInitData {@link DrmInitData} to be included in the format.
174174
* @return The AC-3 format parsed from data in the header.
175175
*/
176176
public static Format parseAc3AnnexFFormat(
177-
ParsableByteArray data, String trackId, String language, @Nullable DrmInitData drmInitData) {
177+
ParsableByteArray data,
178+
String trackId,
179+
@Nullable String language,
180+
@Nullable DrmInitData drmInitData) {
178181
ParsableBitArray dataBitArray = new ParsableBitArray();
179182
dataBitArray.reset(data);
180183

@@ -208,12 +211,15 @@ public static Format parseAc3AnnexFFormat(
208211
*
209212
* @param data The EC3SpecificBox to parse.
210213
* @param trackId The track identifier to set on the format.
211-
* @param language The language to set on the format.
214+
* @param language The language to set on the format, or {@code null} if unset.
212215
* @param drmInitData {@link DrmInitData} to be included in the format.
213216
* @return The E-AC-3 format parsed from data in the header.
214217
*/
215218
public static Format parseEAc3AnnexFFormat(
216-
ParsableByteArray data, String trackId, String language, @Nullable DrmInitData drmInitData) {
219+
ParsableByteArray data,
220+
String trackId,
221+
@Nullable String language,
222+
@Nullable DrmInitData drmInitData) {
217223
ParsableBitArray dataBitArray = new ParsableBitArray();
218224
dataBitArray.reset(data);
219225

libraries/extractor/src/main/java/androidx/media3/extractor/Ac4Util.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -163,14 +163,17 @@ private SyncFrameInfo(
163163
*
164164
* @param data The AC4SpecificBox to parse.
165165
* @param trackId The track identifier to set on the format.
166-
* @param language The language to set on the format.
166+
* @param language The language to set on the format, or {@code null} if unset.
167167
* @param drmInitData {@link DrmInitData} to be included in the format.
168168
* @return The AC-4 format parsed from data in the header.
169169
* @throws ParserException If an unsupported container feature is encountered while parsing AC-4
170170
* Annex E.
171171
*/
172172
public static Format parseAc4AnnexEFormat(
173-
ParsableByteArray data, String trackId, String language, @Nullable DrmInitData drmInitData)
173+
ParsableByteArray data,
174+
String trackId,
175+
@Nullable String language,
176+
@Nullable DrmInitData drmInitData)
174177
throws ParserException {
175178
ParsableBitArray dataBitArray = new ParsableBitArray();
176179
dataBitArray.reset(data);

libraries/extractor/src/main/java/androidx/media3/extractor/mp4/BoxParser.java

+24-12
Original file line numberDiff line numberDiff line change
@@ -997,22 +997,34 @@ private static MdhdData parseMdhd(ParsableByteArray mdhd) {
997997
mediaDurationUs = Util.scaleLargeTimestamp(mediaDuration, C.MICROS_PER_SECOND, timescale);
998998
}
999999
}
1000-
int languageCode = mdhd.readUnsignedShort();
1001-
String language =
1002-
""
1003-
+ (char) (((languageCode >> 10) & 0x1F) + 0x60)
1004-
+ (char) (((languageCode >> 5) & 0x1F) + 0x60)
1005-
+ (char) ((languageCode & 0x1F) + 0x60);
1000+
1001+
String language = getLanguageFromCode(/* languageCode= */ mdhd.readUnsignedShort());
10061002
return new MdhdData(timescale, mediaDurationUs, language);
10071003
}
10081004

1005+
@Nullable
1006+
private static String getLanguageFromCode(int languageCode) {
1007+
char[] chars = {
1008+
(char) (((languageCode >> 10) & 0x1F) + 0x60),
1009+
(char) (((languageCode >> 5) & 0x1F) + 0x60),
1010+
(char) ((languageCode & 0x1F) + 0x60)
1011+
};
1012+
1013+
for (char c : chars) {
1014+
if (c < 'a' || c > 'z') {
1015+
return null;
1016+
}
1017+
}
1018+
return new String(chars);
1019+
}
1020+
10091021
/**
10101022
* Parses a stsd atom (defined in ISO/IEC 14496-12).
10111023
*
10121024
* @param stsd The stsd atom to decode.
10131025
* @param trackId The track's identifier in its container.
10141026
* @param rotationDegrees The rotation of the track in degrees.
1015-
* @param language The language of the track.
1027+
* @param language The language of the track, or {@code null} if unset.
10161028
* @param drmInitData {@link DrmInitData} to be included in the format, or {@code null}.
10171029
* @param isQuickTime True for QuickTime media. False otherwise.
10181030
* @return An object containing the parsed data.
@@ -1021,7 +1033,7 @@ private static StsdData parseStsd(
10211033
ParsableByteArray stsd,
10221034
int trackId,
10231035
int rotationDegrees,
1024-
String language,
1036+
@Nullable String language,
10251037
@Nullable DrmInitData drmInitData,
10261038
boolean isQuickTime)
10271039
throws ParserException {
@@ -1125,7 +1137,7 @@ private static void parseTextSampleEntry(
11251137
int position,
11261138
int atomSize,
11271139
int trackId,
1128-
String language,
1140+
@Nullable String language,
11291141
StsdData out) {
11301142
parent.setPosition(position + Mp4Box.HEADER_SIZE + StsdData.STSD_HEADER_SIZE);
11311143

@@ -1820,7 +1832,7 @@ private static void parseAudioSampleEntry(
18201832
int position,
18211833
int size,
18221834
int trackId,
1823-
String language,
1835+
@Nullable String language,
18241836
boolean isQuickTime,
18251837
@Nullable DrmInitData drmInitData,
18261838
StsdData out,
@@ -2593,9 +2605,9 @@ public EyesData(StriData striData) {
25932605
private static final class MdhdData {
25942606
private final long timescale;
25952607
private final long mediaDurationUs;
2596-
private final String language;
2608+
@Nullable private final String language;
25972609

2598-
public MdhdData(long timescale, long mediaDurationUs, String language) {
2610+
public MdhdData(long timescale, long mediaDurationUs, @Nullable String language) {
25992611
this.timescale = timescale;
26002612
this.mediaDurationUs = mediaDurationUs;
26012613
this.language = language;

libraries/test_data/src/test/assets/extractordumps/mp4/sample_opus_fragmented.mp4.0.dump

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ track 0:
1212
sampleMimeType = audio/opus
1313
channelCount = 2
1414
sampleRate = 16000
15-
language = 
1615
initializationData:
1716
data = length 19, hash 4034F23B
1817
data = length 8, hash 94446F01

libraries/test_data/src/test/assets/extractordumps/mp4/sample_opus_fragmented.mp4.reading_within_gop_sample_dependencies.0.dump

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ track 0:
1212
sampleMimeType = audio/opus
1313
channelCount = 2
1414
sampleRate = 16000
15-
language = 
1615
initializationData:
1716
data = length 19, hash 4034F23B
1817
data = length 8, hash 94446F01

libraries/test_data/src/test/assets/extractordumps/mp4/sample_opus_fragmented.mp4.reading_within_gop_sample_dependencies.unknown_length.dump

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ track 0:
1212
sampleMimeType = audio/opus
1313
channelCount = 2
1414
sampleRate = 16000
15-
language = 
1615
initializationData:
1716
data = length 19, hash 4034F23B
1817
data = length 8, hash 94446F01

libraries/test_data/src/test/assets/extractordumps/mp4/sample_opus_fragmented.mp4.unknown_length.dump

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ track 0:
1212
sampleMimeType = audio/opus
1313
channelCount = 2
1414
sampleRate = 16000
15-
language = 
1615
initializationData:
1716
data = length 19, hash 4034F23B
1817
data = length 8, hash 94446F01

libraries/test_data/src/test/assets/muxerdumps/bbb_1ch_16kHz_q10_vorbis.ogg.dump

-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ track 0:
1818
maxInputSize = 295
1919
channelCount = 1
2020
sampleRate = 16000
21-
language = ```
2221
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
2322
initializationData:
2423
data = length 30, hash C22462B1

libraries/test_data/src/test/assets/muxerdumps/bbb_1ch_16kHz_q10_vorbis.ogg_fragmented.dump

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ track 0:
1313
sampleMimeType = audio/vorbis
1414
channelCount = 1
1515
sampleRate = 16000
16-
language = ```
1716
initializationData:
1817
data = length 30, hash C22462B1
1918
data = length 3539, hash F8106892

libraries/test_data/src/test/assets/muxerdumps/bbb_2ch_44kHz.wav.dump

-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ track 0:
1818
channelCount = 2
1919
sampleRate = 44100
2020
pcmEncoding = 2
21-
language = ```
2221
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
2322
sample 0:
2423
time = 0

libraries/test_data/src/test/assets/muxerdumps/bbb_2ch_44kHz.wav_fragmented.dump

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ track 0:
1313
channelCount = 2
1414
sampleRate = 44100
1515
pcmEncoding = 2
16-
language = ```
1716
sample 0:
1817
time = 0
1918
flags = 1

libraries/test_data/src/test/assets/muxerdumps/bbb_6ch_8kHz_opus.ogg.dump

-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ track 0:
1717
maxInputSize = 1185
1818
channelCount = 6
1919
sampleRate = 48000
20-
language = ```
2120
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
2221
initializationData:
2322
data = length 27, hash 9EE6F879

libraries/test_data/src/test/assets/muxerdumps/bbb_6ch_8kHz_opus.ogg_fragmented.dump

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ track 0:
1212
sampleMimeType = audio/opus
1313
channelCount = 6
1414
sampleRate = 48000
15-
language = ```
1615
initializationData:
1716
data = length 27, hash 9EE6F879
1817
data = length 8, hash CA22068C

libraries/test_data/src/test/assets/muxerdumps/h265_with_metadata_track.mp4.dump

-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ track 1:
4242
maxInputSize = 627
4343
channelCount = 2
4444
sampleRate = 48000
45-
language = ```
4645
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
4746
initializationData:
4847
data = length 2, hash 560

libraries/test_data/src/test/assets/muxerdumps/h265_with_metadata_track.mp4_fragmented.dump

-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ track 1:
3434
codecs = mp4a.40.2
3535
channelCount = 2
3636
sampleRate = 48000
37-
language = ```
3837
initializationData:
3938
data = length 2, hash 560
4039
sample 0:

libraries/test_data/src/test/assets/muxerdumps/hdr10-720p.mp4.dump

-1
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,6 @@ track 1:
552552
maxInputSize = 877
553553
channelCount = 2
554554
sampleRate = 48000
555-
language = ```
556555
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
557556
initializationData:
558557
data = length 2, hash 560

libraries/test_data/src/test/assets/muxerdumps/hdr10-720p.mp4_fragmented.dump

-1
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,6 @@ track 1:
543543
codecs = mp4a.40.2
544544
channelCount = 2
545545
sampleRate = 48000
546-
language = ```
547546
initializationData:
548547
data = length 2, hash 560
549548
sample 0:

libraries/test_data/src/test/assets/muxerdumps/partial_hdr10-720p.mp4.dump

-1
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,6 @@ track 1:
416416
maxInputSize = 877
417417
channelCount = 2
418418
sampleRate = 48000
419-
language = ```
420419
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
421420
initializationData:
422421
data = length 2, hash 560

libraries/test_data/src/test/assets/muxerdumps/sample_batching_and_attempt_streamable_output_disabled_hdr10-720p.mp4.dump

-1
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,6 @@ track 1:
552552
maxInputSize = 877
553553
channelCount = 2
554554
sampleRate = 48000
555-
language = ```
556555
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
557556
initializationData:
558557
data = length 2, hash 560

libraries/test_data/src/test/assets/muxerdumps/sample_batching_disabled_hdr10-720p.mp4.dump

-1
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,6 @@ track 1:
552552
maxInputSize = 877
553553
channelCount = 2
554554
sampleRate = 48000
555-
language = ```
556555
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
557556
initializationData:
558557
data = length 2, hash 560

libraries/test_data/src/test/assets/transformerdumps/mp4/bbb_1ch_16kHz_q10_vorbis.ogg/transmuxed_with_inappmuxer.dump

-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ track 0:
1818
maxInputSize = 295
1919
channelCount = 1
2020
sampleRate = 16000
21-
language = ```
2221
metadata = entries=[Mp4Timestamp: creation time=3000000000, modification time=4000000000, timescale=10000]
2322
initializationData:
2423
data = length 30, hash C22462B1

libraries/test_data/src/test/assets/transformerdumps/mp4/bbb_6ch_8kHz_opus.ogg/transmuxed_with_inappmuxer.dump

-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ track 0:
1717
maxInputSize = 1185
1818
channelCount = 6
1919
sampleRate = 48000
20-
language = ```
2120
metadata = entries=[Mp4Timestamp: creation time=3000000000, modification time=4000000000, timescale=10000]
2221
initializationData:
2322
data = length 27, hash 9EE6F879

libraries/test_data/src/test/assets/transformerdumps/mp4/h265_with_metadata_track.mp4/transmuxed_with_inappmuxer.dump

-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ track 1:
5757
maxInputSize = 627
5858
channelCount = 2
5959
sampleRate = 48000
60-
language = ```
6160
metadata = entries=[xyz: latitude=51.5932, longitude=-0.2431, Mp4Timestamp: creation time=3000000000, modification time=4000000000, timescale=10000]
6261
initializationData:
6362
data = length 2, hash 560

0 commit comments

Comments
 (0)