Refactor CaptureReset into CaptureControl

Expose `CaptureControl` directly in `SurfaceCapture` to remove a layer
of indirection (`CaptureListener`).

This will make it easier to expose other methods without boilerplate.
This commit is contained in:
Romain Vimont 2026-04-11 16:29:37 +02:00
parent ac1ed420e4
commit 9d7fa2a7e6
7 changed files with 21 additions and 32 deletions

View file

@ -815,7 +815,7 @@ public class Controller implements AsyncProcessor, VirtualDisplayListener {
private void resetVideo() {
if (surfaceCapture != null) {
Ln.i("Video capture reset");
surfaceCapture.invalidate();
surfaceCapture.getCaptureControl().reset();
}
}
}

View file

@ -323,7 +323,7 @@ public class CameraCapture extends SurfaceCapture {
} catch (CameraAccessException e) {
Ln.e("Camera error", e);
disconnected.set(true);
invalidate();
getCaptureControl().reset();
}
}
@ -331,7 +331,7 @@ public class CameraCapture extends SurfaceCapture {
public void onConfigureFailed(CameraCaptureSession session) {
Ln.e("Camera configuration error");
disconnected.set(true);
invalidate();
getCaptureControl().reset();
}
});
@ -388,7 +388,7 @@ public class CameraCapture extends SurfaceCapture {
public void onDisconnected(CameraDevice camera) {
Ln.w("Camera disconnected");
disconnected.set(true);
invalidate();
getCaptureControl().reset();
}
@Override

View file

@ -4,7 +4,7 @@ import android.media.MediaCodec;
import java.util.concurrent.atomic.AtomicBoolean;
public class CaptureReset implements SurfaceCapture.CaptureListener {
public class CaptureControl {
private final AtomicBoolean reset = new AtomicBoolean();
@ -29,9 +29,4 @@ public class CaptureReset implements SurfaceCapture.CaptureListener {
public synchronized void setRunningMediaCodec(MediaCodec runningMediaCodec) {
this.runningMediaCodec = runningMediaCodec;
}
@Override
public void onInvalidated() {
reset();
}
}

View file

@ -201,7 +201,7 @@ public class NewDisplayCapture extends SurfaceCapture {
ServiceManager.getWindowManager().setDisplayImePolicy(virtualDisplayId, displayImePolicy);
}
displayMonitor.start(virtualDisplayId, this::invalidate);
displayMonitor.start(virtualDisplayId, () -> getCaptureControl().reset());
} catch (Exception e) {
Ln.e("Could not create display", e);
throw new AssertionError("Could not create display");

View file

@ -61,7 +61,7 @@ public class ScreenCapture extends SurfaceCapture {
@Override
public void init() {
displayMonitor.start(displayId, this::invalidate);
displayMonitor.start(displayId, () -> getCaptureControl().reset());
}
@Override

View file

@ -12,29 +12,23 @@ import java.io.IOException;
*/
public abstract class SurfaceCapture {
public interface CaptureListener {
void onInvalidated();
}
private CaptureListener listener;
private CaptureControl captureControl;
private VideoConstraints constraints;
/**
* Notify the listener that the capture has been invalidated (for example, because its size changed, or due to a manual user request).
*/
public void invalidate() {
listener.onInvalidated();
}
/**
* Called once before the first capture starts.
*/
public final void init(CaptureListener listener, VideoConstraints constraints) throws ConfigurationException, IOException {
this.listener = listener;
public final void init(CaptureControl captureControl, VideoConstraints constraints) throws ConfigurationException, IOException {
this.captureControl = captureControl;
this.constraints = constraints;
init();
}
public CaptureControl getCaptureControl() {
return captureControl;
}
/**
* Called once before the first capture starts.
*/

View file

@ -43,7 +43,7 @@ public class SurfaceEncoder implements AsyncProcessor {
private Thread thread;
private final AtomicBoolean stopped = new AtomicBoolean();
private final CaptureReset reset = new CaptureReset();
private final CaptureControl captureControl = new CaptureControl();
public SurfaceEncoder(SurfaceCapture capture, Streamer streamer, Options options) {
this.capture = capture;
@ -89,7 +89,7 @@ public class SurfaceEncoder implements AsyncProcessor {
assert caps != null; // caps cannot be null for a video codec
VideoConstraints constraints = createVideoConstraints(maxSize, minSizeAlignment, caps);
capture.init(reset, constraints);
capture.init(captureControl, constraints);
try {
boolean alive;
@ -97,7 +97,7 @@ public class SurfaceEncoder implements AsyncProcessor {
streamer.writeVideoHeader();
do {
reset.consumeReset(); // If a capture reset was requested, it is implicitly fulfilled
captureControl.consumeReset(); // If a capture reset was requested, it is implicitly fulfilled
capture.prepare();
Size size = capture.getSize();
@ -118,12 +118,12 @@ public class SurfaceEncoder implements AsyncProcessor {
mediaCodecStarted = true;
// Set the MediaCodec instance to "interrupt" (by signaling an EOS) on reset
reset.setRunningMediaCodec(mediaCodec);
captureControl.setRunningMediaCodec(mediaCodec);
if (stopped.get()) {
alive = false;
} else {
boolean resetRequested = reset.consumeReset();
boolean resetRequested = captureControl.consumeReset();
if (!resetRequested) {
// If a reset is requested during encode(), it will interrupt the encoding by an EOS
streamer.writeSessionMeta(size.getWidth(), size.getHeight());
@ -133,7 +133,7 @@ public class SurfaceEncoder implements AsyncProcessor {
alive = !stopped.get() && !capture.isClosed();
}
} finally {
reset.setRunningMediaCodec(null);
captureControl.setRunningMediaCodec(null);
if (captureStarted) {
capture.stop();
}
@ -275,7 +275,7 @@ public class SurfaceEncoder implements AsyncProcessor {
public void stop() {
if (thread != null) {
stopped.set(true);
reset.reset();
captureControl.reset();
}
}