Work around broken AAC decoder EoS handling on L.
SoftAAC2 would cause an exception to be thrown from dequeueOutputBuffer/releaseOutputBuffer after queueing an end-of-stream buffer for certain streams. The bug was introduced in L and fixed in L MR1, so the workaround is targeted to API 21. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=147613659
This commit is contained in:
parent
d6e15b7953
commit
ec98bd9ea1
@ -183,6 +183,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||
private boolean codecNeedsAdaptationWorkaround;
|
||||
private boolean codecNeedsEosPropagationWorkaround;
|
||||
private boolean codecNeedsEosFlushWorkaround;
|
||||
private boolean codecNeedsEosOutputExceptionWorkaround;
|
||||
private boolean codecNeedsMonoChannelCountWorkaround;
|
||||
private boolean codecNeedsAdaptationWorkaroundBuffer;
|
||||
private boolean shouldSkipAdaptationWorkaroundOutputBuffer;
|
||||
@ -342,6 +343,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||
codecNeedsAdaptationWorkaround = codecNeedsAdaptationWorkaround(codecName);
|
||||
codecNeedsEosPropagationWorkaround = codecNeedsEosPropagationWorkaround(codecName);
|
||||
codecNeedsEosFlushWorkaround = codecNeedsEosFlushWorkaround(codecName);
|
||||
codecNeedsEosOutputExceptionWorkaround = codecNeedsEosOutputExceptionWorkaround(codecName);
|
||||
codecNeedsMonoChannelCountWorkaround = codecNeedsMonoChannelCountWorkaround(codecName, format);
|
||||
try {
|
||||
long codecInitializingTimestamp = SystemClock.elapsedRealtime();
|
||||
@ -513,7 +515,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||
codecNeedsAdaptationWorkaroundBuffer = false;
|
||||
shouldSkipAdaptationWorkaroundOutputBuffer = false;
|
||||
if (codecNeedsFlushWorkaround || (codecNeedsEosFlushWorkaround && codecReceivedEos)) {
|
||||
// Workaround framework bugs. See [Internal: b/8347958, b/8578467, b/8543366, b/23361053].
|
||||
releaseCodec();
|
||||
maybeInitCodec();
|
||||
} else if (codecReinitializationState != REINITIALIZATION_STATE_NONE) {
|
||||
@ -867,7 +868,22 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||
private boolean drainOutputBuffer(long positionUs, long elapsedRealtimeUs)
|
||||
throws ExoPlaybackException {
|
||||
if (outputIndex < 0) {
|
||||
outputIndex = codec.dequeueOutputBuffer(outputBufferInfo, getDequeueOutputBufferTimeoutUs());
|
||||
if (codecNeedsEosOutputExceptionWorkaround && codecReceivedEos) {
|
||||
try {
|
||||
outputIndex = codec.dequeueOutputBuffer(outputBufferInfo,
|
||||
getDequeueOutputBufferTimeoutUs());
|
||||
} catch (IllegalStateException e) {
|
||||
processEndOfStream();
|
||||
if (outputStreamEnded) {
|
||||
// Release the codec, as it's in an error state.
|
||||
releaseCodec();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
outputIndex = codec.dequeueOutputBuffer(outputBufferInfo,
|
||||
getDequeueOutputBufferTimeoutUs());
|
||||
}
|
||||
if (outputIndex >= 0) {
|
||||
// We've dequeued a buffer.
|
||||
if (shouldSkipAdaptationWorkaroundOutputBuffer) {
|
||||
@ -906,9 +922,27 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
if (processOutputBuffer(positionUs, elapsedRealtimeUs, codec, outputBuffers[outputIndex],
|
||||
outputIndex, outputBufferInfo.flags, outputBufferInfo.presentationTimeUs,
|
||||
shouldSkipOutputBuffer)) {
|
||||
boolean processedOutputBuffer;
|
||||
if (codecNeedsEosOutputExceptionWorkaround && codecReceivedEos) {
|
||||
try {
|
||||
processedOutputBuffer = processOutputBuffer(positionUs, elapsedRealtimeUs, codec,
|
||||
outputBuffers[outputIndex], outputIndex, outputBufferInfo.flags,
|
||||
outputBufferInfo.presentationTimeUs, shouldSkipOutputBuffer);
|
||||
} catch (IllegalStateException e) {
|
||||
processEndOfStream();
|
||||
if (outputStreamEnded) {
|
||||
// Release the codec, as it's in an error state.
|
||||
releaseCodec();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
processedOutputBuffer = processOutputBuffer(positionUs, elapsedRealtimeUs, codec,
|
||||
outputBuffers[outputIndex], outputIndex, outputBufferInfo.flags,
|
||||
outputBufferInfo.presentationTimeUs, shouldSkipOutputBuffer);
|
||||
}
|
||||
|
||||
if (processedOutputBuffer) {
|
||||
onProcessedOutputBuffer(outputBufferInfo.presentationTimeUs);
|
||||
outputIndex = C.INDEX_UNSET;
|
||||
return true;
|
||||
@ -1010,6 +1044,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||
* <p>
|
||||
* If true is returned, the renderer will work around the issue by releasing the decoder and
|
||||
* instantiating a new one rather than flushing the current instance.
|
||||
* <p>
|
||||
* See [Internal: b/8347958, b/8543366].
|
||||
*
|
||||
* @param name The name of the decoder.
|
||||
* @return True if the decoder is known to fail when flushed.
|
||||
@ -1079,6 +1115,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||
* <p>
|
||||
* If true is returned, the renderer will work around the issue by instantiating a new decoder
|
||||
* when this case occurs.
|
||||
* <p>
|
||||
* See [Internal: b/8578467, b/23361053].
|
||||
*
|
||||
* @param name The name of the decoder.
|
||||
* @return True if the decoder is known to behave incorrectly if flushed after receiving an input
|
||||
@ -1091,6 +1129,21 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||
|| "OMX.amlogic.avc.decoder.awesome.secure".equals(name)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the decoder may throw an {@link IllegalStateException} from
|
||||
* {@link MediaCodec#dequeueOutputBuffer(MediaCodec.BufferInfo, long)} or
|
||||
* {@link MediaCodec#releaseOutputBuffer(int, boolean)} after receiving an input
|
||||
* buffer with {@link MediaCodec#BUFFER_FLAG_END_OF_STREAM} set.
|
||||
* <p>
|
||||
* See [Internal: b/17933838].
|
||||
*
|
||||
* @param name The name of the decoder.
|
||||
* @return True if the decoder may throw an exception after receiving an end-of-stream buffer.
|
||||
*/
|
||||
private static boolean codecNeedsEosOutputExceptionWorkaround(String name) {
|
||||
return Util.SDK_INT == 21 && "OMX.google.aac.decoder".equals(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the decoder is known to set the number of audio channels in the output format
|
||||
* to 2 for the given input format, whilst only actually outputting a single channel.
|
||||
|
Loading…
x
Reference in New Issue
Block a user