mirror of
https://github.com/samsonjs/media.git
synced 2026-04-04 11:05:47 +00:00
Extend MP4 extractor implementation with complete parsing of mhaC and mhaP boxes
This commit is contained in:
parent
98e9022c0e
commit
94442291bd
4 changed files with 228 additions and 5 deletions
|
|
@ -1,3 +1,28 @@
|
|||
/***************************************************************************
|
||||
|
||||
Fraunhofer hereby grants to Google free of charge a worldwide, perpetual,
|
||||
irrevocable, non-exclusive copyright license with the right to sublicense
|
||||
through multiple tiers to use, copy, distribute, modify and create
|
||||
derivative works of the Software Patches for Exoplayer in source code form
|
||||
and/or object code versions of the software. For the avoidance of doubt,
|
||||
this license does not include any license to any Fraunhofer patents or any
|
||||
third-party patents. Since the license is granted without any charge,
|
||||
Fraunhofer provides the Software Patches for Exoplayer, in accordance with
|
||||
the laws of the Federal Republic of Germany, on an “as is” basis, WITHOUT
|
||||
WARRANTIES or conditions of any kind, either express or implied, including,
|
||||
without limitation, any warranties or conditions of title, non-infringement,
|
||||
merchantability, or fitness for a particular purpose.
|
||||
|
||||
For the purpose of clarity, the provision of the Software Patches for
|
||||
Exoplayer by Fraunhofer and the use of the same by Google shall be subject
|
||||
solely to the license stated above.
|
||||
|
||||
This file was originally licensed under the Apache 2.0 license (see license
|
||||
note below). Fraunhofer has modified this files and provides its copyright
|
||||
in the modifications to Google under the above terms, which shall not be
|
||||
considered a contribution under the Apache 2.0 license.
|
||||
|
||||
***************************************************************************/
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
|
|
@ -1608,4 +1633,51 @@ public final class C {
|
|||
int mediaDrmErrorCode) {
|
||||
return Util.getErrorCodeForMediaDrmErrorCode(mediaDrmErrorCode);
|
||||
}
|
||||
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({
|
||||
Format.NO_VALUE,
|
||||
MPEGH_PROFILE_MAIN_L1,
|
||||
MPEGH_PROFILE_MAIN_L2,
|
||||
MPEGH_PROFILE_MAIN_L3,
|
||||
MPEGH_PROFILE_MAIN_L4,
|
||||
MPEGH_PROFILE_MAIN_L5,
|
||||
MPEGH_PROFILE_HIGH_L1,
|
||||
MPEGH_PROFILE_HIGH_L2,
|
||||
MPEGH_PROFILE_HIGH_L3,
|
||||
MPEGH_PROFILE_HIGH_L4,
|
||||
MPEGH_PROFILE_HIGH_L5,
|
||||
MPEGH_PROFILE_LC_L1,
|
||||
MPEGH_PROFILE_LC_L2,
|
||||
MPEGH_PROFILE_LC_L3,
|
||||
MPEGH_PROFILE_LC_L4,
|
||||
MPEGH_PROFILE_LC_L5,
|
||||
MPEGH_PROFILE_BL_L1,
|
||||
MPEGH_PROFILE_BL_L2,
|
||||
MPEGH_PROFILE_BL_L3,
|
||||
MPEGH_PROFILE_BL_L4,
|
||||
MPEGH_PROFILE_BL_L5
|
||||
})
|
||||
public @interface MpeghProfileLevelIndication {}
|
||||
public static final int MPEGH_PROFILE_MAIN_L1 = 1;
|
||||
public static final int MPEGH_PROFILE_MAIN_L2 = 2;
|
||||
public static final int MPEGH_PROFILE_MAIN_L3 = 3;
|
||||
public static final int MPEGH_PROFILE_MAIN_L4 = 4;
|
||||
public static final int MPEGH_PROFILE_MAIN_L5 = 5;
|
||||
public static final int MPEGH_PROFILE_HIGH_L1 = 6;
|
||||
public static final int MPEGH_PROFILE_HIGH_L2 = 7;
|
||||
public static final int MPEGH_PROFILE_HIGH_L3 = 8;
|
||||
public static final int MPEGH_PROFILE_HIGH_L4 = 9;
|
||||
public static final int MPEGH_PROFILE_HIGH_L5 = 10;
|
||||
public static final int MPEGH_PROFILE_LC_L1 = 11;
|
||||
public static final int MPEGH_PROFILE_LC_L2 = 12;
|
||||
public static final int MPEGH_PROFILE_LC_L3 = 13;
|
||||
public static final int MPEGH_PROFILE_LC_L4 = 14;
|
||||
public static final int MPEGH_PROFILE_LC_L5 = 15;
|
||||
public static final int MPEGH_PROFILE_BL_L1 = 16;
|
||||
public static final int MPEGH_PROFILE_BL_L2 = 17;
|
||||
public static final int MPEGH_PROFILE_BL_L3 = 18;
|
||||
public static final int MPEGH_PROFILE_BL_L4 = 19;
|
||||
public static final int MPEGH_PROFILE_BL_L5 = 20;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,28 @@
|
|||
/***************************************************************************
|
||||
|
||||
Fraunhofer hereby grants to Google free of charge a worldwide, perpetual,
|
||||
irrevocable, non-exclusive copyright license with the right to sublicense
|
||||
through multiple tiers to use, copy, distribute, modify and create
|
||||
derivative works of the Software Patches for Exoplayer in source code form
|
||||
and/or object code versions of the software. For the avoidance of doubt,
|
||||
this license does not include any license to any Fraunhofer patents or any
|
||||
third-party patents. Since the license is granted without any charge,
|
||||
Fraunhofer provides the Software Patches for Exoplayer, in accordance with
|
||||
the laws of the Federal Republic of Germany, on an “as is” basis, WITHOUT
|
||||
WARRANTIES or conditions of any kind, either express or implied, including,
|
||||
without limitation, any warranties or conditions of title, non-infringement,
|
||||
merchantability, or fitness for a particular purpose.
|
||||
|
||||
For the purpose of clarity, the provision of the Software Patches for
|
||||
Exoplayer by Fraunhofer and the use of the same by Google shall be subject
|
||||
solely to the license stated above.
|
||||
|
||||
This file was originally licensed under the Apache 2.0 license (see license
|
||||
note below). Fraunhofer has modified this files and provides its copyright
|
||||
in the modifications to Google under the above terms, which shall not be
|
||||
considered a contribution under the Apache 2.0 license.
|
||||
|
||||
***************************************************************************/
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
|
|
@ -176,6 +201,10 @@ public final class Format implements Bundleable {
|
|||
private int encoderDelay;
|
||||
private int encoderPadding;
|
||||
|
||||
@C.MpeghProfileLevelIndication private int mpeghProfileLevelIndication;
|
||||
private int mpeghReferenceChannelLayout;
|
||||
@Nullable @C.MpeghProfileLevelIndication private int[] mpeghCompatibleProfileLevelSet;
|
||||
|
||||
// Text specific.
|
||||
|
||||
private int accessibilityChannel;
|
||||
|
|
@ -207,6 +236,8 @@ public final class Format implements Bundleable {
|
|||
channelCount = NO_VALUE;
|
||||
sampleRate = NO_VALUE;
|
||||
pcmEncoding = NO_VALUE;
|
||||
mpeghProfileLevelIndication = NO_VALUE;
|
||||
mpeghReferenceChannelLayout = NO_VALUE;
|
||||
// Text specific.
|
||||
accessibilityChannel = NO_VALUE;
|
||||
cueReplacementBehavior = CUE_REPLACEMENT_BEHAVIOR_MERGE;
|
||||
|
|
@ -255,6 +286,9 @@ public final class Format implements Bundleable {
|
|||
this.pcmEncoding = format.pcmEncoding;
|
||||
this.encoderDelay = format.encoderDelay;
|
||||
this.encoderPadding = format.encoderPadding;
|
||||
this.mpeghReferenceChannelLayout = format.mpeghReferenceChannelLayout;
|
||||
this.mpeghProfileLevelIndication = format.mpeghProfileLevelIndication;
|
||||
this.mpeghCompatibleProfileLevelSet = format.mpeghCompatibleProfileLevelSet;
|
||||
// Text specific.
|
||||
this.accessibilityChannel = format.accessibilityChannel;
|
||||
this.cueReplacementBehavior = format.cueReplacementBehavior;
|
||||
|
|
@ -622,6 +656,19 @@ public final class Format implements Bundleable {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder setMpeghProfileLevelIndication(@C.MpeghProfileLevelIndication int mpeghProfileLevelIndication) {
|
||||
this.mpeghProfileLevelIndication = mpeghProfileLevelIndication;
|
||||
return this;
|
||||
}
|
||||
public Builder setMpeghReferenceChannelLayout(int mpeghReferenceChannelLayout) {
|
||||
this.mpeghReferenceChannelLayout = mpeghReferenceChannelLayout;
|
||||
return this;
|
||||
}
|
||||
public Builder setMpeghCompatibleProfileLevelSet(@Nullable @C.MpeghProfileLevelIndication int[] mpeghCompatibleProfileLevelSet) {
|
||||
this.mpeghCompatibleProfileLevelSet = mpeghCompatibleProfileLevelSet;
|
||||
return this;
|
||||
}
|
||||
|
||||
// Text specific.
|
||||
|
||||
/**
|
||||
|
|
@ -895,6 +942,10 @@ public final class Format implements Bundleable {
|
|||
*/
|
||||
@UnstableApi public final int encoderPadding;
|
||||
|
||||
@C.MpeghProfileLevelIndication public final int mpeghProfileLevelIndication;
|
||||
public final int mpeghReferenceChannelLayout;
|
||||
@Nullable @C.MpeghProfileLevelIndication public final int[] mpeghCompatibleProfileLevelSet;
|
||||
|
||||
// Text specific.
|
||||
|
||||
/** The Accessibility channel, or {@link #NO_VALUE} if not known or applicable. */
|
||||
|
|
@ -965,6 +1016,9 @@ public final class Format implements Bundleable {
|
|||
pcmEncoding = builder.pcmEncoding;
|
||||
encoderDelay = builder.encoderDelay == NO_VALUE ? 0 : builder.encoderDelay;
|
||||
encoderPadding = builder.encoderPadding == NO_VALUE ? 0 : builder.encoderPadding;
|
||||
mpeghProfileLevelIndication = builder.mpeghProfileLevelIndication;
|
||||
mpeghReferenceChannelLayout = builder.mpeghReferenceChannelLayout;
|
||||
mpeghCompatibleProfileLevelSet = builder.mpeghCompatibleProfileLevelSet;
|
||||
// Text specific.
|
||||
accessibilityChannel = builder.accessibilityChannel;
|
||||
cueReplacementBehavior = builder.cueReplacementBehavior;
|
||||
|
|
@ -1138,6 +1192,9 @@ public final class Format implements Bundleable {
|
|||
result = 31 * result + pcmEncoding;
|
||||
result = 31 * result + encoderDelay;
|
||||
result = 31 * result + encoderPadding;
|
||||
result = 31 * result + mpeghProfileLevelIndication;
|
||||
result = 31 * result + mpeghReferenceChannelLayout;
|
||||
// [Omitted] mpeghCompatibleProfileLevelSet.
|
||||
// Text specific.
|
||||
result = 31 * result + accessibilityChannel;
|
||||
// Image specific.
|
||||
|
|
@ -1178,6 +1235,9 @@ public final class Format implements Bundleable {
|
|||
&& pcmEncoding == other.pcmEncoding
|
||||
&& encoderDelay == other.encoderDelay
|
||||
&& encoderPadding == other.encoderPadding
|
||||
&& mpeghReferenceChannelLayout == other.mpeghReferenceChannelLayout
|
||||
&& mpeghProfileLevelIndication == other.mpeghProfileLevelIndication
|
||||
&& Util.areEqual(mpeghCompatibleProfileLevelSet, other.mpeghCompatibleProfileLevelSet)
|
||||
&& accessibilityChannel == other.accessibilityChannel
|
||||
&& tileCountHorizontal == other.tileCountHorizontal
|
||||
&& tileCountVertical == other.tileCountVertical
|
||||
|
|
@ -1382,6 +1442,9 @@ public final class Format implements Bundleable {
|
|||
private static final String FIELD_CRYPTO_TYPE = Util.intToStringMaxRadix(29);
|
||||
private static final String FIELD_TILE_COUNT_HORIZONTAL = Util.intToStringMaxRadix(30);
|
||||
private static final String FIELD_TILE_COUNT_VERTICAL = Util.intToStringMaxRadix(31);
|
||||
private static final String FIELD_MPEGH_PROFILE_LEVEL_INDICATION = Util.intToStringMaxRadix(32);
|
||||
private static final String FIELD_MPEGH_REFERENCE_CHANNEL_LAYOUT = Util.intToStringMaxRadix(33);
|
||||
private static final String FIELD_MPEGH_COMPATIBLE_PROFILE_LEVEL_SET = Util.intToStringMaxRadix(34);
|
||||
|
||||
@UnstableApi
|
||||
@Override
|
||||
|
|
@ -1437,6 +1500,9 @@ public final class Format implements Bundleable {
|
|||
bundle.putInt(FIELD_PCM_ENCODING, pcmEncoding);
|
||||
bundle.putInt(FIELD_ENCODER_DELAY, encoderDelay);
|
||||
bundle.putInt(FIELD_ENCODER_PADDING, encoderPadding);
|
||||
bundle.putInt(FIELD_MPEGH_PROFILE_LEVEL_INDICATION, mpeghProfileLevelIndication);
|
||||
bundle.putInt(FIELD_MPEGH_REFERENCE_CHANNEL_LAYOUT, mpeghReferenceChannelLayout);
|
||||
bundle.putIntArray(FIELD_MPEGH_COMPATIBLE_PROFILE_LEVEL_SET, mpeghCompatibleProfileLevelSet);
|
||||
// Text specific.
|
||||
bundle.putInt(FIELD_ACCESSIBILITY_CHANNEL, accessibilityChannel);
|
||||
// Image specific.
|
||||
|
|
@ -1512,6 +1578,12 @@ public final class Format implements Bundleable {
|
|||
.setPcmEncoding(bundle.getInt(FIELD_PCM_ENCODING, DEFAULT.pcmEncoding))
|
||||
.setEncoderDelay(bundle.getInt(FIELD_ENCODER_DELAY, DEFAULT.encoderDelay))
|
||||
.setEncoderPadding(bundle.getInt(FIELD_ENCODER_PADDING, DEFAULT.encoderPadding))
|
||||
.setMpeghProfileLevelIndication(
|
||||
bundle.getInt(FIELD_MPEGH_PROFILE_LEVEL_INDICATION, DEFAULT.mpeghProfileLevelIndication))
|
||||
.setMpeghReferenceChannelLayout(
|
||||
bundle.getInt(FIELD_MPEGH_REFERENCE_CHANNEL_LAYOUT, DEFAULT.mpeghReferenceChannelLayout))
|
||||
.setMpeghCompatibleProfileLevelSet(
|
||||
bundle.getIntArray(FIELD_MPEGH_COMPATIBLE_PROFILE_LEVEL_SET))
|
||||
// Text specific.
|
||||
.setAccessibilityChannel(
|
||||
bundle.getInt(FIELD_ACCESSIBILITY_CHANNEL, DEFAULT.accessibilityChannel))
|
||||
|
|
|
|||
|
|
@ -1,3 +1,28 @@
|
|||
/***************************************************************************
|
||||
|
||||
Fraunhofer hereby grants to Google free of charge a worldwide, perpetual,
|
||||
irrevocable, non-exclusive copyright license with the right to sublicense
|
||||
through multiple tiers to use, copy, distribute, modify and create
|
||||
derivative works of the Software Patches for Exoplayer in source code form
|
||||
and/or object code versions of the software. For the avoidance of doubt,
|
||||
this license does not include any license to any Fraunhofer patents or any
|
||||
third-party patents. Since the license is granted without any charge,
|
||||
Fraunhofer provides the Software Patches for Exoplayer, in accordance with
|
||||
the laws of the Federal Republic of Germany, on an “as is” basis, WITHOUT
|
||||
WARRANTIES or conditions of any kind, either express or implied, including,
|
||||
without limitation, any warranties or conditions of title, non-infringement,
|
||||
merchantability, or fitness for a particular purpose.
|
||||
|
||||
For the purpose of clarity, the provision of the Software Patches for
|
||||
Exoplayer by Fraunhofer and the use of the same by Google shall be subject
|
||||
solely to the license stated above.
|
||||
|
||||
This file was originally licensed under the Apache 2.0 license (see license
|
||||
note below). Fraunhofer has modified this files and provides its copyright
|
||||
in the modifications to Google under the above terms, which shall not be
|
||||
considered a contribution under the Apache 2.0 license.
|
||||
|
||||
***************************************************************************/
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
|
|
@ -125,6 +150,9 @@ import java.util.List;
|
|||
@SuppressWarnings("ConstantCaseForConstants")
|
||||
public static final int TYPE_mhaC = 0x6d686143;
|
||||
|
||||
@SuppressWarnings("ConstantCaseForConstants")
|
||||
public static final int TYPE_mhaP = 0x6d686150;
|
||||
|
||||
@SuppressWarnings("ConstantCaseForConstants")
|
||||
public static final int TYPE_wave = 0x77617665;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,28 @@
|
|||
/***************************************************************************
|
||||
|
||||
Fraunhofer hereby grants to Google free of charge a worldwide, perpetual,
|
||||
irrevocable, non-exclusive copyright license with the right to sublicense
|
||||
through multiple tiers to use, copy, distribute, modify and create
|
||||
derivative works of the Software Patches for Exoplayer in source code form
|
||||
and/or object code versions of the software. For the avoidance of doubt,
|
||||
this license does not include any license to any Fraunhofer patents or any
|
||||
third-party patents. Since the license is granted without any charge,
|
||||
Fraunhofer provides the Software Patches for Exoplayer, in accordance with
|
||||
the laws of the Federal Republic of Germany, on an “as is” basis, WITHOUT
|
||||
WARRANTIES or conditions of any kind, either express or implied, including,
|
||||
without limitation, any warranties or conditions of title, non-infringement,
|
||||
merchantability, or fitness for a particular purpose.
|
||||
|
||||
For the purpose of clarity, the provision of the Software Patches for
|
||||
Exoplayer by Fraunhofer and the use of the same by Google shall be subject
|
||||
solely to the license stated above.
|
||||
|
||||
This file was originally licensed under the Apache 2.0 license (see license
|
||||
note below). Fraunhofer has modified this files and provides its copyright
|
||||
in the modifications to Google under the above terms, which shall not be
|
||||
considered a contribution under the Apache 2.0 license.
|
||||
|
||||
***************************************************************************/
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
|
|
@ -1598,6 +1623,9 @@ import java.util.List;
|
|||
int sampleRateMlp = 0;
|
||||
@C.PcmEncoding int pcmEncoding = Format.NO_VALUE;
|
||||
@Nullable String codecs = null;
|
||||
@C.MpeghProfileLevelIndication int mpeghProfileLevelIndication = Format.NO_VALUE;
|
||||
int mpeghReferenceChannelLayout = Format.NO_VALUE;
|
||||
@Nullable @C.MpeghProfileLevelIndication int[] mpeghCompatibleProfileLevelSet = null;
|
||||
@Nullable EsdsData esdsData = null;
|
||||
|
||||
if (quickTimeSoundDescriptionVersion == 0 || quickTimeSoundDescriptionVersion == 1) {
|
||||
|
|
@ -1720,15 +1748,35 @@ import java.util.List;
|
|||
ExtractorUtil.checkContainerInput(childAtomSize > 0, "childAtomSize must be positive");
|
||||
int childAtomType = parent.readInt();
|
||||
if (childAtomType == Atom.TYPE_mhaC) {
|
||||
// See ISO_IEC_23008-3;2019 MHADecoderConfigurationRecord
|
||||
// See ISO_IEC_23008-3;2022 MHADecoderConfigurationRecord
|
||||
// The header consists of: size (4), boxtype 'mhaC' (4), configurationVersion (1),
|
||||
// mpegh3daProfileLevelIndication (1), referenceChannelLayout (1), mpegh3daConfigLength (2).
|
||||
int mhacHeaderSize = 13;
|
||||
int childAtomBodySize = childAtomSize - mhacHeaderSize;
|
||||
byte[] initializationDataBytes = new byte[childAtomBodySize];
|
||||
parent.setPosition(childPosition + mhacHeaderSize);
|
||||
parent.readBytes(initializationDataBytes, 0, childAtomBodySize);
|
||||
parent.setPosition(childPosition + Atom.HEADER_SIZE);
|
||||
int configurationVersion = parent.readUnsignedByte();
|
||||
mpeghProfileLevelIndication = parent.readUnsignedByte();
|
||||
mpeghReferenceChannelLayout = parent.readUnsignedByte();
|
||||
if (mimeType.equals(MimeTypes.AUDIO_MPEGH_MHM1)) {
|
||||
codecs = String.format("mhm1.0x%02X", mpeghProfileLevelIndication);
|
||||
} else {
|
||||
codecs = String.format("mha1.0x%02X", mpeghProfileLevelIndication);
|
||||
}
|
||||
int mpegh3daConfigLength = parent.readUnsignedShort();
|
||||
byte[] initializationDataBytes = new byte[mpegh3daConfigLength];
|
||||
parent.readBytes(initializationDataBytes, 0, mpegh3daConfigLength);
|
||||
initializationData = ImmutableList.of(initializationDataBytes);
|
||||
} else if (childAtomType == Atom.TYPE_mhaP) {
|
||||
// See ISO_IEC_23008-3;2022 MHAProfileAndLevelCompatibilitySetBox
|
||||
// The header consists of: size (4), boxtype 'mhaP' (4), numCompatibleSets (1).
|
||||
int mhapHeaderSize = 9;
|
||||
parent.setPosition(childPosition + Atom.HEADER_SIZE);
|
||||
int numCompatibleSets = parent.readUnsignedByte();
|
||||
if (numCompatibleSets > 0) {
|
||||
mpeghCompatibleProfileLevelSet = new int[numCompatibleSets];
|
||||
for (int i = 0; i < numCompatibleSets; i++) {
|
||||
mpeghCompatibleProfileLevelSet[i] = parent.readUnsignedByte();
|
||||
}
|
||||
}
|
||||
} else if (childAtomType == Atom.TYPE_esds
|
||||
|| (isQuickTime && childAtomType == Atom.TYPE_wave)) {
|
||||
int esdsAtomPosition =
|
||||
|
|
@ -1835,6 +1883,9 @@ import java.util.List;
|
|||
.setPcmEncoding(pcmEncoding)
|
||||
.setInitializationData(initializationData)
|
||||
.setDrmInitData(drmInitData)
|
||||
.setMpeghProfileLevelIndication(mpeghProfileLevelIndication)
|
||||
.setMpeghReferenceChannelLayout(mpeghReferenceChannelLayout)
|
||||
.setMpeghCompatibleProfileLevelSet(mpeghCompatibleProfileLevelSet)
|
||||
.setLanguage(language);
|
||||
|
||||
if (esdsData != null) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue