mirror of
https://github.com/androidx/media.git
synced 2025-05-07 15:40:37 +08:00
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
This commit is contained in:
parent
a7d4d2d21c
commit
4f36ab203f
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user