mirror of
https://github.com/Genymobile/scrcpy.git
synced 2025-12-17 21:44:20 +01:00
Add --audio-dup
Add an option to duplicate audio on the device, compatible with the new audio playback capture (--audio-source=playback). Fixes #3875 <https://github.com/Genymobile/scrcpy/issues/3875> Fixes #4380 <https://github.com/Genymobile/scrcpy/issues/4380> PR #5102 <https://github.com/Genymobile/scrcpy/pull/5102> Co-authored-by: Simon Chan <1330321+yume-chan@users.noreply.github.com>
This commit is contained in:
@@ -26,6 +26,7 @@ public class Options {
|
||||
private AudioCodec audioCodec = AudioCodec.OPUS;
|
||||
private VideoSource videoSource = VideoSource.DISPLAY;
|
||||
private AudioSource audioSource = AudioSource.OUTPUT;
|
||||
private boolean audioDup;
|
||||
private int videoBitRate = 8000000;
|
||||
private int audioBitRate = 128000;
|
||||
private int maxFps;
|
||||
@@ -100,6 +101,10 @@ public class Options {
|
||||
return audioSource;
|
||||
}
|
||||
|
||||
public boolean getAudioDup() {
|
||||
return audioDup;
|
||||
}
|
||||
|
||||
public int getVideoBitRate() {
|
||||
return videoBitRate;
|
||||
}
|
||||
@@ -303,6 +308,9 @@ public class Options {
|
||||
}
|
||||
options.audioSource = audioSource;
|
||||
break;
|
||||
case "audio_dup":
|
||||
options.audioDup = Boolean.parseBoolean(value);
|
||||
break;
|
||||
case "max_size":
|
||||
options.maxSize = Integer.parseInt(value) & ~7; // multiple of 8
|
||||
break;
|
||||
|
||||
@@ -167,7 +167,13 @@ public final class Server {
|
||||
if (audio) {
|
||||
AudioCodec audioCodec = options.getAudioCodec();
|
||||
AudioSource audioSource = options.getAudioSource();
|
||||
AudioCapture audioCapture = audioSource.isDirect() ? new AudioDirectCapture(audioSource) : new AudioPlaybackCapture();
|
||||
AudioCapture audioCapture;
|
||||
if (audioSource.isDirect()) {
|
||||
audioCapture = new AudioDirectCapture(audioSource);
|
||||
} else {
|
||||
audioCapture = new AudioPlaybackCapture(options.getAudioDup());
|
||||
}
|
||||
|
||||
Streamer audioStreamer = new Streamer(connection.getAudioFd(), audioCodec, options.getSendCodecMeta(), options.getSendFrameMeta());
|
||||
AsyncProcessor audioRecorder;
|
||||
if (audioCodec == AudioCodec.RAW) {
|
||||
|
||||
@@ -18,9 +18,15 @@ import java.nio.ByteBuffer;
|
||||
|
||||
public final class AudioPlaybackCapture implements AudioCapture {
|
||||
|
||||
private final boolean keepPlayingOnDevice;
|
||||
|
||||
private AudioRecord recorder;
|
||||
private AudioRecordReader reader;
|
||||
|
||||
public AudioPlaybackCapture(boolean keepPlayingOnDevice) {
|
||||
this.keepPlayingOnDevice = keepPlayingOnDevice;
|
||||
}
|
||||
|
||||
@SuppressLint("PrivateApi")
|
||||
private AudioRecord createAudioRecord() throws AudioCaptureException {
|
||||
// See <https://github.com/Genymobile/scrcpy/issues/4380>
|
||||
@@ -60,7 +66,8 @@ public final class AudioPlaybackCapture implements AudioCapture {
|
||||
Method setFormat = audioMixBuilder.getClass().getMethod("setFormat", AudioFormat.class);
|
||||
setFormat.invoke(audioMixBuilder, AudioConfig.createAudioFormat());
|
||||
|
||||
int routeFlags = audioMixClass.getField("ROUTE_FLAG_LOOP_BACK").getInt(null);
|
||||
String routeFlagName = keepPlayingOnDevice ? "ROUTE_FLAG_LOOP_BACK_RENDER" : "ROUTE_FLAG_LOOP_BACK";
|
||||
int routeFlags = audioMixClass.getField(routeFlagName).getInt(null);
|
||||
|
||||
// audioMixBuilder.setRouteFlags(routeFlag);
|
||||
Method setRouteFlags = audioMixBuilder.getClass().getMethod("setRouteFlags", int.class);
|
||||
|
||||
Reference in New Issue
Block a user