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