mirror of
https://github.com/Genymobile/scrcpy
synced 2025-08-31 22:35:37 +00:00
Add camera mirroring
Add --video-source=camera, and related options: - --camera-id=<id>: select the camera by its id (see --list-cameras); - --camera-size=<width>x<height>: select the capture size. Fixed #241 <https://github.com/Genymobile/scrcpy/issues/241> PR #4213 <https://github.com/Genymobile/scrcpy/pull/4213> Co-authored-by: Romain Vimont <rom@rom1v.com> Signed-off-by: Romain Vimont <rom@rom1v.com>
This commit is contained in:
committed by
Romain Vimont
parent
f032262cd7
commit
bfeecc0131
@@ -77,12 +77,15 @@ enum {
|
||||
OPT_NO_VIDEO,
|
||||
OPT_NO_AUDIO_PLAYBACK,
|
||||
OPT_NO_VIDEO_PLAYBACK,
|
||||
OPT_VIDEO_SOURCE,
|
||||
OPT_AUDIO_SOURCE,
|
||||
OPT_KILL_ADB_ON_CLOSE,
|
||||
OPT_TIME_LIMIT,
|
||||
OPT_PAUSE_ON_EXIT,
|
||||
OPT_LIST_CAMERAS,
|
||||
OPT_LIST_CAMERA_SIZES,
|
||||
OPT_CAMERA_ID,
|
||||
OPT_CAMERA_SIZE,
|
||||
};
|
||||
|
||||
struct sc_option {
|
||||
@@ -199,6 +202,20 @@ static const struct sc_option options[] = {
|
||||
.longopt = "bit-rate",
|
||||
.argdesc = "value",
|
||||
},
|
||||
{
|
||||
.longopt_id = OPT_CAMERA_ID,
|
||||
.longopt = "camera-id",
|
||||
.argdesc = "id",
|
||||
.text = "Specify the device camera id to mirror.\n"
|
||||
"The available camera ids can be listed by:\n"
|
||||
" scrcpy --list-cameras",
|
||||
},
|
||||
{
|
||||
.longopt_id = OPT_CAMERA_SIZE,
|
||||
.longopt = "camera-size",
|
||||
.argdesc = "<width>x<height>",
|
||||
.text = "Specify an explicit camera capture size.",
|
||||
},
|
||||
{
|
||||
// Not really deprecated (--codec has never been released), but without
|
||||
// declaring an explicit --codec option, getopt_long() partial matching
|
||||
@@ -703,6 +720,14 @@ static const struct sc_option options[] = {
|
||||
"codec provided by --video-codec).\n"
|
||||
"The available encoders can be listed by --list-encoders.",
|
||||
},
|
||||
{
|
||||
.longopt_id = OPT_VIDEO_SOURCE,
|
||||
.longopt = "video-source",
|
||||
.argdesc = "source",
|
||||
.text = "Select the video source (display or camera).\n"
|
||||
"Camera mirroring requires Android 12+.\n"
|
||||
"Default is display.",
|
||||
},
|
||||
{
|
||||
.shortopt = 'w',
|
||||
.longopt = "stay-awake",
|
||||
@@ -1643,6 +1668,22 @@ parse_audio_codec(const char *optarg, enum sc_codec *codec) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_video_source(const char *optarg, enum sc_video_source *source) {
|
||||
if (!strcmp(optarg, "display")) {
|
||||
*source = SC_VIDEO_SOURCE_DISPLAY;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!strcmp(optarg, "camera")) {
|
||||
*source = SC_VIDEO_SOURCE_CAMERA;
|
||||
return true;
|
||||
}
|
||||
|
||||
LOGE("Unsupported video source: %s (expected display or camera)", optarg);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_audio_source(const char *optarg, enum sc_audio_source *source) {
|
||||
if (!strcmp(optarg, "mic")) {
|
||||
@@ -2030,6 +2071,11 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case OPT_VIDEO_SOURCE:
|
||||
if (!parse_video_source(optarg, &opts->video_source)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case OPT_AUDIO_SOURCE:
|
||||
if (!parse_audio_source(optarg, &opts->audio_source)) {
|
||||
return false;
|
||||
@@ -2048,6 +2094,12 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case OPT_CAMERA_ID:
|
||||
opts->camera_id = optarg;
|
||||
break;
|
||||
case OPT_CAMERA_SIZE:
|
||||
opts->camera_size = optarg;
|
||||
break;
|
||||
default:
|
||||
// getopt prints the error message on stderr
|
||||
return false;
|
||||
@@ -2141,6 +2193,32 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
||||
opts->force_adb_forward = true;
|
||||
}
|
||||
|
||||
if (opts->video_source == SC_VIDEO_SOURCE_CAMERA) {
|
||||
if (opts->display_id) {
|
||||
LOGE("--display-id is only available with --video-source=display");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!opts->camera_id) {
|
||||
LOGE("Camera id must be specified by --camera-id "
|
||||
"(list the available ids with --list-cameras)");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!opts->camera_size) {
|
||||
LOGE("Camera size must be specified by --camera-size");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (opts->control) {
|
||||
LOGI("Camera video source: control disabled");
|
||||
opts->control = false;
|
||||
}
|
||||
} else if (opts->camera_id || opts->camera_size) {
|
||||
LOGE("Camera options are only available with --video-source=camera");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (opts->record_format && !opts->record_filename) {
|
||||
LOGE("Record format specified without recording");
|
||||
return false;
|
||||
|
Reference in New Issue
Block a user