mirror of
https://github.com/samsonjs/media.git
synced 2026-03-25 09:25:53 +00:00
Changes based on internal review
This commit is contained in:
parent
6811b8394b
commit
cbe17bcd0a
3 changed files with 98 additions and 43 deletions
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue