Skip to content

Commit a8895b0

Browse files
committed
Add --require-audio
By default, scrcpy mirrors only the video when audio capture fails on the device. Add a flag to force scrcpy to fail if audio is enabled but does not work. PR #3757 <Genymobile/scrcpy#3757>
1 parent 427245e commit a8895b0

File tree

9 files changed

+47
-15
lines changed

9 files changed

+47
-15
lines changed

app/data/bash-completion/scrcpy

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ _scrcpy() {
4545
-r --record=
4646
--record-format=
4747
--render-driver=
48+
--require-audio
4849
--rotation=
4950
-s --serial=
5051
--shortcut-mod=

app/data/zsh-completion/_scrcpy

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ arguments=(
5151
{-r,--record=}'[Record screen to file]:record file:_files'
5252
'--record-format=[Force recording format]:format:(mp4 mkv)'
5353
'--render-driver=[Request SDL to use the given render driver]:driver name:(direct3d opengl opengles2 opengles metal software)'
54+
'--require-audio=[Make scrcpy fail if audio is enabled but does not work]'
5455
'--rotation=[Set the initial display rotation]:rotation values:(0 1 2 3)'
5556
{-s,--serial=}'[The device serial number \(mandatory for multiple devices only\)]:serial:($("${ADB-adb}" devices | awk '\''$2 == "device" {print $1}'\''))'
5657
'--shortcut-mod=[\[key1,key2+key3,...\] Specify the modifiers to use for scrcpy shortcuts]:shortcut mod:(lctrl rctrl lalt ralt lsuper rsuper)'

app/scrcpy.1

+4
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,10 @@ Supported names are currently "direct3d", "opengl", "opengles2", "opengles", "me
262262
.UR https://wiki.libsdl.org/SDL_HINT_RENDER_DRIVER
263263
.UE
264264

265+
.TP
266+
.B \-\-require\-audio
267+
By default, scrcpy mirrors only the video if audio capture fails on the device. This flag makes scrcpy fail if audio is enabled but does not work.
268+
265269
.TP
266270
.BI "\-\-rotation " value
267271
Set the initial display rotation. Possibles values are 0, 1, 2 and 3. Each increment adds a 90 degrees rotation counterclockwise.

app/src/cli.c

+11
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ enum {
6969
OPT_AUDIO_ENCODER,
7070
OPT_LIST_ENCODERS,
7171
OPT_LIST_DISPLAYS,
72+
OPT_REQUIRE_AUDIO,
7273
};
7374

7475
struct sc_option {
@@ -458,6 +459,13 @@ static const struct sc_option options[] = {
458459
.longopt_id = OPT_RENDER_EXPIRED_FRAMES,
459460
.longopt = "render-expired-frames",
460461
},
462+
{
463+
.longopt_id = OPT_REQUIRE_AUDIO,
464+
.longopt = "require-audio",
465+
.text = "By default, scrcpy mirrors only the video when audio capture "
466+
"fails on the device. This flag makes scrcpy fail if audio is "
467+
"enabled but does not work."
468+
},
461469
{
462470
.longopt_id = OPT_ROTATION,
463471
.longopt = "rotation",
@@ -1801,6 +1809,9 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
18011809
case OPT_LIST_DISPLAYS:
18021810
opts->list_displays = true;
18031811
break;
1812+
case OPT_REQUIRE_AUDIO:
1813+
opts->require_audio = true;
1814+
break;
18041815
default:
18051816
// getopt prints the error message on stderr
18061817
return false;

app/src/demuxer.c

+4-5
Original file line numberDiff line numberDiff line change
@@ -176,22 +176,21 @@ run_demuxer(void *data) {
176176
struct sc_demuxer *demuxer = data;
177177

178178
// Flag to report end-of-stream (i.e. device disconnected)
179-
bool eos = false;
179+
enum sc_demuxer_status status = SC_DEMUXER_STATUS_ERROR;
180180

181181
uint32_t raw_codec_id;
182182
bool ok = sc_demuxer_recv_codec_id(demuxer, &raw_codec_id);
183183
if (!ok) {
184184
LOGE("Demuxer '%s': stream disabled due to connection error",
185185
demuxer->name);
186-
eos = true;
187186
goto end;
188187
}
189188

190189
if (raw_codec_id == 0) {
191190
LOGW("Demuxer '%s': stream explicitly disabled by the device",
192191
demuxer->name);
193192
sc_demuxer_disable_sinks(demuxer);
194-
eos = true;
193+
status = SC_DEMUXER_STATUS_DISABLED;
195194
goto end;
196195
}
197196

@@ -241,7 +240,7 @@ run_demuxer(void *data) {
241240
bool ok = sc_demuxer_recv_packet(demuxer, packet);
242241
if (!ok) {
243242
// end of stream
244-
eos = true;
243+
status = SC_DEMUXER_STATUS_EOS;
245244
break;
246245
}
247246

@@ -272,7 +271,7 @@ run_demuxer(void *data) {
272271
finally_close_sinks:
273272
sc_demuxer_close_sinks(demuxer);
274273
end:
275-
demuxer->cbs->on_ended(demuxer, eos, demuxer->cbs_userdata);
274+
demuxer->cbs->on_ended(demuxer, status, demuxer->cbs_userdata);
276275

277276
return 0;
278277
}

app/src/demuxer.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,15 @@ struct sc_demuxer {
2727
void *cbs_userdata;
2828
};
2929

30+
enum sc_demuxer_status {
31+
SC_DEMUXER_STATUS_EOS,
32+
SC_DEMUXER_STATUS_DISABLED,
33+
SC_DEMUXER_STATUS_ERROR,
34+
};
35+
3036
struct sc_demuxer_callbacks {
31-
void (*on_ended)(struct sc_demuxer *demuxer, bool eos, void *userdata);
37+
void (*on_ended)(struct sc_demuxer *demuxer, enum sc_demuxer_status,
38+
void *userdata);
3239
};
3340

3441
// The name must be statically allocated (e.g. a string literal)

app/src/options.c

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ const struct scrcpy_options scrcpy_options_default = {
7272
.start_fps_counter = false,
7373
.power_on = true,
7474
.audio = true,
75+
.require_audio = false,
7576
.list_encoders = false,
7677
.list_displays = false,
7778
};

app/src/options.h

+1
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ struct scrcpy_options {
154154
bool start_fps_counter;
155155
bool power_on;
156156
bool audio;
157+
bool require_audio;
157158
bool list_encoders;
158159
bool list_displays;
159160
};

app/src/scrcpy.c

+16-9
Original file line numberDiff line numberDiff line change
@@ -218,33 +218,40 @@ sc_recorder_on_ended(struct sc_recorder *recorder, bool success,
218218
}
219219

220220
static void
221-
sc_video_demuxer_on_ended(struct sc_demuxer *demuxer, bool eos,
222-
void *userdata) {
221+
sc_video_demuxer_on_ended(struct sc_demuxer *demuxer,
222+
enum sc_demuxer_status status, void *userdata) {
223223
(void) demuxer;
224224
(void) userdata;
225225

226-
if (eos) {
226+
// The device may not decide to disable the video
227+
assert(status != SC_DEMUXER_STATUS_DISABLED);
228+
229+
if (status == SC_DEMUXER_STATUS_EOS) {
227230
PUSH_EVENT(SC_EVENT_DEVICE_DISCONNECTED);
228231
} else {
229232
PUSH_EVENT(SC_EVENT_DEMUXER_ERROR);
230233
}
231234
}
232235

233236
static void
234-
sc_audio_demuxer_on_ended(struct sc_demuxer *demuxer, bool eos,
235-
void *userdata) {
237+
sc_audio_demuxer_on_ended(struct sc_demuxer *demuxer,
238+
enum sc_demuxer_status status, void *userdata) {
236239
(void) demuxer;
237-
(void) userdata;
238240

239-
// Contrary to the video demuxer, keep mirroring if only the audio fails.
241+
const struct scrcpy_options *options = userdata;
242+
243+
// Contrary to the video demuxer, keep mirroring if only the audio fails
244+
// (unless --require-audio is set).
240245
// 'eos' is true on end-of-stream, including when audio capture is not
241246
// possible on the device (so that scrcpy continue to mirror video without
242247
// failing).
243248
// However, if an audio configuration failure occurs (for example the user
244249
// explicitly selected an unknown audio encoder), 'eos' is false and scrcpy
245250
// must exit.
246251

247-
if (!eos) {
252+
if (status == SC_DEMUXER_STATUS_ERROR
253+
|| (status == SC_DEMUXER_STATUS_DISABLED
254+
&& options->require_audio)) {
248255
PUSH_EVENT(SC_EVENT_DEMUXER_ERROR);
249256
}
250257
}
@@ -443,7 +450,7 @@ scrcpy(struct scrcpy_options *options) {
443450
.on_ended = sc_audio_demuxer_on_ended,
444451
};
445452
sc_demuxer_init(&s->audio_demuxer, "audio", s->server.audio_socket,
446-
&audio_demuxer_cbs, NULL);
453+
&audio_demuxer_cbs, options);
447454
}
448455

449456
bool needs_video_decoder = options->display;

0 commit comments

Comments
 (0)