Downsize on error

Some devices are not able to encode at the device screen definition.

Instead of just failing, try with a lower definition on any MediaCodec
error.

PR #2947 <https://github.com/Genymobile/scrcpy/pull/2947>
This commit is contained in:
Romain Vimont 2022-01-15 22:47:27 +01:00
parent 723faa5dee
commit 26b4104844
2 changed files with 33 additions and 1 deletions

View file

@ -44,7 +44,7 @@ public final class Device {
private final Size deviceSize;
private final Rect crop;
private final int maxSize;
private int maxSize;
private final int lockVideoOrientation;
private ScreenInfo screenInfo;
@ -133,6 +133,11 @@ public final class Device {
}
}
public synchronized void setMaxSize(int newMaxSize) {
maxSize = newMaxSize;
screenInfo = ScreenInfo.computeScreenInfo(screenInfo.getReverseVideoRotation(), deviceSize, crop, newMaxSize, lockVideoOrientation);
}
public synchronized ScreenInfo getScreenInfo() {
return screenInfo;
}

View file

@ -25,6 +25,9 @@ public class ScreenEncoder implements Device.RotationListener {
private static final int REPEAT_FRAME_DELAY_US = 100_000; // repeat after 100ms
private static final String KEY_MAX_FPS_TO_ENCODER = "max-fps-to-encoder";
// Keep the values in descending order
private static final int[] MAX_SIZE_FALLBACK = {2560, 1920, 1600, 1280, 1024, 800};
private static final int NO_PTS = -1;
private final AtomicBoolean rotationChanged = new AtomicBoolean();
@ -91,6 +94,18 @@ public class ScreenEncoder implements Device.RotationListener {
alive = encode(codec, fd);
// do not call stop() on exception, it would trigger an IllegalStateException
codec.stop();
} catch (Exception e) {
Ln.e("Encoding error: " + e.getClass().getName() + ": " + e.getMessage());
int newMaxSize = chooseMaxSizeFallback(screenInfo.getVideoSize());
if (newMaxSize == 0) {
// Definitively fail
throw e;
}
// Retry with a smaller device size
Ln.i("Retrying with -m" + newMaxSize + "...");
device.setMaxSize(newMaxSize);
alive = true;
} finally {
destroyDisplay(display);
codec.release();
@ -102,6 +117,18 @@ public class ScreenEncoder implements Device.RotationListener {
}
}
private static int chooseMaxSizeFallback(Size failedSize) {
int currentMaxSize = Math.max(failedSize.getWidth(), failedSize.getHeight());
for (int value : MAX_SIZE_FALLBACK) {
if (value < currentMaxSize) {
// We found a smaller value to reduce the video size
return value;
}
}
// No fallback, fail definitively
return 0;
}
private boolean encode(MediaCodec codec, FileDescriptor fd) throws IOException {
boolean eof = false;
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();