From 4f36ab203f6b8c54a582cf07aea290ca10a645a3 Mon Sep 17 00:00:00 2001 From: hoangtc Date: Thu, 1 Feb 2018 02:44:00 -0800 Subject: [PATCH] Use new MediaCodec APIs in MediaCodecRenderer. In MediaCodecRenderer, we currently uses codec.getInput/OutputBuffers event though these APIs are deprecated and are not recommended from API 21+. This change makes sure that: - On API 20 and below, we will keep using codec.getInput/OutputBuffers. - On API 21+, we will use getInput/OutputBuffer(index) APIs instead. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=184112329 --- .../mediacodec/MediaCodecRenderer.java | 147 ++++++++++++------ 1 file changed, 103 insertions(+), 44 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java index 99d96865af..2e8fc602a2 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java @@ -224,6 +224,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { private long codecHotswapDeadlineMs; private int inputIndex; private int outputIndex; + private ByteBuffer outputBuffer; private boolean shouldSkipOutputBuffer; private boolean codecReconfigured; private @ReconfigurationState int codecReconfigurationState; @@ -322,7 +323,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer { protected abstract void configureCodec(MediaCodecInfo codecInfo, MediaCodec codec, Format format, MediaCrypto crypto) throws DecoderQueryException; - @SuppressWarnings("deprecation") protected final void maybeInitCodec() throws ExoPlaybackException { if (codec != null || format == null) { // We have a codec already, or we don't have a format with which to instantiate one. @@ -402,16 +402,15 @@ public abstract class MediaCodecRenderer extends BaseRenderer { long codecInitializedTimestamp = SystemClock.elapsedRealtime(); onCodecInitialized(codecName, codecInitializedTimestamp, codecInitializedTimestamp - codecInitializingTimestamp); - inputBuffers = codec.getInputBuffers(); - outputBuffers = codec.getOutputBuffers(); + getCodecBuffers(); } catch (Exception e) { throwDecoderInitError(new DecoderInitializationException(format, e, drmSessionRequiresSecureDecoder, codecName)); } codecHotswapDeadlineMs = getState() == STATE_STARTED ? (SystemClock.elapsedRealtime() + MAX_CODEC_HOTSWAP_TIME_MS) : C.TIME_UNSET; - inputIndex = C.INDEX_UNSET; - outputIndex = C.INDEX_UNSET; + resetInputBuffer(); + resetOutputBuffer(); waitingForFirstSyncFrame = true; decoderCounters.decoderInitCount++; } @@ -487,13 +486,12 @@ public abstract class MediaCodecRenderer extends BaseRenderer { protected void releaseCodec() { codecHotswapDeadlineMs = C.TIME_UNSET; - inputIndex = C.INDEX_UNSET; - outputIndex = C.INDEX_UNSET; + resetInputBuffer(); + resetOutputBuffer(); waitingForKeys = false; shouldSkipOutputBuffer = false; decodeOnlyPresentationTimestamps.clear(); - inputBuffers = null; - outputBuffers = null; + resetCodecBuffers(); codecInfo = null; codecReconfigured = false; codecReceivedBuffers = false; @@ -508,7 +506,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer { codecReceivedEos = false; codecReconfigurationState = RECONFIGURATION_STATE_NONE; codecReinitializationState = REINITIALIZATION_STATE_NONE; - buffer.data = null; if (codec != null) { decoderCounters.decoderReleaseCount++; try { @@ -591,8 +588,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer { protected void flushCodec() throws ExoPlaybackException { codecHotswapDeadlineMs = C.TIME_UNSET; - inputIndex = C.INDEX_UNSET; - outputIndex = C.INDEX_UNSET; + resetInputBuffer(); + resetOutputBuffer(); waitingForFirstSyncFrame = true; waitingForKeys = false; shouldSkipOutputBuffer = false; @@ -635,7 +632,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { if (inputIndex < 0) { return false; } - buffer.data = inputBuffers[inputIndex]; + buffer.data = getInputBuffer(inputIndex); buffer.clear(); } @@ -647,7 +644,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { } else { codecReceivedEos = true; codec.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); - inputIndex = C.INDEX_UNSET; + resetInputBuffer(); } codecReinitializationState = REINITIALIZATION_STATE_WAIT_END_OF_STREAM; return false; @@ -657,7 +654,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { codecNeedsAdaptationWorkaroundBuffer = false; buffer.data.put(ADAPTATION_WORKAROUND_BUFFER); codec.queueInputBuffer(inputIndex, 0, ADAPTATION_WORKAROUND_BUFFER.length, 0, 0); - inputIndex = C.INDEX_UNSET; + resetInputBuffer(); codecReceivedBuffers = true; return true; } @@ -715,7 +712,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { } else { codecReceivedEos = true; codec.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); - inputIndex = C.INDEX_UNSET; + resetInputBuffer(); } } catch (CryptoException e) { throw ExoPlaybackException.createForRenderer(e, getIndex()); @@ -760,7 +757,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { } else { codec.queueInputBuffer(inputIndex, 0, buffer.data.limit(), presentationTimeUs, 0); } - inputIndex = C.INDEX_UNSET; + resetInputBuffer(); codecReceivedBuffers = true; codecReconfigurationState = RECONFIGURATION_STATE_NONE; decoderCounters.inputBufferCount++; @@ -770,6 +767,50 @@ public abstract class MediaCodecRenderer extends BaseRenderer { return true; } + private void getCodecBuffers() { + if (Util.SDK_INT < 21) { + inputBuffers = codec.getInputBuffers(); + outputBuffers = codec.getOutputBuffers(); + } + } + + private void resetCodecBuffers() { + if (Util.SDK_INT < 21) { + inputBuffers = null; + outputBuffers = null; + } + } + + private ByteBuffer getInputBuffer(int inputIndex) { + if (Util.SDK_INT >= 21) { + return codec.getInputBuffer(inputIndex); + } else { + return inputBuffers[inputIndex]; + } + } + + private ByteBuffer getOutputBuffer(int outputIndex) { + if (Util.SDK_INT >= 21) { + return codec.getOutputBuffer(outputIndex); + } else { + return outputBuffers[outputIndex]; + } + } + + private boolean hasOutputBuffer() { + return outputIndex >= 0; + } + + private void resetInputBuffer() { + inputIndex = C.INDEX_UNSET; + buffer.data = null; + } + + private void resetOutputBuffer() { + outputIndex = C.INDEX_UNSET; + outputBuffer = null; + } + private static MediaCodec.CryptoInfo getFrameworkCryptoInfo(DecoderInputBuffer buffer, int adaptiveReconfigurationBytes) { MediaCodec.CryptoInfo cryptoInfo = buffer.cryptoInfo.getFrameworkCryptoInfoV16(); @@ -922,9 +963,12 @@ public abstract class MediaCodecRenderer extends BaseRenderer { @Override public boolean isReady() { - return format != null && !waitingForKeys && (isSourceReady() || outputIndex >= 0 - || (codecHotswapDeadlineMs != C.TIME_UNSET - && SystemClock.elapsedRealtime() < codecHotswapDeadlineMs)); + return format != null + && !waitingForKeys + && (isSourceReady() + || hasOutputBuffer() + || (codecHotswapDeadlineMs != C.TIME_UNSET + && SystemClock.elapsedRealtime() < codecHotswapDeadlineMs)); } /** @@ -940,14 +984,14 @@ public abstract class MediaCodecRenderer extends BaseRenderer { * @return Whether it may be possible to drain more output data. * @throws ExoPlaybackException If an error occurs draining the output buffer. */ - @SuppressWarnings("deprecation") private boolean drainOutputBuffer(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException { - if (outputIndex < 0) { + if (!hasOutputBuffer()) { + int outputIndex; if (codecNeedsEosOutputExceptionWorkaround && codecReceivedEos) { try { - outputIndex = codec.dequeueOutputBuffer(outputBufferInfo, - getDequeueOutputBufferTimeoutUs()); + outputIndex = + codec.dequeueOutputBuffer(outputBufferInfo, getDequeueOutputBufferTimeoutUs()); } catch (IllegalStateException e) { processEndOfStream(); if (outputStreamEnded) { @@ -957,26 +1001,25 @@ public abstract class MediaCodecRenderer extends BaseRenderer { return false; } } else { - outputIndex = codec.dequeueOutputBuffer(outputBufferInfo, - getDequeueOutputBufferTimeoutUs()); + outputIndex = + codec.dequeueOutputBuffer(outputBufferInfo, getDequeueOutputBufferTimeoutUs()); } + if (outputIndex >= 0) { // We've dequeued a buffer. if (shouldSkipAdaptationWorkaroundOutputBuffer) { shouldSkipAdaptationWorkaroundOutputBuffer = false; codec.releaseOutputBuffer(outputIndex, false); - outputIndex = C.INDEX_UNSET; return true; - } - if ((outputBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { + } else if ((outputBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { // The dequeued buffer indicates the end of the stream. Process it immediately. processEndOfStream(); - outputIndex = C.INDEX_UNSET; return false; } else { - // The dequeued buffer is a media buffer. Do some initial setup. The buffer will be - // processed by calling processOutputBuffer (possibly multiple times) below. - ByteBuffer outputBuffer = outputBuffers[outputIndex]; + this.outputIndex = outputIndex; + outputBuffer = getOutputBuffer(outputIndex); + // The dequeued buffer is a media buffer. Do some initial setup. + // It will be processed by calling processOutputBuffer (possibly multiple times). if (outputBuffer != null) { outputBuffer.position(outputBufferInfo.offset); outputBuffer.limit(outputBufferInfo.offset + outputBufferInfo.size); @@ -990,8 +1033,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer { processOutputBuffersChanged(); return true; } else /* MediaCodec.INFO_TRY_AGAIN_LATER (-1) or unknown negative return value */ { - if (codecNeedsEosPropagationWorkaround && (inputStreamEnded - || codecReinitializationState == REINITIALIZATION_STATE_WAIT_END_OF_STREAM)) { + if (codecNeedsEosPropagationWorkaround + && (inputStreamEnded + || codecReinitializationState == REINITIALIZATION_STATE_WAIT_END_OF_STREAM)) { processEndOfStream(); } return false; @@ -1001,9 +1045,16 @@ public abstract class MediaCodecRenderer extends BaseRenderer { boolean processedOutputBuffer; if (codecNeedsEosOutputExceptionWorkaround && codecReceivedEos) { try { - processedOutputBuffer = processOutputBuffer(positionUs, elapsedRealtimeUs, codec, - outputBuffers[outputIndex], outputIndex, outputBufferInfo.flags, - outputBufferInfo.presentationTimeUs, shouldSkipOutputBuffer); + processedOutputBuffer = + processOutputBuffer( + positionUs, + elapsedRealtimeUs, + codec, + outputBuffer, + outputIndex, + outputBufferInfo.flags, + outputBufferInfo.presentationTimeUs, + shouldSkipOutputBuffer); } catch (IllegalStateException e) { processEndOfStream(); if (outputStreamEnded) { @@ -1013,14 +1064,21 @@ public abstract class MediaCodecRenderer extends BaseRenderer { return false; } } else { - processedOutputBuffer = processOutputBuffer(positionUs, elapsedRealtimeUs, codec, - outputBuffers[outputIndex], outputIndex, outputBufferInfo.flags, - outputBufferInfo.presentationTimeUs, shouldSkipOutputBuffer); + processedOutputBuffer = + processOutputBuffer( + positionUs, + elapsedRealtimeUs, + codec, + outputBuffer, + outputIndex, + outputBufferInfo.flags, + outputBufferInfo.presentationTimeUs, + shouldSkipOutputBuffer); } if (processedOutputBuffer) { onProcessedOutputBuffer(outputBufferInfo.presentationTimeUs); - outputIndex = C.INDEX_UNSET; + resetOutputBuffer(); return true; } @@ -1048,9 +1106,10 @@ public abstract class MediaCodecRenderer extends BaseRenderer { /** * Processes a change in the output buffers. */ - @SuppressWarnings("deprecation") private void processOutputBuffersChanged() { - outputBuffers = codec.getOutputBuffers(); + if (Util.SDK_INT < 21) { + outputBuffers = codec.getOutputBuffers(); + } } /**