Commit ad859904 by olly Committed by Oliver Woodman

Fix buffer subsample data before calling onQueueInputBuffer

It's very unlikely any onQueueInputBuffer implementations are looking
at the subsample encryption data, but from a correctness perspective
we should be passing a buffer object that's self-consistent.

PiperOrigin-RevId: 311011246
parent ea08bfd3
...@@ -34,7 +34,6 @@ import com.google.android.exoplayer2.C; ...@@ -34,7 +34,6 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder; import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.decoder.CryptoInfo;
import com.google.android.exoplayer2.decoder.DecoderCounters; import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
...@@ -1274,8 +1273,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -1274,8 +1273,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
// We've already read an encrypted sample into buffer, and are waiting for keys. // We've already read an encrypted sample into buffer, and are waiting for keys.
result = C.RESULT_BUFFER_READ; result = C.RESULT_BUFFER_READ;
} else { } else {
// For adaptive reconfiguration OMX decoders expect all reconfiguration data to be supplied // For adaptive reconfiguration, decoders expect all reconfiguration data to be supplied at
// at the start of the buffer that also contains the first frame in the new format. // the start of the buffer that also contains the first frame in the new format.
if (codecReconfigurationState == RECONFIGURATION_STATE_WRITE_PENDING) { if (codecReconfigurationState == RECONFIGURATION_STATE_WRITE_PENDING) {
for (int i = 0; i < codecFormat.initializationData.size(); i++) { for (int i = 0; i < codecFormat.initializationData.size(); i++) {
byte[] data = codecFormat.initializationData.get(i); byte[] data = codecFormat.initializationData.get(i);
...@@ -1325,7 +1324,12 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -1325,7 +1324,12 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
// Do nothing. // Do nothing.
} else { } else {
codecReceivedEos = true; codecReceivedEos = true;
codecAdapter.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); codecAdapter.queueInputBuffer(
inputIndex,
/* offset= */ 0,
/* size= */ 0,
/* presentationTimeUs= */ 0,
MediaCodec.BUFFER_FLAG_END_OF_STREAM);
resetInputBuffer(); resetInputBuffer();
} }
} catch (CryptoException e) { } catch (CryptoException e) {
...@@ -1333,6 +1337,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -1333,6 +1337,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
} }
return false; return false;
} }
// TODO: This code block may be unnecessary, because it's probably the case that the buffer will
// always be a keyframe if waitingForFirstSyncSample is true. Check this, and remove if so.
if (waitingForFirstSyncSample && !buffer.isKeyFrame()) { if (waitingForFirstSyncSample && !buffer.isKeyFrame()) {
buffer.clear(); buffer.clear();
if (codecReconfigurationState == RECONFIGURATION_STATE_QUEUE_PENDING) { if (codecReconfigurationState == RECONFIGURATION_STATE_QUEUE_PENDING) {
...@@ -1343,11 +1350,16 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -1343,11 +1350,16 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
return true; return true;
} }
waitingForFirstSyncSample = false; waitingForFirstSyncSample = false;
boolean bufferEncrypted = buffer.isEncrypted(); boolean bufferEncrypted = buffer.isEncrypted();
waitingForKeys = shouldWaitForKeys(bufferEncrypted); waitingForKeys = shouldWaitForKeys(bufferEncrypted);
if (waitingForKeys) { if (waitingForKeys) {
return false; return false;
} }
if (bufferEncrypted) {
buffer.cryptoInfo.increaseClearDataFirstSubSampleBy(adaptiveReconfigurationBytes);
}
if (codecNeedsDiscardToSpsWorkaround && !bufferEncrypted) { if (codecNeedsDiscardToSpsWorkaround && !bufferEncrypted) {
NalUnitUtil.discardToSps(buffer.data); NalUnitUtil.discardToSps(buffer.data);
if (buffer.data.position() == 0) { if (buffer.data.position() == 0) {
...@@ -1355,38 +1367,39 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -1355,38 +1367,39 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
} }
codecNeedsDiscardToSpsWorkaround = false; codecNeedsDiscardToSpsWorkaround = false;
} }
try {
long presentationTimeUs = buffer.timeUs;
if (buffer.isDecodeOnly()) {
decodeOnlyPresentationTimestamps.add(presentationTimeUs);
}
if (waitingForFirstSampleInFormat) {
formatQueue.add(presentationTimeUs, inputFormat);
waitingForFirstSampleInFormat = false;
}
largestQueuedPresentationTimeUs =
Math.max(largestQueuedPresentationTimeUs, presentationTimeUs);
buffer.flip(); long presentationTimeUs = buffer.timeUs;
if (buffer.hasSupplementalData()) { if (buffer.isDecodeOnly()) {
handleInputBufferSupplementalData(buffer); decodeOnlyPresentationTimestamps.add(presentationTimeUs);
} }
onQueueInputBuffer(buffer); if (waitingForFirstSampleInFormat) {
formatQueue.add(presentationTimeUs, inputFormat);
waitingForFirstSampleInFormat = false;
}
largestQueuedPresentationTimeUs = Math.max(largestQueuedPresentationTimeUs, presentationTimeUs);
buffer.flip();
if (buffer.hasSupplementalData()) {
handleInputBufferSupplementalData(buffer);
}
onQueueInputBuffer(buffer);
try {
if (bufferEncrypted) { if (bufferEncrypted) {
CryptoInfo cryptoInfo = buffer.cryptoInfo; codecAdapter.queueSecureInputBuffer(
cryptoInfo.increaseClearDataFirstSubSampleBy(adaptiveReconfigurationBytes); inputIndex, /* offset= */ 0, buffer.cryptoInfo, presentationTimeUs, /* flags= */ 0);
codecAdapter.queueSecureInputBuffer(inputIndex, 0, cryptoInfo, presentationTimeUs, 0);
} else { } else {
codecAdapter.queueInputBuffer(inputIndex, 0, buffer.data.limit(), presentationTimeUs, 0); codecAdapter.queueInputBuffer(
inputIndex, /* offset= */ 0, buffer.data.limit(), presentationTimeUs, /* flags= */ 0);
} }
resetInputBuffer();
codecReceivedBuffers = true;
codecReconfigurationState = RECONFIGURATION_STATE_NONE;
decoderCounters.inputBufferCount++;
} catch (CryptoException e) { } catch (CryptoException e) {
throw createRendererException(e, inputFormat); throw createRendererException(e, inputFormat);
} }
resetInputBuffer();
codecReceivedBuffers = true;
codecReconfigurationState = RECONFIGURATION_STATE_NONE;
decoderCounters.inputBufferCount++;
return true; return true;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment