From dc228eaad0ea53f57c27e9aba2b51a422ed3aa94 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Fri, 3 Mar 2023 18:49:05 +0100 Subject: [PATCH] Extract async processor interface On the server side, several components are started, stopped and joined. Extract an interface to handle them generically. This will help to support both encoded and raw audio stream, because they will be two different concrete components, but implementing the same interface. PR #3757 --- .../com/genymobile/scrcpy/AsyncProcessor.java | 7 ++++ .../com/genymobile/scrcpy/AudioEncoder.java | 2 +- .../com/genymobile/scrcpy/Controller.java | 2 +- .../java/com/genymobile/scrcpy/Server.java | 35 +++++++++---------- 4 files changed, 25 insertions(+), 21 deletions(-) create mode 100644 server/src/main/java/com/genymobile/scrcpy/AsyncProcessor.java 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