Changes based on internal review

This commit is contained in:
Rohit Singh 2023-12-12 18:06:27 +00:00
parent 44b2071ee0
commit 5df45f7e64
3 changed files with 438 additions and 369 deletions

View file

@ -17,6 +17,7 @@ package androidx.media3.common.util;
import static java.lang.Math.min; import static java.lang.Math.min;
import androidx.media3.common.C;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import com.google.errorprone.annotations.CheckReturnValue; import com.google.errorprone.annotations.CheckReturnValue;
import java.nio.charset.Charset; import java.nio.charset.Charset;
@ -248,6 +249,16 @@ public final class ParsableBitArray {
assertValidOffset(); assertValidOffset();
} }
/**
* Whether the position is byte-aligned. A bit position is considered byte-aligned if the number
* of bits left in the current position is a multiple of {@link C#BITS_PER_BYTE}.
*
* @return {@code true} if the position is byte-aligned, {@code false} otherwise.
*/
public boolean isByteAligned() {
return bitsLeft() % C.BITS_PER_BYTE == 0;
}
/** /**
* Reads the next {@code length} bytes into {@code buffer}. Must only be called when the position * Reads the next {@code length} bytes into {@code buffer}. Must only be called when the position
* is byte aligned. * is byte aligned.

View file

@ -28,6 +28,7 @@ import androidx.media3.common.ParserException;
import androidx.media3.common.util.ParsableBitArray; import androidx.media3.common.util.ParsableBitArray;
import androidx.media3.common.util.ParsableByteArray; import androidx.media3.common.util.ParsableByteArray;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import androidx.media3.extractor.ExtractorOutput; import androidx.media3.extractor.ExtractorOutput;
import androidx.media3.extractor.MpeghUtil; import androidx.media3.extractor.MpeghUtil;
import androidx.media3.extractor.TrackOutput; import androidx.media3.extractor.TrackOutput;
@ -41,29 +42,26 @@ public final class MpeghReader implements ElementaryStreamReader {
private static final String TAG = "MpeghReader"; private static final String TAG = "MpeghReader";
private final ParsableByteArray dataBuffer;
private @MonotonicNonNull String formatId; private @MonotonicNonNull String formatId;
private @MonotonicNonNull TrackOutput output; private @MonotonicNonNull TrackOutput output;
private final ParsableByteArray dataBuffer;
private final ParsableBitArray dataBitBuffer;
private int dataInBuffer; private int dataInBuffer;
private MpeghUtil.FrameInfo prevFrameInfo; @Nullable private MpeghUtil.FrameInfo prevFrameInfo;
// The timestamp to attach to the next sample in the current packet. // The timestamp to attach to the next sample in the current packet.
private double timeUs; private double timeUs;
private double timeUsPending; private double timeUsPending;
private boolean dataPending; private boolean dataPending;
private boolean rapPending; private boolean rapPending;
private boolean raiSet; private @TsPayloadReader.Flags int flags;
private boolean daiSet;
public MpeghReader() { public MpeghReader() {
dataBuffer = new ParsableByteArray(0); dataBuffer = new ParsableByteArray();
dataBitBuffer = new ParsableBitArray();
rapPending = true; rapPending = true;
timeUs = C.TIME_UNSET; timeUs = C.TIME_UNSET;
timeUsPending = C.TIME_UNSET; timeUsPending = C.TIME_UNSET;
prevFrameInfo = new MpeghUtil.FrameInfo();
} }
@Override @Override
@ -82,11 +80,10 @@ public final class MpeghReader implements ElementaryStreamReader {
@Override @Override
public void packetStarted(long pesTimeUs, @TsPayloadReader.Flags int flags) { public void packetStarted(long pesTimeUs, @TsPayloadReader.Flags int flags) {
raiSet = (flags & FLAG_RANDOM_ACCESS_INDICATOR) == FLAG_RANDOM_ACCESS_INDICATOR; this.flags = flags;
daiSet = (flags & FLAG_DATA_ALIGNMENT_INDICATOR) == FLAG_DATA_ALIGNMENT_INDICATOR;
if (daiSet && dataInBuffer != 0) { if ((this.flags & FLAG_DATA_ALIGNMENT_INDICATOR) != 0 && dataInBuffer != 0) {
Log.w(TAG, "Internal bit buffer was unexpectedly not empty at data aligned PES"); Log.w(TAG, "Internal byte buffer was unexpectedly not empty at data aligned PES");
clearDataBuffer(); clearDataBuffer();
} }
@ -115,6 +112,7 @@ public final class MpeghReader implements ElementaryStreamReader {
// try to find the sync packet and adjust the data buffer if necessary // try to find the sync packet and adjust the data buffer if necessary
maybeFindSync(); maybeFindSync();
ParsableBitArray dataBitBuffer = new ParsableBitArray();
// get as many MPEG-H AUs as possible from the data buffer // get as many MPEG-H AUs as possible from the data buffer
while (true) { while (true) {
dataBitBuffer.reset(dataBuffer); dataBitBuffer.reset(dataBuffer);
@ -147,7 +145,8 @@ public final class MpeghReader implements ElementaryStreamReader {
if (frameInfo.compatibleSetIndication != null if (frameInfo.compatibleSetIndication != null
&& frameInfo.compatibleSetIndication.length > 0) { && 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(Util.EMPTY_BYTE_ARRAY, frameInfo.compatibleSetIndication);
} }
Format format = Format format =
new Format.Builder() new Format.Builder()
@ -164,7 +163,7 @@ public final class MpeghReader implements ElementaryStreamReader {
dataBuffer.setPosition(0); dataBuffer.setPosition(0);
output.sampleData(dataBuffer, frameInfo.frameBytes); output.sampleData(dataBuffer, frameInfo.frameBytes);
int flag = 0; @C.BufferFlags int flag = 0;
// if we have a frame with an mpegh3daConfig, set the first obtained AU to a key frame // if we have a frame with an mpegh3daConfig, set the first obtained AU to a key frame
if (frameInfo.containsConfig) { if (frameInfo.containsConfig) {
flag = C.BUFFER_FLAG_KEY_FRAME; flag = C.BUFFER_FLAG_KEY_FRAME;
@ -189,20 +188,18 @@ 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) {
if (!raiSet) { if ((flags & FLAG_RANDOM_ACCESS_INDICATOR) == 0) {
// RAI is not signalled -> drop the PES data // RAI is not signalled -> drop the PES data
clearDataBuffer(); clearDataBuffer();
} else { } else {
if (!daiSet) { if ((flags & FLAG_DATA_ALIGNMENT_INDICATOR) == 0) {
// if RAI is signalled but the data is not aligned we need to find the sync packet // if RAI is signalled but the data is not aligned we need to find the sync packet
int syncPosByte = MpeghUtil.findSyncPacket(dataBuffer); if (!MpeghUtil.findSyncPacket(dataBuffer)) {
if (syncPosByte < 0) {
// sync packet could not be found -> drop the PES data // sync packet could not be found -> drop the PES data
clearDataBuffer(); clearDataBuffer();
return; return;
} }
// sync packet was found -> remove PES data before the sync packet // sync packet was found -> remove PES data before the sync packet
dataBuffer.setPosition(syncPosByte);
removeUsedFromDataBuffer(); removeUsedFromDataBuffer();
} }
} }