diff --git a/server/src/main/java/com/genymobile/scrcpy/video/ScreenCapture.java b/server/src/main/java/com/genymobile/scrcpy/video/ScreenCapture.java index af9a9283..16731280 100644 --- a/server/src/main/java/com/genymobile/scrcpy/video/ScreenCapture.java +++ b/server/src/main/java/com/genymobile/scrcpy/video/ScreenCapture.java @@ -1,7 +1,6 @@ package com.genymobile.scrcpy.video; import com.genymobile.scrcpy.AndroidVersions; -import com.genymobile.scrcpy.device.ConfigurationException; import com.genymobile.scrcpy.device.Device; import com.genymobile.scrcpy.device.DisplayInfo; import com.genymobile.scrcpy.device.Size; @@ -26,9 +25,8 @@ public class ScreenCapture extends SurfaceCapture { private int maxSize; private final Rect crop; private final int lockVideoOrientation; - private int layerStack; - private Size deviceSize; + private DisplayInfo displayInfo; private ScreenInfo screenInfo; private IBinder display; @@ -46,27 +44,11 @@ public class ScreenCapture extends SurfaceCapture { } @Override - public void init() throws ConfigurationException { - DisplayInfo displayInfo = ServiceManager.getDisplayManager().getDisplayInfo(displayId); - if (displayInfo == null) { - Ln.e("Display " + displayId + " not found\n" + LogUtils.buildDisplayListMessage()); - throw new ConfigurationException("Unknown display id: " + displayId); - } - - deviceSize = displayInfo.getSize(); - ScreenInfo si = ScreenInfo.computeScreenInfo(displayInfo.getRotation(), deviceSize, crop, maxSize, lockVideoOrientation); - setScreenInfo(si); - layerStack = displayInfo.getLayerStack(); - + public void init() { if (displayId == 0) { rotationWatcher = new IRotationWatcher.Stub() { @Override public void onRotationChanged(int rotation) { - synchronized (ScreenCapture.this) { - ScreenInfo si = screenInfo.withDeviceRotation(rotation); - setScreenInfo(si); - } - requestReset(); } }; @@ -82,37 +64,30 @@ public class ScreenCapture extends SurfaceCapture { return; } - synchronized (ScreenCapture.this) { - DisplayInfo displayInfo = ServiceManager.getDisplayManager().getDisplayInfo(displayId); - if (displayInfo == null) { - Ln.e("Display " + displayId + " not found\n" + LogUtils.buildDisplayListMessage()); - return; - } - - deviceSize = displayInfo.getSize(); - ScreenInfo si = ScreenInfo.computeScreenInfo(displayInfo.getRotation(), deviceSize, crop, maxSize, lockVideoOrientation); - setScreenInfo(si); - } - requestReset(); } }; ServiceManager.getWindowManager().registerDisplayFoldListener(displayFoldListener); } + } + + @Override + public void prepare() { + displayInfo = ServiceManager.getDisplayManager().getDisplayInfo(displayId); + if (displayInfo == null) { + Ln.e("Display " + displayId + " not found\n" + LogUtils.buildDisplayListMessage()); + throw new AssertionError("Display " + display + " not found"); + } if ((displayInfo.getFlags() & DisplayInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS) == 0) { Ln.w("Display doesn't have FLAG_SUPPORTS_PROTECTED_BUFFERS flag, mirroring can be restricted"); } + + screenInfo = ScreenInfo.computeScreenInfo(displayInfo.getRotation(), displayInfo.getSize(), crop, maxSize, lockVideoOrientation); } @Override public void start(Surface surface) { - Rect contentRect = screenInfo.getContentRect(); - - // does not include the locked video orientation - Rect unlockedVideoRect = screenInfo.getUnlockedVideoSize().toRect(); - int videoRotation = screenInfo.getVideoRotation(); - if (display != null) { SurfaceControl.destroyDisplay(display); display = null; @@ -122,14 +97,23 @@ public class ScreenCapture extends SurfaceCapture { virtualDisplay = null; } + Size displaySize = screenInfo.getVideoSize(); + try { - Rect videoRect = screenInfo.getVideoSize().toRect(); virtualDisplay = ServiceManager.getDisplayManager() - .createVirtualDisplay("scrcpy", videoRect.width(), videoRect.height(), displayId, surface); + .createVirtualDisplay("scrcpy", displaySize.getWidth(), displaySize.getHeight(), displayId, surface); Ln.d("Display: using DisplayManager API"); } catch (Exception displayManagerException) { try { display = createDisplay(); + + Rect contentRect = screenInfo.getContentRect(); + + // does not include the locked video orientation + Rect unlockedVideoRect = screenInfo.getUnlockedVideoSize().toRect(); + int videoRotation = screenInfo.getVideoRotation(); + int layerStack = displayInfo.getLayerStack(); + setDisplaySurface(display, surface, videoRotation, contentRect, unlockedVideoRect, layerStack); Ln.d("Display: using SurfaceControl API"); } catch (Exception surfaceControlException) { @@ -138,6 +122,8 @@ public class ScreenCapture extends SurfaceCapture { throw new AssertionError("Could not create display"); } } + + device.setScreenInfo(screenInfo); } @Override @@ -159,15 +145,13 @@ public class ScreenCapture extends SurfaceCapture { } @Override - public synchronized Size getSize() { + public Size getSize() { return screenInfo.getVideoSize(); } @Override - public synchronized boolean setMaxSize(int newMaxSize) { + public boolean setMaxSize(int newMaxSize) { maxSize = newMaxSize; - ScreenInfo si = ScreenInfo.computeScreenInfo(screenInfo.getReverseVideoRotation(), deviceSize, crop, newMaxSize, lockVideoOrientation); - setScreenInfo(si); return true; } @@ -189,9 +173,4 @@ public class ScreenCapture extends SurfaceCapture { SurfaceControl.closeTransaction(); } } - - private void setScreenInfo(ScreenInfo si) { - screenInfo = si; - device.setScreenInfo(si); - } } diff --git a/server/src/main/java/com/genymobile/scrcpy/video/SurfaceCapture.java b/server/src/main/java/com/genymobile/scrcpy/video/SurfaceCapture.java index fe679beb..869ee4f7 100644 --- a/server/src/main/java/com/genymobile/scrcpy/video/SurfaceCapture.java +++ b/server/src/main/java/com/genymobile/scrcpy/video/SurfaceCapture.java @@ -33,15 +33,22 @@ public abstract class SurfaceCapture { } /** - * Called once before the capture starts. + * Called once before the first capture starts. */ public abstract void init() throws ConfigurationException, IOException; /** - * Called after the capture ends (if and only if {@link #init()} has been called). + * Called after the last capture ends (if and only if {@link #init()} has been called). */ public abstract void release(); + /** + * Called once before each capture starts, before {@link #getSize()}. + */ + public void prepare() { + // empty by default + } + /** * Start the capture to the target surface. * diff --git a/server/src/main/java/com/genymobile/scrcpy/video/SurfaceEncoder.java b/server/src/main/java/com/genymobile/scrcpy/video/SurfaceEncoder.java index 4da1454d..84bda1ce 100644 --- a/server/src/main/java/com/genymobile/scrcpy/video/SurfaceEncoder.java +++ b/server/src/main/java/com/genymobile/scrcpy/video/SurfaceEncoder.java @@ -72,6 +72,7 @@ public class SurfaceEncoder implements AsyncProcessor { boolean headerWritten = false; do { + capture.prepare(); Size size = capture.getSize(); if (!headerWritten) { streamer.writeVideoHeader(size);