mirror of
https://github.com/samsonjs/media.git
synced 2026-04-04 11:05:47 +00:00
Format with google-java-format
This commit is contained in:
parent
66718c2b3d
commit
2da1bb1877
3 changed files with 211 additions and 220 deletions
|
|
@ -1,23 +1,18 @@
|
|||
/***************************************************************************
|
||||
|
||||
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.
|
||||
|
||||
***************************************************************************/
|
||||
/*
|
||||
* Copyright 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package androidx.media3.extractor;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
|
|
@ -69,9 +64,7 @@ public final class MpeghUtil {
|
|||
/** An array of compatible profile level indications of the audio in the frame. */
|
||||
@Nullable public byte[] compatibleSetIndication;
|
||||
|
||||
/**
|
||||
* Initializes the {@link FrameInfo} with fields containing default values.
|
||||
*/
|
||||
/** Initializes the {@link FrameInfo} with fields containing default values. */
|
||||
public FrameInfo() {
|
||||
standardFrameSamples = C.LENGTH_UNSET;
|
||||
samplingRate = C.RATE_UNSET_INT;
|
||||
|
|
@ -95,9 +88,16 @@ public final class MpeghUtil {
|
|||
* @param mpegh3daProfileLevelIndication See {@link #mpegh3daProfileLevelIndication}.
|
||||
* @param compatibleSetIndication See {@link #compatibleSetIndication}.
|
||||
*/
|
||||
public FrameInfo(boolean containsConfig, boolean configChanged, int standardFrameSamples,
|
||||
int samplingRate, int frameSamples, int frameBytes, long mainStreamLabel,
|
||||
int mpegh3daProfileLevelIndication, @Nullable byte[] compatibleSetIndication) {
|
||||
public FrameInfo(
|
||||
boolean containsConfig,
|
||||
boolean configChanged,
|
||||
int standardFrameSamples,
|
||||
int samplingRate,
|
||||
int frameSamples,
|
||||
int frameBytes,
|
||||
long mainStreamLabel,
|
||||
int mpegh3daProfileLevelIndication,
|
||||
@Nullable byte[] compatibleSetIndication) {
|
||||
this.containsConfig = containsConfig;
|
||||
this.configChanged = configChanged;
|
||||
this.standardFrameSamples = standardFrameSamples;
|
||||
|
|
@ -107,14 +107,12 @@ public final class MpeghUtil {
|
|||
this.mainStreamLabel = mainStreamLabel;
|
||||
this.mpegh3daProfileLevelIndication = mpegh3daProfileLevelIndication;
|
||||
if (compatibleSetIndication != null && compatibleSetIndication.length > 0) {
|
||||
this.compatibleSetIndication = Arrays.copyOf(compatibleSetIndication,
|
||||
compatibleSetIndication.length);
|
||||
this.compatibleSetIndication =
|
||||
Arrays.copyOf(compatibleSetIndication, compatibleSetIndication.length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the fields of the {@link FrameInfo} to its default values.
|
||||
*/
|
||||
/** Resets the fields of the {@link FrameInfo} to its default values. */
|
||||
public void reset() {
|
||||
containsConfig = false;
|
||||
configChanged = false;
|
||||
|
|
@ -129,40 +127,40 @@ public final class MpeghUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* MHAS packet types. See ISO_IEC_23008-3;2022, 14.3.1, Table 226.
|
||||
* One of {@link #PACTYP_FILLDATA}, {@link #PACTYP_MPEGH3DACFG}, {@link #PACTYP_MPEGH3DAFRAME},
|
||||
* {@link #PACTYP_AUDIOSCENEINFO}, {@link #PACTYP_SYNC}, {@link #PACTYP_SYNCGAP},
|
||||
* {@link #PACTYP_MARKER}, {@link #PACTYP_CRC16}, {@link #PACTYP_CRC32},
|
||||
* {@link #PACTYP_DESCRIPTOR}, {@link #PACTYP_USERINTERACTION}, {@link #PACTYP_LOUDNESS_DRC},
|
||||
* {@link #PACTYP_BUFFERINFO}, {@link #PACTYP_GLOBAL_CRC16}, {@link #PACTYP_GLOBAL_CRC32},
|
||||
* {@link #PACTYP_AUDIOTRUNCATION}, {@link #PACTYP_GENDATA}, {@link #PACTYPE_EARCON},
|
||||
* {@link #PACTYPE_PCMCONFIG}, {@link #PACTYPE_PCMDATA}, {@link #PACTYP_LOUDNESS}.
|
||||
* MHAS packet types. See ISO_IEC_23008-3;2022, 14.3.1, Table 226. One of {@link
|
||||
* #PACTYP_FILLDATA}, {@link #PACTYP_MPEGH3DACFG}, {@link #PACTYP_MPEGH3DAFRAME}, {@link
|
||||
* #PACTYP_AUDIOSCENEINFO}, {@link #PACTYP_SYNC}, {@link #PACTYP_SYNCGAP}, {@link #PACTYP_MARKER},
|
||||
* {@link #PACTYP_CRC16}, {@link #PACTYP_CRC32}, {@link #PACTYP_DESCRIPTOR}, {@link
|
||||
* #PACTYP_USERINTERACTION}, {@link #PACTYP_LOUDNESS_DRC}, {@link #PACTYP_BUFFERINFO}, {@link
|
||||
* #PACTYP_GLOBAL_CRC16}, {@link #PACTYP_GLOBAL_CRC32}, {@link #PACTYP_AUDIOTRUNCATION}, {@link
|
||||
* #PACTYP_GENDATA}, {@link #PACTYPE_EARCON}, {@link #PACTYPE_PCMCONFIG}, {@link
|
||||
* #PACTYPE_PCMDATA}, {@link #PACTYP_LOUDNESS}.
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target(TYPE_USE)
|
||||
@IntDef({
|
||||
PACTYP_FILLDATA,
|
||||
PACTYP_MPEGH3DACFG,
|
||||
PACTYP_MPEGH3DAFRAME,
|
||||
PACTYP_AUDIOSCENEINFO,
|
||||
PACTYP_SYNC,
|
||||
PACTYP_SYNCGAP,
|
||||
PACTYP_MARKER,
|
||||
PACTYP_CRC16,
|
||||
PACTYP_CRC32,
|
||||
PACTYP_DESCRIPTOR,
|
||||
PACTYP_USERINTERACTION,
|
||||
PACTYP_LOUDNESS_DRC,
|
||||
PACTYP_BUFFERINFO,
|
||||
PACTYP_GLOBAL_CRC16,
|
||||
PACTYP_GLOBAL_CRC32,
|
||||
PACTYP_AUDIOTRUNCATION,
|
||||
PACTYP_GENDATA,
|
||||
PACTYPE_EARCON,
|
||||
PACTYPE_PCMCONFIG,
|
||||
PACTYPE_PCMDATA,
|
||||
PACTYP_LOUDNESS
|
||||
PACTYP_FILLDATA,
|
||||
PACTYP_MPEGH3DACFG,
|
||||
PACTYP_MPEGH3DAFRAME,
|
||||
PACTYP_AUDIOSCENEINFO,
|
||||
PACTYP_SYNC,
|
||||
PACTYP_SYNCGAP,
|
||||
PACTYP_MARKER,
|
||||
PACTYP_CRC16,
|
||||
PACTYP_CRC32,
|
||||
PACTYP_DESCRIPTOR,
|
||||
PACTYP_USERINTERACTION,
|
||||
PACTYP_LOUDNESS_DRC,
|
||||
PACTYP_BUFFERINFO,
|
||||
PACTYP_GLOBAL_CRC16,
|
||||
PACTYP_GLOBAL_CRC32,
|
||||
PACTYP_AUDIOTRUNCATION,
|
||||
PACTYP_GENDATA,
|
||||
PACTYPE_EARCON,
|
||||
PACTYPE_PCMCONFIG,
|
||||
PACTYPE_PCMDATA,
|
||||
PACTYP_LOUDNESS
|
||||
})
|
||||
private @interface MhasPacketType {}
|
||||
|
||||
|
|
@ -188,43 +186,29 @@ public final class MpeghUtil {
|
|||
private static final int PACTYPE_PCMDATA = 21;
|
||||
private static final int PACTYP_LOUDNESS = 22;
|
||||
|
||||
/**
|
||||
* See ISO_IEC_23003-3;2020, 6.1.1.1, Table 72.
|
||||
*/
|
||||
/** See ISO_IEC_23003-3;2020, 6.1.1.1, Table 72. */
|
||||
private static final int[] SAMPLING_RATE_TABLE =
|
||||
new int[]{
|
||||
96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350,
|
||||
C.RATE_UNSET_INT, C.RATE_UNSET_INT, 57600, 51200, 40000, 38400, 34150, 28800, 25600,
|
||||
20000, 19200, 17075, 14400, 12800, 9600
|
||||
new int[] {
|
||||
96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, 0,
|
||||
0, 57600, 51200, 40000, 38400, 34150, 28800, 25600, 20000, 19200, 17075, 14400, 12800, 9600
|
||||
};
|
||||
|
||||
/**
|
||||
* See ISO_IEC_23003-3;2020, 6.1.1.1, Table 75.
|
||||
*/
|
||||
private static final int[] OUTPUT_FRAMELENGTH_TABLE =
|
||||
new int[]{
|
||||
768, 1024, 2048, 2048, 4096
|
||||
};
|
||||
/** See ISO_IEC_23003-3;2020, 6.1.1.1, Table 75. */
|
||||
private static final int[] OUTPUT_FRAMELENGTH_TABLE = new int[] {768, 1024, 2048, 2048, 4096};
|
||||
|
||||
/**
|
||||
* See ISO_IEC_23003-3;2020, 6.1.1.1, Table 75.
|
||||
*/
|
||||
private static final int[] SBR_RATIO_INDEX_TABLE =
|
||||
new int[]{
|
||||
0, 0, 2, 3, 1
|
||||
};
|
||||
/** See ISO_IEC_23003-3;2020, 6.1.1.1, Table 75. */
|
||||
private static final int[] SBR_RATIO_INDEX_TABLE = new int[] {0, 0, 2, 3, 1};
|
||||
|
||||
/**
|
||||
* See ISO_IEC_23003-8;2022, 14.4.4.
|
||||
*/
|
||||
/** See ISO_IEC_23003-8;2022, 14.4.4. */
|
||||
private static final int MHAS_SYNCPACKET = 0xC001A5;
|
||||
|
||||
/**
|
||||
* Finds the start position of the MHAS sync packet in the provided data buffer.
|
||||
* See ISO_IEC_23008-3;2022, 14.4.4.
|
||||
* Finds the start position of the MHAS sync packet in the provided data buffer. See
|
||||
* ISO_IEC_23008-3;2022, 14.4.4.
|
||||
*
|
||||
* @param data The byte array to parse.
|
||||
* @return Byte index in data of the MHAS sync packet on success, {@link C#INDEX_UNSET} on failure.
|
||||
* @return Byte index in data of the MHAS sync packet on success, {@link C#INDEX_UNSET} on
|
||||
* failure.
|
||||
*/
|
||||
public static int findSyncPacket(ParsableByteArray data) {
|
||||
int startPos = data.getPosition();
|
||||
|
|
@ -243,8 +227,8 @@ public final class MpeghUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks if a complete MHAS frame could be parsed by calculating if enough data is available
|
||||
* in the provided ParsableBitArray.
|
||||
* Checks if a complete MHAS frame could be parsed by calculating if enough data is available in
|
||||
* the provided ParsableBitArray.
|
||||
*
|
||||
* @param data The bit array to parse.
|
||||
* @return Whether a complete MHAS frame could be parsed.
|
||||
|
|
@ -299,12 +283,12 @@ public final class MpeghUtil {
|
|||
int availableBits = data.bitsLeft();
|
||||
|
||||
if (availableBits == 0) {
|
||||
throw ParserException.createForMalformedContainer(/* message= */
|
||||
"Not enough data available", /* cause= */ null);
|
||||
throw ParserException.createForMalformedContainer(
|
||||
/* message= */ "Not enough data available", /* cause= */ null);
|
||||
}
|
||||
if (availableBits % C.BITS_PER_BYTE != 0) {
|
||||
throw ParserException.createForMalformedContainer(/* message= */
|
||||
"Input data buffer is not Byte aligned", /* cause= */ null);
|
||||
throw ParserException.createForMalformedContainer(
|
||||
/* message= */ "Input data buffer is not Byte aligned", /* cause= */ null);
|
||||
}
|
||||
|
||||
do {
|
||||
|
|
@ -320,15 +304,16 @@ public final class MpeghUtil {
|
|||
switch (packetHeader.packetType) {
|
||||
case PACTYP_MPEGH3DACFG:
|
||||
if (packetHeader.packetLabel == 0) {
|
||||
throw ParserException.createForMalformedContainer(/* message= */
|
||||
"Mpegh3daConfig packet with wrong packet label "
|
||||
+ packetHeader.packetLabel, /* cause= */ null);
|
||||
throw ParserException.createForMalformedContainer(
|
||||
/* message= */ "Mpegh3daConfig packet with wrong packet label "
|
||||
+ packetHeader.packetLabel,
|
||||
/* cause= */ null);
|
||||
}
|
||||
|
||||
// we already found a mpegh3daConfig
|
||||
if (configFound) {
|
||||
throw ParserException.createForMalformedContainer(/* message= */
|
||||
"Found a second mpegh3daConfig packet", /* cause= */ null);
|
||||
throw ParserException.createForMalformedContainer(
|
||||
/* message= */ "Found a second mpegh3daConfig packet", /* cause= */ null);
|
||||
}
|
||||
configFound = true;
|
||||
|
||||
|
|
@ -357,15 +342,16 @@ public final class MpeghUtil {
|
|||
|
||||
case PACTYP_AUDIOTRUNCATION:
|
||||
if (packetHeader.packetLabel == 0) {
|
||||
throw ParserException.createForMalformedContainer(/* message= */
|
||||
"AudioTruncation packet with wrong packet label "
|
||||
+ packetHeader.packetLabel, /* cause= */ null);
|
||||
throw ParserException.createForMalformedContainer(
|
||||
/* message= */ "AudioTruncation packet with wrong packet label "
|
||||
+ packetHeader.packetLabel,
|
||||
/* cause= */ null);
|
||||
}
|
||||
|
||||
truncationSamples = parseAudioTruncationInfo(data);
|
||||
if (truncationSamples > standardFrameSamples) {
|
||||
throw ParserException.createForMalformedContainer(/* message= */
|
||||
"Truncation size is too big", /* cause= */ null);
|
||||
throw ParserException.createForMalformedContainer(
|
||||
/* message= */ "Truncation size is too big", /* cause= */ null);
|
||||
}
|
||||
|
||||
data.setPosition(dataPos);
|
||||
|
|
@ -374,9 +360,10 @@ public final class MpeghUtil {
|
|||
|
||||
case PACTYP_MPEGH3DAFRAME:
|
||||
if (packetHeader.packetLabel == 0) {
|
||||
throw ParserException.createForMalformedContainer(/* message= */
|
||||
"Mpegh3daFrame packet with wrong packet label "
|
||||
+ packetHeader.packetLabel, /* cause= */ null);
|
||||
throw ParserException.createForMalformedContainer(
|
||||
/* message= */ "Mpegh3daFrame packet with wrong packet label "
|
||||
+ packetHeader.packetLabel,
|
||||
/* cause= */ null);
|
||||
}
|
||||
|
||||
if (!configFound) {
|
||||
|
|
@ -385,8 +372,9 @@ public final class MpeghUtil {
|
|||
|
||||
// check packet label
|
||||
if (packetHeader.packetLabel != mainStreamLabel) {
|
||||
throw ParserException.createForMalformedContainer(/* message= */
|
||||
"Mpegh3daFrame packet does not belong to main stream", /* cause= */ null);
|
||||
throw ParserException.createForMalformedContainer(
|
||||
/* message= */ "Mpegh3daFrame packet does not belong to main stream",
|
||||
/* cause= */ null);
|
||||
}
|
||||
frameFound = true;
|
||||
data.skipBits(packetHeader.packetLength * C.BITS_PER_BYTE);
|
||||
|
|
@ -398,8 +386,8 @@ public final class MpeghUtil {
|
|||
}
|
||||
|
||||
if (data.bitsLeft() % C.BITS_PER_BYTE != 0) {
|
||||
throw ParserException.createForMalformedContainer(/* message= */
|
||||
"Data buffer is not Byte aligned after parsing", /* cause= */ null);
|
||||
throw ParserException.createForMalformedContainer(
|
||||
/* message= */ "Data buffer is not Byte aligned after parsing", /* cause= */ null);
|
||||
}
|
||||
|
||||
} while (!frameFound);
|
||||
|
|
@ -407,24 +395,29 @@ public final class MpeghUtil {
|
|||
int parsedBytes = (availableBits - data.bitsLeft()) / C.BITS_PER_BYTE;
|
||||
|
||||
if (samplingFrequency <= 0) {
|
||||
throw ParserException.createForUnsupportedContainerFeature(/* message= */
|
||||
"Unsupported sampling frequency " + samplingFrequency);
|
||||
throw ParserException.createForUnsupportedContainerFeature(
|
||||
/* message= */ "Unsupported sampling frequency " + samplingFrequency);
|
||||
}
|
||||
|
||||
if (standardFrameSamples <= 0) {
|
||||
throw ParserException.createForUnsupportedContainerFeature(/* message= */
|
||||
"Unsupported value of standardFrameSamples " + standardFrameSamples);
|
||||
throw ParserException.createForUnsupportedContainerFeature(
|
||||
/* message= */ "Unsupported value of standardFrameSamples " + standardFrameSamples);
|
||||
}
|
||||
|
||||
return new FrameInfo(configFound, configChanged, standardFrameSamples, /* samplingRate= */
|
||||
samplingFrequency, /* frameSamples= */ standardFrameSamples - truncationSamples,
|
||||
/* frameBytes= */ parsedBytes, mainStreamLabel, mpegh3daProfileLevelIndication,
|
||||
return new FrameInfo(
|
||||
configFound,
|
||||
configChanged,
|
||||
standardFrameSamples,
|
||||
/* samplingRate= */ samplingFrequency,
|
||||
/* frameSamples= */ standardFrameSamples - truncationSamples,
|
||||
/* frameBytes= */ parsedBytes,
|
||||
mainStreamLabel,
|
||||
mpegh3daProfileLevelIndication,
|
||||
compatibleSetIndication);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an MHAS packet header.
|
||||
* See ISO_IEC_23008-3;2022, 14.2.1, Table 222.
|
||||
* Parses an MHAS packet header. See ISO_IEC_23008-3;2022, 14.2.1, Table 222.
|
||||
*
|
||||
* @param data The bit array to parse.
|
||||
* @return The {@link MhasPacketHeader} info.
|
||||
|
|
@ -450,8 +443,8 @@ public final class MpeghUtil {
|
|||
if (idx == 0x1F) {
|
||||
sampleRate = data.readBits(24);
|
||||
} else if (idx == 13 || idx == 14 || idx >= SAMPLING_RATE_TABLE.length) {
|
||||
throw ParserException.createForUnsupportedContainerFeature(/* message= */
|
||||
"Unsupported sampling rate index " + idx);
|
||||
throw ParserException.createForUnsupportedContainerFeature(
|
||||
/* message= */ "Unsupported sampling rate index " + idx);
|
||||
} else {
|
||||
sampleRate = SAMPLING_RATE_TABLE[idx];
|
||||
}
|
||||
|
|
@ -459,8 +452,8 @@ public final class MpeghUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* Obtains the resampling ratio according to the provided sampling frequency.
|
||||
* See ISO_IEC_23008-3;2022, 4.8.2, Table 10.
|
||||
* Obtains the resampling ratio according to the provided sampling frequency. See
|
||||
* ISO_IEC_23008-3;2022, 4.8.2, Table 10.
|
||||
*
|
||||
* @param usacSamplingFrequency The USAC sampling frequency.
|
||||
* @return The resampling ratio.
|
||||
|
|
@ -490,17 +483,16 @@ public final class MpeghUtil {
|
|||
resamplingRatio = 3;
|
||||
break;
|
||||
default:
|
||||
throw ParserException.createForUnsupportedContainerFeature(/* message= */
|
||||
"Unsupported sampling rate " + usacSamplingFrequency);
|
||||
throw ParserException.createForUnsupportedContainerFeature(
|
||||
/* message= */ "Unsupported sampling rate " + usacSamplingFrequency);
|
||||
}
|
||||
return resamplingRatio;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains an escaped value from an MPEG-H bit stream.
|
||||
* See ISO_IEC_23003-3;2020, 5.2, Table 19.
|
||||
* Obtains an escaped value from an MPEG-H bit stream. See ISO_IEC_23003-3;2020, 5.2, Table 19.
|
||||
*
|
||||
* @param data The bit array to be parsed.
|
||||
* @param data The bit array to be parsed.
|
||||
* @param bits1 number of bits to be parsed.
|
||||
* @param bits2 number of bits to be parsed.
|
||||
* @param bits3 number of bits to be parsed.
|
||||
|
|
@ -522,8 +514,8 @@ public final class MpeghUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* Obtains the necessary info of the Mpegh3daConfig from an MPEG-H bit stream.
|
||||
* See ISO_IEC_23008-3;2022, 5.2.2.1, Table 15.
|
||||
* Obtains the necessary info of the Mpegh3daConfig from an MPEG-H bit stream. See
|
||||
* ISO_IEC_23008-3;2022, 5.2.2.1, Table 15.
|
||||
*
|
||||
* @param data The bit array to be parsed.
|
||||
* @return The {@link Mpegh3daConfig}.
|
||||
|
|
@ -538,10 +530,10 @@ public final class MpeghUtil {
|
|||
int coreSbrFrameLengthIndex = data.readBits(3);
|
||||
data.skipBits(2); // cfg_reserved(1), receiverDelayCompensation(1)
|
||||
|
||||
if (coreSbrFrameLengthIndex >= OUTPUT_FRAMELENGTH_TABLE.length ||
|
||||
coreSbrFrameLengthIndex >= SBR_RATIO_INDEX_TABLE.length) {
|
||||
throw ParserException.createForUnsupportedContainerFeature(/* message= */
|
||||
"Unsupported coreSbrFrameLengthIndex " + coreSbrFrameLengthIndex);
|
||||
if (coreSbrFrameLengthIndex >= OUTPUT_FRAMELENGTH_TABLE.length
|
||||
|| coreSbrFrameLengthIndex >= SBR_RATIO_INDEX_TABLE.length) {
|
||||
throw ParserException.createForUnsupportedContainerFeature(
|
||||
/* message= */ "Unsupported coreSbrFrameLengthIndex " + coreSbrFrameLengthIndex);
|
||||
}
|
||||
|
||||
int outputFrameLength = OUTPUT_FRAMELENGTH_TABLE[coreSbrFrameLengthIndex];
|
||||
|
|
@ -553,7 +545,7 @@ public final class MpeghUtil {
|
|||
|
||||
if (data.readBit()) { // usacConfigExtensionPresent
|
||||
// Mpegh3daConfigExtension
|
||||
int numConfigExtensions = (int) readEscapedValue(data, 2, 4, 8) + 1;
|
||||
int numConfigExtensions = (int) (readEscapedValue(data, 2, 4, 8) + 1);
|
||||
for (int confExtIdx = 0; confExtIdx < numConfigExtensions; confExtIdx++) {
|
||||
int usacConfigExtType = (int) readEscapedValue(data, 4, 8, 16);
|
||||
int usacConfigExtLength = (int) readEscapedValue(data, 4, 8, 16);
|
||||
|
|
@ -580,7 +572,6 @@ public final class MpeghUtil {
|
|||
return mpegh3daConfig;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtains the number of truncated samples of the AudioTruncationInfo from an MPEG-H bit stream.
|
||||
* See ISO_IEC_23008-3;2022, 14.2.2, Table 225.
|
||||
|
|
@ -599,10 +590,9 @@ public final class MpeghUtil {
|
|||
return truncationSamples;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses the SpeakerConfig3d from an MPEG-H bit stream.
|
||||
* See ISO_IEC_23008-3;2022, 5.2.2.2, Table 18.
|
||||
* Parses the SpeakerConfig3d from an MPEG-H bit stream. See ISO_IEC_23008-3;2022, 5.2.2.2, Table
|
||||
* 18.
|
||||
*
|
||||
* @param data The bit array to be parsed.
|
||||
*/
|
||||
|
|
@ -611,7 +601,7 @@ public final class MpeghUtil {
|
|||
if (speakerLayoutType == 0) {
|
||||
data.skipBits(6); // cicpSpeakerLayoutIdx
|
||||
} else {
|
||||
int numSpeakers = (int) readEscapedValue(data, 5, 8, 16) + 1;
|
||||
int numSpeakers = (int) (readEscapedValue(data, 5, 8, 16) + 1);
|
||||
if (speakerLayoutType == 1) {
|
||||
data.skipBits(7 * numSpeakers); // cicpSpeakerIdx per speaker
|
||||
} else if (speakerLayoutType == 2) {
|
||||
|
|
@ -653,8 +643,8 @@ public final class MpeghUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* Obtains the necessary info of Signals3d from an MPEG-H bit stream.
|
||||
* See ISO_IEC_23008-3;2022, 5.2.2.1, Table 17.
|
||||
* Obtains the necessary info of Signals3d from an MPEG-H bit stream. See ISO_IEC_23008-3;2022,
|
||||
* 5.2.2.1, Table 17.
|
||||
*
|
||||
* @param data The bit array to be parsed.
|
||||
* @return The number of overall signals in the bit stream.
|
||||
|
|
@ -668,8 +658,8 @@ public final class MpeghUtil {
|
|||
int bsNumberOfSignals = (int) readEscapedValue(data, 5, 8, 16);
|
||||
|
||||
numSignals += bsNumberOfSignals + 1;
|
||||
if (signalGroupType == 0 /*SignalGroupTypeChannels*/ ||
|
||||
signalGroupType == 2 /*SignalGroupTypeSAOC*/) {
|
||||
if (signalGroupType == 0 /*SignalGroupTypeChannels*/
|
||||
|| signalGroupType == 2 /*SignalGroupTypeSAOC*/) {
|
||||
if (data.readBit()) { // differsFromReferenceLayout OR saocDmxLayoutPresent
|
||||
parseSpeakerConfig3d(data); // audioChannelLayout[grp] OR saocDmxChannelLayout
|
||||
}
|
||||
|
|
@ -679,17 +669,17 @@ public final class MpeghUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* Parses the Mpegh3daDecoderConfig from an MPEG-H bit stream.
|
||||
* See ISO_IEC_23008-3;2022, 5.2.2.3, Table 21.
|
||||
* Parses the Mpegh3daDecoderConfig from an MPEG-H bit stream. See ISO_IEC_23008-3;2022, 5.2.2.3,
|
||||
* Table 21.
|
||||
*
|
||||
* @param data The bit array to be parsed.
|
||||
* @param numSignals The number of overall signals.
|
||||
* @param sbrRatioIndex The SBR ration index.
|
||||
*/
|
||||
private static void parseMpegh3daDecoderConfig(ParsableBitArray data,
|
||||
int numSignals, int sbrRatioIndex) {
|
||||
private static void parseMpegh3daDecoderConfig(
|
||||
ParsableBitArray data, int numSignals, int sbrRatioIndex) {
|
||||
|
||||
int numElements = (int) readEscapedValue(data, 4, 8, 16) + 1;
|
||||
int numElements = (int) (readEscapedValue(data, 4, 8, 16) + 1);
|
||||
data.skipBit(); // elementLengthPresent
|
||||
|
||||
for (int elemIdx = 0; elemIdx < numElements; elemIdx++) {
|
||||
|
|
@ -716,7 +706,7 @@ public final class MpeghUtil {
|
|||
// mps212Config
|
||||
data.skipBits(6); // bsFreqRes(3), bsFixedGainDMX(3),
|
||||
int bsTempShapeConfig = data.readBits(2);
|
||||
data.skipBits(4);// bsDecorrConfig(2), bsHighRateMode(1), bsPhaseCoding(1)
|
||||
data.skipBits(4); // bsDecorrConfig(2), bsHighRateMode(1), bsPhaseCoding(1)
|
||||
if (data.readBit()) { // bsOttBandsPhasePresent
|
||||
data.skipBits(5); // bsOttBandsPhase
|
||||
}
|
||||
|
|
@ -747,7 +737,7 @@ public final class MpeghUtil {
|
|||
int usacExtElementConfigLength = (int) readEscapedValue(data, 4, 8, 16);
|
||||
|
||||
if (data.readBit()) { // usacExtElementDefaultLengthPresent
|
||||
readEscapedValue(data, 8, 16, 0)/*+1*/; // usacExtElementDefaultLength
|
||||
readEscapedValue(data, 8, 16, 0) /*+1*/; // usacExtElementDefaultLength
|
||||
}
|
||||
data.skipBit(); // usacExtElementPayloadFrag
|
||||
|
||||
|
|
@ -762,8 +752,8 @@ public final class MpeghUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* Obtains the necessary info of the Mpegh3daCoreConfig from an MPEG-H bit stream.
|
||||
* See ISO_IEC_23008-3;2022, 5.2.2.3, Table 24.
|
||||
* Obtains the necessary info of the Mpegh3daCoreConfig from an MPEG-H bit stream. See
|
||||
* ISO_IEC_23008-3;2022, 5.2.2.3, Table 24.
|
||||
*
|
||||
* @param data The bit array to be parsed.
|
||||
* @return The enhanced noise filling flag.
|
||||
|
|
@ -772,32 +762,32 @@ public final class MpeghUtil {
|
|||
data.skipBits(3); // tw_mdct(1), fullbandLpd(1), noiseFilling(1)
|
||||
boolean enhancedNoiseFilling = data.readBit();
|
||||
if (enhancedNoiseFilling) {
|
||||
data.skipBits(13); // igfUseEnf(1), igfUseHighRes(1), igfUseWhitening(1), igfAfterTnsSynth(1), igfStartIndex(5), igfStopIndex(4)
|
||||
data.skipBits(13); // igfUseEnf(1), igfUseHighRes(1), igfUseWhitening(1), igfAfterTnsSynth(1),
|
||||
// igfStartIndex(5), igfStopIndex(4)
|
||||
}
|
||||
return enhancedNoiseFilling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the SbrConfig from an MPEG-H bit stream.
|
||||
* See ISO_IEC_23003-3;2020, 5.2, Table 14.
|
||||
* Parses the SbrConfig from an MPEG-H bit stream. See ISO_IEC_23003-3;2020, 5.2, Table 14.
|
||||
*
|
||||
* @param data The bit array to be parsed.
|
||||
*/
|
||||
private static void parseSbrConfig(ParsableBitArray data) {
|
||||
data.skipBits(3); // harmonicSBR(1), bs_interTes(1), bs_pvc(1)
|
||||
data.skipBits(8); // dflt_start_freq(4), dflt_stop_freq(4)
|
||||
boolean dflt_header_extra1 = data.readBit();
|
||||
boolean dflt_header_extra2 = data.readBit();
|
||||
if (dflt_header_extra1) {
|
||||
boolean dfltHeaderExtra1 = data.readBit();
|
||||
boolean dfltHeaderExtra2 = data.readBit();
|
||||
if (dfltHeaderExtra1) {
|
||||
data.skipBits(5); // dflt_freq_scale(2), dflt_alter_scale(1), dflt_noise_bands(2)
|
||||
}
|
||||
if (dflt_header_extra2) {
|
||||
data.skipBits(6); // dflt_limiter_bands(2), dflt_limiter_gains(2), dflt_interpol_freq(1), dflt_smoothing_mode(1)
|
||||
if (dfltHeaderExtra2) {
|
||||
data.skipBits(6); // dflt_limiter_bands(2), dflt_limiter_gains(2), dflt_interpol_freq(1),
|
||||
// dflt_smoothing_mode(1)
|
||||
}
|
||||
}
|
||||
|
||||
private MpeghUtil() {
|
||||
}
|
||||
private MpeghUtil() {}
|
||||
|
||||
private static class MhasPacketHeader {
|
||||
@MhasPacketType int packetType;
|
||||
|
|
|
|||
|
|
@ -1,32 +1,25 @@
|
|||
/***************************************************************************
|
||||
|
||||
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.
|
||||
|
||||
***************************************************************************/
|
||||
/*
|
||||
* Copyright 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package androidx.media3.extractor.ts;
|
||||
|
||||
import static androidx.media3.extractor.ts.TsPayloadReader.FLAG_DATA_ALIGNMENT_INDICATOR;
|
||||
import static androidx.media3.extractor.ts.TsPayloadReader.FLAG_RANDOM_ACCESS_INDICATOR;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.Format;
|
||||
import androidx.media3.common.MimeTypes;
|
||||
|
|
@ -41,10 +34,7 @@ import com.google.common.collect.ImmutableList;
|
|||
import java.util.List;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
|
||||
/**
|
||||
* Parses a continuous MPEG-H audio byte stream and extracts MPEG-H frames.
|
||||
*/
|
||||
/** Parses a continuous MPEG-H audio byte stream and extracts MPEG-H frames. */
|
||||
@UnstableApi
|
||||
public final class MpeghReader implements ElementaryStreamReader {
|
||||
|
||||
|
|
@ -82,8 +72,8 @@ public final class MpeghReader implements ElementaryStreamReader {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void createTracks(ExtractorOutput extractorOutput,
|
||||
TsPayloadReader.TrackIdGenerator idGenerator) {
|
||||
public void createTracks(
|
||||
ExtractorOutput extractorOutput, TsPayloadReader.TrackIdGenerator idGenerator) {
|
||||
idGenerator.generateNewId();
|
||||
formatId = idGenerator.getFormatId();
|
||||
output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_AUDIO);
|
||||
|
|
@ -152,17 +142,19 @@ public final class MpeghReader implements ElementaryStreamReader {
|
|||
codecs += String.format(".%02X", frameInfo.mpegh3daProfileLevelIndication);
|
||||
}
|
||||
@Nullable List<byte[]> initializationData = null;
|
||||
if (frameInfo.compatibleSetIndication != null && frameInfo.compatibleSetIndication.length > 0) {
|
||||
if (frameInfo.compatibleSetIndication != null
|
||||
&& frameInfo.compatibleSetIndication.length > 0) {
|
||||
// The first entry in initializationData is reserved for the audio specific config.
|
||||
initializationData = ImmutableList.of(new byte[0], frameInfo.compatibleSetIndication);
|
||||
}
|
||||
Format format = new Format.Builder()
|
||||
.setId(formatId)
|
||||
.setSampleMimeType(MimeTypes.AUDIO_MPEGH_MHM1)
|
||||
.setSampleRate(frameInfo.samplingRate)
|
||||
.setCodecs(codecs)
|
||||
.setInitializationData(initializationData)
|
||||
.build();
|
||||
Format format =
|
||||
new Format.Builder()
|
||||
.setId(formatId)
|
||||
.setSampleMimeType(MimeTypes.AUDIO_MPEGH_MHM1)
|
||||
.setSampleRate(frameInfo.samplingRate)
|
||||
.setCodecs(codecs)
|
||||
.setInitializationData(initializationData)
|
||||
.build();
|
||||
output.format(format);
|
||||
}
|
||||
|
||||
|
|
@ -176,7 +168,8 @@ public final class MpeghReader implements ElementaryStreamReader {
|
|||
flag = C.BUFFER_FLAG_KEY_FRAME;
|
||||
rapPending = false;
|
||||
}
|
||||
double sampleDurationUs = (double)C.MICROS_PER_SECOND * frameInfo.frameSamples / frameInfo.samplingRate;
|
||||
double sampleDurationUs =
|
||||
(double) C.MICROS_PER_SECOND * frameInfo.frameSamples / frameInfo.samplingRate;
|
||||
long pts = Math.round(timeUs);
|
||||
if (dataPending) {
|
||||
dataPending = false;
|
||||
|
|
@ -191,7 +184,6 @@ public final class MpeghReader implements ElementaryStreamReader {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private void maybeFindSync() {
|
||||
// we are still waiting for a RAP frame
|
||||
if (rapPending) {
|
||||
|
|
@ -215,7 +207,6 @@ public final class MpeghReader implements ElementaryStreamReader {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private void clearDataBuffer() {
|
||||
dataPending = false;
|
||||
rapPending = true;
|
||||
|
|
@ -226,8 +217,8 @@ public final class MpeghReader implements ElementaryStreamReader {
|
|||
private void appendToDataBuffer(ParsableByteArray data) {
|
||||
int bytesToRead = data.bytesLeft();
|
||||
dataBuffer.ensureCapacity(dataInBuffer + bytesToRead);
|
||||
System.arraycopy(data.getData(), data.getPosition(), dataBuffer.getData(),
|
||||
dataInBuffer, bytesToRead);
|
||||
System.arraycopy(
|
||||
data.getData(), data.getPosition(), dataBuffer.getData(), dataInBuffer, bytesToRead);
|
||||
data.skipBytes(bytesToRead);
|
||||
dataInBuffer += bytesToRead;
|
||||
dataBuffer.reset(dataInBuffer);
|
||||
|
|
@ -235,8 +226,8 @@ public final class MpeghReader implements ElementaryStreamReader {
|
|||
|
||||
private void removeUsedFromDataBuffer() {
|
||||
dataInBuffer -= dataBuffer.getPosition();
|
||||
System.arraycopy(dataBuffer.getData(), dataBuffer.getPosition(), dataBuffer.getData(),
|
||||
0, dataInBuffer);
|
||||
System.arraycopy(
|
||||
dataBuffer.getData(), dataBuffer.getPosition(), dataBuffer.getData(), 0, dataInBuffer);
|
||||
dataBuffer.reset(dataInBuffer);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -247,64 +247,74 @@ public final class TsExtractorTest {
|
|||
|
||||
@Test
|
||||
public void sampleWithMpeghBlCicp1Single() throws Exception {
|
||||
ExtractorAsserts.assertBehavior(TsExtractor::new, "media/ts/sample_mpegh_bl_cicp1_single.ts", simulationConfig);
|
||||
ExtractorAsserts.assertBehavior(
|
||||
TsExtractor::new, "media/ts/sample_mpegh_bl_cicp1_single.ts", simulationConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sampleWithMpeghLcBlCicp1Single() throws Exception {
|
||||
ExtractorAsserts.assertBehavior(TsExtractor::new, "media/ts/sample_mpegh_lcbl_cicp1_single.ts", simulationConfig);
|
||||
ExtractorAsserts.assertBehavior(
|
||||
TsExtractor::new, "media/ts/sample_mpegh_lcbl_cicp1_single.ts", simulationConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sampleWithMpeghBlConfigChangeSingle() throws Exception {
|
||||
ExtractorAsserts.assertBehavior(TsExtractor::new, "media/ts/sample_mpegh_bl_configchange_single.ts", simulationConfig);
|
||||
ExtractorAsserts.assertBehavior(
|
||||
TsExtractor::new, "media/ts/sample_mpegh_bl_configchange_single.ts", simulationConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sampleWithMpeghLcBlConfigChangeSingle() throws Exception {
|
||||
ExtractorAsserts.assertBehavior(TsExtractor::new, "media/ts/sample_mpegh_lcbl_configchange_single.ts", simulationConfig);
|
||||
ExtractorAsserts.assertBehavior(
|
||||
TsExtractor::new, "media/ts/sample_mpegh_lcbl_configchange_single.ts", simulationConfig);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void sampleWithMpeghBlCicp1Multi() throws Exception {
|
||||
ExtractorAsserts.assertBehavior(TsExtractor::new, "media/ts/sample_mpegh_bl_cicp1_multi.ts", simulationConfig);
|
||||
ExtractorAsserts.assertBehavior(
|
||||
TsExtractor::new, "media/ts/sample_mpegh_bl_cicp1_multi.ts", simulationConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sampleWithMpeghLcBlCicp1Multi() throws Exception {
|
||||
ExtractorAsserts.assertBehavior(TsExtractor::new, "media/ts/sample_mpegh_lcbl_cicp1_multi.ts", simulationConfig);
|
||||
ExtractorAsserts.assertBehavior(
|
||||
TsExtractor::new, "media/ts/sample_mpegh_lcbl_cicp1_multi.ts", simulationConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sampleWithMpeghBlConfigChangeMulti() throws Exception {
|
||||
ExtractorAsserts.assertBehavior(TsExtractor::new, "media/ts/sample_mpegh_bl_configchange_multi.ts", simulationConfig);
|
||||
ExtractorAsserts.assertBehavior(
|
||||
TsExtractor::new, "media/ts/sample_mpegh_bl_configchange_multi.ts", simulationConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sampleWithMpeghLcBlConfigChangeMulti() throws Exception {
|
||||
ExtractorAsserts.assertBehavior(TsExtractor::new, "media/ts/sample_mpegh_lcbl_configchange_multi.ts", simulationConfig);
|
||||
ExtractorAsserts.assertBehavior(
|
||||
TsExtractor::new, "media/ts/sample_mpegh_lcbl_configchange_multi.ts", simulationConfig);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void sampleWithMpeghBlCicp1Cont() throws Exception {
|
||||
ExtractorAsserts.assertBehavior(TsExtractor::new, "media/ts/sample_mpegh_bl_cicp1_cont.ts", simulationConfig);
|
||||
ExtractorAsserts.assertBehavior(
|
||||
TsExtractor::new, "media/ts/sample_mpegh_bl_cicp1_cont.ts", simulationConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sampleWithMpeghLcBlCicp1Cont() throws Exception {
|
||||
ExtractorAsserts.assertBehavior(TsExtractor::new, "media/ts/sample_mpegh_lcbl_cicp1_cont.ts", simulationConfig);
|
||||
ExtractorAsserts.assertBehavior(
|
||||
TsExtractor::new, "media/ts/sample_mpegh_lcbl_cicp1_cont.ts", simulationConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sampleWithMpeghBlConfigChangeCont() throws Exception {
|
||||
ExtractorAsserts.assertBehavior(TsExtractor::new, "media/ts/sample_mpegh_bl_configchange_cont.ts", simulationConfig);
|
||||
ExtractorAsserts.assertBehavior(
|
||||
TsExtractor::new, "media/ts/sample_mpegh_bl_configchange_cont.ts", simulationConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sampleWithMpeghLcBlConfigChangeCont() throws Exception {
|
||||
ExtractorAsserts.assertBehavior(TsExtractor::new, "media/ts/sample_mpegh_lcbl_configchange_cont.ts", simulationConfig);
|
||||
ExtractorAsserts.assertBehavior(
|
||||
TsExtractor::new, "media/ts/sample_mpegh_lcbl_configchange_cont.ts", simulationConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
Loading…
Reference in a new issue