Only catch IllegalStateException or subclasses

This commit is contained in:
Cameron Gutman
2022-09-18 17:42:37 -05:00
parent 06099b2663
commit 173483eb84
@@ -2,7 +2,6 @@ package com.limelight.binding.video;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import org.jcodec.codecs.h264.H264Utils; import org.jcodec.codecs.h264.H264Utils;
@@ -525,6 +524,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
if (codecRecoveryThreadQuiescedFlags == CR_FLAG_ALL) { if (codecRecoveryThreadQuiescedFlags == CR_FLAG_ALL) {
// This is the final thread to quiesce, so let's perform the codec recovery now. // This is the final thread to quiesce, so let's perform the codec recovery now.
codecRecoveryAttempts++; codecRecoveryAttempts++;
LimeLog.info("Codec recovery attempt: "+codecRecoveryAttempts);
// Input and output buffers are invalidated by stop() and reset(). // Input and output buffers are invalidated by stop() and reset().
nextInputBuffer = null; nextInputBuffer = null;
@@ -609,7 +609,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
} }
// Returns true if the exception is transient // Returns true if the exception is transient
private boolean handleDecoderException(RuntimeException e, ByteBuffer buf, int codecFlags) { private boolean handleDecoderException(IllegalStateException e) {
// Print the stack trace for debugging purposes // Print the stack trace for debugging purposes
e.printStackTrace(); e.printStackTrace();
@@ -642,7 +642,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
return false; return false;
} }
} }
else if (e instanceof IllegalStateException) { else {
// IllegalStateException was primarily used prior to the introduction of CodecException. // IllegalStateException was primarily used prior to the introduction of CodecException.
// Recovery from this requires a full decoder reset. // Recovery from this requires a full decoder reset.
// //
@@ -652,10 +652,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
return false; return false;
} }
} }
else {
// If it's not a CodecException or IllegalStateException, it's not an "expected" failure.
throw e;
}
// Only throw if we're not in the middle of codec recovery // Only throw if we're not in the middle of codec recovery
if (!needsReset && !needsRestart) { if (!needsReset && !needsRestart) {
@@ -679,7 +675,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
} }
else { else {
// This is the first exception we've hit // This is the first exception we've hit
initialException = new RendererException(this, e, buf, codecFlags); initialException = new RendererException(this, e);
initialExceptionTimestamp = SystemClock.uptimeMillis(); initialExceptionTimestamp = SystemClock.uptimeMillis();
} }
} }
@@ -717,13 +713,13 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
lastRenderedFrameTimeNanos = frameTimeNanos; lastRenderedFrameTimeNanos = frameTimeNanos;
activeWindowVideoStats.totalFramesRendered++; activeWindowVideoStats.totalFramesRendered++;
} catch (RuntimeException ignored) { } catch (IllegalStateException ignored) {
try { try {
// Try to avoid leaking the output buffer by releasing it without rendering // Try to avoid leaking the output buffer by releasing it without rendering
videoDecoder.releaseOutputBuffer(nextOutputBuffer, false); videoDecoder.releaseOutputBuffer(nextOutputBuffer, false);
} catch (RuntimeException e) { } catch (IllegalStateException e) {
// This will leak nextOutputBuffer, but there's really nothing else we can do // This will leak nextOutputBuffer, but there's really nothing else we can do
handleDecoderException(e, null, 0); handleDecoderException(e);
} }
} finally { } finally {
doCodecRecoveryIfRequired(CR_FLAG_CHOREOGRAPHER); doCodecRecoveryIfRequired(CR_FLAG_CHOREOGRAPHER);
@@ -851,8 +847,8 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
break; break;
} }
} }
} catch (RuntimeException e) { } catch (IllegalStateException e) {
handleDecoderException(e, null, 0); handleDecoderException(e);
} finally { } finally {
doCodecRecoveryIfRequired(CR_FLAG_RENDER_THREAD); doCodecRecoveryIfRequired(CR_FLAG_RENDER_THREAD);
} }
@@ -901,8 +897,8 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
nextInputBuffer.clear(); nextInputBuffer.clear();
} }
} }
} catch (RuntimeException e) { } catch (IllegalStateException e) {
handleDecoderException(e, null, 0); handleDecoderException(e);
return false; return false;
} finally { } finally {
codecRecovered = doCodecRecoveryIfRequired(CR_FLAG_INPUT_THREAD); codecRecovered = doCodecRecoveryIfRequired(CR_FLAG_INPUT_THREAD);
@@ -1022,8 +1018,8 @@ 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;
} catch (RuntimeException e) { } catch (IllegalStateException e) {
if (handleDecoderException(e, nextInputBuffer, codecFlags)) { if (handleDecoderException(e)) {
// 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
// (to avoid leaking it), clear it, and keep it for the next frame. We'll return // (to avoid leaking it), clear it, and keep it for the next frame. We'll return
// false to trigger an IDR frame to recover. // false to trigger an IDR frame to recover.
@@ -1475,18 +1471,14 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
private String text; private String text;
RendererException(MediaCodecDecoderRenderer renderer, Exception e) { RendererException(MediaCodecDecoderRenderer renderer, Exception e) {
this.text = generateText(renderer, e, null, 0); this.text = generateText(renderer, e);
}
RendererException(MediaCodecDecoderRenderer renderer, Exception e, ByteBuffer currentBuffer, int currentCodecFlags) {
this.text = generateText(renderer, e, currentBuffer, currentCodecFlags);
} }
public String toString() { public String toString() {
return text; return text;
} }
private String generateText(MediaCodecDecoderRenderer renderer, Exception originalException, ByteBuffer currentBuffer, int currentCodecFlags) { private String generateText(MediaCodecDecoderRenderer renderer, Exception originalException) {
String str; String str;
if (renderer.numVpsIn == 0 && renderer.numSpsIn == 0 && renderer.numPpsIn == 0) { if (renderer.numVpsIn == 0 && renderer.numSpsIn == 0 && renderer.numPpsIn == 0) {
@@ -1576,16 +1568,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
str += "Average hardware decoder latency: "+renderer.getAverageDecoderLatency()+"ms\n"; str += "Average hardware decoder latency: "+renderer.getAverageDecoderLatency()+"ms\n";
str += "Frame pacing mode: "+renderer.prefs.framePacing+"\n"; str += "Frame pacing mode: "+renderer.prefs.framePacing+"\n";
if (currentBuffer != null) {
str += "Current buffer: ";
currentBuffer.flip();
while (currentBuffer.hasRemaining() && currentBuffer.position() < 10) {
str += String.format((Locale)null, "%02x ", currentBuffer.get());
}
str += "\n";
str += "Buffer codec flags: "+currentCodecFlags+"\n";
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (originalException instanceof CodecException) { if (originalException instanceof CodecException) {
CodecException ce = (CodecException) originalException; CodecException ce = (CodecException) originalException;