diff --git a/server/src/main/java/com/genymobile/scrcpy/AsyncProcessor.java b/server/src/main/java/com/genymobile/scrcpy/AsyncProcessor.java new file mode 100644 index 00000000..cbc435b0 --- /dev/null +++ b/server/src/main/java/com/genymobile/scrcpy/AsyncProcessor.java @@ -0,0 +1,7 @@ +package com.genymobile.scrcpy; + +public interface AsyncProcessor { + void start(); + void stop(); + void join() throws InterruptedException; +} diff --git a/server/src/main/java/com/genymobile/scrcpy/AudioEncoder.java b/server/src/main/java/com/genymobile/scrcpy/AudioEncoder.java index 8b60d37e..0ba424ca 100644 --- a/server/src/main/java/com/genymobile/scrcpy/AudioEncoder.java +++ b/server/src/main/java/com/genymobile/scrcpy/AudioEncoder.java @@ -14,7 +14,7 @@ import java.util.List; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; -public final class AudioEncoder { +public final class AudioEncoder implements AsyncProcessor { private static class InputTask { private final int index; diff --git a/server/src/main/java/com/genymobile/scrcpy/Controller.java b/server/src/main/java/com/genymobile/scrcpy/Controller.java index 02d77cb1..59fae602 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Controller.java +++ b/server/src/main/java/com/genymobile/scrcpy/Controller.java @@ -14,7 +14,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -public class Controller { +public class Controller implements AsyncProcessor { private static final int DEFAULT_DEVICE_ID = 0; diff --git a/server/src/main/java/com/genymobile/scrcpy/Server.java b/server/src/main/java/com/genymobile/scrcpy/Server.java index 35da6965..3d3e02fd 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Server.java +++ b/server/src/main/java/com/genymobile/scrcpy/Server.java @@ -5,6 +5,7 @@ import android.os.BatteryManager; import android.os.Build; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -91,8 +92,7 @@ public final class Server { Workarounds.fillAppInfo(); } - Controller controller = null; - AudioEncoder audioEncoder = null; + List asyncProcessors = new ArrayList<>(); try (DesktopConnection connection = DesktopConnection.open(scid, tunnelForward, audio, control, sendDummyByte)) { if (options.getSendDeviceMeta()) { @@ -101,24 +101,27 @@ public final class Server { } if (control) { - controller = new Controller(device, connection, options.getClipboardAutosync(), options.getPowerOn()); - controller.start(); - - final Controller controllerRef = controller; - device.setClipboardListener(text -> controllerRef.getSender().pushClipboardText(text)); + Controller controller = new Controller(device, connection, options.getClipboardAutosync(), options.getPowerOn()); + device.setClipboardListener(text -> controller.getSender().pushClipboardText(text)); + asyncProcessors.add(controller); } if (audio) { Streamer audioStreamer = new Streamer(connection.getAudioFd(), options.getAudioCodec(), options.getSendCodecId(), options.getSendFrameMeta()); - audioEncoder = new AudioEncoder(audioStreamer, options.getAudioBitRate(), options.getAudioCodecOptions(), options.getAudioEncoder()); - audioEncoder.start(); + AudioEncoder audioRecorder = new AudioEncoder(audioStreamer, options.getAudioBitRate(), options.getAudioCodecOptions(), options.getAudioEncoder()); + asyncProcessors.add(audioRecorder); } Streamer videoStreamer = new Streamer(connection.getVideoFd(), options.getVideoCodec(), options.getSendCodecId(), options.getSendFrameMeta()); ScreenEncoder screenEncoder = new ScreenEncoder(device, videoStreamer, options.getVideoBitRate(), options.getMaxFps(), options.getVideoCodecOptions(), options.getVideoEncoder(), options.getDownsizeOnError()); + + for (AsyncProcessor asyncProcessor : asyncProcessors) { + asyncProcessor.start(); + } + try { // synchronous screenEncoder.streamScreen(); @@ -131,20 +134,14 @@ public final class Server { } finally { Ln.d("Screen streaming stopped"); initThread.interrupt(); - if (audioEncoder != null) { - audioEncoder.stop(); - } - if (controller != null) { - controller.stop(); + for (AsyncProcessor asyncProcessor : asyncProcessors) { + asyncProcessor.stop(); } try { initThread.join(); - if (audioEncoder != null) { - audioEncoder.join(); - } - if (controller != null) { - controller.join(); + for (AsyncProcessor asyncProcessor : asyncProcessors) { + asyncProcessor.join(); } } catch (InterruptedException e) { // ignore