mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
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 (cherry picked from commit 2a4cbc3be47b54a59aef384b288ea802e34fb2f0)
This commit is contained in:
parent
963bae9dd8
commit
d920cf87a6
@ -169,12 +169,15 @@ public final class Ac3Util {
|
|||||||
*
|
*
|
||||||
* @param data The AC3SpecificBox to parse.
|
* @param data The AC3SpecificBox to parse.
|
||||||
* @param trackId The track identifier to set on the format.
|
* @param trackId The track identifier to set on the format.
|
||||||
* @param language The language to set on the format.
|
* @param language The language to set on the format, or {@code null} if unset.
|
||||||
* @param drmInitData {@link DrmInitData} to be included in the format.
|
* @param drmInitData {@link DrmInitData} to be included in the format.
|
||||||
* @return The AC-3 format parsed from data in the header.
|
* @return The AC-3 format parsed from data in the header.
|
||||||
*/
|
*/
|
||||||
public static Format parseAc3AnnexFFormat(
|
public static Format parseAc3AnnexFFormat(
|
||||||
ParsableByteArray data, String trackId, String language, @Nullable DrmInitData drmInitData) {
|
ParsableByteArray data,
|
||||||
|
String trackId,
|
||||||
|
@Nullable String language,
|
||||||
|
@Nullable DrmInitData drmInitData) {
|
||||||
ParsableBitArray dataBitArray = new ParsableBitArray();
|
ParsableBitArray dataBitArray = new ParsableBitArray();
|
||||||
dataBitArray.reset(data);
|
dataBitArray.reset(data);
|
||||||
|
|
||||||
@ -208,12 +211,15 @@ public final class Ac3Util {
|
|||||||
*
|
*
|
||||||
* @param data The EC3SpecificBox to parse.
|
* @param data The EC3SpecificBox to parse.
|
||||||
* @param trackId The track identifier to set on the format.
|
* @param trackId The track identifier to set on the format.
|
||||||
* @param language The language to set on the format.
|
* @param language The language to set on the format, or {@code null} if unset.
|
||||||
* @param drmInitData {@link DrmInitData} to be included in the format.
|
* @param drmInitData {@link DrmInitData} to be included in the format.
|
||||||
* @return The E-AC-3 format parsed from data in the header.
|
* @return The E-AC-3 format parsed from data in the header.
|
||||||
*/
|
*/
|
||||||
public static Format parseEAc3AnnexFFormat(
|
public static Format parseEAc3AnnexFFormat(
|
||||||
ParsableByteArray data, String trackId, String language, @Nullable DrmInitData drmInitData) {
|
ParsableByteArray data,
|
||||||
|
String trackId,
|
||||||
|
@Nullable String language,
|
||||||
|
@Nullable DrmInitData drmInitData) {
|
||||||
ParsableBitArray dataBitArray = new ParsableBitArray();
|
ParsableBitArray dataBitArray = new ParsableBitArray();
|
||||||
dataBitArray.reset(data);
|
dataBitArray.reset(data);
|
||||||
|
|
||||||
|
@ -163,14 +163,17 @@ public final class Ac4Util {
|
|||||||
*
|
*
|
||||||
* @param data The AC4SpecificBox to parse.
|
* @param data The AC4SpecificBox to parse.
|
||||||
* @param trackId The track identifier to set on the format.
|
* @param trackId The track identifier to set on the format.
|
||||||
* @param language The language to set on the format.
|
* @param language The language to set on the format, or {@code null} if unset.
|
||||||
* @param drmInitData {@link DrmInitData} to be included in the format.
|
* @param drmInitData {@link DrmInitData} to be included in the format.
|
||||||
* @return The AC-4 format parsed from data in the header.
|
* @return The AC-4 format parsed from data in the header.
|
||||||
* @throws ParserException If an unsupported container feature is encountered while parsing AC-4
|
* @throws ParserException If an unsupported container feature is encountered while parsing AC-4
|
||||||
* Annex E.
|
* Annex E.
|
||||||
*/
|
*/
|
||||||
public static Format parseAc4AnnexEFormat(
|
public static Format parseAc4AnnexEFormat(
|
||||||
ParsableByteArray data, String trackId, String language, @Nullable DrmInitData drmInitData)
|
ParsableByteArray data,
|
||||||
|
String trackId,
|
||||||
|
@Nullable String language,
|
||||||
|
@Nullable DrmInitData drmInitData)
|
||||||
throws ParserException {
|
throws ParserException {
|
||||||
ParsableBitArray dataBitArray = new ParsableBitArray();
|
ParsableBitArray dataBitArray = new ParsableBitArray();
|
||||||
dataBitArray.reset(data);
|
dataBitArray.reset(data);
|
||||||
|
@ -997,22 +997,34 @@ public final class BoxParser {
|
|||||||
mediaDurationUs = Util.scaleLargeTimestamp(mediaDuration, C.MICROS_PER_SECOND, timescale);
|
mediaDurationUs = Util.scaleLargeTimestamp(mediaDuration, C.MICROS_PER_SECOND, timescale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int languageCode = mdhd.readUnsignedShort();
|
|
||||||
String language =
|
String language = getLanguageFromCode(/* languageCode= */ mdhd.readUnsignedShort());
|
||||||
""
|
|
||||||
+ (char) (((languageCode >> 10) & 0x1F) + 0x60)
|
|
||||||
+ (char) (((languageCode >> 5) & 0x1F) + 0x60)
|
|
||||||
+ (char) ((languageCode & 0x1F) + 0x60);
|
|
||||||
return new MdhdData(timescale, mediaDurationUs, language);
|
return new MdhdData(timescale, mediaDurationUs, language);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static String getLanguageFromCode(int languageCode) {
|
||||||
|
char[] chars = {
|
||||||
|
(char) (((languageCode >> 10) & 0x1F) + 0x60),
|
||||||
|
(char) (((languageCode >> 5) & 0x1F) + 0x60),
|
||||||
|
(char) ((languageCode & 0x1F) + 0x60)
|
||||||
|
};
|
||||||
|
|
||||||
|
for (char c : chars) {
|
||||||
|
if (c < 'a' || c > 'z') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new String(chars);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a stsd atom (defined in ISO/IEC 14496-12).
|
* Parses a stsd atom (defined in ISO/IEC 14496-12).
|
||||||
*
|
*
|
||||||
* @param stsd The stsd atom to decode.
|
* @param stsd The stsd atom to decode.
|
||||||
* @param trackId The track's identifier in its container.
|
* @param trackId The track's identifier in its container.
|
||||||
* @param rotationDegrees The rotation of the track in degrees.
|
* @param rotationDegrees The rotation of the track in degrees.
|
||||||
* @param language The language of the track.
|
* @param language The language of the track, or {@code null} if unset.
|
||||||
* @param drmInitData {@link DrmInitData} to be included in the format, or {@code null}.
|
* @param drmInitData {@link DrmInitData} to be included in the format, or {@code null}.
|
||||||
* @param isQuickTime True for QuickTime media. False otherwise.
|
* @param isQuickTime True for QuickTime media. False otherwise.
|
||||||
* @return An object containing the parsed data.
|
* @return An object containing the parsed data.
|
||||||
@ -1021,7 +1033,7 @@ public final class BoxParser {
|
|||||||
ParsableByteArray stsd,
|
ParsableByteArray stsd,
|
||||||
int trackId,
|
int trackId,
|
||||||
int rotationDegrees,
|
int rotationDegrees,
|
||||||
String language,
|
@Nullable String language,
|
||||||
@Nullable DrmInitData drmInitData,
|
@Nullable DrmInitData drmInitData,
|
||||||
boolean isQuickTime)
|
boolean isQuickTime)
|
||||||
throws ParserException {
|
throws ParserException {
|
||||||
@ -1125,7 +1137,7 @@ public final class BoxParser {
|
|||||||
int position,
|
int position,
|
||||||
int atomSize,
|
int atomSize,
|
||||||
int trackId,
|
int trackId,
|
||||||
String language,
|
@Nullable String language,
|
||||||
StsdData out) {
|
StsdData out) {
|
||||||
parent.setPosition(position + Mp4Box.HEADER_SIZE + StsdData.STSD_HEADER_SIZE);
|
parent.setPosition(position + Mp4Box.HEADER_SIZE + StsdData.STSD_HEADER_SIZE);
|
||||||
|
|
||||||
@ -1820,7 +1832,7 @@ public final class BoxParser {
|
|||||||
int position,
|
int position,
|
||||||
int size,
|
int size,
|
||||||
int trackId,
|
int trackId,
|
||||||
String language,
|
@Nullable String language,
|
||||||
boolean isQuickTime,
|
boolean isQuickTime,
|
||||||
@Nullable DrmInitData drmInitData,
|
@Nullable DrmInitData drmInitData,
|
||||||
StsdData out,
|
StsdData out,
|
||||||
@ -2593,9 +2605,9 @@ public final class BoxParser {
|
|||||||
private static final class MdhdData {
|
private static final class MdhdData {
|
||||||
private final long timescale;
|
private final long timescale;
|
||||||
private final long mediaDurationUs;
|
private final long mediaDurationUs;
|
||||||
private final String language;
|
@Nullable private final String language;
|
||||||
|
|
||||||
public MdhdData(long timescale, long mediaDurationUs, String language) {
|
public MdhdData(long timescale, long mediaDurationUs, @Nullable String language) {
|
||||||
this.timescale = timescale;
|
this.timescale = timescale;
|
||||||
this.mediaDurationUs = mediaDurationUs;
|
this.mediaDurationUs = mediaDurationUs;
|
||||||
this.language = language;
|
this.language = language;
|
||||||
|
@ -12,7 +12,6 @@ track 0:
|
|||||||
sampleMimeType = audio/opus
|
sampleMimeType = audio/opus
|
||||||
channelCount = 2
|
channelCount = 2
|
||||||
sampleRate = 16000
|
sampleRate = 16000
|
||||||
language =
|
|
||||||
initializationData:
|
initializationData:
|
||||||
data = length 19, hash 4034F23B
|
data = length 19, hash 4034F23B
|
||||||
data = length 8, hash 94446F01
|
data = length 8, hash 94446F01
|
||||||
|
@ -12,7 +12,6 @@ track 0:
|
|||||||
sampleMimeType = audio/opus
|
sampleMimeType = audio/opus
|
||||||
channelCount = 2
|
channelCount = 2
|
||||||
sampleRate = 16000
|
sampleRate = 16000
|
||||||
language =
|
|
||||||
initializationData:
|
initializationData:
|
||||||
data = length 19, hash 4034F23B
|
data = length 19, hash 4034F23B
|
||||||
data = length 8, hash 94446F01
|
data = length 8, hash 94446F01
|
||||||
|
@ -12,7 +12,6 @@ track 0:
|
|||||||
sampleMimeType = audio/opus
|
sampleMimeType = audio/opus
|
||||||
channelCount = 2
|
channelCount = 2
|
||||||
sampleRate = 16000
|
sampleRate = 16000
|
||||||
language =
|
|
||||||
initializationData:
|
initializationData:
|
||||||
data = length 19, hash 4034F23B
|
data = length 19, hash 4034F23B
|
||||||
data = length 8, hash 94446F01
|
data = length 8, hash 94446F01
|
||||||
|
@ -12,7 +12,6 @@ track 0:
|
|||||||
sampleMimeType = audio/opus
|
sampleMimeType = audio/opus
|
||||||
channelCount = 2
|
channelCount = 2
|
||||||
sampleRate = 16000
|
sampleRate = 16000
|
||||||
language =
|
|
||||||
initializationData:
|
initializationData:
|
||||||
data = length 19, hash 4034F23B
|
data = length 19, hash 4034F23B
|
||||||
data = length 8, hash 94446F01
|
data = length 8, hash 94446F01
|
||||||
|
@ -18,7 +18,6 @@ track 0:
|
|||||||
maxInputSize = 295
|
maxInputSize = 295
|
||||||
channelCount = 1
|
channelCount = 1
|
||||||
sampleRate = 16000
|
sampleRate = 16000
|
||||||
language = ```
|
|
||||||
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
|
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
|
||||||
initializationData:
|
initializationData:
|
||||||
data = length 30, hash C22462B1
|
data = length 30, hash C22462B1
|
||||||
|
@ -18,7 +18,6 @@ track 0:
|
|||||||
channelCount = 2
|
channelCount = 2
|
||||||
sampleRate = 44100
|
sampleRate = 44100
|
||||||
pcmEncoding = 2
|
pcmEncoding = 2
|
||||||
language = ```
|
|
||||||
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
|
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
|
||||||
sample 0:
|
sample 0:
|
||||||
time = 0
|
time = 0
|
||||||
|
@ -17,7 +17,6 @@ track 0:
|
|||||||
maxInputSize = 1185
|
maxInputSize = 1185
|
||||||
channelCount = 6
|
channelCount = 6
|
||||||
sampleRate = 48000
|
sampleRate = 48000
|
||||||
language = ```
|
|
||||||
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
|
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
|
||||||
initializationData:
|
initializationData:
|
||||||
data = length 27, hash 9EE6F879
|
data = length 27, hash 9EE6F879
|
||||||
|
@ -42,7 +42,6 @@ track 1:
|
|||||||
maxInputSize = 627
|
maxInputSize = 627
|
||||||
channelCount = 2
|
channelCount = 2
|
||||||
sampleRate = 48000
|
sampleRate = 48000
|
||||||
language = ```
|
|
||||||
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
|
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
|
||||||
initializationData:
|
initializationData:
|
||||||
data = length 2, hash 560
|
data = length 2, hash 560
|
||||||
|
@ -552,7 +552,6 @@ track 1:
|
|||||||
maxInputSize = 877
|
maxInputSize = 877
|
||||||
channelCount = 2
|
channelCount = 2
|
||||||
sampleRate = 48000
|
sampleRate = 48000
|
||||||
language = ```
|
|
||||||
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
|
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
|
||||||
initializationData:
|
initializationData:
|
||||||
data = length 2, hash 560
|
data = length 2, hash 560
|
||||||
|
@ -543,7 +543,6 @@ track 1:
|
|||||||
codecs = mp4a.40.2
|
codecs = mp4a.40.2
|
||||||
channelCount = 2
|
channelCount = 2
|
||||||
sampleRate = 48000
|
sampleRate = 48000
|
||||||
language = ```
|
|
||||||
initializationData:
|
initializationData:
|
||||||
data = length 2, hash 560
|
data = length 2, hash 560
|
||||||
sample 0:
|
sample 0:
|
||||||
|
@ -416,7 +416,6 @@ track 1:
|
|||||||
maxInputSize = 877
|
maxInputSize = 877
|
||||||
channelCount = 2
|
channelCount = 2
|
||||||
sampleRate = 48000
|
sampleRate = 48000
|
||||||
language = ```
|
|
||||||
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
|
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
|
||||||
initializationData:
|
initializationData:
|
||||||
data = length 2, hash 560
|
data = length 2, hash 560
|
||||||
|
@ -552,7 +552,6 @@ track 1:
|
|||||||
maxInputSize = 877
|
maxInputSize = 877
|
||||||
channelCount = 2
|
channelCount = 2
|
||||||
sampleRate = 48000
|
sampleRate = 48000
|
||||||
language = ```
|
|
||||||
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
|
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
|
||||||
initializationData:
|
initializationData:
|
||||||
data = length 2, hash 560
|
data = length 2, hash 560
|
||||||
|
@ -552,7 +552,6 @@ track 1:
|
|||||||
maxInputSize = 877
|
maxInputSize = 877
|
||||||
channelCount = 2
|
channelCount = 2
|
||||||
sampleRate = 48000
|
sampleRate = 48000
|
||||||
language = ```
|
|
||||||
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
|
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
|
||||||
initializationData:
|
initializationData:
|
||||||
data = length 2, hash 560
|
data = length 2, hash 560
|
||||||
|
@ -18,7 +18,6 @@ track 0:
|
|||||||
maxInputSize = 295
|
maxInputSize = 295
|
||||||
channelCount = 1
|
channelCount = 1
|
||||||
sampleRate = 16000
|
sampleRate = 16000
|
||||||
language = ```
|
|
||||||
metadata = entries=[Mp4Timestamp: creation time=3000000000, modification time=4000000000, timescale=10000]
|
metadata = entries=[Mp4Timestamp: creation time=3000000000, modification time=4000000000, timescale=10000]
|
||||||
initializationData:
|
initializationData:
|
||||||
data = length 30, hash C22462B1
|
data = length 30, hash C22462B1
|
||||||
|
@ -17,7 +17,6 @@ track 0:
|
|||||||
maxInputSize = 1185
|
maxInputSize = 1185
|
||||||
channelCount = 6
|
channelCount = 6
|
||||||
sampleRate = 48000
|
sampleRate = 48000
|
||||||
language = ```
|
|
||||||
metadata = entries=[Mp4Timestamp: creation time=3000000000, modification time=4000000000, timescale=10000]
|
metadata = entries=[Mp4Timestamp: creation time=3000000000, modification time=4000000000, timescale=10000]
|
||||||
initializationData:
|
initializationData:
|
||||||
data = length 27, hash 9EE6F879
|
data = length 27, hash 9EE6F879
|
||||||
|
@ -57,7 +57,6 @@ track 1:
|
|||||||
maxInputSize = 627
|
maxInputSize = 627
|
||||||
channelCount = 2
|
channelCount = 2
|
||||||
sampleRate = 48000
|
sampleRate = 48000
|
||||||
language = ```
|
|
||||||
metadata = entries=[xyz: latitude=51.5932, longitude=-0.2431, Mp4Timestamp: creation time=3000000000, modification time=4000000000, timescale=10000]
|
metadata = entries=[xyz: latitude=51.5932, longitude=-0.2431, Mp4Timestamp: creation time=3000000000, modification time=4000000000, timescale=10000]
|
||||||
initializationData:
|
initializationData:
|
||||||
data = length 2, hash 560
|
data = length 2, hash 560
|
||||||
|
Loading…
x
Reference in New Issue
Block a user