mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2026-04-23 16:56:41 +00:00
Improve handling of transient CodecExceptions
This commit is contained in:
@@ -478,15 +478,16 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleDecoderException(Exception e, ByteBuffer buf, int codecFlags, boolean throwOnTransient) {
|
// Returns true if the exception is transient
|
||||||
|
private boolean handleDecoderException(Exception e, ByteBuffer buf, int codecFlags) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
if (e instanceof CodecException) {
|
if (e instanceof CodecException) {
|
||||||
CodecException codecExc = (CodecException) e;
|
CodecException codecExc = (CodecException) e;
|
||||||
|
|
||||||
if (codecExc.isTransient() && !throwOnTransient) {
|
if (codecExc.isTransient()) {
|
||||||
// We'll let transient exceptions go
|
// We'll let transient exceptions go
|
||||||
LimeLog.warning(codecExc.getDiagnosticInfo());
|
LimeLog.warning(codecExc.getDiagnosticInfo());
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
LimeLog.severe(codecExc.getDiagnosticInfo());
|
LimeLog.severe(codecExc.getDiagnosticInfo());
|
||||||
@@ -524,6 +525,9 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
initialExceptionTimestamp = SystemClock.uptimeMillis();
|
initialExceptionTimestamp = SystemClock.uptimeMillis();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Not transient
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -555,9 +559,14 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
|
|
||||||
lastRenderedFrameTimeNanos = frameTimeNanos;
|
lastRenderedFrameTimeNanos = frameTimeNanos;
|
||||||
activeWindowVideoStats.totalFramesRendered++;
|
activeWindowVideoStats.totalFramesRendered++;
|
||||||
} catch (Exception e) {
|
} catch (Exception ignored) {
|
||||||
// This will leak nextOutputBuffer, but there's really nothing else we can do
|
try {
|
||||||
handleDecoderException(e, null, 0, false);
|
// Try to avoid leaking the output buffer by releasing it without rendering
|
||||||
|
videoDecoder.releaseOutputBuffer(nextOutputBuffer, false);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// This will leak nextOutputBuffer, but there's really nothing else we can do
|
||||||
|
handleDecoderException(e, null, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -677,7 +686,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
handleDecoderException(e, null, 0, false);
|
handleDecoderException(e, null, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -724,7 +733,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
handleDecoderException(e, null, 0, true);
|
handleDecoderException(e, null, 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -830,12 +839,24 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
videoDecoder.queueInputBuffer(nextInputBufferIndex,
|
videoDecoder.queueInputBuffer(nextInputBufferIndex,
|
||||||
0, nextInputBuffer.position(),
|
0, nextInputBuffer.position(),
|
||||||
timestampUs, codecFlags);
|
timestampUs, codecFlags);
|
||||||
} catch (Exception e) {
|
|
||||||
handleDecoderException(e, null, codecFlags, true);
|
// We need a new buffer now
|
||||||
return false;
|
|
||||||
} finally {
|
|
||||||
nextInputBufferIndex = -1;
|
nextInputBufferIndex = -1;
|
||||||
nextInputBuffer = null;
|
nextInputBuffer = null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (handleDecoderException(e, null, codecFlags)) {
|
||||||
|
// 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
|
||||||
|
// false to trigger an IDR frame to recover.
|
||||||
|
nextInputBuffer.clear();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// We encountered a non-transient error. In this case, we will simply leak the
|
||||||
|
// buffer because we cannot be sure we will ever succeed in queuing it.
|
||||||
|
nextInputBufferIndex = -1;
|
||||||
|
nextInputBuffer = null;
|
||||||
|
}
|
||||||
|
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
|
||||||
|
|||||||
Reference in New Issue
Block a user