Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f7869d130 | ||
|
|
0f28d39127 |
@@ -19,9 +19,8 @@ _scrcpy() {
|
|||||||
-f --fullscreen
|
-f --fullscreen
|
||||||
--force-adb-forward
|
--force-adb-forward
|
||||||
--forward-all-clicks
|
--forward-all-clicks
|
||||||
-h --help
|
|
||||||
--kill-adb-on-close
|
|
||||||
-K --hid-keyboard
|
-K --hid-keyboard
|
||||||
|
-h --help
|
||||||
--legacy-paste
|
--legacy-paste
|
||||||
--list-displays
|
--list-displays
|
||||||
--list-encoders
|
--list-encoders
|
||||||
|
|||||||
@@ -26,9 +26,8 @@ arguments=(
|
|||||||
{-f,--fullscreen}'[Start in fullscreen]'
|
{-f,--fullscreen}'[Start in fullscreen]'
|
||||||
'--force-adb-forward[Do not attempt to use \"adb reverse\" to connect to the device]'
|
'--force-adb-forward[Do not attempt to use \"adb reverse\" to connect to the device]'
|
||||||
'--forward-all-clicks[Forward clicks to device]'
|
'--forward-all-clicks[Forward clicks to device]'
|
||||||
{-h,--help}'[Print the help]'
|
|
||||||
'--kill-adb-on-close[Kill adb when scrcpy terminates]'
|
|
||||||
{-K,--hid-keyboard}'[Simulate a physical keyboard by using HID over AOAv2]'
|
{-K,--hid-keyboard}'[Simulate a physical keyboard by using HID over AOAv2]'
|
||||||
|
{-h,--help}'[Print the help]'
|
||||||
'--legacy-paste[Inject computer clipboard text as a sequence of key events on Ctrl+v]'
|
'--legacy-paste[Inject computer clipboard text as a sequence of key events on Ctrl+v]'
|
||||||
'--list-displays[List displays available on the device]'
|
'--list-displays[List displays available on the device]'
|
||||||
'--list-encoders[List video and audio encoders available on the device]'
|
'--list-encoders[List video and audio encoders available on the device]'
|
||||||
|
|||||||
@@ -129,10 +129,6 @@ By default, right-click triggers BACK (or POWER on) and middle-click triggers HO
|
|||||||
.B \-h, \-\-help
|
.B \-h, \-\-help
|
||||||
Print this help.
|
Print this help.
|
||||||
|
|
||||||
.TP
|
|
||||||
.B \-\-kill\-adb\-on\-close
|
|
||||||
Kill adb when scrcpy terminates.
|
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-K, \-\-hid\-keyboard
|
.B \-K, \-\-hid\-keyboard
|
||||||
Simulate a physical keyboard by using HID over AOAv2.
|
Simulate a physical keyboard by using HID over AOAv2.
|
||||||
|
|||||||
+5
-14
@@ -77,7 +77,6 @@ enum {
|
|||||||
OPT_NO_AUDIO_PLAYBACK,
|
OPT_NO_AUDIO_PLAYBACK,
|
||||||
OPT_NO_VIDEO_PLAYBACK,
|
OPT_NO_VIDEO_PLAYBACK,
|
||||||
OPT_AUDIO_SOURCE,
|
OPT_AUDIO_SOURCE,
|
||||||
OPT_KILL_ADB_ON_CLOSE,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sc_option {
|
struct sc_option {
|
||||||
@@ -276,16 +275,6 @@ static const struct sc_option options[] = {
|
|||||||
"middle-click triggers HOME. This option disables these "
|
"middle-click triggers HOME. This option disables these "
|
||||||
"shortcuts and forwards the clicks to the device instead.",
|
"shortcuts and forwards the clicks to the device instead.",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
.shortopt = 'h',
|
|
||||||
.longopt = "help",
|
|
||||||
.text = "Print this help.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.longopt_id = OPT_KILL_ADB_ON_CLOSE,
|
|
||||||
.longopt = "kill-adb-on-close",
|
|
||||||
.text = "Kill adb when scrcpy terminates.",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
.shortopt = 'K',
|
.shortopt = 'K',
|
||||||
.longopt = "hid-keyboard",
|
.longopt = "hid-keyboard",
|
||||||
@@ -303,6 +292,11 @@ static const struct sc_option options[] = {
|
|||||||
"is enabled (or a physical keyboard is connected).\n"
|
"is enabled (or a physical keyboard is connected).\n"
|
||||||
"Also see --hid-mouse.",
|
"Also see --hid-mouse.",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.shortopt = 'h',
|
||||||
|
.longopt = "help",
|
||||||
|
.text = "Print this help.",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.longopt_id = OPT_LEGACY_PASTE,
|
.longopt_id = OPT_LEGACY_PASTE,
|
||||||
.longopt = "legacy-paste",
|
.longopt = "legacy-paste",
|
||||||
@@ -1950,9 +1944,6 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPT_KILL_ADB_ON_CLOSE:
|
|
||||||
opts->kill_adb_on_close = true;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
// getopt prints the error message on stderr
|
// getopt prints the error message on stderr
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -80,5 +80,4 @@ const struct scrcpy_options scrcpy_options_default = {
|
|||||||
.require_audio = false,
|
.require_audio = false,
|
||||||
.list_encoders = false,
|
.list_encoders = false,
|
||||||
.list_displays = false,
|
.list_displays = false,
|
||||||
.kill_adb_on_close = false,
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -180,7 +180,6 @@ struct scrcpy_options {
|
|||||||
bool require_audio;
|
bool require_audio;
|
||||||
bool list_encoders;
|
bool list_encoders;
|
||||||
bool list_displays;
|
bool list_displays;
|
||||||
bool kill_adb_on_close;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const struct scrcpy_options scrcpy_options_default;
|
extern const struct scrcpy_options scrcpy_options_default;
|
||||||
|
|||||||
+41
-46
@@ -96,30 +96,23 @@ sc_recorder_rescale_packet(AVStream *stream, AVPacket *packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
sc_recorder_write_stream(struct sc_recorder *recorder,
|
sc_recorder_write_stream(struct sc_recorder *recorder, int stream_index,
|
||||||
struct sc_recorder_stream *st, AVPacket *packet) {
|
AVPacket *packet) {
|
||||||
AVStream *stream = recorder->ctx->streams[st->index];
|
AVStream *stream = recorder->ctx->streams[stream_index];
|
||||||
sc_recorder_rescale_packet(stream, packet);
|
sc_recorder_rescale_packet(stream, packet);
|
||||||
if (st->last_pts != AV_NOPTS_VALUE && packet->pts <= st->last_pts) {
|
|
||||||
LOGW("Fixing PTS non monotonically increasing in stream %d "
|
|
||||||
"(%" PRIi64 " >= %" PRIi64 ")",
|
|
||||||
st->index, 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;
|
return av_interleaved_write_frame(recorder->ctx, packet) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
sc_recorder_write_video(struct sc_recorder *recorder, AVPacket *packet) {
|
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
|
static inline bool
|
||||||
sc_recorder_write_audio(struct sc_recorder *recorder, AVPacket *packet) {
|
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
|
static bool
|
||||||
@@ -185,11 +178,10 @@ static bool
|
|||||||
sc_recorder_process_header(struct sc_recorder *recorder) {
|
sc_recorder_process_header(struct sc_recorder *recorder) {
|
||||||
sc_mutex_lock(&recorder->mutex);
|
sc_mutex_lock(&recorder->mutex);
|
||||||
|
|
||||||
while (!recorder->stopped &&
|
while (!recorder->stopped && (!recorder->video_init
|
||||||
((recorder->video && !recorder->video_init)
|
|| !recorder->audio_init
|
||||||
|| (recorder->audio && !recorder->audio_init)
|
|| sc_recorder_has_empty_queues(recorder))) {
|
||||||
|| sc_recorder_has_empty_queues(recorder))) {
|
sc_cond_wait(&recorder->stream_cond, &recorder->mutex);
|
||||||
sc_cond_wait(&recorder->cond, &recorder->mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recorder->video && sc_vecdeque_is_empty(&recorder->video_queue)) {
|
if (recorder->video && sc_vecdeque_is_empty(&recorder->video_queue)) {
|
||||||
@@ -222,9 +214,9 @@ sc_recorder_process_header(struct sc_recorder *recorder) {
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(recorder->video_stream.index >= 0);
|
assert(recorder->video_stream_index >= 0);
|
||||||
AVStream *video_stream =
|
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);
|
bool ok = sc_recorder_set_extradata(video_stream, video_pkt);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
goto end;
|
goto end;
|
||||||
@@ -237,9 +229,9 @@ sc_recorder_process_header(struct sc_recorder *recorder) {
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(recorder->audio_stream.index >= 0);
|
assert(recorder->audio_stream_index >= 0);
|
||||||
AVStream *audio_stream =
|
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);
|
bool ok = sc_recorder_set_extradata(audio_stream, audio_pkt);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
goto end;
|
goto end;
|
||||||
@@ -297,7 +289,7 @@ sc_recorder_process_packets(struct sc_recorder *recorder) {
|
|||||||
// A new packet may be assigned to audio_pkt and be processed
|
// A new packet may be assigned to audio_pkt and be processed
|
||||||
break;
|
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
|
// If stopped is set, continue to process the remaining events (to
|
||||||
@@ -512,10 +504,10 @@ sc_recorder_video_packet_sink_open(struct sc_packet_sink *sink,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
recorder->video_stream.index = stream->index;
|
recorder->video_stream_index = stream->index;
|
||||||
|
|
||||||
recorder->video_init = true;
|
recorder->video_init = true;
|
||||||
sc_cond_signal(&recorder->cond);
|
sc_cond_signal(&recorder->stream_cond);
|
||||||
sc_mutex_unlock(&recorder->mutex);
|
sc_mutex_unlock(&recorder->mutex);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -530,7 +522,7 @@ sc_recorder_video_packet_sink_close(struct sc_packet_sink *sink) {
|
|||||||
sc_mutex_lock(&recorder->mutex);
|
sc_mutex_lock(&recorder->mutex);
|
||||||
// EOS also stops the recorder
|
// EOS also stops the recorder
|
||||||
recorder->stopped = true;
|
recorder->stopped = true;
|
||||||
sc_cond_signal(&recorder->cond);
|
sc_cond_signal(&recorder->queue_cond);
|
||||||
sc_mutex_unlock(&recorder->mutex);
|
sc_mutex_unlock(&recorder->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -556,7 +548,7 @@ sc_recorder_video_packet_sink_push(struct sc_packet_sink *sink,
|
|||||||
return false;
|
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);
|
bool ok = sc_vecdeque_push(&recorder->video_queue, rec);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
@@ -565,7 +557,7 @@ sc_recorder_video_packet_sink_push(struct sc_packet_sink *sink,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_cond_signal(&recorder->cond);
|
sc_cond_signal(&recorder->queue_cond);
|
||||||
|
|
||||||
sc_mutex_unlock(&recorder->mutex);
|
sc_mutex_unlock(&recorder->mutex);
|
||||||
return true;
|
return true;
|
||||||
@@ -593,10 +585,10 @@ sc_recorder_audio_packet_sink_open(struct sc_packet_sink *sink,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
recorder->audio_stream.index = stream->index;
|
recorder->audio_stream_index = stream->index;
|
||||||
|
|
||||||
recorder->audio_init = true;
|
recorder->audio_init = true;
|
||||||
sc_cond_signal(&recorder->cond);
|
sc_cond_signal(&recorder->stream_cond);
|
||||||
sc_mutex_unlock(&recorder->mutex);
|
sc_mutex_unlock(&recorder->mutex);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -612,7 +604,7 @@ sc_recorder_audio_packet_sink_close(struct sc_packet_sink *sink) {
|
|||||||
sc_mutex_lock(&recorder->mutex);
|
sc_mutex_lock(&recorder->mutex);
|
||||||
// EOS also stops the recorder
|
// EOS also stops the recorder
|
||||||
recorder->stopped = true;
|
recorder->stopped = true;
|
||||||
sc_cond_signal(&recorder->cond);
|
sc_cond_signal(&recorder->queue_cond);
|
||||||
sc_mutex_unlock(&recorder->mutex);
|
sc_mutex_unlock(&recorder->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,7 +631,7 @@ sc_recorder_audio_packet_sink_push(struct sc_packet_sink *sink,
|
|||||||
return false;
|
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);
|
bool ok = sc_vecdeque_push(&recorder->audio_queue, rec);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
@@ -648,7 +640,7 @@ sc_recorder_audio_packet_sink_push(struct sc_packet_sink *sink,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_cond_signal(&recorder->cond);
|
sc_cond_signal(&recorder->queue_cond);
|
||||||
|
|
||||||
sc_mutex_unlock(&recorder->mutex);
|
sc_mutex_unlock(&recorder->mutex);
|
||||||
return true;
|
return true;
|
||||||
@@ -666,16 +658,10 @@ sc_recorder_audio_packet_sink_disable(struct sc_packet_sink *sink) {
|
|||||||
sc_mutex_lock(&recorder->mutex);
|
sc_mutex_lock(&recorder->mutex);
|
||||||
recorder->audio = false;
|
recorder->audio = false;
|
||||||
recorder->audio_init = true;
|
recorder->audio_init = true;
|
||||||
sc_cond_signal(&recorder->cond);
|
sc_cond_signal(&recorder->stream_cond);
|
||||||
sc_mutex_unlock(&recorder->mutex);
|
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
|
bool
|
||||||
sc_recorder_init(struct sc_recorder *recorder, const char *filename,
|
sc_recorder_init(struct sc_recorder *recorder, const char *filename,
|
||||||
enum sc_record_format format, bool video, bool audio,
|
enum sc_record_format format, bool video, bool audio,
|
||||||
@@ -691,11 +677,16 @@ sc_recorder_init(struct sc_recorder *recorder, const char *filename,
|
|||||||
goto error_free_filename;
|
goto error_free_filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = sc_cond_init(&recorder->cond);
|
ok = sc_cond_init(&recorder->queue_cond);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
goto error_mutex_destroy;
|
goto error_mutex_destroy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ok = sc_cond_init(&recorder->stream_cond);
|
||||||
|
if (!ok) {
|
||||||
|
goto error_queue_cond_destroy;
|
||||||
|
}
|
||||||
|
|
||||||
assert(video || audio);
|
assert(video || audio);
|
||||||
recorder->video = video;
|
recorder->video = video;
|
||||||
recorder->audio = audio;
|
recorder->audio = audio;
|
||||||
@@ -707,8 +698,8 @@ sc_recorder_init(struct sc_recorder *recorder, const char *filename,
|
|||||||
recorder->video_init = false;
|
recorder->video_init = false;
|
||||||
recorder->audio_init = false;
|
recorder->audio_init = false;
|
||||||
|
|
||||||
sc_recorder_stream_init(&recorder->video_stream);
|
recorder->video_stream_index = -1;
|
||||||
sc_recorder_stream_init(&recorder->audio_stream);
|
recorder->audio_stream_index = -1;
|
||||||
|
|
||||||
recorder->format = format;
|
recorder->format = format;
|
||||||
|
|
||||||
@@ -739,6 +730,8 @@ sc_recorder_init(struct sc_recorder *recorder, const char *filename,
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
error_queue_cond_destroy:
|
||||||
|
sc_cond_destroy(&recorder->queue_cond);
|
||||||
error_mutex_destroy:
|
error_mutex_destroy:
|
||||||
sc_mutex_destroy(&recorder->mutex);
|
sc_mutex_destroy(&recorder->mutex);
|
||||||
error_free_filename:
|
error_free_filename:
|
||||||
@@ -763,7 +756,8 @@ void
|
|||||||
sc_recorder_stop(struct sc_recorder *recorder) {
|
sc_recorder_stop(struct sc_recorder *recorder) {
|
||||||
sc_mutex_lock(&recorder->mutex);
|
sc_mutex_lock(&recorder->mutex);
|
||||||
recorder->stopped = true;
|
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);
|
sc_mutex_unlock(&recorder->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -774,7 +768,8 @@ sc_recorder_join(struct sc_recorder *recorder) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
sc_recorder_destroy(struct sc_recorder *recorder) {
|
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);
|
sc_mutex_destroy(&recorder->mutex);
|
||||||
free(recorder->filename);
|
free(recorder->filename);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-8
@@ -14,11 +14,6 @@
|
|||||||
|
|
||||||
struct sc_recorder_queue SC_VECDEQUE(AVPacket *);
|
struct sc_recorder_queue SC_VECDEQUE(AVPacket *);
|
||||||
|
|
||||||
struct sc_recorder_stream {
|
|
||||||
int index;
|
|
||||||
int64_t last_pts;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sc_recorder {
|
struct sc_recorder {
|
||||||
struct sc_packet_sink video_packet_sink;
|
struct sc_packet_sink video_packet_sink;
|
||||||
struct sc_packet_sink audio_packet_sink;
|
struct sc_packet_sink audio_packet_sink;
|
||||||
@@ -40,18 +35,19 @@ struct sc_recorder {
|
|||||||
|
|
||||||
sc_thread thread;
|
sc_thread thread;
|
||||||
sc_mutex mutex;
|
sc_mutex mutex;
|
||||||
sc_cond cond;
|
sc_cond queue_cond;
|
||||||
// set on sc_recorder_stop(), packet_sink close or recording failure
|
// set on sc_recorder_stop(), packet_sink close or recording failure
|
||||||
bool stopped;
|
bool stopped;
|
||||||
struct sc_recorder_queue video_queue;
|
struct sc_recorder_queue video_queue;
|
||||||
struct sc_recorder_queue audio_queue;
|
struct sc_recorder_queue audio_queue;
|
||||||
|
|
||||||
// wake up the recorder thread once the video or audio codec is known
|
// wake up the recorder thread once the video or audio codec is known
|
||||||
|
sc_cond stream_cond;
|
||||||
bool video_init;
|
bool video_init;
|
||||||
bool audio_init;
|
bool audio_init;
|
||||||
|
|
||||||
struct sc_recorder_stream video_stream;
|
int video_stream_index;
|
||||||
struct sc_recorder_stream audio_stream;
|
int audio_stream_index;
|
||||||
|
|
||||||
const struct sc_recorder_callbacks *cbs;
|
const struct sc_recorder_callbacks *cbs;
|
||||||
void *cbs_userdata;
|
void *cbs_userdata;
|
||||||
|
|||||||
@@ -364,7 +364,6 @@ scrcpy(struct scrcpy_options *options) {
|
|||||||
.power_on = options->power_on,
|
.power_on = options->power_on,
|
||||||
.list_encoders = options->list_encoders,
|
.list_encoders = options->list_encoders,
|
||||||
.list_displays = options->list_displays,
|
.list_displays = options->list_displays,
|
||||||
.kill_adb_on_close = options->kill_adb_on_close,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct sc_server_callbacks cbs = {
|
static const struct sc_server_callbacks cbs = {
|
||||||
|
|||||||
+1
-13
@@ -794,15 +794,6 @@ sc_server_configure_tcpip_unknown_address(struct sc_server *server,
|
|||||||
return sc_server_connect_to_tcpip(server, ip_port);
|
return sc_server_connect_to_tcpip(server, ip_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
sc_server_kill_adb_if_requested(struct sc_server *server) {
|
|
||||||
if (server->params.kill_adb_on_close) {
|
|
||||||
LOGI("Killing adb server...");
|
|
||||||
unsigned flags = SC_ADB_NO_STDOUT | SC_ADB_NO_STDERR | SC_ADB_NO_LOGERR;
|
|
||||||
sc_adb_kill_server(&server->intr, flags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
run_server(void *data) {
|
run_server(void *data) {
|
||||||
struct sc_server *server = data;
|
struct sc_server *server = data;
|
||||||
@@ -814,7 +805,7 @@ run_server(void *data) {
|
|||||||
// is parsed, so it is not output)
|
// is parsed, so it is not output)
|
||||||
bool ok = sc_adb_start_server(&server->intr, 0);
|
bool ok = sc_adb_start_server(&server->intr, 0);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
LOGE("Could not start adb server");
|
LOGE("Could not start adb daemon");
|
||||||
goto error_connection_failed;
|
goto error_connection_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1002,12 +993,9 @@ run_server(void *data) {
|
|||||||
|
|
||||||
sc_process_close(pid);
|
sc_process_close(pid);
|
||||||
|
|
||||||
sc_server_kill_adb_if_requested(server);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_connection_failed:
|
error_connection_failed:
|
||||||
sc_server_kill_adb_if_requested(server);
|
|
||||||
server->cbs->on_connection_failed(server, server->cbs_userdata);
|
server->cbs->on_connection_failed(server, server->cbs_userdata);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ struct sc_server_params {
|
|||||||
bool power_on;
|
bool power_on;
|
||||||
bool list_encoders;
|
bool list_encoders;
|
||||||
bool list_displays;
|
bool list_displays;
|
||||||
bool kill_adb_on_close;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sc_server {
|
struct sc_server {
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ scrcpy_otg(struct scrcpy_options *options) {
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// On Windows, only one process could open a USB device
|
// On Windows, only one process could open a USB device
|
||||||
// <https://github.com/Genymobile/scrcpy/issues/2773>
|
// <https://github.com/Genymobile/scrcpy/issues/2773>
|
||||||
LOGI("Killing adb server (if any)...");
|
LOGI("Killing adb daemon (if any)...");
|
||||||
unsigned flags = SC_ADB_NO_STDOUT | SC_ADB_NO_STDERR | SC_ADB_NO_LOGERR;
|
unsigned flags = SC_ADB_NO_STDOUT | SC_ADB_NO_STDERR | SC_ADB_NO_LOGERR;
|
||||||
// uninterruptible (intr == NULL), but in practice it's very quick
|
// uninterruptible (intr == NULL), but in practice it's very quick
|
||||||
sc_adb_kill_server(NULL, flags);
|
sc_adb_kill_server(NULL, flags);
|
||||||
|
|||||||
+1
-1
@@ -56,7 +56,7 @@ For example, to use the device as a dictaphone and record a capture directly on
|
|||||||
the computer:
|
the computer:
|
||||||
|
|
||||||
```
|
```
|
||||||
scrcpy --audio-source=mic --no-video --no-playback --record=file.opus
|
scrcpy --audio-source=mic --no-video --no-audio-playback --record=file.opus
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@ To record only the audio:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
scrcpy --no-video --record=file.opus
|
scrcpy --no-video --record=file.opus
|
||||||
scrcpy --no-video --audio-codec=aac --record=file.aac
|
scrcpy --no-video --audio-codec=aac --record-file=file.aac
|
||||||
# .m4a/.mp4 and .mka/.mkv are also supported for both opus and aac
|
# .m4a/.mp4 and .mka/.mkv are also supported for both opus and aac
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ public final class AudioCapture {
|
|||||||
// - an estimation from the previous PTS and the packet size as a fallback.
|
// - an estimation from the previous PTS and the packet size as a fallback.
|
||||||
//
|
//
|
||||||
// Therefore, the property that PTS are monotonically increasing is no guaranteed in corner cases, so enforce it.
|
// Therefore, the property that PTS are monotonically increasing is no guaranteed in corner cases, so enforce it.
|
||||||
pts = previousPts + 1;
|
pts = previousPts;
|
||||||
}
|
}
|
||||||
previousPts = pts;
|
previousPts = pts;
|
||||||
|
|
||||||
|
|||||||
@@ -105,8 +105,17 @@ public final class AudioEncoder implements AsyncProcessor {
|
|||||||
private void outputThread(MediaCodec mediaCodec) throws IOException, InterruptedException {
|
private void outputThread(MediaCodec mediaCodec) throws IOException, InterruptedException {
|
||||||
streamer.writeAudioHeader();
|
streamer.writeAudioHeader();
|
||||||
|
|
||||||
|
long lastPts = 0;
|
||||||
while (!Thread.currentThread().isInterrupted()) {
|
while (!Thread.currentThread().isInterrupted()) {
|
||||||
OutputTask task = outputTasks.take();
|
OutputTask task = outputTasks.take();
|
||||||
|
|
||||||
|
if (task.bufferInfo.presentationTimeUs < lastPts) {
|
||||||
|
// Fix PTS if not monotonically increasing
|
||||||
|
task.bufferInfo.presentationTimeUs = lastPts;
|
||||||
|
} else {
|
||||||
|
lastPts = task.bufferInfo.presentationTimeUs;
|
||||||
|
}
|
||||||
|
|
||||||
ByteBuffer buffer = mediaCodec.getOutputBuffer(task.index);
|
ByteBuffer buffer = mediaCodec.getOutputBuffer(task.index);
|
||||||
try {
|
try {
|
||||||
streamer.writePacket(buffer, task.bufferInfo);
|
streamer.writePacket(buffer, task.bufferInfo);
|
||||||
|
|||||||
@@ -14,13 +14,13 @@ public final class InputManager {
|
|||||||
public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT = 1;
|
public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT = 1;
|
||||||
public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2;
|
public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2;
|
||||||
|
|
||||||
private final Object manager;
|
private final android.hardware.input.InputManager manager;
|
||||||
private Method injectInputEventMethod;
|
private Method injectInputEventMethod;
|
||||||
|
|
||||||
private static Method setDisplayIdMethod;
|
private static Method setDisplayIdMethod;
|
||||||
private static Method setActionButtonMethod;
|
private static Method setActionButtonMethod;
|
||||||
|
|
||||||
public InputManager(Object manager) {
|
public InputManager(android.hardware.input.InputManager manager) {
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,21 +62,11 @@ public final class ServiceManager {
|
|||||||
return displayManager;
|
return displayManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Class<?> getInputManagerClass() {
|
|
||||||
try {
|
|
||||||
// Parts of the InputManager class have been moved to a new InputManagerGlobal class in Android 14 preview
|
|
||||||
return Class.forName("android.hardware.input.InputManagerGlobal");
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
return android.hardware.input.InputManager.class;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static InputManager getInputManager() {
|
public static InputManager getInputManager() {
|
||||||
if (inputManager == null) {
|
if (inputManager == null) {
|
||||||
try {
|
try {
|
||||||
Class<?> inputManagerClass = getInputManagerClass();
|
Method getInstanceMethod = android.hardware.input.InputManager.class.getDeclaredMethod("getInstance");
|
||||||
Method getInstanceMethod = inputManagerClass.getDeclaredMethod("getInstance");
|
android.hardware.input.InputManager im = (android.hardware.input.InputManager) getInstanceMethod.invoke(null);
|
||||||
Object im = (android.hardware.input.InputManager) getInstanceMethod.invoke(null);
|
|
||||||
inputManager = new InputManager(im);
|
inputManager = new InputManager(im);
|
||||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
|
|||||||
Reference in New Issue
Block a user