Changes based on internal review

This commit is contained in:
Rohit Singh 2024-04-16 14:51:47 +01:00
parent 6811b8394b
commit cbe17bcd0a
3 changed files with 98 additions and 43 deletions

View file

@ -245,10 +245,10 @@ public final class MpeghUtil {
// accordingly.
double resamplingRatio = getResamplingRatio(usacSamplingFrequency);
int samplingFrequency = (int) (usacSamplingFrequency * resamplingRatio);
int standardFrameSamples = (int) (outputFrameLength * resamplingRatio);
int standardFrameLength = (int) (outputFrameLength * resamplingRatio);
return new Mpegh3daConfig(
profileLevelIndication, samplingFrequency, standardFrameSamples, compatibleProfileLevelSet);
profileLevelIndication, samplingFrequency, standardFrameLength, compatibleProfileLevelSet);
}
/**
@ -558,6 +558,10 @@ public final class MpeghUtil {
private MpeghUtil() {}
/**
* Represents the header of an MHAS (MPEG-H 3D Audio System) packet. This header provides
* essential information to identify and parse the packet's contents.
*/
public static class MhasPacketHeader {
/** MHAS packet types. See ISO_IEC_23008-3;2022, 14.4. */
@ -611,11 +615,19 @@ public final class MpeghUtil {
public static final int PACTYPE_PCMDATA = 21;
public static final int PACTYP_LOUDNESS = 22;
/** The payload type in the actual packet. */
public final @Type int packetType;
/** A label indicating which packets belong together. */
public final long packetLabel;
/** The length of MHAS packet in bytes. */
public final int packetLength;
/** The length of MHAS packet header in bytes. */
public final int headerLength;
/** Creates an instance. */
public MhasPacketHeader(
@Type int packetType, long packetLabel, int packetLength, int headerLength) {
this.packetType = packetType;
@ -625,21 +637,32 @@ public final class MpeghUtil {
}
}
/** Represents an MPEG-H 3D audio configuration. */
public static class Mpegh3daConfig {
/** The MPEG-H 3D audio profile and level indication. */
public final int profileLevelIndication;
/** The sampling frequency of the MPEG-H 3D Audio stream. */
public final int samplingFrequency;
public final int standardFrameSamples;
/** The standard frame length in samples. */
public final int standardFrameLength;
/**
* A list of MPEG-H 3D audio profile-level set that are compatible with the current
* configuration.
*/
@Nullable public final byte[] compatibleProfileLevelSet;
private Mpegh3daConfig(
int profileLevelIndication,
int samplingFrequency,
int standardFrameSamples,
int standardFrameLength,
@Nullable byte[] compatibleProfileLevelSet) {
this.profileLevelIndication = profileLevelIndication;
this.samplingFrequency = samplingFrequency;
this.standardFrameSamples = standardFrameSamples;
this.standardFrameLength = standardFrameLength;
this.compatibleProfileLevelSet = compatibleProfileLevelSet;
}
}

View file

@ -209,26 +209,10 @@ public final class MpeghReader implements ElementaryStreamReader {
ParsableByteArray source, ParsableByteArray target, int targetLength) {
int bytesToRead = min(source.bytesLeft(), targetLength - target.getPosition());
source.readBytes(target.getData(), target.getPosition(), bytesToRead);
target.setPosition(target.getPosition() + bytesToRead);
target.skipBytes(bytesToRead);
return target.getPosition() == targetLength;
}
/**
* Copies data from the provided {@code source} into a given {@code target} without progressing
* the position of the {@code source}.
*
* @param source The source from which to read.
* @param target The target into which data is to be read.
* @param targetLength The target length of the read.
*/
private void copyData(ParsableByteArray source, ParsableByteArray target, int targetLength) {
int sourcePosition = source.getPosition();
int bytesToRead = min(source.bytesLeft(), targetLength - target.getPosition());
source.readBytes(target.getData(), target.getPosition(), bytesToRead);
target.setPosition(target.getPosition() + bytesToRead);
source.setPosition(sourcePosition);
}
/**
* Locates the next SYNC value in the buffer, advancing the position to the byte that immediately
* follows it. If SYNC was not located, the position is advanced to the limit.
@ -249,7 +233,6 @@ public final class MpeghReader implements ElementaryStreamReader {
syncBytes <<= C.BITS_PER_BYTE;
syncBytes |= pesBuffer.readUnsignedByte();
if (MpeghUtil.isSyncWord(syncBytes)) {
pesBuffer.setPosition(pesBuffer.getPosition() - MpeghUtil.MHAS_SYNC_WORD_LENGTH);
syncBytes = 0;
return true;
}
@ -275,12 +258,9 @@ public final class MpeghReader implements ElementaryStreamReader {
payloadBytesRead = 0;
frameBytes += header.packetLength + header.headerLength;
if (header.packetType == MpeghUtil.MhasPacketHeader.PACTYP_AUDIOTRUNCATION
|| header.packetType == MpeghUtil.MhasPacketHeader.PACTYP_MPEGH3DACFG) {
if (shouldParsePacket(header.packetType)) {
// prepare data scratch buffer
dataScratchBytes.ensureCapacity(header.packetLength);
dataScratchBytes.setPosition(0);
dataScratchBytes.setLimit(header.packetLength);
dataScratchBytes.reset(header.packetLength);
}
headerDataFinished = true;
}
@ -308,8 +288,7 @@ public final class MpeghReader implements ElementaryStreamReader {
* not be changed.
*/
private void maybeCopyToDataScratchBuffer(ParsableByteArray data) {
if (header.packetType == MpeghUtil.MhasPacketHeader.PACTYP_MPEGH3DACFG
|| header.packetType == MpeghUtil.MhasPacketHeader.PACTYP_AUDIOTRUNCATION) {
if (shouldParsePacket(header.packetType)) {
// read bytes from header scratch buffer into the data scratch buffer
if (headerScratchBytes.getPosition() != MpeghUtil.MAX_MHAS_PACKET_HEADER_SIZE) {
copyData(headerScratchBytes, dataScratchBytes, header.packetLength);
@ -319,6 +298,35 @@ public final class MpeghReader implements ElementaryStreamReader {
}
}
/**
* Copies data from the provided {@code source} into a given {@code target} without progressing
* the position of the {@code source}.
*
* @param source The source from which to read.
* @param target The target into which data is to be read.
* @param targetLength The target length of the read.
*/
private void copyData(ParsableByteArray source, ParsableByteArray target, int targetLength) {
int sourcePosition = source.getPosition();
int bytesToRead = min(source.bytesLeft(), targetLength - target.getPosition());
source.readBytes(target.getData(), target.getPosition(), bytesToRead);
target.skipBytes(bytesToRead);
source.setPosition(sourcePosition);
}
/**
* Determines whether a packet should be parsed based on its type.
*
* @param packetType The {@link MpeghUtil.MhasPacketHeader.Type} of the MHAS packet header.
* @return {@code true} if the packet type is either {@link
* MpeghUtil.MhasPacketHeader#PACTYP_MPEGH3DACFG} or {@link
* MpeghUtil.MhasPacketHeader#PACTYP_AUDIOTRUNCATION}, {@code false} otherwise.
*/
private boolean shouldParsePacket(@MpeghUtil.MhasPacketHeader.Type int packetType) {
return packetType == MpeghUtil.MhasPacketHeader.PACTYP_MPEGH3DACFG
|| packetType == MpeghUtil.MhasPacketHeader.PACTYP_AUDIOTRUNCATION;
}
/**
* Writes sample data to the output.
*
@ -348,7 +356,7 @@ public final class MpeghReader implements ElementaryStreamReader {
private void parseConfig(ParsableBitArray bitArray) throws ParserException {
MpeghUtil.Mpegh3daConfig config = MpeghUtil.parseMpegh3daConfig(bitArray);
samplingRate = config.samplingFrequency;
standardFrameLength = config.standardFrameSamples;
standardFrameLength = config.standardFrameLength;
if (mainStreamLabel != header.packetLabel) {
mainStreamLabel = header.packetLabel;
// set the output format

View file

@ -248,73 +248,97 @@ public final class TsExtractorTest {
@Test
public void sampleWithMpeghBlCicp1Single() throws Exception {
ExtractorAsserts.assertBehavior(
TsExtractor::new, "media/ts/sample_mpegh_bl_cicp1_single.ts", simulationConfig);
getExtractorFactory(subtitlesParsedDuringExtraction),
"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);
getExtractorFactory(subtitlesParsedDuringExtraction),
"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);
getExtractorFactory(subtitlesParsedDuringExtraction),
"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);
getExtractorFactory(subtitlesParsedDuringExtraction),
"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);
getExtractorFactory(subtitlesParsedDuringExtraction),
"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);
getExtractorFactory(subtitlesParsedDuringExtraction),
"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);
getExtractorFactory(subtitlesParsedDuringExtraction),
"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);
getExtractorFactory(subtitlesParsedDuringExtraction),
"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);
getExtractorFactory(subtitlesParsedDuringExtraction),
"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);
getExtractorFactory(subtitlesParsedDuringExtraction),
"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);
getExtractorFactory(subtitlesParsedDuringExtraction),
"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);
getExtractorFactory(subtitlesParsedDuringExtraction),
"media/ts/sample_mpegh_lcbl_configchange_cont.ts",
simulationConfig);
}
@Test