From ae364f69bdd6c35023226b23aaf878099beb31e5 Mon Sep 17 00:00:00 2001 From: Kristian Ollikainen <14197772+DatCaptainHorse@users.noreply.github.com> Date: Fri, 23 May 2025 11:33:40 +0300 Subject: [PATCH] =?UTF-8?q?=E2=AD=90feat(runner):=20Improve=20robustness?= =?UTF-8?q?=20and=20argument=20handling=20(#285)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Made argument parsing and handling much nicer with clap features. Changed to tracing package for logging and made other improvements around to hopefully make things more robust and logical. Default audio-capture-method is now PipeWire since it seems to work perfectly fine with latest gstreamer :tada: ## Summary by CodeRabbit - **New Features** - Improved command-line argument parsing with stricter validation, type safety, and clearer help messages. - Enhanced GPU selection and logging, including explicit GPU info logging and support for negative GPU indices for auto-selection. - Added support for new audio and video codec and encoder enums, providing safer and more flexible codec handling. - **Bug Fixes** - Improved error handling and logging throughout the application, unifying logs under the `tracing` system for better diagnostics. - Fixed issues with directory ownership and environment variable handling in startup scripts. - **Refactor** - Replaced string-based parsing and manual conversions with strongly typed enums and value parsers. - Updated logging from `println!` and `log` macros to the `tracing` crate for consistency. - Simplified and unified the handling of pipeline and element references in the signaling and data channel logic. - **Chores** - Updated and cleaned up dependencies, including switching from `log` to `tracing` and upgrading the `webrtc` crate. - Removed unused or redundant code and environment variables for improved maintainability. --------- Co-authored-by: DatCaptainHorse --- containers/runner.Containerfile | 3 +- packages/scripts/entrypoint.sh | 26 +- packages/scripts/entrypoint_nestri.sh | 11 - packages/scripts/envs.sh | 3 - packages/server/Cargo.lock | 529 +++++++++++----------- packages/server/Cargo.toml | 9 +- packages/server/src/args.rs | 55 ++- packages/server/src/args/app_args.rs | 31 +- packages/server/src/args/device_args.rs | 28 +- packages/server/src/args/encoding_args.rs | 188 ++++---- packages/server/src/enc_helper.rs | 128 ++++-- packages/server/src/gpu.rs | 8 + packages/server/src/main.rs | 151 +++--- packages/server/src/messages.rs | 1 - packages/server/src/nestrisink/imp.rs | 36 +- packages/server/src/nestrisink/mod.rs | 4 +- packages/server/src/websocket.rs | 59 +-- 17 files changed, 653 insertions(+), 617 deletions(-) diff --git a/containers/runner.Containerfile b/containers/runner.Containerfile index 294825fc..fec41b43 100644 --- a/containers/runner.Containerfile +++ b/containers/runner.Containerfile @@ -168,8 +168,7 @@ ENV USER="nestri" \ USER_PWD="nestri1234" \ XDG_RUNTIME_DIR=/run/user/1000 \ HOME=/home/nestri \ - NVIDIA_DRIVER_CAPABILITIES=all \ - NVIDIA_VISIBLE_DEVICES=all + NVIDIA_DRIVER_CAPABILITIES=all RUN mkdir -p /home/${USER} && \ groupadd -g ${GID} ${USER} && \ diff --git a/packages/scripts/entrypoint.sh b/packages/scripts/entrypoint.sh index 684f0701..06747d25 100644 --- a/packages/scripts/entrypoint.sh +++ b/packages/scripts/entrypoint.sh @@ -10,6 +10,16 @@ log() { echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" } +# Ensures user directory ownership +chown_user_directory() { + local user_group="${USER}:${GID}" + if ! chown -R -h --no-preserve-root "$user_group" "${HOME}" 2>/dev/null; then + echo "Error: Failed to change ownership of ${HOME} to ${user_group}" >&2 + return 1 + fi + return 0 +} + # Waits for a given socket to be ready wait_for_socket() { local socket_path="$1" @@ -110,6 +120,13 @@ install_nvidia_driver() { return 0 } +function log_gpu_info { + log "Detected GPUs:" + for vendor in "${!vendor_devices[@]}"; do + log "> $vendor: ${vendor_devices[$vendor]}" + done +} + main() { # Wait for required sockets wait_for_socket "/run/dbus/system_bus_socket" "DBus" || exit 1 @@ -126,10 +143,11 @@ main() { log "Error: Failed to detect GPU information." exit 1 } + log_gpu_info # Handle NVIDIA GPU if [[ -n "${vendor_devices[nvidia]:-}" ]]; then - log "NVIDIA GPU detected, applying driver fix..." + log "NVIDIA GPU(s) detected, applying driver fix..." # Determine NVIDIA driver version local nvidia_driver_version="" @@ -180,8 +198,6 @@ main() { fi } fi - else - log "No NVIDIA GPU detected, skipping driver fix." fi # Make sure gamescope has CAP_SYS_NICE capabilities if available @@ -195,6 +211,10 @@ main() { log "Skipping CAP_SYS_NICE for gamescope, capability not available..." fi + # Handle user directory permissions + log "Ensuring user directory permissions..." + chown_user_directory || exit 1 + # Switch to nestri user log "Switching to nestri user for application startup..." if [[ ! -x /etc/nestri/entrypoint_nestri.sh ]]; then diff --git a/packages/scripts/entrypoint_nestri.sh b/packages/scripts/entrypoint_nestri.sh index 0bb35862..1ff1d6bd 100644 --- a/packages/scripts/entrypoint_nestri.sh +++ b/packages/scripts/entrypoint_nestri.sh @@ -5,16 +5,6 @@ log() { echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" } -# Ensures user directory ownership -chown_user_directory() { - local user_group="$(id -nu):$(id -ng)" - chown -f "$user_group" ~ 2>/dev/null || - sudo chown -f "$user_group" ~ 2>/dev/null || - chown -R -f -h --no-preserve-root "$user_group" ~ 2>/dev/null || - sudo chown -R -f -h --no-preserve-root "$user_group" ~ 2>/dev/null || - log "Warning: Failed to change user directory permissions, there may be permission issues, continuing..." -} - # Parses resolution string parse_resolution() { local resolution="$1" @@ -156,7 +146,6 @@ main_loop() { } main() { - chown_user_directory load_envs parse_resolution "${RESOLUTION:-1920x1080}" || exit 1 restart_chain diff --git a/packages/scripts/envs.sh b/packages/scripts/envs.sh index 006a3369..f97f1a72 100644 --- a/packages/scripts/envs.sh +++ b/packages/scripts/envs.sh @@ -11,6 +11,3 @@ export PROTON_NO_FSYNC=1 # Sleeker Mangohud preset :) export MANGOHUD_CONFIG=preset=2 - -# Our preferred prefix -export WINEPREFIX=/home/${USER}/.nestripfx/ diff --git a/packages/server/Cargo.lock b/packages/server/Cargo.lock index 5d4f8b54..15673e25 100644 --- a/packages/server/Cargo.lock +++ b/packages/server/Cargo.lock @@ -128,9 +128,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "arc-swap" @@ -238,9 +238,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-rs" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b756939cb2f8dc900aa6dcd505e6e2428e9cae7ff7b028c49e3946efa70878" +checksum = "93fcc8f365936c834db5514fc45aee5b1202d677e6b40e48468aaaa8183ca8c7" dependencies = [ "aws-lc-sys", "zeroize", @@ -248,9 +248,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f7720b74ed28ca77f90769a71fd8c637a0137f6fae4ae947e1050229cff57f" +checksum = "61b1d86e7705efe1be1b569bab41d4fa1e14e220b60a160f78de2db687add079" dependencies = [ "bindgen", "cc", @@ -261,9 +261,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", "cfg-if", @@ -313,7 +313,7 @@ version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "cexpr", "clang-sys", "itertools 0.12.1", @@ -338,9 +338,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "block-buffer" @@ -389,9 +389,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.18" +version = "1.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c" +checksum = "5f4ac86a9e5bc1e2b3449ab9d7d3a6a405e3d1bb28d7b9be8614f55846ae3766" dependencies = [ "jobserver", "libc", @@ -421,9 +421,9 @@ dependencies = [ [[package]] name = "cfg-expr" -version = "0.17.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d4ba6e40bd1184518716a6e1a781bf9160e286d219ccdb8ab2612e74cfe4789" +checksum = "e34e221e91c7eb5e8315b5c9cf1a61670938c0626451f954a51693ed44b37f45" dependencies = [ "smallvec", "target-lexicon", @@ -443,9 +443,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ "android-tzdata", "iana-time-zone", @@ -478,9 +478,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.35" +version = "4.5.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944" +checksum = "ed93b9805f8ba930df42c2590f05453d5ec36cbb85d018868a5b24d31f6ac000" dependencies = [ "clap_builder", "clap_derive", @@ -488,9 +488,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.35" +version = "4.5.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9" +checksum = "379026ff283facf611b0ea629334361c4211d1b12ee01024eec1591133b04120" dependencies = [ "anstream", "anstyle", @@ -564,9 +564,9 @@ dependencies = [ [[package]] name = "crc" -version = "3.2.1" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" dependencies = [ "crc-catalog", ] @@ -611,11 +611,11 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.4.6" +version = "3.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697b5419f348fd5ae2478e8018cb016c00a5881c7f46c717de98ffd135a5651c" +checksum = "46f93780a459b7d656ef7f071fe699c4d3d2cb201c4b24d085b6ddc505276e73" dependencies = [ - "nix 0.29.0", + "nix 0.30.1", "windows-sys 0.59.0", ] @@ -647,15 +647,15 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] name = "der" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ "const-oid", "pem-rfc7468", @@ -772,9 +772,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" +checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" dependencies = [ "libc", "windows-sys 0.59.0", @@ -940,9 +940,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", @@ -951,9 +951,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", @@ -980,7 +980,7 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "gio" version = "0.21.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#2af41a12deb9a8ad532bc4f3b5e3d0499463dce4" +source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#8b1c516f2ea930d67fadd36ebdccb9747096f2db" dependencies = [ "futures-channel", "futures-core", @@ -996,7 +996,7 @@ dependencies = [ [[package]] name = "gio-sys" version = "0.21.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#2af41a12deb9a8ad532bc4f3b5e3d0499463dce4" +source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#8b1c516f2ea930d67fadd36ebdccb9747096f2db" dependencies = [ "glib-sys", "gobject-sys", @@ -1008,9 +1008,9 @@ dependencies = [ [[package]] name = "glib" version = "0.21.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#2af41a12deb9a8ad532bc4f3b5e3d0499463dce4" +source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#8b1c516f2ea930d67fadd36ebdccb9747096f2db" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "futures-channel", "futures-core", "futures-executor", @@ -1028,7 +1028,7 @@ dependencies = [ [[package]] name = "glib-macros" version = "0.21.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#2af41a12deb9a8ad532bc4f3b5e3d0499463dce4" +source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#8b1c516f2ea930d67fadd36ebdccb9747096f2db" dependencies = [ "heck", "proc-macro-crate", @@ -1040,7 +1040,7 @@ dependencies = [ [[package]] name = "glib-sys" version = "0.21.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#2af41a12deb9a8ad532bc4f3b5e3d0499463dce4" +source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#8b1c516f2ea930d67fadd36ebdccb9747096f2db" dependencies = [ "libc", "system-deps", @@ -1055,7 +1055,7 @@ checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "gobject-sys" version = "0.21.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#2af41a12deb9a8ad532bc4f3b5e3d0499463dce4" +source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#8b1c516f2ea930d67fadd36ebdccb9747096f2db" dependencies = [ "glib-sys", "libc", @@ -1076,7 +1076,7 @@ dependencies = [ [[package]] name = "gst-plugin-version-helper" version = "0.8.1" -source = "git+https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs?branch=main#916e946bf1446316c4aa7d29c35fc7f732f1f1b5" +source = "git+https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs?branch=main#64503810177805870bb8f835638ccfa4eef2a028" dependencies = [ "chrono", "toml_edit", @@ -1085,7 +1085,7 @@ dependencies = [ [[package]] name = "gst-plugin-webrtc" version = "0.14.0-alpha.1" -source = "git+https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs?branch=main#916e946bf1446316c4aa7d29c35fc7f732f1f1b5" +source = "git+https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs?branch=main#64503810177805870bb8f835638ccfa4eef2a028" dependencies = [ "anyhow", "async-recursion", @@ -1111,7 +1111,7 @@ dependencies = [ "human_bytes", "itertools 0.14.0", "parse_link_header", - "rand 0.9.0", + "rand 0.9.1", "reqwest", "serde", "serde_json", @@ -1130,7 +1130,7 @@ dependencies = [ [[package]] name = "gst-plugin-webrtc-signalling" version = "0.14.0-alpha.1" -source = "git+https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs?branch=main#916e946bf1446316c4aa7d29c35fc7f732f1f1b5" +source = "git+https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs?branch=main#64503810177805870bb8f835638ccfa4eef2a028" dependencies = [ "anyhow", "async-tungstenite", @@ -1153,7 +1153,7 @@ dependencies = [ [[package]] name = "gst-plugin-webrtc-signalling-protocol" version = "0.14.0-alpha.1" -source = "git+https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs?branch=main#916e946bf1446316c4aa7d29c35fc7f732f1f1b5" +source = "git+https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs?branch=main#64503810177805870bb8f835638ccfa4eef2a028" dependencies = [ "serde", "serde_json", @@ -1162,7 +1162,7 @@ dependencies = [ [[package]] name = "gstreamer" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#b6e4e615d22f2a0a81130d69535baa0d2faf440a" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#c3d3ce5f2da7a0d3939be2997ccae9f2e9c9e359" dependencies = [ "cfg-if", "futures-channel", @@ -1188,7 +1188,7 @@ dependencies = [ [[package]] name = "gstreamer-app" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#b6e4e615d22f2a0a81130d69535baa0d2faf440a" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#c3d3ce5f2da7a0d3939be2997ccae9f2e9c9e359" dependencies = [ "futures-core", "futures-sink", @@ -1202,7 +1202,7 @@ dependencies = [ [[package]] name = "gstreamer-app-sys" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#b6e4e615d22f2a0a81130d69535baa0d2faf440a" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#c3d3ce5f2da7a0d3939be2997ccae9f2e9c9e359" dependencies = [ "glib-sys", "gstreamer-base-sys", @@ -1214,7 +1214,7 @@ dependencies = [ [[package]] name = "gstreamer-audio" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#b6e4e615d22f2a0a81130d69535baa0d2faf440a" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#c3d3ce5f2da7a0d3939be2997ccae9f2e9c9e359" dependencies = [ "cfg-if", "glib", @@ -1229,7 +1229,7 @@ dependencies = [ [[package]] name = "gstreamer-audio-sys" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#b6e4e615d22f2a0a81130d69535baa0d2faf440a" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#c3d3ce5f2da7a0d3939be2997ccae9f2e9c9e359" dependencies = [ "glib-sys", "gobject-sys", @@ -1242,7 +1242,7 @@ dependencies = [ [[package]] name = "gstreamer-base" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#b6e4e615d22f2a0a81130d69535baa0d2faf440a" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#c3d3ce5f2da7a0d3939be2997ccae9f2e9c9e359" dependencies = [ "atomic_refcell", "cfg-if", @@ -1255,7 +1255,7 @@ dependencies = [ [[package]] name = "gstreamer-base-sys" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#b6e4e615d22f2a0a81130d69535baa0d2faf440a" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#c3d3ce5f2da7a0d3939be2997ccae9f2e9c9e359" dependencies = [ "glib-sys", "gobject-sys", @@ -1267,7 +1267,7 @@ dependencies = [ [[package]] name = "gstreamer-net" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#b6e4e615d22f2a0a81130d69535baa0d2faf440a" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#c3d3ce5f2da7a0d3939be2997ccae9f2e9c9e359" dependencies = [ "gio", "glib", @@ -1278,7 +1278,7 @@ dependencies = [ [[package]] name = "gstreamer-net-sys" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#b6e4e615d22f2a0a81130d69535baa0d2faf440a" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#c3d3ce5f2da7a0d3939be2997ccae9f2e9c9e359" dependencies = [ "gio-sys", "glib-sys", @@ -1290,7 +1290,7 @@ dependencies = [ [[package]] name = "gstreamer-rtp" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#b6e4e615d22f2a0a81130d69535baa0d2faf440a" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#c3d3ce5f2da7a0d3939be2997ccae9f2e9c9e359" dependencies = [ "glib", "gstreamer", @@ -1301,7 +1301,7 @@ dependencies = [ [[package]] name = "gstreamer-rtp-sys" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#b6e4e615d22f2a0a81130d69535baa0d2faf440a" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#c3d3ce5f2da7a0d3939be2997ccae9f2e9c9e359" dependencies = [ "glib-sys", "gstreamer-base-sys", @@ -1313,7 +1313,7 @@ dependencies = [ [[package]] name = "gstreamer-sdp" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#b6e4e615d22f2a0a81130d69535baa0d2faf440a" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#c3d3ce5f2da7a0d3939be2997ccae9f2e9c9e359" dependencies = [ "glib", "gstreamer", @@ -1323,7 +1323,7 @@ dependencies = [ [[package]] name = "gstreamer-sdp-sys" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#b6e4e615d22f2a0a81130d69535baa0d2faf440a" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#c3d3ce5f2da7a0d3939be2997ccae9f2e9c9e359" dependencies = [ "glib-sys", "gstreamer-sys", @@ -1334,7 +1334,7 @@ dependencies = [ [[package]] name = "gstreamer-sys" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#b6e4e615d22f2a0a81130d69535baa0d2faf440a" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#c3d3ce5f2da7a0d3939be2997ccae9f2e9c9e359" dependencies = [ "cfg-if", "glib-sys", @@ -1346,7 +1346,7 @@ dependencies = [ [[package]] name = "gstreamer-utils" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#b6e4e615d22f2a0a81130d69535baa0d2faf440a" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#c3d3ce5f2da7a0d3939be2997ccae9f2e9c9e359" dependencies = [ "gstreamer", "gstreamer-app", @@ -1357,7 +1357,7 @@ dependencies = [ [[package]] name = "gstreamer-video" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#b6e4e615d22f2a0a81130d69535baa0d2faf440a" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#c3d3ce5f2da7a0d3939be2997ccae9f2e9c9e359" dependencies = [ "cfg-if", "futures-channel", @@ -1373,7 +1373,7 @@ dependencies = [ [[package]] name = "gstreamer-video-sys" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#b6e4e615d22f2a0a81130d69535baa0d2faf440a" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#c3d3ce5f2da7a0d3939be2997ccae9f2e9c9e359" dependencies = [ "glib-sys", "gobject-sys", @@ -1386,7 +1386,7 @@ dependencies = [ [[package]] name = "gstreamer-webrtc" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#b6e4e615d22f2a0a81130d69535baa0d2faf440a" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#c3d3ce5f2da7a0d3939be2997ccae9f2e9c9e359" dependencies = [ "glib", "gstreamer", @@ -1398,7 +1398,7 @@ dependencies = [ [[package]] name = "gstreamer-webrtc-sys" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#b6e4e615d22f2a0a81130d69535baa0d2faf440a" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#c3d3ce5f2da7a0d3939be2997ccae9f2e9c9e359" dependencies = [ "glib-sys", "gstreamer-sdp-sys", @@ -1428,9 +1428,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2" +checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" dependencies = [ "atomic-waker", "bytes", @@ -1447,9 +1447,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" [[package]] name = "headers" @@ -1621,7 +1621,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.8", + "h2 0.4.10", "http 1.3.1", "http-body 1.0.1", "httparse", @@ -1642,7 +1642,7 @@ dependencies = [ "http 1.3.1", "hyper 1.6.0", "hyper-util", - "rustls 0.23.25", + "rustls 0.23.27", "rustls-pki-types", "tokio", "tokio-rustls 0.26.2", @@ -1667,9 +1667,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2" +checksum = "cf9f1e950e0d9d1d3c47184416723cf29c0d1f93bd8cccf37e4beb6b44f31710" dependencies = [ "bytes", "futures-channel", @@ -1711,21 +1711,22 @@ dependencies = [ [[package]] name = "icu_collections" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" dependencies = [ "displaydoc", + "potential_utf", "yoke", "zerofrom", "zerovec", ] [[package]] -name = "icu_locid" -version = "1.5.0" +name = "icu_locale_core" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" dependencies = [ "displaydoc", "litemap", @@ -1734,31 +1735,11 @@ dependencies = [ "zerovec", ] -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" - [[package]] name = "icu_normalizer" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" dependencies = [ "displaydoc", "icu_collections", @@ -1766,67 +1747,54 @@ dependencies = [ "icu_properties", "icu_provider", "smallvec", - "utf16_iter", - "utf8_iter", - "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" -version = "1.5.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" [[package]] name = "icu_properties" -version = "1.5.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" dependencies = [ "displaydoc", "icu_collections", - "icu_locid_transform", + "icu_locale_core", "icu_properties_data", "icu_provider", - "tinystr", + "potential_utf", + "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "1.5.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" [[package]] name = "icu_provider" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" dependencies = [ "displaydoc", - "icu_locid", - "icu_provider_macros", + "icu_locale_core", "stable_deref_trait", "tinystr", "writeable", "yoke", "zerofrom", + "zerotrie", "zerovec", ] -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "idna" version = "1.0.3" @@ -1840,9 +1808,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", @@ -1870,9 +1838,9 @@ dependencies = [ [[package]] name = "interceptor" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ab04c530fd82e414e40394cabe5f0ebfe30d119f10fe29d6e3561926af412e" +checksum = "1ac0781c825d602095113772e389ef0607afcb869ae0e68a590d8e0799cdcef8" dependencies = [ "async-trait", "bytes", @@ -1930,7 +1898,7 @@ version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ - "getrandom 0.3.2", + "getrandom 0.3.3", "libc", ] @@ -1967,18 +1935,18 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.171" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libloading" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +checksum = "6a793df0d7afeac54f95b471d3af7f0d4fb975699f972341a4b76988d49cdf0c" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.53.0", ] [[package]] @@ -1989,15 +1957,15 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "litemap" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "lock_api" @@ -2143,19 +2111,20 @@ dependencies = [ "gst-plugin-webrtc", "gstreamer", "gstreamer-webrtc", - "log", "num-derive", "num-traits", "parking_lot", "prost", "prost-types", - "rand 0.9.0", + "rand 0.9.1", "regex", - "rustls 0.23.25", + "rustls 0.23.27", "serde", "serde_json", "tokio", "tokio-tungstenite 0.26.2", + "tracing", + "tracing-subscriber", "webrtc", ] @@ -2174,11 +2143,11 @@ dependencies = [ [[package]] name = "nix" -version = "0.29.0" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "cfg-if", "cfg_aliases", "libc", @@ -2296,7 +2265,7 @@ version = "0.10.72" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "cfg-if", "foreign-types", "libc", @@ -2324,9 +2293,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.107" +version = "0.9.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" +checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847" dependencies = [ "cc", "libc", @@ -2505,6 +2474,15 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -2550,9 +2528,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -2617,13 +2595,12 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", - "zerocopy", ] [[package]] @@ -2652,7 +2629,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", ] [[package]] @@ -2661,7 +2638,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.2", + "getrandom 0.3.3", ] [[package]] @@ -2680,11 +2657,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" +checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", ] [[package]] @@ -2742,7 +2719,7 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2 0.4.8", + "h2 0.4.10", "http 1.3.1", "http-body 1.0.1", "http-body-util", @@ -2793,7 +2770,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.15", + "getrandom 0.2.16", "libc", "untrusted", "windows-sys 0.52.0", @@ -2801,9 +2778,9 @@ dependencies = [ [[package]] name = "rtcp" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8306430fb118b7834bbee50e744dc34826eca1da2158657a3d6cbc70e24c2096" +checksum = "e9689528bf3a9eb311fd938d05516dd546412f9ce4fffc8acfc1db27cc3dbf72" dependencies = [ "bytes", "thiserror 1.0.69", @@ -2812,9 +2789,9 @@ dependencies = [ [[package]] name = "rtp" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e68baca5b6cb4980678713f0d06ef3a432aa642baefcbfd0f4dd2ef9eb5ab550" +checksum = "c54733451a67d76caf9caa07a7a2cec6871ea9dda92a7847f98063d459200f4b" dependencies = [ "bytes", "memchr", @@ -2861,7 +2838,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "errno", "libc", "linux-raw-sys 0.4.15", @@ -2870,14 +2847,14 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.5" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "errno", "libc", - "linux-raw-sys 0.9.3", + "linux-raw-sys 0.9.4", "windows-sys 0.59.0", ] @@ -2897,16 +2874,16 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.25" +version = "0.23.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c" +checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" dependencies = [ "aws-lc-rs", "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.103.1", + "rustls-webpki 0.103.3", "subtle", "zeroize", ] @@ -2922,9 +2899,12 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "zeroize", +] [[package]] name = "rustls-webpki" @@ -2939,9 +2919,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.1" +version = "0.103.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" +checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" dependencies = [ "aws-lc-rs", "ring", @@ -2984,9 +2964,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sdp" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02a526161f474ae94b966ba622379d939a8fe46c930eebbadb73e339622599d5" +checksum = "4cd277015eada44a0bb810a4b84d3bf6e810573fa62fb442f457edf6a1087a69" dependencies = [ "rand 0.8.5", "substring", @@ -3014,7 +2994,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "core-foundation", "core-foundation-sys", "libc", @@ -3112,9 +3092,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -3138,9 +3118,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" dependencies = [ "libc", ] @@ -3225,9 +3205,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "stun" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea256fb46a13f9204e9dee9982997b2c3097db175a9fddaa8350310d03c4d5a3" +checksum = "7dbc2bab375524093c143dc362a03fb6a1fb79e938391cdb21665688f88a088a" dependencies = [ "base64 0.22.1", "crc", @@ -3259,9 +3239,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.100" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", @@ -3279,9 +3259,9 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", @@ -3294,7 +3274,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "core-foundation", "system-configuration-sys", ] @@ -3311,9 +3291,9 @@ dependencies = [ [[package]] name = "system-deps" -version = "7.0.3" +version = "7.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d23aaf9f331227789a99e8de4c91bf46703add012bdfd45fdecdfb2975a005" +checksum = "550b2c61a9c30b85ca1f6ef0afcd2befcb12e73b1d31ef0526423bc7b6a99d7f" dependencies = [ "cfg-expr", "heck", @@ -3324,20 +3304,20 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.16" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" +checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a" [[package]] name = "tempfile" -version = "3.19.1" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ "fastrand", - "getrandom 0.3.2", + "getrandom 0.3.3", "once_cell", - "rustix 1.0.5", + "rustix 1.0.7", "windows-sys 0.59.0", ] @@ -3445,9 +3425,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.6" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ "displaydoc", "zerovec", @@ -3455,9 +3435,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.44.2" +version = "1.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" +checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165" dependencies = [ "backtrace", "bytes", @@ -3509,7 +3489,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ - "rustls 0.23.25", + "rustls 0.23.27", "tokio", ] @@ -3552,9 +3532,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.14" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" dependencies = [ "bytes", "futures-core", @@ -3565,9 +3545,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.20" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" dependencies = [ "serde", "serde_spanned", @@ -3577,18 +3557,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.24" +version = "0.22.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" dependencies = [ "indexmap", "serde", @@ -3723,7 +3703,7 @@ dependencies = [ "httparse", "log", "native-tls", - "rand 0.9.0", + "rand 0.9.1", "sha1", "thiserror 2.0.12", "url", @@ -3732,9 +3712,9 @@ dependencies = [ [[package]] name = "turn" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0044fdae001dd8a1e247ea6289abf12f4fcea1331a2364da512f9cd680bbd8cb" +checksum = "3f5aea1116456e1da71c45586b87c72e3b43164fbf435eb93ff6aa475416a9a4" dependencies = [ "async-trait", "base64 0.22.1", @@ -3802,12 +3782,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -3826,7 +3800,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" dependencies = [ - "getrandom 0.3.2", + "getrandom 0.3.3", ] [[package]] @@ -4000,9 +3974,9 @@ dependencies = [ [[package]] name = "webrtc" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30367074d9f18231d28a74fab0120856b2b665da108d71a12beab7185a36f97b" +checksum = "24bab7195998d605c862772f90a452ba655b90a2f463c850ac032038890e367a" dependencies = [ "arc-swap", "async-trait", @@ -4019,7 +3993,7 @@ dependencies = [ "ring", "rtcp", "rtp", - "rustls 0.23.25", + "rustls 0.23.27", "sdp", "serde", "serde_json", @@ -4044,9 +4018,9 @@ dependencies = [ [[package]] name = "webrtc-data" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec93b991efcd01b73c5b3503fa8adba159d069abe5785c988ebe14fcf8f05d1" +checksum = "4e97b932854da633a767eff0cc805425a2222fc6481e96f463e57b015d949d1d" dependencies = [ "bytes", "log", @@ -4059,9 +4033,9 @@ dependencies = [ [[package]] name = "webrtc-dtls" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c9b89fc909f9da0499283b1112cd98f72fec28e55a54a9e352525ca65cd95c" +checksum = "5ccbe4d9049390ab52695c3646c1395c877e16c15fb05d3bda8eee0c7351711c" dependencies = [ "aes", "aes-gcm", @@ -4081,7 +4055,7 @@ dependencies = [ "rand_core 0.6.4", "rcgen", "ring", - "rustls 0.23.25", + "rustls 0.23.27", "sec1", "serde", "sha1", @@ -4096,9 +4070,9 @@ dependencies = [ [[package]] name = "webrtc-ice" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0348b28b593f7709ac98d872beb58c0009523df652c78e01b950ab9c537ff17d" +checksum = "eb51bde0d790f109a15bfe4d04f1b56fb51d567da231643cb3f21bb74d678997" dependencies = [ "arc-swap", "async-trait", @@ -4121,9 +4095,9 @@ dependencies = [ [[package]] name = "webrtc-mdns" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6dfe9686c6c9c51428da4de415cb6ca2dc0591ce2b63212e23fd9cccf0e316b" +checksum = "979cc85259c53b7b620803509d10d35e2546fa505d228850cbe3f08765ea6ea8" dependencies = [ "log", "socket2", @@ -4134,9 +4108,9 @@ dependencies = [ [[package]] name = "webrtc-media" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e153be16b8650021ad3e9e49ab6e5fa9fb7f6d1c23c213fd8bbd1a1135a4c704" +checksum = "80041211deccda758a3e19aa93d6b10bc1d37c9183b519054b40a83691d13810" dependencies = [ "byteorder", "bytes", @@ -4147,9 +4121,9 @@ dependencies = [ [[package]] name = "webrtc-sctp" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5faf3846ec4b7e64b56338d62cbafe084aa79806b0379dff5cc74a8b7a2b3063" +checksum = "07439c134425d51d2f10907aaf2f815fdfb587dce19fe94a4ae8b5faf2aae5ae" dependencies = [ "arc-swap", "async-trait", @@ -4165,9 +4139,9 @@ dependencies = [ [[package]] name = "webrtc-srtp" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771db9993712a8fb3886d5be4613ebf27250ef422bd4071988bf55f1ed1a64fa" +checksum = "01e773f79b09b057ffbda6b03fe7b43403b012a240cf8d05d630674c3723b5bb" dependencies = [ "aead", "aes", @@ -4188,9 +4162,9 @@ dependencies = [ [[package]] name = "webrtc-util" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1438a8fd0d69c5775afb4a71470af92242dbd04059c61895163aa3c1ef933375" +checksum = "64bfb10dbe6d762f80169ae07cf252bafa1f764b9594d140008a0231c0cdce58" dependencies = [ "async-trait", "bitflags 1.3.2", @@ -4243,15 +4217,15 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.61.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", "windows-link", "windows-result", - "windows-strings 0.4.0", + "windows-strings 0.4.2", ] [[package]] @@ -4295,9 +4269,9 @@ dependencies = [ [[package]] name = "windows-result" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ "windows-link", ] @@ -4313,9 +4287,9 @@ dependencies = [ [[package]] name = "windows-strings" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ "windows-link", ] @@ -4468,9 +4442,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.7.6" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10" +checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" dependencies = [ "memchr", ] @@ -4481,20 +4455,14 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - [[package]] name = "writeable" -version = "0.5.5" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "x25519-dalek" @@ -4537,9 +4505,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ "serde", "stable_deref_trait", @@ -4549,9 +4517,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", @@ -4561,18 +4529,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.24" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" +checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.24" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" +checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", @@ -4621,10 +4589,21 @@ dependencies = [ ] [[package]] -name = "zerovec" -version = "0.10.4" +name = "zerotrie" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" dependencies = [ "yoke", "zerofrom", @@ -4633,9 +4612,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", diff --git a/packages/server/Cargo.toml b/packages/server/Cargo.toml index eb8b2c64..ca754fb6 100644 --- a/packages/server/Cargo.toml +++ b/packages/server/Cargo.toml @@ -10,17 +10,18 @@ path = "src/main.rs" [dependencies] gst = { package = "gstreamer", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", branch = "main", features = ["v1_26"] } gst-webrtc = { package = "gstreamer-webrtc", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", branch = "main", features = ["v1_26"] } -gstrswebrtc = { package = "gst-plugin-webrtc", git = "https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs", branch = "main", features = ["v1_22"] } +gstrswebrtc = { package = "gst-plugin-webrtc", git = "https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs", branch = "main" } serde = {version = "1.0", features = ["derive"] } tokio = { version = "1.44", features = ["full"] } clap = { version = "4.5", features = ["env"] } serde_json = "1.0" -webrtc = "0.12" +webrtc = "0.13" regex = "1.11" rand = "0.9" rustls = { version = "0.23", features = ["ring"] } tokio-tungstenite = { version = "0.26", features = ["native-tls"] } -log = { version = "0.4", features = ["std"] } +tracing = "0.1" +tracing-subscriber = "0.3" chrono = "0.4" futures-util = "0.3" num-derive = "0.4" @@ -28,4 +29,4 @@ num-traits = "0.2" prost = "0.13" prost-types = "0.13" parking_lot = "0.12" -atomic_refcell = "0.1" +atomic_refcell = "0.1" \ No newline at end of file diff --git a/packages/server/src/args.rs b/packages/server/src/args.rs index 9c3907b7..ad3df445 100644 --- a/packages/server/src/args.rs +++ b/packages/server/src/args.rs @@ -1,4 +1,7 @@ -use clap::{Arg, Command}; +use crate::args::encoding_args::AudioCaptureMethod; +use crate::enc_helper::{AudioCodec, EncoderType, VideoCodec}; +use clap::{Arg, Command, value_parser}; +use clap::builder::{BoolishValueParser, NonEmptyStringValueParser}; pub mod app_args; pub mod device_args; @@ -19,6 +22,7 @@ impl Args { .long("verbose") .env("VERBOSE") .help("Enable verbose output") + .value_parser(BoolishValueParser::new()) .default_value("false"), ) .arg( @@ -26,7 +30,8 @@ impl Args { .short('d') .long("debug") .env("DEBUG") - .help("Enable additional debugging information and features") + .help("Enable additional debugging features") + .value_parser(BoolishValueParser::new()) .default_value("false"), ) .arg( @@ -34,6 +39,7 @@ impl Args { .short('u') .long("relay-url") .env("RELAY_URL") + .value_parser(NonEmptyStringValueParser::new()) .help("Nestri relay URL"), ) .arg( @@ -42,6 +48,7 @@ impl Args { .long("resolution") .env("RESOLUTION") .help("Display/stream resolution in 'WxH' format") + .value_parser(NonEmptyStringValueParser::new()) .default_value("1280x720"), ) .arg( @@ -50,6 +57,7 @@ impl Args { .long("framerate") .env("FRAMERATE") .help("Display/stream framerate") + .value_parser(value_parser!(u32).range(5..240)) .default_value("60"), ) .arg( @@ -63,7 +71,7 @@ impl Args { .short('g') .long("gpu-vendor") .env("GPU_VENDOR") - .help("GPU to find by vendor (e.g. 'nvidia')") + .help("GPU to use by vendor") .required(false), ) .arg( @@ -71,7 +79,7 @@ impl Args { .short('n') .long("gpu-name") .env("GPU_NAME") - .help("GPU to find by name (e.g. 'rtx 3060')") + .help("GPU to use by name") .required(false), ) .arg( @@ -79,14 +87,15 @@ impl Args { .short('i') .long("gpu-index") .env("GPU_INDEX") - .help("GPU index, if multiple similar GPUs are present") - .default_value("0"), + .help("GPU to use by index") + .value_parser(value_parser!(i32).range(-1..)) + .default_value("-1") ) .arg( Arg::new("gpu-card-path") .long("gpu-card-path") .env("GPU_CARD_PATH") - .help("Force a specific GPU by card/render path (e.g. '/dev/dri/card0')") + .help("Force a specific GPU by /dev/dri/ card or render path") .required(false) .conflicts_with_all(["gpu-vendor", "gpu-name", "gpu-index"]), ) @@ -95,27 +104,30 @@ impl Args { .short('c') .long("video-codec") .env("VIDEO_CODEC") - .help("Preferred video codec ('h264', 'h265', 'av1')") + .help("Preferred video codec") + .value_parser(value_parser!(VideoCodec)) .default_value("h264"), ) .arg( Arg::new("video-encoder") .long("video-encoder") .env("VIDEO_ENCODER") - .help("Override video encoder (e.g. 'vah264enc')"), + .help("Override video encoder"), ) .arg( Arg::new("video-rate-control") .long("video-rate-control") .env("VIDEO_RATE_CONTROL") - .help("Rate control method ('cqp', 'vbr', 'cbr')") - .default_value("vbr"), + .help("Rate control method") + .value_parser(value_parser!(encoding_args::RateControlMethod)) + .default_value("cbr"), ) .arg( Arg::new("video-cqp") .long("video-cqp") .env("VIDEO_CQP") .help("Constant Quantization Parameter (CQP) quality") + .value_parser(value_parser!(u32).range(1..51)) .default_value("26"), ) .arg( @@ -123,6 +135,7 @@ impl Args { .long("video-bitrate") .env("VIDEO_BITRATE") .help("Target bitrate in kbps") + .value_parser(value_parser!(u32).range(1..)) .default_value("6000"), ) .arg( @@ -130,27 +143,31 @@ impl Args { .long("video-bitrate-max") .env("VIDEO_BITRATE_MAX") .help("Maximum bitrate in kbps") + .value_parser(value_parser!(u32).range(1..)) .default_value("8000"), ) .arg( Arg::new("video-encoder-type") .long("video-encoder-type") .env("VIDEO_ENCODER_TYPE") - .help("Encoder type ('hardware', 'software')") + .help("Encoder type") + .value_parser(value_parser!(EncoderType)) .default_value("hardware"), ) .arg( Arg::new("audio-capture-method") .long("audio-capture-method") .env("AUDIO_CAPTURE_METHOD") - .help("Audio capture method ('pipewire', 'pulseaudio', 'alsa')") - .default_value("pulseaudio"), + .help("Audio capture method") + .value_parser(value_parser!(AudioCaptureMethod)) + .default_value("pipewire"), ) .arg( Arg::new("audio-codec") .long("audio-codec") .env("AUDIO_CODEC") - .help("Preferred audio codec ('opus', 'aac')") + .help("Preferred audio codec") + .value_parser(value_parser!(AudioCodec)) .default_value("opus"), ) .arg( @@ -163,14 +180,16 @@ impl Args { Arg::new("audio-rate-control") .long("audio-rate-control") .env("AUDIO_RATE_CONTROL") - .help("Rate control method ('cqp', 'vbr', 'cbr')") - .default_value("vbr"), + .help("Rate control method") + .value_parser(value_parser!(encoding_args::RateControlMethod)) + .default_value("cbr"), ) .arg( Arg::new("audio-bitrate") .long("audio-bitrate") .env("AUDIO_BITRATE") .help("Target bitrate in kbps") + .value_parser(value_parser!(u32).range(1..)) .default_value("128"), ) .arg( @@ -178,6 +197,7 @@ impl Args { .long("audio-bitrate-max") .env("AUDIO_BITRATE_MAX") .help("Maximum bitrate in kbps") + .value_parser(value_parser!(u32).range(1..)) .default_value("192"), ) .arg( @@ -185,6 +205,7 @@ impl Args { .long("dma-buf") .env("DMA_BUF") .help("Use DMA-BUF for pipeline") + .value_parser(BoolishValueParser::new()) .default_value("false"), ) .get_matches(); diff --git a/packages/server/src/args/app_args.rs b/packages/server/src/args/app_args.rs index 5fc4525f..37cef070 100644 --- a/packages/server/src/args/app_args.rs +++ b/packages/server/src/args/app_args.rs @@ -20,10 +20,8 @@ pub struct AppArgs { impl AppArgs { pub fn from_matches(matches: &clap::ArgMatches) -> Self { Self { - verbose: matches.get_one::("verbose").unwrap() == "true" - || matches.get_one::("verbose").unwrap() == "1", - debug: matches.get_one::("debug").unwrap() == "true" - || matches.get_one::("debug").unwrap() == "1", + verbose: matches.get_one::("verbose").unwrap_or(&false).clone(), + debug: matches.get_one::("debug").unwrap_or(&false).clone(), resolution: { let res = matches .get_one::("resolution") @@ -39,11 +37,7 @@ impl AppArgs { (1280, 720) } }, - framerate: matches - .get_one::("framerate") - .unwrap() - .parse::() - .unwrap_or(60), + framerate: matches.get_one::("framerate").unwrap_or(&60).clone(), relay_url: matches .get_one::("relay-url") .expect("relay url cannot be empty") @@ -53,19 +47,18 @@ impl AppArgs { .get_one::("room") .unwrap_or(&rand::random::().to_string()) .clone(), - dma_buf: matches.get_one::("dma-buf").unwrap() == "true" - || matches.get_one::("dma-buf").unwrap() == "1", + dma_buf: matches.get_one::("dma-buf").unwrap_or(&false).clone(), } } pub fn debug_print(&self) { - println!("AppArgs:"); - println!("> verbose: {}", self.verbose); - println!("> debug: {}", self.debug); - println!("> resolution: {}x{}", self.resolution.0, self.resolution.1); - println!("> framerate: {}", self.framerate); - println!("> relay_url: {}", self.relay_url); - println!("> room: {}", self.room); - println!("> dma_buf: {}", self.dma_buf); + tracing::info!("AppArgs:"); + tracing::info!("> verbose: {}", self.verbose); + tracing::info!("> debug: {}", self.debug); + tracing::info!("> resolution: '{}x{}'", self.resolution.0, self.resolution.1); + tracing::info!("> framerate: {}", self.framerate); + tracing::info!("> relay_url: '{}'", self.relay_url); + tracing::info!("> room: '{}'", self.room); + tracing::info!("> dma_buf: {}", self.dma_buf); } } diff --git a/packages/server/src/args/device_args.rs b/packages/server/src/args/device_args.rs index a7a672b5..e9a61c09 100644 --- a/packages/server/src/args/device_args.rs +++ b/packages/server/src/args/device_args.rs @@ -3,8 +3,8 @@ pub struct DeviceArgs { pub gpu_vendor: String, /// GPU name (e.g. "a770") pub gpu_name: String, - /// GPU index, if multiple same GPUs are present - pub gpu_index: u32, + /// GPU index, if multiple same GPUs are present, -1 for auto-selection + pub gpu_index: i32, /// GPU card/render path, sets card explicitly from such path pub gpu_card_path: String, } @@ -20,10 +20,9 @@ impl DeviceArgs { .unwrap_or(&"".to_string()) .clone(), gpu_index: matches - .get_one::("gpu-index") - .unwrap() - .parse::() - .unwrap(), + .get_one::("gpu-index") + .unwrap_or(&-1) + .clone(), gpu_card_path: matches .get_one::("gpu-card-path") .unwrap_or(&"".to_string()) @@ -32,17 +31,10 @@ impl DeviceArgs { } pub fn debug_print(&self) { - println!("DeviceArgs:"); - println!("> gpu_vendor: {}", self.gpu_vendor); - println!("> gpu_name: {}", self.gpu_name); - println!("> gpu_index: {}", self.gpu_index); - println!( - "> gpu_card_path: {}", - if self.gpu_card_path.is_empty() { - "Auto-Selection" - } else { - &self.gpu_card_path - } - ); + tracing::info!("DeviceArgs:"); + tracing::info!("> gpu_vendor: '{}'", self.gpu_vendor); + tracing::info!("> gpu_name: '{}'", self.gpu_name); + tracing::info!("> gpu_index: {}", self.gpu_index); + tracing::info!("> gpu_card_path: '{}'", self.gpu_card_path); } } diff --git a/packages/server/src/args/encoding_args.rs b/packages/server/src/args/encoding_args.rs index 1800e0ef..c0ea478d 100644 --- a/packages/server/src/args/encoding_args.rs +++ b/packages/server/src/args/encoding_args.rs @@ -1,4 +1,8 @@ +use crate::enc_helper::Codec::{Audio, Video}; +use crate::enc_helper::{AudioCodec, Codec, EncoderType, VideoCodec}; +use clap::ValueEnum; use std::ops::Deref; +use std::str::FromStr; #[derive(Debug, PartialEq, Eq, Clone)] pub struct RateControlCQP { @@ -8,14 +12,42 @@ pub struct RateControlCQP { #[derive(Debug, PartialEq, Eq, Clone)] pub struct RateControlVBR { /// Target bitrate in kbps - pub target_bitrate: i32, + pub target_bitrate: u32, /// Maximum bitrate in kbps - pub max_bitrate: i32, + pub max_bitrate: u32, } #[derive(Debug, PartialEq, Eq, Clone)] pub struct RateControlCBR { /// Target bitrate in kbps - pub target_bitrate: i32, + pub target_bitrate: u32, +} + +#[derive(Debug, PartialEq, Eq, Clone, ValueEnum)] +pub enum RateControlMethod { + CQP, + VBR, + CBR, +} +impl RateControlMethod { + pub fn as_str(&self) -> &str { + match self { + RateControlMethod::CQP => "cqp", + RateControlMethod::VBR => "vbr", + RateControlMethod::CBR => "cbr", + } + } +} +impl FromStr for RateControlMethod { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "cqp" => Ok(RateControlMethod::CQP), + "vbr" => Ok(RateControlMethod::VBR), + "cbr" => Ok(RateControlMethod::CBR), + _ => Err(format!("Invalid rate control method: {}", s)), + } + } } #[derive(Debug, PartialEq, Eq, Clone)] @@ -30,7 +62,7 @@ pub enum RateControl { pub struct EncodingOptionsBase { /// Codec (e.g. "h264", "opus" etc.) - pub codec: String, + pub codec: Codec, /// Overridable encoder (e.g. "vah264lpenc", "opusenc" etc.) pub encoder: String, /// Rate control method (e.g. "cqp", "vbr", "cbr") @@ -38,28 +70,21 @@ pub struct EncodingOptionsBase { } impl EncodingOptionsBase { pub fn debug_print(&self) { - println!("> Codec: {}", self.codec); - println!( - "> Encoder: {}", - if self.encoder.is_empty() { - "Auto-Selection" - } else { - &self.encoder - } - ); + tracing::info!("> Codec: '{}'", self.codec.as_str()); + tracing::info!("> Encoder: '{}'", self.encoder); match &self.rate_control { RateControl::CQP(cqp) => { - println!("> Rate Control: CQP"); - println!("-> Quality: {}", cqp.quality); + tracing::info!("> Rate Control: CQP"); + tracing::info!("-> Quality: {}", cqp.quality); } RateControl::VBR(vbr) => { - println!("> Rate Control: VBR"); - println!("-> Target Bitrate: {}", vbr.target_bitrate); - println!("-> Max Bitrate: {}", vbr.max_bitrate); + tracing::info!("> Rate Control: VBR"); + tracing::info!("-> Target Bitrate: {}", vbr.target_bitrate); + tracing::info!("-> Max Bitrate: {}", vbr.max_bitrate); } RateControl::CBR(cbr) => { - println!("> Rate Control: CBR"); - println!("-> Target Bitrate: {}", cbr.target_bitrate); + tracing::info!("> Rate Control: CBR"); + tracing::info!("-> Target Bitrate: {}", cbr.target_bitrate); } } } @@ -67,63 +92,62 @@ impl EncodingOptionsBase { pub struct VideoEncodingOptions { pub base: EncodingOptionsBase, - /// Encoder type (e.g. "hardware", "software") - pub encoder_type: String, + pub encoder_type: EncoderType, } impl VideoEncodingOptions { pub fn from_matches(matches: &clap::ArgMatches) -> Self { Self { base: EncodingOptionsBase { - codec: matches.get_one::("video-codec").unwrap().clone(), + codec: Video( + matches + .get_one::("video-codec") + .unwrap_or(&VideoCodec::H264) + .clone(), + ), encoder: matches .get_one::("video-encoder") .unwrap_or(&"".to_string()) .clone(), rate_control: match matches - .get_one::("video-rate-control") - .unwrap() - .as_str() + .get_one::("video-rate-control") + .unwrap_or(&RateControlMethod::CBR) { - "cqp" => RateControl::CQP(RateControlCQP { + RateControlMethod::CQP => RateControl::CQP(RateControlCQP { quality: matches .get_one::("video-cqp") .unwrap() .parse::() .unwrap(), }), - "cbr" => RateControl::CBR(RateControlCBR { + RateControlMethod::CBR => RateControl::CBR(RateControlCBR { target_bitrate: matches - .get_one::("video-bitrate") + .get_one::("video-bitrate") .unwrap() - .parse::() - .unwrap(), + .clone(), }), - "vbr" => RateControl::VBR(RateControlVBR { + RateControlMethod::VBR => RateControl::VBR(RateControlVBR { target_bitrate: matches - .get_one::("video-bitrate") + .get_one::("video-bitrate") .unwrap() - .parse::() - .unwrap(), + .clone(), max_bitrate: matches - .get_one::("video-bitrate-max") + .get_one::("video-bitrate-max") .unwrap() - .parse::() - .unwrap(), + .clone(), }), - _ => panic!("Invalid rate control method for video"), }, }, encoder_type: matches - .get_one::("video-encoder-type") - .unwrap_or(&"hardware".to_string()) + .get_one::("video-encoder-type") + .unwrap_or(&EncoderType::HARDWARE) .clone(), } } pub fn debug_print(&self) { - println!("Video Encoding Options:"); + tracing::info!("Video Encoding Options:"); self.base.debug_print(); - println!("> Encoder Type: {}", self.encoder_type); + tracing::info!("> Encoder Type: {}", self.encoder_type.as_str()); } } impl Deref for VideoEncodingOptions { @@ -134,18 +158,30 @@ impl Deref for VideoEncodingOptions { } } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Clone, ValueEnum)] pub enum AudioCaptureMethod { - PulseAudio, - PipeWire, + PULSEAUDIO, + PIPEWIRE, ALSA, } impl AudioCaptureMethod { pub fn as_str(&self) -> &str { match self { - AudioCaptureMethod::PulseAudio => "pulseaudio", - AudioCaptureMethod::PipeWire => "pipewire", - AudioCaptureMethod::ALSA => "alsa", + AudioCaptureMethod::PULSEAUDIO => "PulseAudio", + AudioCaptureMethod::PIPEWIRE => "PipeWire", + AudioCaptureMethod::ALSA => "ALSA", + } + } +} +impl FromStr for AudioCaptureMethod { + type Err = String; + + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "pulseaudio" => Ok(AudioCaptureMethod::PULSEAUDIO), + "pipewire" => Ok(AudioCaptureMethod::PIPEWIRE), + "alsa" => Ok(AudioCaptureMethod::ALSA), + _ => Err(format!("Invalid audio capture method: {}", s)), } } } @@ -158,56 +194,50 @@ impl AudioEncodingOptions { pub fn from_matches(matches: &clap::ArgMatches) -> Self { Self { base: EncodingOptionsBase { - codec: matches.get_one::("audio-codec").unwrap().clone(), + codec: Audio( + matches + .get_one::("audio-codec") + .unwrap_or(&AudioCodec::OPUS) + .clone(), + ), encoder: matches .get_one::("audio-encoder") .unwrap_or(&"".to_string()) .clone(), rate_control: match matches - .get_one::("audio-rate-control") - .unwrap() - .as_str() + .get_one::("audio-rate-control") + .unwrap_or(&RateControlMethod::CBR) { - "cbr" => RateControl::CBR(RateControlCBR { + RateControlMethod::CBR => RateControl::CBR(RateControlCBR { target_bitrate: matches - .get_one::("audio-bitrate") + .get_one::("audio-bitrate") .unwrap() - .parse::() - .unwrap(), + .clone(), }), - "vbr" => RateControl::VBR(RateControlVBR { + RateControlMethod::VBR => RateControl::VBR(RateControlVBR { target_bitrate: matches - .get_one::("audio-bitrate") + .get_one::("audio-bitrate") .unwrap() - .parse::() - .unwrap(), + .clone(), max_bitrate: matches - .get_one::("audio-bitrate-max") + .get_one::("audio-bitrate-max") .unwrap() - .parse::() - .unwrap(), + .clone(), }), - _ => panic!("Invalid rate control method for audio"), + wot => panic!("Invalid rate control method for audio: {}", wot.as_str()), }, }, - capture_method: match matches - .get_one::("audio-capture-method") - .unwrap() - .as_str() - { - "pulseaudio" => AudioCaptureMethod::PulseAudio, - "pipewire" => AudioCaptureMethod::PipeWire, - "alsa" => AudioCaptureMethod::ALSA, - // Default to PulseAudio - _ => AudioCaptureMethod::PulseAudio, - }, + capture_method: matches + .get_one::("audio-capture-method") + .unwrap_or(&AudioCaptureMethod::PIPEWIRE) + .clone(), } } pub fn debug_print(&self) { - println!("Audio Encoding Options:"); + tracing::info!("Audio Encoding Options:"); self.base.debug_print(); - println!("> Capture Method: {}", self.capture_method.as_str()); + tracing::info!("> Capture Method: {}", self.capture_method.as_str()); } } impl Deref for AudioEncodingOptions { @@ -233,7 +263,7 @@ impl EncodingArgs { } pub fn debug_print(&self) { - println!("Encoding Arguments:"); + tracing::info!("Encoding Arguments:"); self.video.debug_print(); self.audio.debug_print(); } diff --git a/packages/server/src/enc_helper.rs b/packages/server/src/enc_helper.rs index 83683605..d7be0f8b 100644 --- a/packages/server/src/enc_helper.rs +++ b/packages/server/src/enc_helper.rs @@ -1,31 +1,70 @@ use crate::args::encoding_args::RateControl; use crate::gpu::{self, GPUInfo, get_gpu_by_card_path, get_gpus_by_vendor}; +use clap::ValueEnum; use gst::prelude::*; +use std::error::Error; +use std::str::FromStr; -#[derive(Debug, Eq, PartialEq, Clone)] +#[derive(Debug, Eq, PartialEq, Clone, ValueEnum)] +pub enum AudioCodec { + OPUS, +} +impl AudioCodec { + pub fn as_str(&self) -> &'static str { + match self { + Self::OPUS => "Opus", + } + } +} +impl FromStr for AudioCodec { + type Err = String; + + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "opus" => Ok(Self::OPUS), + _ => Err(format!("Invalid audio codec: {}", s)), + } + } +} + +#[derive(Debug, Eq, PartialEq, Clone, ValueEnum)] pub enum VideoCodec { H264, H265, AV1, - UNKNOWN, } - impl VideoCodec { - pub fn to_str(&self) -> &'static str { + pub fn as_str(&self) -> &'static str { match self { Self::H264 => "H.264", Self::H265 => "H.265", Self::AV1 => "AV1", - Self::UNKNOWN => "Unknown", } } +} +impl FromStr for VideoCodec { + type Err = String; - pub fn from_str(s: &str) -> Self { + fn from_str(s: &str) -> Result { match s.to_lowercase().as_str() { - "h264" | "h.264" | "avc" => Self::H264, - "h265" | "h.265" | "hevc" | "hev1" => Self::H265, - "av1" => Self::AV1, - _ => Self::UNKNOWN, + "h264" | "h.264" | "avc" => Ok(Self::H264), + "h265" | "h.265" | "hevc" | "hev1" => Ok(Self::H265), + "av1" => Ok(Self::AV1), + _ => Err(format!("Invalid video codec: {}", s)), + } + } +} + +#[derive(Debug, Eq, PartialEq, Clone)] +pub enum Codec { + Audio(AudioCodec), + Video(VideoCodec), +} +impl Codec { + pub fn as_str(&self) -> &'static str { + match self { + Self::Audio(codec) => codec.as_str(), + Self::Video(codec) => codec.as_str(), } } } @@ -53,27 +92,17 @@ impl EncoderAPI { } } -#[derive(Debug, Eq, PartialEq, Clone)] +#[derive(Debug, Eq, PartialEq, Clone, ValueEnum)] pub enum EncoderType { SOFTWARE, HARDWARE, - UNKNOWN, } impl EncoderType { - pub fn to_str(&self) -> &'static str { + pub fn as_str(&self) -> &'static str { match self { Self::SOFTWARE => "Software", Self::HARDWARE => "Hardware", - Self::UNKNOWN => "Unknown", - } - } - - pub fn from_str(s: &str) -> Self { - match s.to_lowercase().as_str() { - "software" => Self::SOFTWARE, - "hardware" => Self::HARDWARE, - _ => Self::UNKNOWN, } } } @@ -121,7 +150,7 @@ impl VideoEncoderInfo { for (key, value) in &self.parameters { if element.has_property(key) { if verbose { - println!("Setting property {} to {}", key, value); + tracing::debug!("Setting property {} to {}", key, value); } element.set_property_from_str(key, value); } @@ -145,19 +174,15 @@ fn get_encoder_api(encoder: &str, encoder_type: &EncoderType) -> EncoderAPI { } } EncoderType::SOFTWARE => EncoderAPI::SOFTWARE, - _ => EncoderAPI::UNKNOWN, } } fn codec_from_encoder_name(name: &str) -> Option { - if name.contains("h264") { - Some(VideoCodec::H264) - } else if name.contains("h265") { - Some(VideoCodec::H265) - } else if name.contains("av1") { - Some(VideoCodec::AV1) - } else { - None + match name.to_lowercase() { + n if n.contains("h264") => Some(VideoCodec::H264), + n if n.contains("h265") => Some(VideoCodec::H265), + n if n.contains("av1") => Some(VideoCodec::AV1), + _ => None, } } @@ -272,7 +297,6 @@ pub fn encoder_low_latency_params( let usage = match encoder_optz.codec { VideoCodec::H264 | VideoCodec::H265 => "ultra-low-latency", VideoCodec::AV1 => "low-latency", - _ => "", }; if !usage.is_empty() { encoder_optz.set_parameter("usage", usage); @@ -378,8 +402,8 @@ pub fn get_compatible_encoders() -> Vec { } }) .unwrap_or_else(|_| { - log::error!( - "Panic occurred while querying properties for {}", + tracing::error!( + "Error occurred while querying properties for {}", encoder_name ); None @@ -401,16 +425,20 @@ pub fn get_compatible_encoders() -> Vec { /// * `encoders` - A vector containing information about each encoder. /// * `name` - A string slice that holds the encoder name. /// # Returns -/// * `Option` - A reference to an EncoderInfo struct if found. +/// * `Result>` - A Result containing EncoderInfo if found, or an error. pub fn get_encoder_by_name( encoders: &Vec, name: &str, -) -> Option { +) -> Result> { let name = name.to_lowercase(); - encoders + if let Some(encoder) = encoders .iter() .find(|encoder| encoder.name.to_lowercase() == name) - .cloned() + { + Ok(encoder.clone()) + } else { + Err(format!("Encoder '{}' not found", name).into()) + } } /// Helper to get encoders from vector by video codec. @@ -453,15 +481,23 @@ pub fn get_encoders_by_type( /// * `codec` - Desired codec. /// * `encoder_type` - Desired encoder type. /// # Returns -/// * `Option` - Best-case compatible encoder. +/// * `Result>` - A Result containing the best compatible encoder if found, or an error. pub fn get_best_compatible_encoder( encoders: &Vec, - codec: VideoCodec, - encoder_type: EncoderType, -) -> Option { + codec: &Codec, + encoder_type: &EncoderType, +) -> Result> { let mut best_encoder: Option = None; let mut best_score: i32 = 0; + let codec = match codec { + Codec::Video(c) => c.clone(), + Codec::Audio(_) => { + // Only for video currently + return Err("Attempted to get best compatible video encoder with audio codec".into()); + } + }; + // Filter by codec and type first let encoders = get_encoders_by_videocodec(encoders, &codec); let encoders = get_encoders_by_type(&encoders, &encoder_type); @@ -498,5 +534,9 @@ pub fn get_best_compatible_encoder( } } - best_encoder + if let Some(encoder) = best_encoder { + Ok(encoder) + } else { + Err("No compatible encoder found".into()) + } } diff --git a/packages/server/src/gpu.rs b/packages/server/src/gpu.rs index 5199c514..8827b0e2 100644 --- a/packages/server/src/gpu.rs +++ b/packages/server/src/gpu.rs @@ -161,3 +161,11 @@ pub fn get_gpu_by_card_path(gpus: &[GPUInfo], path: &str) -> Option { }) .cloned() } + +pub fn get_gpu_by_index(gpus: &[GPUInfo], index: i32) -> Option { + if index < 0 || index as usize >= gpus.len() { + None + } else { + Some(gpus[index as usize].clone()) + } +} diff --git a/packages/server/src/main.rs b/packages/server/src/main.rs index 4206fc7d..fffd1ccc 100644 --- a/packages/server/src/main.rs +++ b/packages/server/src/main.rs @@ -8,6 +8,7 @@ mod proto; mod websocket; use crate::args::encoding_args; +use crate::enc_helper::EncoderType; use crate::gpu::GPUVendor; use crate::nestrisink::NestriSignaller; use crate::websocket::NestriWebSocket; @@ -20,16 +21,16 @@ use std::str::FromStr; use std::sync::Arc; // Handles gathering GPU information and selecting the most suitable GPU -fn handle_gpus(args: &args::Args) -> Option { - println!("Gathering GPU information.."); +fn handle_gpus(args: &args::Args) -> Result> { + tracing::info!("Gathering GPU information.."); let gpus = gpu::get_gpus(); if gpus.is_empty() { - println!("No GPUs found"); - return None; + return Err("No GPUs found".into()); } - for gpu in &gpus { - println!( - "> [GPU] Vendor: '{}', Card Path: '{}', Render Path: '{}', Device Name: '{}'", + for (i, gpu) in gpus.iter().enumerate() { + tracing::info!( + "> [GPU:{}] Vendor: '{}', Card Path: '{}', Render Path: '{}', Device Name: '{}'", + i, gpu.vendor_string(), gpu.card_path(), gpu.render_path(), @@ -50,9 +51,12 @@ fn handle_gpus(args: &args::Args) -> Option { if !args.device.gpu_name.is_empty() { filtered_gpus = gpu::get_gpus_by_device_name(&filtered_gpus, &args.device.gpu_name); } - if args.device.gpu_index != 0 { + if args.device.gpu_index > -1 { // get single GPU by index - gpu = filtered_gpus.get(args.device.gpu_index as usize).cloned(); + gpu = gpu::get_gpu_by_index(&filtered_gpus, args.device.gpu_index).or_else(|| { + tracing::warn!("GPU index {} is out of range", args.device.gpu_index); + None + }); } else { // get first GPU gpu = filtered_gpus @@ -61,35 +65,33 @@ fn handle_gpus(args: &args::Args) -> Option { } } if gpu.is_none() { - println!( + return Err(format!( "No GPU found with the specified parameters: vendor='{}', name='{}', index='{}', card_path='{}'", args.device.gpu_vendor, args.device.gpu_name, args.device.gpu_index, args.device.gpu_card_path - ); - return None; + ).into()); } let gpu = gpu.unwrap(); - println!("Selected GPU: '{}'", gpu.device_name()); - Some(gpu) + tracing::info!("Selected GPU: '{}'", gpu.device_name()); + Ok(gpu) } // Handles picking video encoder -fn handle_encoder_video(args: &args::Args) -> Option { - println!("Getting compatible video encoders.."); +fn handle_encoder_video(args: &args::Args) -> Result> { + tracing::info!("Getting compatible video encoders.."); let video_encoders = enc_helper::get_compatible_encoders(); if video_encoders.is_empty() { - println!("No compatible video encoders found"); - return None; + return Err("No compatible video encoders found".into()); } for encoder in &video_encoders { - println!( + tracing::info!( "> [Video Encoder] Name: '{}', Codec: '{}', API: '{}', Type: '{}', Device: '{}'", encoder.name, - encoder.codec.to_str(), + encoder.codec.as_str(), encoder.encoder_api.to_str(), - encoder.encoder_type.to_str(), + encoder.encoder_type.as_str(), if let Some(gpu) = &encoder.gpu_info { gpu.device_name() } else { @@ -101,26 +103,16 @@ fn handle_encoder_video(args: &args::Args) -> Option { optimized_encoder = enc_helper::encoder_vbr_params( &optimized_encoder, - vbr.target_bitrate as u32, - vbr.max_bitrate as u32, + vbr.target_bitrate, + vbr.max_bitrate, ); } encoding_args::RateControl::CBR(cbr) => { optimized_encoder = - enc_helper::encoder_cbr_params(&optimized_encoder, cbr.target_bitrate as u32); + enc_helper::encoder_cbr_params(&optimized_encoder, cbr.target_bitrate); } } - println!( + tracing::info!( "Selected video encoder settings: '{}'", optimized_encoder.get_parameters_string() ); @@ -165,16 +157,23 @@ fn handle_encoder_audio(args: &args::Args) -> String { } else { args.encoding.audio.encoder.clone() }; - println!("Selected audio encoder: '{}'", audio_encoder); + tracing::info!("Selected audio encoder: '{}'", audio_encoder); audio_encoder } #[tokio::main] async fn main() -> Result<(), Box> { // Parse command line arguments - let args = args::Args::new(); + let mut args = args::Args::new(); if args.app.verbose { + // Make sure tracing has INFO level + tracing_subscriber::fmt() + .with_max_level(tracing::Level::INFO) + .init(); + args.debug_print(); + } else { + tracing_subscriber::fmt::init(); } rustls::crypto::ring::default_provider() @@ -192,33 +191,39 @@ async fn main() -> Result<(), Box> { // Setup our websocket let nestri_ws = Arc::new(NestriWebSocket::new(ws_url).await?); - log::set_max_level(log::LevelFilter::Info); - log::set_boxed_logger(Box::new(nestri_ws.clone())).unwrap(); gst::init()?; gstrswebrtc::plugin_register_static()?; // Handle GPU selection - let gpu = handle_gpus(&args); - if gpu.is_none() { - log::error!("Failed to find a suitable GPU. Exiting.."); - return Err("Failed to find a suitable GPU. Exiting..".into()); - } - let gpu = gpu.unwrap(); + let gpu = match handle_gpus(&args) { + Ok(gpu) => gpu, + Err(e) => { + tracing::error!("Failed to find a suitable GPU: {}", e); + return Err(e); + } + }; if args.app.dma_buf { - log::warn!( - "DMA-BUF is experimental, it may or may not improve performance, or even work at all." - ); + if args.encoding.video.encoder_type != EncoderType::HARDWARE { + tracing::warn!("DMA-BUF is only supported with hardware encoders, disabling DMA-BUF.."); + args.app.dma_buf = false; + } else { + tracing::warn!( + "DMA-BUF is experimental, it may or may not improve performance, or even work at all." + ); + } } // Handle video encoder selection - let video_encoder_info = handle_encoder_video(&args); - if video_encoder_info.is_none() { - log::error!("Failed to find a suitable video encoder. Exiting.."); - return Err("Failed to find a suitable video encoder. Exiting..".into()); - } - let mut video_encoder_info = video_encoder_info.unwrap(); + let mut video_encoder_info = match handle_encoder_video(&args) { + Ok(encoder) => encoder, + Err(e) => { + tracing::error!("Failed to find a suitable video encoder: {}", e); + return Err(e); + } + }; + // Handle video encoder settings video_encoder_info = handle_encoder_video_settings(&args, &video_encoder_info); @@ -232,10 +237,10 @@ async fn main() -> Result<(), Box> { /* Audio */ // Audio Source Element let audio_source = match args.encoding.audio.capture_method { - encoding_args::AudioCaptureMethod::PulseAudio => { + encoding_args::AudioCaptureMethod::PULSEAUDIO => { gst::ElementFactory::make("pulsesrc").build()? } - encoding_args::AudioCaptureMethod::PipeWire => { + encoding_args::AudioCaptureMethod::PIPEWIRE => { gst::ElementFactory::make("pipewiresrc").build()? } encoding_args::AudioCaptureMethod::ALSA => gst::ElementFactory::make("alsasrc").build()?, @@ -257,8 +262,8 @@ async fn main() -> Result<(), Box> { audio_encoder.set_property( "bitrate", &match &args.encoding.audio.rate_control { - encoding_args::RateControl::CBR(cbr) => cbr.target_bitrate * 1000i32, - encoding_args::RateControl::VBR(vbr) => vbr.target_bitrate * 1000i32, + encoding_args::RateControl::CBR(cbr) => cbr.target_bitrate.saturating_mul(1000) as i32, + encoding_args::RateControl::VBR(vbr) => vbr.target_bitrate.saturating_mul(1000) as i32, _ => 128000i32, }, ); @@ -269,7 +274,7 @@ async fn main() -> Result<(), Box> { /* Video */ // Video Source Element - let video_source = gst::ElementFactory::make("waylanddisplaysrc").build()?; + let video_source = Arc::new(gst::ElementFactory::make("waylanddisplaysrc").build()?); video_source.set_property_from_str("render-node", gpu.render_path()); // Caps Filter Element (resolution, fps) @@ -323,7 +328,7 @@ async fn main() -> Result<(), Box> { /* Output */ // WebRTC sink Element - let signaller = NestriSignaller::new(nestri_ws.clone(), pipeline.clone()); + let signaller = NestriSignaller::new(nestri_ws.clone(), video_source.clone()); let webrtcsink = BaseWebRTCSink::with_signaller(Signallable::from(signaller.clone())); webrtcsink.set_property_from_str("stun-server", "stun://stun.l.google.com:19302"); webrtcsink.set_property_from_str("congestion-control", "disabled"); @@ -456,9 +461,9 @@ async fn main() -> Result<(), Box> { let result = run_pipeline(pipeline.clone()).await; match result { - Ok(_) => log::info!("All tasks finished"), + Ok(_) => tracing::info!("All tasks finished"), Err(e) => { - log::error!("Error occurred in one of the tasks: {}", e); + tracing::error!("Error occurred in one of the tasks: {}", e); return Err("Error occurred in one of the tasks".into()); } } @@ -471,7 +476,7 @@ async fn run_pipeline(pipeline: Arc) -> Result<(), Box { if let Err(e) = pipeline.set_state(gst::State::Playing) { - log::error!("Failed to start pipeline: {}", e); + tracing::error!("Failed to start pipeline: {}", e); return Err("Failed to start pipeline".into()); } } @@ -479,12 +484,12 @@ async fn run_pipeline(pipeline: Arc) -> Result<(), Box // Wait for EOS or error (don't lock the pipeline indefinitely) tokio::select! { _ = tokio::signal::ctrl_c() => { - log::info!("Pipeline interrupted via Ctrl+C"); + tracing::info!("Pipeline interrupted via Ctrl+C"); } result = listen_for_gst_messages(bus) => { match result { - Ok(_) => log::info!("Pipeline finished with EOS"), - Err(err) => log::error!("Pipeline error: {}", err), + Ok(_) => tracing::info!("Pipeline finished with EOS"), + Err(err) => tracing::error!("Pipeline error: {}", err), } } } @@ -504,7 +509,7 @@ async fn listen_for_gst_messages(bus: gst::Bus) -> Result<(), Box> { while let Some(msg) = bus_stream.next().await { match msg.view() { gst::MessageView::Eos(_) => { - log::info!("Received EOS"); + tracing::info!("Received EOS"); break; } gst::MessageView::Error(err) => { diff --git a/packages/server/src/messages.rs b/packages/server/src/messages.rs index e1550f8d..0a3ede99 100644 --- a/packages/server/src/messages.rs +++ b/packages/server/src/messages.rs @@ -107,7 +107,6 @@ pub fn encode_message(message: &T) -> Result Result> { - println!("Data: {}", data); let base_message: MessageBase = serde_json::from_str(&data)?; Ok(base_message) } diff --git a/packages/server/src/nestrisink/imp.rs b/packages/server/src/nestrisink/imp.rs index 17ac24f8..a04c135e 100644 --- a/packages/server/src/nestrisink/imp.rs +++ b/packages/server/src/nestrisink/imp.rs @@ -21,14 +21,14 @@ use webrtc::peer_connection::sdp::session_description::RTCSessionDescription; pub struct Signaller { nestri_ws: PLRwLock>>, - pipeline: PLRwLock>>, + wayland_src: PLRwLock>>, data_channel: AtomicRefCell>, } impl Default for Signaller { fn default() -> Self { Self { nestri_ws: PLRwLock::new(None), - pipeline: PLRwLock::new(None), + wayland_src: PLRwLock::new(None), data_channel: AtomicRefCell::new(None), } } @@ -38,12 +38,12 @@ impl Signaller { *self.nestri_ws.write() = Some(nestri_ws); } - pub fn set_pipeline(&self, pipeline: Arc) { - *self.pipeline.write() = Some(pipeline); + pub fn set_wayland_src(&self, wayland_src: Arc) { + *self.wayland_src.write() = Some(wayland_src); } - pub fn get_pipeline(&self) -> Option> { - self.pipeline.read().clone() + pub fn get_wayland_src(&self) -> Option> { + self.wayland_src.read().clone() } pub fn set_data_channel(&self, data_channel: gst_webrtc::WebRTCDataChannel) { @@ -159,8 +159,8 @@ impl Signaller { ); if let Some(data_channel) = data_channel { gst::info!(gst::CAT_DEFAULT, "Data channel created"); - if let Some(pipeline) = signaller.imp().get_pipeline() { - setup_data_channel(&data_channel, &pipeline); + if let Some(wayland_src) = signaller.imp().get_wayland_src() { + setup_data_channel(&data_channel, &*wayland_src); signaller.imp().set_data_channel(data_channel); } else { gst::error!(gst::CAT_DEFAULT, "Wayland display source not set"); @@ -201,7 +201,7 @@ impl SignallableImpl for Signaller { // Wait for a reconnection notification reconnected_notify.notified().await; - println!("Reconnected to relay, re-negotiating..."); + tracing::warn!("Reconnected to relay, re-negotiating..."); gst::warning!(gst::CAT_DEFAULT, "Reconnected to relay, re-negotiating..."); // Emit "session-ended" first to make sure the element is cleaned up @@ -255,7 +255,7 @@ impl SignallableImpl for Signaller { }; if let Ok(encoded) = encode_message(&join_msg) { if let Err(e) = nestri_ws.send_message(encoded) { - eprintln!("Failed to send join message: {:?}", e); + tracing::error!("Failed to send join message: {:?}", e); gst::error!(gst::CAT_DEFAULT, "Failed to send join message: {:?}", e); } } else { @@ -283,7 +283,7 @@ impl SignallableImpl for Signaller { }; if let Ok(encoded) = encode_message(&sdp_message) { if let Err(e) = nestri_ws.send_message(encoded) { - eprintln!("Failed to send SDP message: {:?}", e); + tracing::error!("Failed to send SDP message: {:?}", e); gst::error!(gst::CAT_DEFAULT, "Failed to send SDP message: {:?}", e); } } else { @@ -319,7 +319,7 @@ impl SignallableImpl for Signaller { }; if let Ok(encoded) = encode_message(&ice_message) { if let Err(e) = nestri_ws.send_message(encoded) { - eprintln!("Failed to send ICE message: {:?}", e); + tracing::error!("Failed to send ICE message: {:?}", e); gst::error!(gst::CAT_DEFAULT, "Failed to send ICE message: {:?}", e); } } else { @@ -361,8 +361,8 @@ impl ObjectImpl for Signaller { } } -fn setup_data_channel(data_channel: &gst_webrtc::WebRTCDataChannel, pipeline: &gst::Pipeline) { - let pipeline = pipeline.clone(); +fn setup_data_channel(data_channel: &gst_webrtc::WebRTCDataChannel, wayland_src: &gst::Element) { + let wayland_src = wayland_src.clone(); data_channel.connect_on_message_data(move |_data_channel, data| { if let Some(data) = data { @@ -371,15 +371,15 @@ fn setup_data_channel(data_channel: &gst_webrtc::WebRTCDataChannel, pipeline: &g if let Some(input_msg) = message_input.data { // Process the input message and create an event if let Some(event) = handle_input_message(input_msg) { - // Send the event to pipeline, result bool is ignored - let _ = pipeline.send_event(event); + // Send the event to wayland source, result bool is ignored + let _ = wayland_src.send_event(event); } } else { - eprintln!("Failed to parse InputMessage"); + tracing::error!("Failed to parse InputMessage"); } } Err(e) => { - eprintln!("Failed to decode MessageInput: {:?}", e); + tracing::error!("Failed to decode MessageInput: {:?}", e); } } } diff --git a/packages/server/src/nestrisink/mod.rs b/packages/server/src/nestrisink/mod.rs index 62958bff..35ffd77b 100644 --- a/packages/server/src/nestrisink/mod.rs +++ b/packages/server/src/nestrisink/mod.rs @@ -11,10 +11,10 @@ glib::wrapper! { } impl NestriSignaller { - pub fn new(nestri_ws: Arc, pipeline: Arc) -> Self { + pub fn new(nestri_ws: Arc, wayland_src: Arc) -> Self { let obj: Self = glib::Object::new(); obj.imp().set_nestri_ws(nestri_ws); - obj.imp().set_pipeline(pipeline); + obj.imp().set_wayland_src(wayland_src); obj } } diff --git a/packages/server/src/websocket.rs b/packages/server/src/websocket.rs index 391eed0c..28ca6eb3 100644 --- a/packages/server/src/websocket.rs +++ b/packages/server/src/websocket.rs @@ -1,8 +1,7 @@ -use crate::messages::{MessageBase, MessageLog, decode_message, encode_message}; +use crate::messages::decode_message; use futures_util::StreamExt; use futures_util::sink::SinkExt; use futures_util::stream::{SplitSink, SplitStream}; -use log::{Level, Log, Metadata, Record}; use std::collections::HashMap; use std::error::Error; use std::sync::{Arc, RwLock}; @@ -63,7 +62,7 @@ impl NestriWebSocket { return Ok(ws_stream); } Err(e) => { - eprintln!("Failed to connect to WebSocket, retrying: {:?}", e); + tracing::error!("Failed to connect to WebSocket, retrying: {:?}", e); sleep(Duration::from_secs(3)).await; // Wait before retrying } } @@ -87,7 +86,7 @@ impl NestriWebSocket { let mut ws_read = match ws_read_option { Some(ws_read) => ws_read, None => { - eprintln!("Reader is None, cannot proceed"); + tracing::error!("Reader is None, cannot proceed"); return; } }; @@ -101,7 +100,7 @@ impl NestriWebSocket { let base_message = match decode_message(data.to_string()) { Ok(base_message) => base_message, Err(e) => { - eprintln!("Failed to decode message: {:?}", e); + tracing::error!("Failed to decode message: {:?}", e); continue; } }; @@ -113,7 +112,7 @@ impl NestriWebSocket { } } Err(e) => { - eprintln!( + tracing::error!( "Error receiving message: {:?}, reconnecting in 3 seconds...", e ); @@ -150,10 +149,10 @@ impl NestriWebSocket { break; } Err(e) => { - eprintln!("Error sending message: {:?}", e); + tracing::error!("Error sending message: {:?}", e); // Attempt to reconnect if let Err(e) = self_clone.reconnect().await { - eprintln!("Error during reconnection: {:?}", e); + tracing::error!("Error during reconnection: {:?}", e); // Wait before retrying sleep(Duration::from_secs(3)).await; continue; @@ -161,10 +160,10 @@ impl NestriWebSocket { } } } else { - eprintln!("Writer is None, cannot send message"); + tracing::error!("Writer is None, cannot send message"); // Attempt to reconnect if let Err(e) = self_clone.reconnect().await { - eprintln!("Error during reconnection: {:?}", e); + tracing::error!("Error during reconnection: {:?}", e); // Wait before retrying sleep(Duration::from_secs(3)).await; continue; @@ -196,7 +195,7 @@ impl NestriWebSocket { return Ok(()); } Err(e) => { - eprintln!("Failed to reconnect to WebSocket: {:?}", e); + tracing::error!("Failed to reconnect to WebSocket: {:?}", e); sleep(Duration::from_secs(3)).await; // Wait before retrying } } @@ -223,40 +222,4 @@ impl NestriWebSocket { pub fn subscribe_reconnected(&self) -> Arc { self.reconnected_notify.clone() } -} -impl Log for NestriWebSocket { - fn enabled(&self, metadata: &Metadata) -> bool { - metadata.level() <= Level::Info - } - - fn log(&self, record: &Record) { - if self.enabled(record.metadata()) { - let level = record.level().to_string(); - let message = record.args().to_string(); - let time = chrono::Local::now().to_rfc3339(); - - // Print to console as well - println!("{}: {}", level, message); - - // Encode and send the log message - let log_message = MessageLog { - base: MessageBase { - payload_type: "log".to_string(), - latency: None, - }, - level, - message, - time, - }; - if let Ok(encoded_message) = encode_message(&log_message) { - if let Err(e) = self.send_message(encoded_message) { - eprintln!("Failed to send log message: {:?}", e); - } - } - } - } - - fn flush(&self) { - // No-op for this logger - } -} +} \ No newline at end of file