From b223e23f094c60cbd2fd921cf2d243a15da19c98 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sat, 29 Jan 2022 23:10:24 +0100 Subject: [PATCH] Retry on error in MediaCodec configure or start The new retry mechanism with a lower definition only worked if the error occurred during encode(). For example: java.lang.IllegalStateException at android.media.MediaCodec.native_dequeueOutputBuffer(Native Method) at android.media.MediaCodec.dequeueOutputBuffer(MediaCodec.java:3452) at com.genymobile.scrcpy.ScreenEncoder.encode(ScreenEncoder.java:114) at com.genymobile.scrcpy.ScreenEncoder.internalStreamScreen(ScreenEncoder.java:95) at com.genymobile.scrcpy.ScreenEncoder.streamScreen(ScreenEncoder.java:61) at com.genymobile.scrcpy.Server.scrcpy(Server.java:80) at com.genymobile.scrcpy.Server.main(Server.java:255) However, MediaCodec may also fail before encoding, during configure() or start(). For example: android.media.MediaCodec$CodecException: Error 0xfffffc0e at android.media.MediaCodec.native_configure(Native Method) at android.media.MediaCodec.configure(MediaCodec.java:1956) at android.media.MediaCodec.configure(MediaCodec.java:1885) at com.genymobile.scrcpy.ScreenEncoder.configure(ScreenEncoder.java:158) at com.genymobile.scrcpy.ScreenEncoder.streamScreen(ScreenEncoder.java:68) at com.genymobile.scrcpy.Server.scrcpy(Server.java:28) at com.genymobile.scrcpy.Server.main(Server.java:110) Also downscale and retry in these cases. Refs #2947 Refs #2988 --- .../com/genymobile/scrcpy/ScreenEncoder.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java b/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java index 4c23dd92bd..79efc17c8b 100644 --- a/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java +++ b/server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java @@ -89,13 +89,15 @@ private void internalStreamScreen(Device device, FileDescriptor fd) throws IOExc Rect unlockedVideoRect = screenInfo.getUnlockedVideoSize().toRect(); int videoRotation = screenInfo.getVideoRotation(); int layerStack = device.getLayerStack(); - setSize(format, videoRect.width(), videoRect.height()); - configure(codec, format); - Surface surface = codec.createInputSurface(); - setDisplaySurface(display, surface, videoRotation, contentRect, unlockedVideoRect, layerStack); - codec.start(); + + Surface surface = null; try { + configure(codec, format); + surface = codec.createInputSurface(); + setDisplaySurface(display, surface, videoRotation, contentRect, unlockedVideoRect, layerStack); + codec.start(); + alive = encode(codec, fd); // do not call stop() on exception, it would trigger an IllegalStateException codec.stop(); @@ -119,7 +121,9 @@ private void internalStreamScreen(Device device, FileDescriptor fd) throws IOExc } finally { destroyDisplay(display); codec.release(); - surface.release(); + if (surface != null) { + surface.release(); + } } } while (alive); } finally {