Compare commits
1 Commits
fix_audio_
...
no_kill_ad
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbeb53009a |
@@ -77,6 +77,7 @@ enum {
|
||||
OPT_NO_AUDIO_PLAYBACK,
|
||||
OPT_NO_VIDEO_PLAYBACK,
|
||||
OPT_AUDIO_SOURCE,
|
||||
OPT_NO_KILL_ADB_BEFORE_OTG,
|
||||
};
|
||||
|
||||
struct sc_option {
|
||||
@@ -411,6 +412,16 @@ static const struct sc_option options[] = {
|
||||
.longopt = "no-key-repeat",
|
||||
.text = "Do not forward repeated key events when a key is held down.",
|
||||
},
|
||||
{
|
||||
.longopt_id = OPT_NO_KILL_ADB_BEFORE_OTG,
|
||||
.longopt = "no-kill-adb-before-otg",
|
||||
// with .text, the option is not documented on other platforms
|
||||
#ifdef _WIN32
|
||||
.text = "By default, scrcpy kills the adb daemon on Windows if --otg "
|
||||
"is specified.\n"
|
||||
"This option avoids to kill the adb daemon.",
|
||||
#endif
|
||||
},
|
||||
{
|
||||
.longopt_id = OPT_NO_MIPMAPS,
|
||||
.longopt = "no-mipmaps",
|
||||
@@ -1944,6 +1955,14 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case OPT_NO_KILL_ADB_BEFORE_OTG:
|
||||
#ifdef _WIN32
|
||||
opts->kill_adb_before_otg = false;
|
||||
break;
|
||||
#else
|
||||
LOGE("--no-kill-adb-before-otg only exists on Windows.");
|
||||
return false;
|
||||
#endif
|
||||
default:
|
||||
// getopt prints the error message on stderr
|
||||
return false;
|
||||
|
||||
@@ -48,6 +48,9 @@ const struct scrcpy_options scrcpy_options_default = {
|
||||
#endif
|
||||
#ifdef HAVE_USB
|
||||
.otg = false,
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
.kill_adb_before_otg = true,
|
||||
#endif
|
||||
.show_touches = false,
|
||||
.fullscreen = false,
|
||||
|
||||
@@ -148,6 +148,9 @@ struct scrcpy_options {
|
||||
#endif
|
||||
#ifdef HAVE_USB
|
||||
bool otg;
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
bool kill_adb_before_otg;
|
||||
#endif
|
||||
bool show_touches;
|
||||
bool fullscreen;
|
||||
|
||||
@@ -96,29 +96,23 @@ sc_recorder_rescale_packet(AVStream *stream, AVPacket *packet) {
|
||||
}
|
||||
|
||||
static bool
|
||||
sc_recorder_write_stream(struct sc_recorder *recorder,
|
||||
struct sc_recorder_stream *st, AVPacket *packet) {
|
||||
AVStream *stream = recorder->ctx->streams[st->index];
|
||||
sc_recorder_write_stream(struct sc_recorder *recorder, int stream_index,
|
||||
AVPacket *packet) {
|
||||
AVStream *stream = recorder->ctx->streams[stream_index];
|
||||
sc_recorder_rescale_packet(stream, packet);
|
||||
if (st->last_pts != AV_NOPTS_VALUE && packet->pts <= st->last_pts) {
|
||||
LOGW("Fixing PTS non monotonically increasing "
|
||||
"(%" PRIi64 " >= %" PRIi64 ")", st->last_pts, packet->pts);
|
||||
packet->pts = ++st->last_pts;
|
||||
packet->dts = packet->pts;
|
||||
} else {
|
||||
st->last_pts = packet->pts;
|
||||
}
|
||||
return av_interleaved_write_frame(recorder->ctx, packet) >= 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
sc_recorder_write_video(struct sc_recorder *recorder, AVPacket *packet) {
|
||||
return sc_recorder_write_stream(recorder, &recorder->video_stream, packet);
|
||||
return sc_recorder_write_stream(recorder, recorder->video_stream_index,
|
||||
packet);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
sc_recorder_write_audio(struct sc_recorder *recorder, AVPacket *packet) {
|
||||
return sc_recorder_write_stream(recorder, &recorder->audio_stream, packet);
|
||||
return sc_recorder_write_stream(recorder, recorder->audio_stream_index,
|
||||
packet);
|
||||
}
|
||||
|
||||
static bool
|
||||
@@ -184,11 +178,10 @@ static bool
|
||||
sc_recorder_process_header(struct sc_recorder *recorder) {
|
||||
sc_mutex_lock(&recorder->mutex);
|
||||
|
||||
while (!recorder->stopped &&
|
||||
((recorder->video && !recorder->video_init)
|
||||
|| (recorder->audio && !recorder->audio_init)
|
||||
|| sc_recorder_has_empty_queues(recorder))) {
|
||||
sc_cond_wait(&recorder->cond, &recorder->mutex);
|
||||
while (!recorder->stopped && (!recorder->video_init
|
||||
|| !recorder->audio_init
|
||||
|| sc_recorder_has_empty_queues(recorder))) {
|
||||
sc_cond_wait(&recorder->stream_cond, &recorder->mutex);
|
||||
}
|
||||
|
||||
if (recorder->video && sc_vecdeque_is_empty(&recorder->video_queue)) {
|
||||
@@ -221,9 +214,9 @@ sc_recorder_process_header(struct sc_recorder *recorder) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
assert(recorder->video_stream.index >= 0);
|
||||
assert(recorder->video_stream_index >= 0);
|
||||
AVStream *video_stream =
|
||||
recorder->ctx->streams[recorder->video_stream.index];
|
||||
recorder->ctx->streams[recorder->video_stream_index];
|
||||
bool ok = sc_recorder_set_extradata(video_stream, video_pkt);
|
||||
if (!ok) {
|
||||
goto end;
|
||||
@@ -236,9 +229,9 @@ sc_recorder_process_header(struct sc_recorder *recorder) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
assert(recorder->audio_stream.index >= 0);
|
||||
assert(recorder->audio_stream_index >= 0);
|
||||
AVStream *audio_stream =
|
||||
recorder->ctx->streams[recorder->audio_stream.index];
|
||||
recorder->ctx->streams[recorder->audio_stream_index];
|
||||
bool ok = sc_recorder_set_extradata(audio_stream, audio_pkt);
|
||||
if (!ok) {
|
||||
goto end;
|
||||
@@ -296,7 +289,7 @@ sc_recorder_process_packets(struct sc_recorder *recorder) {
|
||||
// A new packet may be assigned to audio_pkt and be processed
|
||||
break;
|
||||
}
|
||||
sc_cond_wait(&recorder->cond, &recorder->mutex);
|
||||
sc_cond_wait(&recorder->queue_cond, &recorder->mutex);
|
||||
}
|
||||
|
||||
// If stopped is set, continue to process the remaining events (to
|
||||
@@ -511,10 +504,10 @@ sc_recorder_video_packet_sink_open(struct sc_packet_sink *sink,
|
||||
return false;
|
||||
}
|
||||
|
||||
recorder->video_stream.index = stream->index;
|
||||
recorder->video_stream_index = stream->index;
|
||||
|
||||
recorder->video_init = true;
|
||||
sc_cond_signal(&recorder->cond);
|
||||
sc_cond_signal(&recorder->stream_cond);
|
||||
sc_mutex_unlock(&recorder->mutex);
|
||||
|
||||
return true;
|
||||
@@ -529,7 +522,7 @@ sc_recorder_video_packet_sink_close(struct sc_packet_sink *sink) {
|
||||
sc_mutex_lock(&recorder->mutex);
|
||||
// EOS also stops the recorder
|
||||
recorder->stopped = true;
|
||||
sc_cond_signal(&recorder->cond);
|
||||
sc_cond_signal(&recorder->queue_cond);
|
||||
sc_mutex_unlock(&recorder->mutex);
|
||||
}
|
||||
|
||||
@@ -555,7 +548,7 @@ sc_recorder_video_packet_sink_push(struct sc_packet_sink *sink,
|
||||
return false;
|
||||
}
|
||||
|
||||
rec->stream_index = recorder->video_stream.index;
|
||||
rec->stream_index = recorder->video_stream_index;
|
||||
|
||||
bool ok = sc_vecdeque_push(&recorder->video_queue, rec);
|
||||
if (!ok) {
|
||||
@@ -564,7 +557,7 @@ sc_recorder_video_packet_sink_push(struct sc_packet_sink *sink,
|
||||
return false;
|
||||
}
|
||||
|
||||
sc_cond_signal(&recorder->cond);
|
||||
sc_cond_signal(&recorder->queue_cond);
|
||||
|
||||
sc_mutex_unlock(&recorder->mutex);
|
||||
return true;
|
||||
@@ -592,10 +585,10 @@ sc_recorder_audio_packet_sink_open(struct sc_packet_sink *sink,
|
||||
return false;
|
||||
}
|
||||
|
||||
recorder->audio_stream.index = stream->index;
|
||||
recorder->audio_stream_index = stream->index;
|
||||
|
||||
recorder->audio_init = true;
|
||||
sc_cond_signal(&recorder->cond);
|
||||
sc_cond_signal(&recorder->stream_cond);
|
||||
sc_mutex_unlock(&recorder->mutex);
|
||||
|
||||
return true;
|
||||
@@ -611,7 +604,7 @@ sc_recorder_audio_packet_sink_close(struct sc_packet_sink *sink) {
|
||||
sc_mutex_lock(&recorder->mutex);
|
||||
// EOS also stops the recorder
|
||||
recorder->stopped = true;
|
||||
sc_cond_signal(&recorder->cond);
|
||||
sc_cond_signal(&recorder->queue_cond);
|
||||
sc_mutex_unlock(&recorder->mutex);
|
||||
}
|
||||
|
||||
@@ -638,7 +631,7 @@ sc_recorder_audio_packet_sink_push(struct sc_packet_sink *sink,
|
||||
return false;
|
||||
}
|
||||
|
||||
rec->stream_index = recorder->audio_stream.index;
|
||||
rec->stream_index = recorder->audio_stream_index;
|
||||
|
||||
bool ok = sc_vecdeque_push(&recorder->audio_queue, rec);
|
||||
if (!ok) {
|
||||
@@ -647,7 +640,7 @@ sc_recorder_audio_packet_sink_push(struct sc_packet_sink *sink,
|
||||
return false;
|
||||
}
|
||||
|
||||
sc_cond_signal(&recorder->cond);
|
||||
sc_cond_signal(&recorder->queue_cond);
|
||||
|
||||
sc_mutex_unlock(&recorder->mutex);
|
||||
return true;
|
||||
@@ -665,16 +658,10 @@ sc_recorder_audio_packet_sink_disable(struct sc_packet_sink *sink) {
|
||||
sc_mutex_lock(&recorder->mutex);
|
||||
recorder->audio = false;
|
||||
recorder->audio_init = true;
|
||||
sc_cond_signal(&recorder->cond);
|
||||
sc_cond_signal(&recorder->stream_cond);
|
||||
sc_mutex_unlock(&recorder->mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
sc_recorder_stream_init(struct sc_recorder_stream *stream) {
|
||||
stream->index = -1;
|
||||
stream->last_pts = AV_NOPTS_VALUE;
|
||||
}
|
||||
|
||||
bool
|
||||
sc_recorder_init(struct sc_recorder *recorder, const char *filename,
|
||||
enum sc_record_format format, bool video, bool audio,
|
||||
@@ -690,11 +677,16 @@ sc_recorder_init(struct sc_recorder *recorder, const char *filename,
|
||||
goto error_free_filename;
|
||||
}
|
||||
|
||||
ok = sc_cond_init(&recorder->cond);
|
||||
ok = sc_cond_init(&recorder->queue_cond);
|
||||
if (!ok) {
|
||||
goto error_mutex_destroy;
|
||||
}
|
||||
|
||||
ok = sc_cond_init(&recorder->stream_cond);
|
||||
if (!ok) {
|
||||
goto error_queue_cond_destroy;
|
||||
}
|
||||
|
||||
assert(video || audio);
|
||||
recorder->video = video;
|
||||
recorder->audio = audio;
|
||||
@@ -706,8 +698,8 @@ sc_recorder_init(struct sc_recorder *recorder, const char *filename,
|
||||
recorder->video_init = false;
|
||||
recorder->audio_init = false;
|
||||
|
||||
sc_recorder_stream_init(&recorder->video_stream);
|
||||
sc_recorder_stream_init(&recorder->audio_stream);
|
||||
recorder->video_stream_index = -1;
|
||||
recorder->audio_stream_index = -1;
|
||||
|
||||
recorder->format = format;
|
||||
|
||||
@@ -738,6 +730,8 @@ sc_recorder_init(struct sc_recorder *recorder, const char *filename,
|
||||
|
||||
return true;
|
||||
|
||||
error_queue_cond_destroy:
|
||||
sc_cond_destroy(&recorder->queue_cond);
|
||||
error_mutex_destroy:
|
||||
sc_mutex_destroy(&recorder->mutex);
|
||||
error_free_filename:
|
||||
@@ -762,7 +756,8 @@ void
|
||||
sc_recorder_stop(struct sc_recorder *recorder) {
|
||||
sc_mutex_lock(&recorder->mutex);
|
||||
recorder->stopped = true;
|
||||
sc_cond_signal(&recorder->cond);
|
||||
sc_cond_signal(&recorder->queue_cond);
|
||||
sc_cond_signal(&recorder->stream_cond);
|
||||
sc_mutex_unlock(&recorder->mutex);
|
||||
}
|
||||
|
||||
@@ -773,7 +768,8 @@ sc_recorder_join(struct sc_recorder *recorder) {
|
||||
|
||||
void
|
||||
sc_recorder_destroy(struct sc_recorder *recorder) {
|
||||
sc_cond_destroy(&recorder->cond);
|
||||
sc_cond_destroy(&recorder->stream_cond);
|
||||
sc_cond_destroy(&recorder->queue_cond);
|
||||
sc_mutex_destroy(&recorder->mutex);
|
||||
free(recorder->filename);
|
||||
}
|
||||
|
||||
@@ -14,11 +14,6 @@
|
||||
|
||||
struct sc_recorder_queue SC_VECDEQUE(AVPacket *);
|
||||
|
||||
struct sc_recorder_stream {
|
||||
int index;
|
||||
int64_t last_pts;
|
||||
};
|
||||
|
||||
struct sc_recorder {
|
||||
struct sc_packet_sink video_packet_sink;
|
||||
struct sc_packet_sink audio_packet_sink;
|
||||
@@ -40,18 +35,19 @@ struct sc_recorder {
|
||||
|
||||
sc_thread thread;
|
||||
sc_mutex mutex;
|
||||
sc_cond cond;
|
||||
sc_cond queue_cond;
|
||||
// set on sc_recorder_stop(), packet_sink close or recording failure
|
||||
bool stopped;
|
||||
struct sc_recorder_queue video_queue;
|
||||
struct sc_recorder_queue audio_queue;
|
||||
|
||||
// wake up the recorder thread once the video or audio codec is known
|
||||
sc_cond stream_cond;
|
||||
bool video_init;
|
||||
bool audio_init;
|
||||
|
||||
struct sc_recorder_stream video_stream;
|
||||
struct sc_recorder_stream audio_stream;
|
||||
int video_stream_index;
|
||||
int audio_stream_index;
|
||||
|
||||
const struct sc_recorder_callbacks *cbs;
|
||||
void *cbs_userdata;
|
||||
|
||||
@@ -83,10 +83,12 @@ scrcpy_otg(struct scrcpy_options *options) {
|
||||
#ifdef _WIN32
|
||||
// On Windows, only one process could open a USB device
|
||||
// <https://github.com/Genymobile/scrcpy/issues/2773>
|
||||
LOGI("Killing adb daemon (if any)...");
|
||||
unsigned flags = SC_ADB_NO_STDOUT | SC_ADB_NO_STDERR | SC_ADB_NO_LOGERR;
|
||||
// uninterruptible (intr == NULL), but in practice it's very quick
|
||||
sc_adb_kill_server(NULL, flags);
|
||||
if (options->kill_adb_before_otg) {
|
||||
LOGI("Killing adb daemon (if any)...");
|
||||
unsigned flags = SC_ADB_NO_STDOUT | SC_ADB_NO_STDERR | SC_ADB_NO_LOGERR;
|
||||
// uninterruptible (intr == NULL), but in practice it's very quick
|
||||
sc_adb_kill_server(NULL, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct sc_usb_callbacks cbs = {
|
||||
|
||||
@@ -30,9 +30,8 @@ To disable only the audio playback, see [no playback](video.md#no-playback).
|
||||
|
||||
To play audio only, disable the video:
|
||||
|
||||
```bash
|
||||
```
|
||||
scrcpy --no-video
|
||||
# interrupt with Ctrl+C
|
||||
```
|
||||
|
||||
Without video, the audio latency is typically not criticial, so it might be
|
||||
|
||||
@@ -168,7 +168,6 @@ the computer. This option is useful when [recording](recording.md) or when
|
||||
```bash
|
||||
scrcpy --v4l2-sink=/dev/video2 --no-playback
|
||||
scrcpy --record=file.mkv --no-playback
|
||||
# interrupt with Ctrl+C
|
||||
```
|
||||
|
||||
It is also possible to disable video and audio playback separately:
|
||||
|
||||
Reference in New Issue
Block a user