Fix a number of bugs in new codec recovery code

This commit is contained in:
Cameron Gutman
2022-09-16 03:19:36 -05:00
parent 10f43e8024
commit be25a7d594
@@ -378,8 +378,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
legacyInputBuffers = videoDecoder.getInputBuffers(); legacyInputBuffers = videoDecoder.getInputBuffers();
} }
fetchNextInputBuffer();
} }
private boolean tryConfigureDecoder(MediaCodecInfo selectedDecoderInfo, MediaFormat format) { private boolean tryConfigureDecoder(MediaCodecInfo selectedDecoderInfo, MediaFormat format) {
@@ -552,6 +550,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
else { else {
// If we haven't quiesced all threads yet, wait to be signalled after recovery. // If we haven't quiesced all threads yet, wait to be signalled after recovery.
// The final thread to be quiesced will handle the codec recovery. // The final thread to be quiesced will handle the codec recovery.
LimeLog.info("Waiting to quiesce decoder threads: "+codecRecoveryThreadQuiescedFlags);
long startTime = SystemClock.uptimeMillis(); long startTime = SystemClock.uptimeMillis();
while (needsReset || needsRestart) { while (needsReset || needsRestart) {
try { try {
@@ -812,6 +811,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
private boolean fetchNextInputBuffer() { private boolean fetchNextInputBuffer() {
long startTime; long startTime;
boolean codecRecovered;
if (nextInputBuffer != null) { if (nextInputBuffer != null) {
// We already have an input buffer // We already have an input buffer
@@ -850,10 +850,13 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
handleDecoderException(e, null, 0); handleDecoderException(e, null, 0);
return false; return false;
} finally { } finally {
// This will reset nextInputBuffer if codec recovery is required, so we will return codecRecovered = doCodecRecoveryIfRequired(CR_FLAG_INPUT_THREAD);
// false below. This will trigger the caller to request an IDR frame to complete }
// the decoder recovery process.
doCodecRecoveryIfRequired(CR_FLAG_INPUT_THREAD); // If codec recovery is required, always return false to ensure the caller will request
// an IDR frame to complete the codec recovery.
if (codecRecovered) {
return false;
} }
int deltaMs = (int)(SystemClock.uptimeMillis() - startTime); int deltaMs = (int)(SystemClock.uptimeMillis() - startTime);
@@ -954,7 +957,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
} }
private boolean queueNextInputBuffer(long timestampUs, int codecFlags) { private boolean queueNextInputBuffer(long timestampUs, int codecFlags) {
boolean ret; boolean codecRecovered;
try { try {
videoDecoder.queueInputBuffer(nextInputBufferIndex, videoDecoder.queueInputBuffer(nextInputBufferIndex,
@@ -964,7 +967,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
// We need a new buffer now // We need a new buffer now
nextInputBufferIndex = -1; nextInputBufferIndex = -1;
nextInputBuffer = null; nextInputBuffer = null;
ret = true;
} catch (RuntimeException e) { } catch (RuntimeException e) {
if (handleDecoderException(e, nextInputBuffer, codecFlags)) { if (handleDecoderException(e, nextInputBuffer, codecFlags)) {
// We encountered a transient error. In this case, just hold onto the buffer // We encountered a transient error. In this case, just hold onto the buffer
@@ -978,20 +980,24 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
nextInputBufferIndex = -1; nextInputBufferIndex = -1;
nextInputBuffer = null; nextInputBuffer = null;
} }
ret = false; return false;
} finally {
codecRecovered = doCodecRecoveryIfRequired(CR_FLAG_INPUT_THREAD);
} }
// If codec recovery is required, always return false to ensure the caller will request // If codec recovery is required, always return false to ensure the caller will request
// an IDR frame to complete the codec recovery. // an IDR frame to complete the codec recovery.
if (doCodecRecoveryIfRequired(CR_FLAG_INPUT_THREAD)) { if (codecRecovered) {
ret = false; return false;
} }
// Fetch a new input buffer now while we have some time between frames // Fetch a new input buffer now while we have some time between frames
// to have it ready immediately when the next frame arrives. // to have it ready immediately when the next frame arrives.
fetchNextInputBuffer(); //
// We must propagate the return value here in order to properly handle
return ret; // codec recovery happening in fetchNextInputBuffer(). If we don't, we'll
// never get an IDR frame to complete the recovery process.
return fetchNextInputBuffer();
} }
private void doProfileSpecificSpsPatching(SeqParameterSet sps) { private void doProfileSpecificSpsPatching(SeqParameterSet sps) {