diff --git a/README.md b/README.md index 6218bee4..a19aec0f 100644 --- a/README.md +++ b/README.md @@ -254,12 +254,13 @@ The [window may also be rotated](#rotation) independently. #### Codec -The video codec can be selected. The possible values are `h264` (default) and -`h265`: +The video codec can be selected. The possible values are `h264` (default), +`h265` and `av1`: ```bash scrcpy --codec=h264 # default scrcpy --codec=h265 +scrcpy --codec=av1 ``` diff --git a/app/scrcpy.1 b/app/scrcpy.1 index be607173..18c70d65 100644 --- a/app/scrcpy.1 +++ b/app/scrcpy.1 @@ -27,7 +27,7 @@ Default is 8000000. .TP .BI "\-\-codec " name -Select a video codec (h264 or h265). +Select a video codec (h264, h265 or av1). .TP .BI "\-\-codec\-options " key\fR[:\fItype\fR]=\fIvalue\fR[,...] diff --git a/app/src/cli.c b/app/src/cli.c index 76d59f38..27b0ddef 100644 --- a/app/src/cli.c +++ b/app/src/cli.c @@ -110,7 +110,7 @@ static const struct sc_option options[] = { .longopt_id = OPT_CODEC, .longopt = "codec", .argdesc = "name", - .text = "Select a video codec (h264 or h265).", + .text = "Select a video codec (h264, h265 or av1).", }, { .longopt_id = OPT_CODEC_OPTIONS, @@ -1394,7 +1394,11 @@ parse_codec(const char *optarg, enum sc_codec *codec) { *codec = SC_CODEC_H265; return true; } - LOGE("Unsupported codec: %s (expected h264 or h265)", optarg); + if (!strcmp(optarg, "av1")) { + *codec = SC_CODEC_AV1; + return true; + } + LOGE("Unsupported codec: %s (expected h264, h265 or av1)", optarg); return false; } @@ -1744,6 +1748,13 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[], } } + if (opts->record_format == SC_RECORD_FORMAT_MP4 + && opts->codec == SC_CODEC_AV1) { + LOGE("Could not mux AV1 stream into MP4 container " + "(record to mkv or select another video codec)"); + return false; + } + if (!opts->control) { if (opts->turn_screen_off) { LOGE("Could not request to turn screen off if control is disabled"); diff --git a/app/src/demuxer.c b/app/src/demuxer.c index 119d4065..6c44a558 100644 --- a/app/src/demuxer.c +++ b/app/src/demuxer.c @@ -27,12 +27,15 @@ sc_demuxer_recv_codec_id(struct sc_demuxer *demuxer) { #define SC_CODEC_ID_H264 UINT32_C(0x68323634) // "h264" in ASCII #define SC_CODEC_ID_H265 UINT32_C(0x68323635) // "h265" in ASCII +#define SC_CODEC_ID_AV1 UINT32_C(0x00617631) // "av1" in ASCII uint32_t codec_id = sc_read32be(data); switch (codec_id) { case SC_CODEC_ID_H264: return AV_CODEC_ID_H264; case SC_CODEC_ID_H265: return AV_CODEC_ID_HEVC; + case SC_CODEC_ID_AV1: + return AV_CODEC_ID_AV1; default: LOGE("Unknown codec id 0x%08" PRIx32, codec_id); return AV_CODEC_ID_NONE; diff --git a/app/src/options.h b/app/src/options.h index b3c39594..b9d237e0 100644 --- a/app/src/options.h +++ b/app/src/options.h @@ -26,6 +26,7 @@ enum sc_record_format { enum sc_codec { SC_CODEC_H264, SC_CODEC_H265, + SC_CODEC_AV1, }; enum sc_lock_video_orientation { diff --git a/app/src/server.c b/app/src/server.c index a63504bb..74d318c8 100644 --- a/app/src/server.c +++ b/app/src/server.c @@ -163,6 +163,8 @@ sc_server_get_codec_name(enum sc_codec codec) { return "h264"; case SC_CODEC_H265: return "h265"; + case SC_CODEC_AV1: + return "av1"; default: return NULL; } diff --git a/server/src/main/java/com/genymobile/scrcpy/VideoCodec.java b/server/src/main/java/com/genymobile/scrcpy/VideoCodec.java index 048765f7..809d7dbc 100644 --- a/server/src/main/java/com/genymobile/scrcpy/VideoCodec.java +++ b/server/src/main/java/com/genymobile/scrcpy/VideoCodec.java @@ -4,7 +4,8 @@ import android.media.MediaFormat; public enum VideoCodec { H264(0x68_32_36_34, "h264", MediaFormat.MIMETYPE_VIDEO_AVC), - H265(0x68_32_36_35, "h265", MediaFormat.MIMETYPE_VIDEO_HEVC); + H265(0x68_32_36_35, "h265", MediaFormat.MIMETYPE_VIDEO_HEVC), + AV1(0x00_61_76_31, "av1", MediaFormat.MIMETYPE_VIDEO_AV1); private final int id; // 4-byte ASCII representation of the name private final String name;