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