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.
This commit is contained in:
Romain Vimont 2023-02-28 21:19:43 +01:00
parent 35689a73ab
commit f0f277ba71
7 changed files with 45 additions and 15 deletions

View file

@ -262,6 +262,10 @@ Supported names are currently "direct3d", "opengl", "opengles2", "opengles", "me
.UR https://wiki.libsdl.org/SDL_HINT_RENDER_DRIVER
.UE
.TP
.B \-\-require\-audio
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.
.TP
.BI "\-\-rotation " value
Set the initial display rotation. Possibles values are 0, 1, 2 and 3. Each increment adds a 90 degrees rotation counterclockwise.

View file

@ -69,6 +69,7 @@ enum {
OPT_AUDIO_ENCODER,
OPT_LIST_ENCODERS,
OPT_LIST_DISPLAYS,
OPT_REQUIRE_AUDIO,
};
struct sc_option {
@ -458,6 +459,13 @@ static const struct sc_option options[] = {
.longopt_id = OPT_RENDER_EXPIRED_FRAMES,
.longopt = "render-expired-frames",
},
{
.longopt_id = OPT_REQUIRE_AUDIO,
.longopt = "require-audio",
.text = "By default, scrcpy mirrors only the video when audio capture "
"fails on the device. This flag makes scrcpy fail if audio is "
"enabled but does not work."
},
{
.longopt_id = OPT_ROTATION,
.longopt = "rotation",
@ -1801,6 +1809,9 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
case OPT_LIST_DISPLAYS:
opts->list_displays = true;
break;
case OPT_REQUIRE_AUDIO:
opts->require_audio = true;
break;
default:
// getopt prints the error message on stderr
return false;

View file

@ -176,14 +176,13 @@ run_demuxer(void *data) {
struct sc_demuxer *demuxer = data;
// Flag to report end-of-stream (i.e. device disconnected)
bool eos = false;
enum sc_demuxer_status status = SC_DEMUXER_STATUS_ERROR;
uint32_t raw_codec_id;
bool ok = sc_demuxer_recv_codec_id(demuxer, &raw_codec_id);
if (!ok) {
LOGE("Demuxer '%s': stream disabled due to connection error",
demuxer->name);
eos = true;
goto end;
}
@ -191,7 +190,7 @@ run_demuxer(void *data) {
LOGW("Demuxer '%s': stream explicitly disabled by the device",
demuxer->name);
sc_demuxer_disable_sinks(demuxer);
eos = true;
status = SC_DEMUXER_STATUS_DISABLED;
goto end;
}
@ -241,7 +240,7 @@ run_demuxer(void *data) {
bool ok = sc_demuxer_recv_packet(demuxer, packet);
if (!ok) {
// end of stream
eos = true;
status = SC_DEMUXER_STATUS_EOS;
break;
}
@ -272,7 +271,7 @@ run_demuxer(void *data) {
finally_close_sinks:
sc_demuxer_close_sinks(demuxer);
end:
demuxer->cbs->on_ended(demuxer, eos, demuxer->cbs_userdata);
demuxer->cbs->on_ended(demuxer, status, demuxer->cbs_userdata);
return 0;
}

View file

@ -27,8 +27,15 @@ struct sc_demuxer {
void *cbs_userdata;
};
enum sc_demuxer_status {
SC_DEMUXER_STATUS_EOS,
SC_DEMUXER_STATUS_DISABLED,
SC_DEMUXER_STATUS_ERROR,
};
struct sc_demuxer_callbacks {
void (*on_ended)(struct sc_demuxer *demuxer, bool eos, void *userdata);
void (*on_ended)(struct sc_demuxer *demuxer, enum sc_demuxer_status,
void *userdata);
};
// The name must be statically allocated (e.g. a string literal)

View file

@ -72,6 +72,7 @@ const struct scrcpy_options scrcpy_options_default = {
.start_fps_counter = false,
.power_on = true,
.audio = true,
.require_audio = false,
.list_encoders = false,
.list_displays = false,
};

View file

@ -154,6 +154,7 @@ struct scrcpy_options {
bool start_fps_counter;
bool power_on;
bool audio;
bool require_audio;
bool list_encoders;
bool list_displays;
};

View file

@ -218,12 +218,15 @@ sc_recorder_on_ended(struct sc_recorder *recorder, bool success,
}
static void
sc_video_demuxer_on_ended(struct sc_demuxer *demuxer, bool eos,
void *userdata) {
sc_video_demuxer_on_ended(struct sc_demuxer *demuxer,
enum sc_demuxer_status status, void *userdata) {
(void) demuxer;
(void) userdata;
if (eos) {
// The device may not decide to disable the video
assert(status != SC_DEMUXER_STATUS_DISABLED);
if (status == SC_DEMUXER_STATUS_EOS) {
PUSH_EVENT(SC_EVENT_DEVICE_DISCONNECTED);
} else {
PUSH_EVENT(SC_EVENT_DEMUXER_ERROR);
@ -231,12 +234,14 @@ sc_video_demuxer_on_ended(struct sc_demuxer *demuxer, bool eos,
}
static void
sc_audio_demuxer_on_ended(struct sc_demuxer *demuxer, bool eos,
void *userdata) {
sc_audio_demuxer_on_ended(struct sc_demuxer *demuxer,
enum sc_demuxer_status status, void *userdata) {
(void) demuxer;
(void) userdata;
// Contrary to the video demuxer, keep mirroring if only the audio fails.
const struct scrcpy_options *options = userdata;
// Contrary to the video demuxer, keep mirroring if only the audio fails
// (unless --require-audio is set).
// 'eos' is true on end-of-stream, including when audio capture is not
// possible on the device (so that scrcpy continue to mirror video without
// failing).
@ -244,7 +249,9 @@ sc_audio_demuxer_on_ended(struct sc_demuxer *demuxer, bool eos,
// explicitly selected an unknown audio encoder), 'eos' is false and scrcpy
// must exit.
if (!eos) {
if (status == SC_DEMUXER_STATUS_ERROR
|| (status == SC_DEMUXER_STATUS_DISABLED
&& options->require_audio)) {
PUSH_EVENT(SC_EVENT_DEMUXER_ERROR);
}
}
@ -443,7 +450,7 @@ scrcpy(struct scrcpy_options *options) {
.on_ended = sc_audio_demuxer_on_ended,
};
sc_demuxer_init(&s->audio_demuxer, "audio", s->server.audio_socket,
&audio_demuxer_cbs, NULL);
&audio_demuxer_cbs, options);
}
bool needs_video_decoder = options->display;