Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package wl-screenrec for openSUSE:Factory checked in at 2023-12-28 23:00:56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/wl-screenrec (Old) and /work/SRC/openSUSE:Factory/.wl-screenrec.new.28375 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "wl-screenrec" Thu Dec 28 23:00:56 2023 rev:2 rq:1135208 version:0.1.2 Changes: -------- --- /work/SRC/openSUSE:Factory/wl-screenrec/wl-screenrec.changes 2023-11-08 22:17:55.991625682 +0100 +++ /work/SRC/openSUSE:Factory/.wl-screenrec.new.28375/wl-screenrec.changes 2023-12-28 23:02:33.880857394 +0100 @@ -1,0 +2,9 @@ +Sat Dec 16 11:50:06 UTC 2023 - Soc Virnyl Estela <uncomfy+openbuildserv...@uncomfyhalomacro.pl> + +- Update to version 0.1.2: + * use LTO for builds to reduce binary size + * fix off-by-one in region + * support ffmpeg 6.1 + * fix negative positions + +------------------------------------------------------------------- Old: ---- wl-screenrec-0.1.0.tar.gz New: ---- wl-screenrec-0.1.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ wl-screenrec.spec ++++++ --- /var/tmp/diff_new_pack.B4s0pC/_old 2023-12-28 23:02:34.716887949 +0100 +++ /var/tmp/diff_new_pack.B4s0pC/_new 2023-12-28 23:02:34.716887949 +0100 @@ -17,7 +17,7 @@ Name: wl-screenrec -Version: 0.1.0 +Version: 0.1.2 License: Apache-2.0 Release: 0 Summary: High performance hardware accelerated wlroots screen recorder @@ -44,21 +44,11 @@ %prep %autosetup -a1 -mkdir -p .cargo/ -cp cargo_config .cargo/config %build -export CC=clang -export CXX=clang++ -export CFLAGS="%optflags" -export CXXFLAGS="%optflags" %{cargo_build} --all-features %install -export CC=clang -export CXX=clang++ -export CFLAGS="%optflags" -export CXXFLAGS="%optflags" %{cargo_install} --all-features %files ++++++ vendor.tar.zst ++++++ Binary files /var/tmp/diff_new_pack.B4s0pC/_old and /var/tmp/diff_new_pack.B4s0pC/_new differ ++++++ wl-screenrec-0.1.0.tar.gz -> wl-screenrec-0.1.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wl-screenrec-0.1.0/Cargo.lock new/wl-screenrec-0.1.2/Cargo.lock --- old/wl-screenrec-0.1.0/Cargo.lock 2023-10-02 05:06:03.000000000 +0200 +++ new/wl-screenrec-0.1.2/Cargo.lock 2023-12-04 04:07:52.000000000 +0100 @@ -4,9 +4,9 @@ [[package]] name = "aho-corasick" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] @@ -99,9 +99,9 @@ [[package]] name = "bitflags" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "cc" @@ -140,9 +140,9 @@ [[package]] name = "clap" -version = "4.4.6" +version = "4.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +checksum = "41fffed7514f420abec6d183b1d3acfd9099c79c3a10a06ade4f8203f1411272" dependencies = [ "clap_builder", "clap_derive", @@ -150,9 +150,9 @@ [[package]] name = "clap_builder" -version = "4.4.6" +version = "4.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" +checksum = "63361bae7eef3771745f02d8d892bec2fee5f6e34af316ba556e7f97a7069ff1" dependencies = [ "anstream", "anstyle", @@ -162,21 +162,21 @@ [[package]] name = "clap_derive" -version = "4.4.2" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.39", ] [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "colorchoice" @@ -207,9 +207,9 @@ [[package]] name = "ffmpeg-next" -version = "6.0.0" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8af03c47ad26832ab3aabc4cdbf210af3d3b878783edd5a7ba044ba33aab7a60" +checksum = "f45d337871329d85f5aad1e3d7b09d033cd611d50f734fd6464c731fe7c769bf" dependencies = [ "bitflags 1.3.2", "ffmpeg-sys-next", @@ -218,9 +218,9 @@ [[package]] name = "ffmpeg-sys-next" -version = "6.0.1" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf650f461ccf130f4eef4927affed703cc387b183bfc4a7dfee86a076c131127" +checksum = "c2529ad916d08c3562c754c21bc9b17a26c7882c0f5706cc2cd69472175f1620" dependencies = [ "bindgen", "cc", @@ -274,9 +274,9 @@ [[package]] name = "libc" -version = "0.2.148" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libloading" @@ -343,7 +343,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "cfg-if", "libc", ] @@ -382,9 +382,9 @@ [[package]] name = "proc-macro2" -version = "1.0.67" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" dependencies = [ "unicode-ident", ] @@ -409,9 +409,9 @@ [[package]] name = "regex" -version = "1.9.6" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", @@ -421,9 +421,9 @@ [[package]] name = "regex-automata" -version = "0.3.9" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", @@ -432,9 +432,9 @@ [[package]] name = "regex-syntax" -version = "0.7.5" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "rustc-hash" @@ -456,29 +456,29 @@ [[package]] name = "serde" -version = "1.0.188" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.39", ] [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", @@ -512,9 +512,9 @@ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "strsim" @@ -535,9 +535,9 @@ [[package]] name = "syn" -version = "2.0.37" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", @@ -546,22 +546,22 @@ [[package]] name = "thiserror" -version = "1.0.49" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.49" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.39", ] [[package]] @@ -602,7 +602,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ca7d52347346f5473bf2f56705f360e8440873052e575e55890c4fa57843ed3" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "nix 0.26.4", "wayland-backend", "wayland-scanner", @@ -614,7 +614,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e253d7107ba913923dc253967f35e8561a3c65f914543e46843c88ddd729e21c" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "wayland-backend", "wayland-client", "wayland-scanner", @@ -626,7 +626,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "wayland-backend", "wayland-client", "wayland-protocols", @@ -745,7 +745,7 @@ [[package]] name = "wl-screenrec" -version = "0.1.0" +version = "0.1.2" dependencies = [ "anyhow", "clap", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wl-screenrec-0.1.0/Cargo.toml new/wl-screenrec-0.1.2/Cargo.toml --- old/wl-screenrec-0.1.0/Cargo.toml 2023-10-02 05:06:03.000000000 +0200 +++ new/wl-screenrec-0.1.2/Cargo.toml 2023-12-04 04:07:52.000000000 +0100 @@ -4,7 +4,7 @@ license-file = "LICENSE" homepage = "https://github.com/russelltg/wl-screenrec" repository = "https://github.com/russelltg/wl-screenrec" -version = "0.1.0" +version = "0.1.2" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -26,7 +26,9 @@ "staging", ] } wayland-protocols-wlr = { version = "0.2", features = ["client"] } -ffmpeg-next = "6.0.0" + +# ffmpeg-next does not support ffmpeg 6.1 yet, so grab from the 6.1 PR +ffmpeg-next = "6.1" thiserror = "1.0.38" drm-fourcc = "2.2.0" human-size = "0.4.2" @@ -41,3 +43,6 @@ "process", ] } serde_json = "1.0.103" + +[profile.release] +lto = "thin" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wl-screenrec-0.1.0/README.md new/wl-screenrec-0.1.2/README.md --- old/wl-screenrec-0.1.0/README.md 2023-10-02 05:06:03.000000000 +0200 +++ new/wl-screenrec-0.1.2/README.md 2023-12-04 04:07:52.000000000 +0100 @@ -41,6 +41,8 @@ ## From the AUR ```bash +paru -S wl-screenrec +# OR paru -S wl-screenrec-git ``` Or, manually: @@ -52,10 +54,14 @@ ## From source using cargo -Install ffmpeg, which is a required dependency. +Install ffmpeg 6 or later, which is a required dependency. +ffmpeg 5 may work, but is untested (open an issue or PR if you test with ffmpeg 5 +so I can update these docs on if it works or not) ```bash -cargo install --git https://github.com/russelltg/wl-screenrec +cargo install wl-screenrec # stable version +# OR +cargo install --git https://github.com/russelltg/wl-screenrec # git version ``` ## FreeBSD @@ -105,13 +111,21 @@ wl-screenrec --audio --audio-device alsa_output.pci-0000_00_1f.3.hdmi-stereo.monitor # capture desktop audio (example, use `pactl list short sources` to figure out what you should put here) ``` -Record with history +Record with history: ```bash wl-screenrec --history 10 & # record the most recent 10 seconds into memory, not writing into the file # ... some important event occurs killall -USR1 wl-screenrec # flush the most recent 10 seconds onto the file, and start appending to the file like recording normally ``` +Capture to [v4l2loopback](https://github.com/umlaeute/v4l2loopback) (for Zoom, etc): + +```bash +sudo modprobe v4l2loopback +v4l2-ctl --list-devices # find "Dummy video device" device. /dev/video6 in my case. +wl-screenrec --ffmpeg-muxer v4l2 -f /dev/video6 +``` + # All options ```text @@ -134,11 +148,15 @@ --low-power <LOW_POWER> [default: auto] [possible values: auto, on, off] --codec <CODEC> - which codec to use. Used in conjunction with --no-hw to determinte which enocder to use. Ignored if `encoder` is supplied [default: auto] [possible values: auto, avc, hevc, vp8, vp9] + which codec to use. Used in conjunction with --no-hw to determine which encoder to use. Ignored if `encoder` is supplied [default: auto] [possible values: auto, avc, hevc, vp8, vp9] + --ffmpeg-muxer <FFMPEG_MUXER> + Which ffmpeg muxer to use. Guessed from output filename by default --ffmpeg-encoder <FFMPEG_ENCODER> Use this to force a particular ffmpeg encoder. Generally, this is not necessary and the combo of --codec and --hw can get you to where you need to be --encode-pixfmt <ENCODE_PIXFMT> which pixel format to encode with. not all codecs will support all pixel formats. This should be a ffmpeg pixel format string, like nv12 or x2rgb10 + --encode-resolution <ENCODE_RESOLUTION> + what resolution to encode at. example: 1920x1080. Default is the resolution of the captured region. If your goal is reducing filesize, it's suggested to try --bitrate/-b first -b, --bitrate <BITRATE> bitrate to encode at. Unit is bytes per second, so 5 MB is 40 Mbps [default: "5 MB"] --history <HISTORY> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wl-screenrec-0.1.0/src/avhw.rs new/wl-screenrec-0.1.2/src/avhw.rs --- old/wl-screenrec-0.1.0/src/avhw.rs 2023-10-02 05:06:03.000000000 +0200 +++ new/wl-screenrec-0.1.2/src/avhw.rs 2023-12-04 04:07:52.000000000 +0100 @@ -15,7 +15,7 @@ } impl AvHwDevCtx { - pub fn new_libva(dri_device: &str) -> Self { + pub fn new_libva(dri_device: &str) -> Result<Self, ffmpeg::Error> { unsafe { let mut hw_device_ctx = null_mut(); @@ -31,9 +31,12 @@ opts.as_mut_ptr(), 0, ); - assert_eq!(sts, 0, "failed to open {dri_device}"); - Self { ptr: hw_device_ctx } + if sts != 0 { + Err(ffmpeg::Error::from(sts)) + } else { + Ok(Self { ptr: hw_device_ctx }) + } } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wl-screenrec-0.1.0/src/main.rs new/wl-screenrec-0.1.2/src/main.rs --- old/wl-screenrec-0.1.0/src/main.rs 2023-10-02 05:06:03.000000000 +0200 +++ new/wl-screenrec-0.1.2/src/main.rs 2023-12-04 04:07:52.000000000 +0100 @@ -32,7 +32,7 @@ media, Packet, Rational, }; use human_size::{Byte, Megabyte, Size, SpecificSize}; -use signal_hook::consts::{SIGINT, SIGUSR1}; +use signal_hook::consts::{SIGINT, SIGTERM, SIGUSR1}; use thiserror::Error; use wayland_client::{ event_created_child, @@ -108,8 +108,8 @@ )] filename: String, - #[clap(long, short, value_parser=parse_geometry, help="geometry to capture, format x,y WxH. Compatiable with the output of `slurp`. Mutually exclusive with --output")] - geometry: Option<(u32, u32, u32, u32)>, + #[clap(long, short, value_parser=parse_geometry, help="geometry to capture, format x,y WxH. Compatiable with the output of `slurp`. Mutually exclusive with --output", allow_hyphen_values=true)] + geometry: Option<(i32, i32, u32, u32)>, #[clap( long, @@ -135,12 +135,18 @@ long, value_enum, default_value_t, - help = "which codec to use. Used in conjunction with --no-hw to determinte which enocder to use. Ignored if `encoder` is supplied" + help = "which codec to use. Used in conjunction with --no-hw to determine which encoder to use. Ignored if `encoder` is supplied" )] codec: Codec, #[clap( long, + help = "Which ffmpeg muxer to use. Guessed from output filename by default" + )] + ffmpeg_muxer: Option<String>, + + #[clap( + long, value_enum, help = "Use this to force a particular ffmpeg encoder. Generally, this is not necessary and the combo of --codec and --hw can get you to where you need to be" )] @@ -152,6 +158,9 @@ )] encode_pixfmt: Option<Pixel>, + #[clap(long, value_parser=parse_size, help="what resolution to encode at. example: 1920x1080. Default is the resolution of the captured region. If your goal is reducing filesize, it's suggested to try --bitrate/-b first")] + encode_resolution: Option<(u32, u32)>, + #[clap(long, short, default_value_t=SpecificSize::new(5, Megabyte).unwrap().into(), help="bitrate to encode at. Unit is bytes per second, so 5 MB is 40 Mbps")] bitrate: Size, @@ -207,7 +216,7 @@ Size, } -fn parse_geometry(s: &str) -> Result<(u32, u32, u32, u32), ParseGeometryError> { +fn parse_geometry(s: &str) -> Result<(i32, i32, u32, u32), ParseGeometryError> { use ParseGeometryError::*; let mut it = s.split(' '); let loc = it.next().ok_or(Structure)?; @@ -223,6 +232,13 @@ return Err(Location); } + let (sizex, sizey) = parse_size(size)?; + + Ok((startx, starty, sizex, sizey)) +} + +fn parse_size(size: &str) -> Result<(u32, u32), ParseGeometryError> { + use ParseGeometryError::*; let mut it = size.split('x'); let sizex = it.next().ok_or(Size)?.parse()?; let sizey = it.next().ok_or(Size)?.parse()?; @@ -230,7 +246,7 @@ return Err(Size); } - Ok((startx, starty, sizex, sizey)) + Ok((sizex, sizey)) } fn parse_duration(arg: &str) -> Result<std::time::Duration, std::num::ParseIntError> { @@ -829,7 +845,7 @@ let _wlr_output_man: ZwlrOutputManagerV1 = gm .bind( &eq, - ZwlrOutputManagerV1::interface().version..=ZwlrOutputManagerV1::interface().version, + 1..=4, (), ) .expect("Your compositor does not seem to support the wlr-output-manager protocol. wl-screenrec requires a wlroots based compositor like sway or Hyprland"); @@ -1008,8 +1024,6 @@ } } (Some((x, y, w, h)), "") => { - let x = x as i32; - let y = y as i32; let w = w as i32; let h = h as i32; // --geometry but no --output @@ -1138,12 +1152,16 @@ capture_pixfmt: Pixel, refresh: Rational, (capture_w, capture_h): (i32, i32), // pixels - (encode_x, encode_y): (i32, i32), - (encode_w, encode_h): (i32, i32), + (roi_x, roi_y): (i32, i32), + (roi_w, roi_h): (i32, i32), sigusr1_flag: Arc<AtomicBool>, dri_device: &str, ) -> anyhow::Result<Self> { - let mut octx = ffmpeg_next::format::output(&args.filename).unwrap(); + let mut octx = if let Some(muxer) = &args.ffmpeg_muxer { + ffmpeg_next::format::output_as(&args.filename, muxer).unwrap() + } else { + ffmpeg_next::format::output(&args.filename).unwrap() + }; let codec = if let Some(encoder) = &args.ffmpeg_encoder { ffmpeg_next::encoder::find_by_name(encoder).ok_or_else(|| { @@ -1187,17 +1205,19 @@ } }; - let codec_id = codec.id(); - let supported_formats = supported_formats(&codec); - if supported_formats.is_empty() { - bail!( - "Encoder {} does not support any pixel formats?", - codec.name() - ); - } - - let enc_pixfmt = if supported_formats.contains(&Pixel::VAAPI) { + let enc_pixfmt = if supported_formats.is_empty() { + match args.encode_pixfmt { + Some(fmt) => EncodePixelFormat::Sw(fmt), + None => { + eprintln!( + "codec \"{}\" does not advertize supported pixel formats, just using NV12. Pass --encode-pixfmt to suppress this warning", + codec.name() + ); + EncodePixelFormat::Sw(Pixel::NV12) + } + } + } else if supported_formats.contains(&Pixel::VAAPI) { EncodePixelFormat::Vaapi(args.encode_pixfmt.unwrap_or(Pixel::NV12)) } else { match args.encode_pixfmt { @@ -1207,6 +1227,7 @@ } }; + let codec_id = codec.id(); if unsafe { avformat_query_codec( octx.format().as_ptr(), @@ -1226,17 +1247,26 @@ eprintln!("Opening libva device from DRM device {dri_device}"); - let mut hw_device_ctx = AvHwDevCtx::new_libva(dri_device); + let mut hw_device_ctx = match AvHwDevCtx::new_libva(dri_device) { + Ok(hdc) => hdc, + Err(e) => bail!("Failed to load vaapi device: {e}\nThis is likely *not* a bug in wl-screenrec, but an issue with your vaapi installation. Follow your distribution's instructions. If you're pretty sure you've done this correctly, create a new issue with the output of `vainfo` and if `wf-recorder -c h264_vaapi -d /dev/dri/card0` works."), + }; let mut frames_rgb = hw_device_ctx .create_frame_ctx(capture_pixfmt, capture_w, capture_h) .unwrap(); + let (enc_w, enc_h) = match args.encode_resolution { + Some((x, y)) => (x as i32, y as i32), + None => (roi_w, roi_h), + }; + let (video_filter, filter_timebase) = video_filter( &mut frames_rgb, enc_pixfmt, (capture_w, capture_h), - (encode_x, encode_y), - (encode_w, encode_h), + (roi_x, roi_y), + (roi_w, roi_h), + (enc_w, enc_h), ); let mut frames_yuv = hw_device_ctx @@ -1245,8 +1275,8 @@ EncodePixelFormat::Vaapi(fmt) => fmt, EncodePixelFormat::Sw(fmt) => fmt, }, - encode_w, - encode_h, + enc_w, + enc_h, ) .unwrap(); @@ -1258,7 +1288,7 @@ args, enc_pixfmt, &codec, - (encode_w, encode_h), + (enc_w, enc_h), refresh, global_header, &mut hw_device_ctx, @@ -1287,7 +1317,7 @@ args, enc_pixfmt, &codec, - (encode_w, encode_h), + (enc_w, enc_h), refresh, global_header, &mut hw_device_ctx, @@ -1540,13 +1570,16 @@ inctx: &mut AvHwFrameCtx, pix_fmt: EncodePixelFormat, (capture_width, capture_height): (i32, i32), - (enc_x, enc_y): (i32, i32), - (enc_width, enc_height): (i32, i32), + (roi_x, roi_y): (i32, i32), + (roi_w, roi_h): (i32, i32), // size (pixels) of the region to capture + (enc_w, enc_h): (i32, i32), // size (pixels) to encode. if not same as roi_{w,h}, the image will be scaled ) -> (filter::Graph, Rational) { let mut g = ffmpeg::filter::graph::Graph::new(); g.add( &filter::find("buffer").unwrap(), "in", + // format is bogus, will be replaced below, as we need to pass + // hw_frames_ctx which isn't possible with args= &format!( "video_size=2840x2160:pix_fmt={}:time_base=1/1000000000", AVPixelFormat::AV_PIX_FMT_VAAPI as c_int @@ -1593,19 +1626,15 @@ ) }; + // exact=1 should not be necessary, as the input is not chroma-subsampled + // however, there is a bug in ffmpeg that makes it required: https://trac.ffmpeg.org/ticket/10669 + // it is harmless to add though, so keep it as a workaround g.output("in", 0) .unwrap() .input("out", 0) .unwrap() .parse(&format!( - "crop={}:{}:{}:{},scale_vaapi=format={}:w={}:h={}{}", - enc_width, - enc_height, - enc_x, - enc_y, - output_real_pixfmt_name, - enc_width, - enc_height, + "crop={roi_w}:{roi_h}:{roi_x}:{roi_y}:exact=1,scale_vaapi=format={output_real_pixfmt_name}:w={enc_w}:h={enc_h}{}", if let EncodePixelFormat::Vaapi(_) = pix_fmt { "" } else { @@ -1638,6 +1667,7 @@ let sigusr1_flag = Arc::new(AtomicBool::new(false)); signal_hook::flag::register(SIGINT, Arc::clone(&quit_flag)).unwrap(); + signal_hook::flag::register(SIGTERM, Arc::clone(&quit_flag)).unwrap(); signal_hook::flag::register(SIGUSR1, Arc::clone(&sigusr1_flag)).unwrap(); let args = Args::parse(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wl-screenrec-0.1.0/tests/cmdline.rs new/wl-screenrec-0.1.2/tests/cmdline.rs --- old/wl-screenrec-0.1.0/tests/cmdline.rs 2023-10-02 05:06:03.000000000 +0200 +++ new/wl-screenrec-0.1.2/tests/cmdline.rs 2023-12-04 04:07:52.000000000 +0100 @@ -59,6 +59,30 @@ } #[test] +fn scale() { + let filename = temp_dir().join("scale.mp4"); + + let mut cmd = Command::new(dbg!(wl_screenrec())) + .arg("--no-damage") + .arg("--encode-resolution=128x128") + .arg("-g=0,0 256x256") + .arg("-f") + .arg(&filename) + .spawn() + .unwrap(); + + sleep(Duration::from_secs(5)); + let pid = Pid::from_raw(cmd.id() as i32); + kill(pid, SIGINT).unwrap(); + + let wait_start = Instant::now(); + cmd.wait().unwrap(); + assert!(wait_start.elapsed() < Duration::from_secs(1)); + + assert_eq!(file_resolution(&filename), (128, 128)); +} + +#[test] fn basic() { let filename = temp_dir().join("basic.mp4"); @@ -84,11 +108,12 @@ assert!(dur < Duration::from_secs_f64(3.5), "{:?} > 3.5s", dur); } -fn file_duration(filename: &Path) -> Duration { - let json: Value = serde_json::from_str( +fn file_metadata(filename: &Path) -> Value { + serde_json::from_str( &String::from_utf8( Command::new("ffprobe") .arg("-show_format") + .arg("-show_streams") .arg("-print_format") .arg("json") .arg(&filename) @@ -98,7 +123,11 @@ ) .unwrap(), ) - .unwrap(); + .unwrap() +} + +fn file_duration(filename: &Path) -> Duration { + let json = file_metadata(filename); let dur: f64 = json .pointer("/format/duration") @@ -109,3 +138,22 @@ .unwrap(); Duration::from_secs_f64(dur) } + +fn file_resolution(filename: &Path) -> (i64, i64) { + let json = file_metadata(filename); + + ( + json.pointer("/streams/0/width") + .unwrap() + .as_number() + .unwrap() + .as_i64() + .unwrap(), + json.pointer("/streams/0/height") + .unwrap() + .as_number() + .unwrap() + .as_i64() + .unwrap(), + ) +}