mirror of
https://github.com/Genymobile/scrcpy.git
synced 2026-04-21 01:33:36 +00:00
Provide reason for capture reset
Add flags to indicate why a capture was reset. This paves the way for properly handling virtual display resize requests.
This commit is contained in:
parent
b4ab0f62ab
commit
4f7e3d165e
6 changed files with 30 additions and 17 deletions
|
|
@ -13,6 +13,7 @@ import com.genymobile.scrcpy.model.Size;
|
|||
import com.genymobile.scrcpy.util.Ln;
|
||||
import com.genymobile.scrcpy.util.LogUtils;
|
||||
import com.genymobile.scrcpy.video.CameraCapture;
|
||||
import com.genymobile.scrcpy.video.CaptureControl;
|
||||
import com.genymobile.scrcpy.video.SurfaceCapture;
|
||||
import com.genymobile.scrcpy.video.VideoSource;
|
||||
import com.genymobile.scrcpy.video.VirtualDisplayListener;
|
||||
|
|
@ -815,7 +816,7 @@ public class Controller implements AsyncProcessor, VirtualDisplayListener {
|
|||
private void resetVideo() {
|
||||
if (surfaceCapture != null) {
|
||||
Ln.i("Video capture reset");
|
||||
surfaceCapture.getCaptureControl().reset();
|
||||
surfaceCapture.getCaptureControl().reset(CaptureControl.RESET_REASON_CLIENT_RESET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -323,7 +323,7 @@ public class CameraCapture extends SurfaceCapture {
|
|||
} catch (CameraAccessException e) {
|
||||
Ln.e("Camera error", e);
|
||||
disconnected.set(true);
|
||||
getCaptureControl().reset();
|
||||
getCaptureControl().reset(CaptureControl.RESET_REASON_TERMINATE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -331,7 +331,7 @@ public class CameraCapture extends SurfaceCapture {
|
|||
public void onConfigureFailed(CameraCaptureSession session) {
|
||||
Ln.e("Camera configuration error");
|
||||
disconnected.set(true);
|
||||
getCaptureControl().reset();
|
||||
getCaptureControl().reset(CaptureControl.RESET_REASON_TERMINATE);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -388,7 +388,7 @@ public class CameraCapture extends SurfaceCapture {
|
|||
public void onDisconnected(CameraDevice camera) {
|
||||
Ln.w("Camera disconnected");
|
||||
disconnected.set(true);
|
||||
getCaptureControl().reset();
|
||||
getCaptureControl().reset(CaptureControl.RESET_REASON_TERMINATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -2,21 +2,30 @@ package com.genymobile.scrcpy.video;
|
|||
|
||||
import android.media.MediaCodec;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class CaptureControl {
|
||||
|
||||
private final AtomicBoolean reset = new AtomicBoolean();
|
||||
public static final int RESET_REASON_TERMINATE = 1;
|
||||
public static final int RESET_REASON_DISPLAY_PROPERTIES_CHANGED = 1 << 1;
|
||||
public static final int RESET_REASON_CLIENT_RESET = 1 << 2;
|
||||
|
||||
private int reset = 0;
|
||||
|
||||
// Current instance of MediaCodec to "interrupt" on reset
|
||||
private MediaCodec runningMediaCodec;
|
||||
|
||||
public boolean consumeReset() {
|
||||
return reset.getAndSet(false);
|
||||
public synchronized boolean isResetRequested() {
|
||||
return reset != 0;
|
||||
}
|
||||
|
||||
public synchronized void reset() {
|
||||
reset.set(true);
|
||||
public synchronized int consumeReset() {
|
||||
int value = reset;
|
||||
reset = 0;
|
||||
return value;
|
||||
}
|
||||
|
||||
public synchronized void reset(int reason) {
|
||||
assert reason != 0;
|
||||
reset |= reason;
|
||||
if (runningMediaCodec != null) {
|
||||
try {
|
||||
runningMediaCodec.signalEndOfInputStream();
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ public class NewDisplayCapture extends SurfaceCapture {
|
|||
ServiceManager.getWindowManager().setDisplayImePolicy(virtualDisplayId, displayImePolicy);
|
||||
}
|
||||
|
||||
displayMonitor.start(virtualDisplayId, () -> getCaptureControl().reset());
|
||||
displayMonitor.start(virtualDisplayId, () -> getCaptureControl().reset(CaptureControl.RESET_REASON_DISPLAY_PROPERTIES_CHANGED));
|
||||
} catch (Exception e) {
|
||||
Ln.e("Could not create display", e);
|
||||
throw new AssertionError("Could not create display");
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ public class ScreenCapture extends SurfaceCapture {
|
|||
|
||||
@Override
|
||||
public void init() {
|
||||
displayMonitor.start(displayId, () -> getCaptureControl().reset());
|
||||
displayMonitor.start(displayId, () -> getCaptureControl().reset(CaptureControl.RESET_REASON_DISPLAY_PROPERTIES_CHANGED));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -97,7 +97,10 @@ public class SurfaceEncoder implements AsyncProcessor {
|
|||
streamer.writeVideoHeader();
|
||||
|
||||
do {
|
||||
captureControl.consumeReset(); // If a capture reset was requested, it is implicitly fulfilled
|
||||
int resetReasons = captureControl.consumeReset();
|
||||
if ((resetReasons & CaptureControl.RESET_REASON_TERMINATE) != 0) {
|
||||
break;
|
||||
}
|
||||
capture.prepare();
|
||||
Size size = capture.getSize();
|
||||
|
||||
|
|
@ -123,12 +126,12 @@ public class SurfaceEncoder implements AsyncProcessor {
|
|||
if (stopped.get()) {
|
||||
alive = false;
|
||||
} else {
|
||||
boolean resetRequested = captureControl.consumeReset();
|
||||
if (!resetRequested) {
|
||||
if (!captureControl.isResetRequested()) {
|
||||
// If a reset is requested during encode(), it will interrupt the encoding by an EOS
|
||||
streamer.writeSessionMeta(size.getWidth(), size.getHeight());
|
||||
encode(mediaCodec, streamer);
|
||||
}
|
||||
|
||||
// The capture might have been closed internally (for example if the camera is disconnected)
|
||||
alive = !stopped.get() && !capture.isClosed();
|
||||
}
|
||||
|
|
@ -275,7 +278,7 @@ public class SurfaceEncoder implements AsyncProcessor {
|
|||
public void stop() {
|
||||
if (thread != null) {
|
||||
stopped.set(true);
|
||||
captureControl.reset();
|
||||
captureControl.reset(CaptureControl.RESET_REASON_TERMINATE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue