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 <https://github.com/Genymobile/scrcpy/pull/3757>
This commit is contained in:
Romain Vimont 2023-03-03 18:49:05 +01:00
parent 65cc9d765d
commit dc228eaad0
4 changed files with 25 additions and 21 deletions

View file

@ -0,0 +1,7 @@
package com.genymobile.scrcpy;
public interface AsyncProcessor {
void start();
void stop();
void join() throws InterruptedException;
}

View file

@ -14,7 +14,7 @@ import java.util.List;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
public final class AudioEncoder { public final class AudioEncoder implements AsyncProcessor {
private static class InputTask { private static class InputTask {
private final int index; private final int index;

View file

@ -14,7 +14,7 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class Controller { public class Controller implements AsyncProcessor {
private static final int DEFAULT_DEVICE_ID = 0; private static final int DEFAULT_DEVICE_ID = 0;

View file

@ -5,6 +5,7 @@ import android.os.BatteryManager;
import android.os.Build; import android.os.Build;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -91,8 +92,7 @@ public final class Server {
Workarounds.fillAppInfo(); Workarounds.fillAppInfo();
} }
Controller controller = null; List<AsyncProcessor> asyncProcessors = new ArrayList<>();
AudioEncoder audioEncoder = null;
try (DesktopConnection connection = DesktopConnection.open(scid, tunnelForward, audio, control, sendDummyByte)) { try (DesktopConnection connection = DesktopConnection.open(scid, tunnelForward, audio, control, sendDummyByte)) {
if (options.getSendDeviceMeta()) { if (options.getSendDeviceMeta()) {
@ -101,24 +101,27 @@ public final class Server {
} }
if (control) { if (control) {
controller = new Controller(device, connection, options.getClipboardAutosync(), options.getPowerOn()); Controller controller = new Controller(device, connection, options.getClipboardAutosync(), options.getPowerOn());
controller.start(); device.setClipboardListener(text -> controller.getSender().pushClipboardText(text));
asyncProcessors.add(controller);
final Controller controllerRef = controller;
device.setClipboardListener(text -> controllerRef.getSender().pushClipboardText(text));
} }
if (audio) { if (audio) {
Streamer audioStreamer = new Streamer(connection.getAudioFd(), options.getAudioCodec(), options.getSendCodecId(), Streamer audioStreamer = new Streamer(connection.getAudioFd(), options.getAudioCodec(), options.getSendCodecId(),
options.getSendFrameMeta()); options.getSendFrameMeta());
audioEncoder = new AudioEncoder(audioStreamer, options.getAudioBitRate(), options.getAudioCodecOptions(), options.getAudioEncoder()); AudioEncoder audioRecorder = new AudioEncoder(audioStreamer, options.getAudioBitRate(), options.getAudioCodecOptions(), options.getAudioEncoder());
audioEncoder.start(); asyncProcessors.add(audioRecorder);
} }
Streamer videoStreamer = new Streamer(connection.getVideoFd(), options.getVideoCodec(), options.getSendCodecId(), Streamer videoStreamer = new Streamer(connection.getVideoFd(), options.getVideoCodec(), options.getSendCodecId(),
options.getSendFrameMeta()); options.getSendFrameMeta());
ScreenEncoder screenEncoder = new ScreenEncoder(device, videoStreamer, options.getVideoBitRate(), options.getMaxFps(), ScreenEncoder screenEncoder = new ScreenEncoder(device, videoStreamer, options.getVideoBitRate(), options.getMaxFps(),
options.getVideoCodecOptions(), options.getVideoEncoder(), options.getDownsizeOnError()); options.getVideoCodecOptions(), options.getVideoEncoder(), options.getDownsizeOnError());
for (AsyncProcessor asyncProcessor : asyncProcessors) {
asyncProcessor.start();
}
try { try {
// synchronous // synchronous
screenEncoder.streamScreen(); screenEncoder.streamScreen();
@ -131,20 +134,14 @@ public final class Server {
} finally { } finally {
Ln.d("Screen streaming stopped"); Ln.d("Screen streaming stopped");
initThread.interrupt(); initThread.interrupt();
if (audioEncoder != null) { for (AsyncProcessor asyncProcessor : asyncProcessors) {
audioEncoder.stop(); asyncProcessor.stop();
}
if (controller != null) {
controller.stop();
} }
try { try {
initThread.join(); initThread.join();
if (audioEncoder != null) { for (AsyncProcessor asyncProcessor : asyncProcessors) {
audioEncoder.join(); asyncProcessor.join();
}
if (controller != null) {
controller.join();
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
// ignore // ignore