diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 79c0e4e..0000000 --- a/.editorconfig +++ /dev/null @@ -1,15 +0,0 @@ -root = true - -[*] -charset = utf-8 -end_of_line = lf -trim_trailing_whitespace = true -insert_final_newline = true -indent_style = tab -indent_size = 4 -max_line_length = 120 - -# YAML doesn't support hard tabs 🙃 -[**.yml] -indent_style = space -indent_size = 2 diff --git a/.envrc b/.envrc deleted file mode 100644 index b06bc5b..0000000 --- a/.envrc +++ /dev/null @@ -1,12 +0,0 @@ -# Automatically load the Nix development shell when entering this directory -# Requires direnv: https://direnv.net/ -# -# To enable: -# 1. Install direnv -# 2. Run: direnv allow -# -# This will automatically install all required dependencies for the project. -if ! has nix_direnv_version || ! nix_direnv_version 3.1.0; then - source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.1.0/direnvrc" "sha256-yMJ2OVMzrFaDPn7q8nCBZFRYpL/f0RcHzhmw/i6btJM=" -fi -use_flake diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml deleted file mode 100644 index ec423cd..0000000 --- a/.github/workflows/pr.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: pr - -on: - pull_request: - branches: ["main"] - -env: - CARGO_TERM_COLOR: always - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - # Install Rust with clippy/rustfmt - - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: - components: clippy, rustfmt - - # We need gstreamer installed to compile this repo - - name: Setup GStreamer - run: | - sudo apt-get update - sudo apt-get remove libunwind-* - sudo apt-get install -y \ - libgstreamer1.0-dev \ - libgstreamer-plugins-base1.0-dev \ - libgstreamer-plugins-bad1.0-dev \ - gstreamer1.0-plugins-base \ - gstreamer1.0-plugins-good \ - gstreamer1.0-plugins-bad \ - gstreamer1.0-plugins-ugly \ - gstreamer1.0-libav \ - gstreamer1.0-tools \ - gstreamer1.0-x \ - gstreamer1.0-alsa \ - gstreamer1.0-gl \ - gstreamer1.0-gtk3 \ - gstreamer1.0-qt5 \ - gstreamer1.0-pulseaudio - - # Make sure u guys don't write bad code - - run: cargo test --verbose - - run: cargo clippy --no-deps - - run: cargo fmt --check diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index f413734..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: release - -permissions: - pull-requests: write - contents: write - -on: - push: - branches: - - main - -jobs: - release: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@stable - - name: Run release-plz - uses: MarcoIeni/release-plz-action@v0.5 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/.gitignore b/.gitignore deleted file mode 100644 index b2ed401..0000000 --- a/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -.DS_Store -target/ -*.mp4 -*.fmp4 -debug/ -.direnv/ diff --git a/.release-plz.toml b/.release-plz.toml deleted file mode 100644 index a74520c..0000000 --- a/.release-plz.toml +++ /dev/null @@ -1,2 +0,0 @@ -[workspace] -dependencies_update = true diff --git a/.rustfmt.toml b/.rustfmt.toml deleted file mode 100644 index b3c42a2..0000000 --- a/.rustfmt.toml +++ /dev/null @@ -1,4 +0,0 @@ -# i die on this hill -hard_tabs = true - -max_width = 120 diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index fef6138..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,42 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [Unreleased] - -## [0.2.2] - 2025-08-12 - -### Other - -- Support an array of authorized paths -- Revamp the Producer/Consumer API for moq_lite - -## [0.2.1] - 2025-07-22 - -### Other - -- Create a type-safe Path wrapper for Javascript -- Add an ANNOUNCE_INIT message - -## [0.1.2] - 2025-06-20 - -### Other - -- updated the following local packages: hang - -## [0.1.1] - 2025-06-03 - -### Other - -- Add support for authentication tokens ([#399](https://github.com/kixelated/moq/pull/399)) -- Add location tracks, fix some bugs, switch to nix ([#401](https://github.com/kixelated/moq/pull/401)) -- Move config to a separate field to match the specification. ([#387](https://github.com/kixelated/moq/pull/387)) - -## [0.1.0](https://github.com/kixelated/moq/releases/tag/hang-gst-v0.1.0) - 2025-05-21 - -### Other - -- Split into Rust/Javascript halves and rebrand as moq-lite/hang ([#376](https://github.com/kixelated/moq/pull/376)) diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 2e33ca2..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,87 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Project Overview - -This is a GStreamer plugin for Media over QUIC (MoQ), written in Rust. It provides `moqsink` and `moqsrc` elements that enable publishing and subscribing to media streams using the MoQ protocol over QUIC transport. - -## Development Setup - -### Prerequisites -- Rust toolchain (via `rustup`) -- Just command runner -- A running moq-relay server from [moq](https://github.com/kixelated/moq) - -### Initial Setup -```bash -# Install dependencies and tools -just setup - -# To see all available commands -just -``` - -## Common Commands - -### Building -```bash -# Build the plugin -just build -# or -cargo build -``` - -### Testing and Quality Checks -```bash -# Run all CI checks (clippy, fmt, cargo check) -just check - -# Run tests -just test - -# Auto-fix issues -just fix -``` - -### Development Workflow -```bash -# Start a relay server (in moq repo) -just relay - -# Publish video stream with broadcast name -just pub bbb - -# Subscribe to video stream with broadcast name -just sub bbb -``` - -## Architecture - -### Plugin Structure -- **lib.rs**: Main plugin entry point, registers both sink and source elements as "moq" plugin -- **sink/**: MoQ sink element (`moqsink`) for publishing streams - - `mod.rs`: GStreamer element wrapper for MoqSink - - `imp.rs`: Core implementation with async Tokio runtime -- **source/**: MoQ source element (`moqsrc`) for consuming streams - - `mod.rs`: GStreamer element wrapper for MoqSrc - - `imp.rs`: Core implementation with async Tokio runtime - -### Key Dependencies -- **hang**: Higher-level protocol utilities and catalog/container handling -- **moq-mux**: MoQ muxing/demuxing for media streams -- **moq-lite**: Lightweight MoQ protocol types -- **moq-native**: Core MoQ protocol implementation with QUIC/TLS -- **gstreamer**: GStreamer bindings for Rust -- **tokio**: Async runtime - -### Plugin Elements -- `moqsink`: Element with request pads (`video_%u`, `audio_%u`) that accepts media data and publishes via MoQ -- `moqsrc`: Bin element that receives MoQ streams and outputs GStreamer buffers - -Both elements use a shared Tokio runtime and support TLS configuration options (url, broadcast, tls-disable-verify). - -## Environment Variables -- `RUST_LOG`: Controls logging level (default: info, overridable via environment) -- `URL`: Relay server URL (default: http://localhost:4443) -- `GST_PLUGIN_PATH_1_0`: Must include the built plugin directory (handled automatically by justfile) \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index bfabad2..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,3615 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "addr2line" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anstream" -version = "0.6.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" - -[[package]] -name = "anstyle-parse" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" -dependencies = [ - "windows-sys 0.60.2", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" -dependencies = [ - "anstyle", - "once_cell_polyfill", - "windows-sys 0.60.2", -] - -[[package]] -name = "anyhow" -version = "1.0.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" -dependencies = [ - "backtrace", -] - -[[package]] -name = "async-compression" -version = "0.4.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0f9ee0f6e02ffd7ad5816e9464499fba7b3effd01123b515c41d1697c43dad1" -dependencies = [ - "compression-codecs", - "compression-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "autocfg" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" - -[[package]] -name = "aws-lc-rs" -version = "1.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879b6c89592deb404ba4dc0ae6b58ffd1795c78991cbb5b8bc441c48a070440d" -dependencies = [ - "aws-lc-sys", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.32.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "107a4e9d9cab9963e04e84bb8dee0e25f2a987f9a8bad5ed054abd439caa8f8c" -dependencies = [ - "bindgen", - "cc", - "cmake", - "dunce", - "fs_extra", -] - -[[package]] -name = "backtrace" -version = "0.3.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-link", -] - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "bindgen" -version = "0.72.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" -dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "itertools 0.13.0", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn", -] - -[[package]] -name = "bitflags" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "buf-list" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6b175f9cf8fffedd4c4b18bcfef092356e952b81f596e148f18e98280994593" -dependencies = [ - "bytes", -] - -[[package]] -name = "bumpalo" -version = "3.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" -dependencies = [ - "serde", -] - -[[package]] -name = "bytestring" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "113b4343b5f6617e7ad401ced8de3cc8b012e73a594347c307b90db3e9271289" -dependencies = [ - "bytes", -] - -[[package]] -name = "cc" -version = "1.2.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" -dependencies = [ - "find-msvc-tools", - "jobserver", - "libc", - "shlex", -] - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-expr" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a2c5f3bf25ec225351aa1c8e230d04d880d3bd89dea133537dafad4ae291e5c" -dependencies = [ - "smallvec", - "target-lexicon", -] - -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - -[[package]] -name = "chrono" -version = "0.4.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" -dependencies = [ - "iana-time-zone", - "num-traits", - "serde", - "windows-link", -] - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "clap" -version = "4.5.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2cfd7bf8a6017ddaa4e32ffe7403d547790db06bd171c1c53926faab501623" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.5.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a4c05b9e80c5ccd3a7ef080ad7b6ba7d6fc00a985b8b157197075677c82c7a0" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.5.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "clap_lex" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" - -[[package]] -name = "cmake" -version = "0.1.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" -dependencies = [ - "cc", -] - -[[package]] -name = "colorchoice" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" - -[[package]] -name = "combine" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes", - "memchr", -] - -[[package]] -name = "compression-codecs" -version = "0.4.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb7b51a7d9c967fc26773061ba86150f19c50c0d65c887cb1fbe295fd16619b7" -dependencies = [ - "compression-core", - "flate2", - "memchr", -] - -[[package]] -name = "compression-core" -version = "0.4.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75984efb6ed102a0d42db99afb6c1948f0380d1d91808d5529916e6c08b49d8d" - -[[package]] -name = "core-foundation" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crypto-common" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "darling" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" -dependencies = [ - "darling_core", - "quote", - "syn", -] - -[[package]] -name = "data-encoding" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" - -[[package]] -name = "deranged" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071" -dependencies = [ - "powerfmt", - "serde_core", -] - -[[package]] -name = "derive_more" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" -dependencies = [ - "derive_more-impl", -] - -[[package]] -name = "derive_more-impl" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - -[[package]] -name = "dyn-clone" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "fastbloom" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18c1ddb9231d8554c2d6bdf4cfaabf0c59251658c68b6c95cd52dd0c513a912a" -dependencies = [ - "getrandom 0.3.4", - "libm", - "rand 0.9.2", - "siphasher", -] - -[[package]] -name = "find-msvc-tools" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" - -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - -[[package]] -name = "flate2" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "form_urlencoded" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - -[[package]] -name = "futures" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-executor" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - -[[package]] -name = "futures-macro" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - -[[package]] -name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-util" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "r-efi", - "wasip2", - "wasm-bindgen", -] - -[[package]] -name = "gimli" -version = "0.32.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" - -[[package]] -name = "gio-sys" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521e93a7e56fc89e84aea9a52cfc9436816a4b363b030260b699950ff1336c83" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", - "windows-sys 0.59.0", -] - -[[package]] -name = "glib" -version = "0.20.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc4b6e352d4716d84d7dde562dd9aee2a7d48beb872dd9ece7f2d1515b2d683" -dependencies = [ - "bitflags", - "futures-channel", - "futures-core", - "futures-executor", - "futures-task", - "futures-util", - "gio-sys", - "glib-macros", - "glib-sys", - "gobject-sys", - "libc", - "memchr", - "smallvec", -] - -[[package]] -name = "glib-macros" -version = "0.20.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8084af62f09475a3f529b1629c10c429d7600ee1398ae12dd3bf175d74e7145" -dependencies = [ - "heck", - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "glib-sys" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ab79e1ed126803a8fb827e3de0e2ff95191912b8db65cee467edb56fc4cc215" -dependencies = [ - "libc", - "system-deps", -] - -[[package]] -name = "glob" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" - -[[package]] -name = "gobject-sys" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec9aca94bb73989e3cfdbf8f2e0f1f6da04db4d291c431f444838925c4c63eda" -dependencies = [ - "glib-sys", - "libc", - "system-deps", -] - -[[package]] -name = "gst-plugin-version-helper" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a68a894ef2d738054b950e1dbef5d9012b63fd968d4d32dbccd31bd8d8d4b219" -dependencies = [ - "chrono", - "toml_edit", -] - -[[package]] -name = "gstreamer" -version = "0.23.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8757a87f3706560037a01a9f06a59fcc7bdb0864744dcf73546606e60c4316e1" -dependencies = [ - "cfg-if", - "futures-channel", - "futures-core", - "futures-util", - "glib", - "gstreamer-sys", - "itertools 0.14.0", - "libc", - "muldiv", - "num-integer", - "num-rational", - "once_cell", - "option-operations", - "paste", - "pin-project-lite", - "smallvec", - "thiserror 2.0.17", -] - -[[package]] -name = "gstreamer-sys" -version = "0.23.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feea73b4d92dbf9c24a203c9cd0bcc740d584f6b5960d5faf359febf288919b2" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", -] - -[[package]] -name = "h264-parser" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2f85be813ce08f0569fcd816f256c6f4287c975d69a9a14ceacc309f1de967" - -[[package]] -name = "hang" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10631856b75596bcfca1c82c654fc006d1814d6eded004f6b170bcbddfe4bc97" -dependencies = [ - "buf-list", - "bytes", - "derive_more", - "futures", - "hex", - "lazy_static", - "moq-lite", - "regex", - "serde", - "serde_json", - "serde_with", - "thiserror 2.0.17", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "http" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" -dependencies = [ - "bytes", - "futures-core", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" - -[[package]] -name = "humantime" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" - -[[package]] -name = "humantime-serde" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a3db5ea5923d99402c94e9feb261dc5ee9b4efa158b0315f788cf549cc200c" -dependencies = [ - "humantime", - "serde", -] - -[[package]] -name = "hyper" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" -dependencies = [ - "atomic-waker", - "bytes", - "futures-channel", - "futures-core", - "http", - "http-body", - "httparse", - "itoa", - "pin-project-lite", - "pin-utils", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" -dependencies = [ - "http", - "hyper", - "hyper-util", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", - "webpki-roots 1.0.6", -] - -[[package]] -name = "hyper-util" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" -dependencies = [ - "base64", - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "http", - "http-body", - "hyper", - "ipnet", - "libc", - "percent-encoding", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "icu_collections" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" -dependencies = [ - "displaydoc", - "potential_utf", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locale_core" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_normalizer" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" - -[[package]] -name = "icu_properties" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "potential_utf", - "zerotrie", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" - -[[package]] -name = "icu_provider" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" -dependencies = [ - "displaydoc", - "icu_locale_core", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", -] - -[[package]] -name = "indexmap" -version = "2.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" -dependencies = [ - "equivalent", - "hashbrown 0.16.0", - "serde", - "serde_core", -] - -[[package]] -name = "ipnet" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "iri-string" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" - -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - -[[package]] -name = "jni" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" -dependencies = [ - "cesu8", - "cfg-if", - "combine", - "jni-sys", - "log", - "thiserror 1.0.69", - "walkdir", - "windows-sys 0.45.0", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" -dependencies = [ - "getrandom 0.3.4", - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "libc" -version = "0.2.177" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" - -[[package]] -name = "libloading" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" -dependencies = [ - "cfg-if", - "windows-link", -] - -[[package]] -name = "libm" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" - -[[package]] -name = "litemap" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" - -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" - -[[package]] -name = "lru-slab" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" - -[[package]] -name = "m3u8-rs" -version = "5.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c1d7ba86f7ea62f17f4310c55e93244619ddc7dadfc7e565de1967e4e41e6e7" -dependencies = [ - "chrono", - "nom", -] - -[[package]] -name = "matchers" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" -dependencies = [ - "regex-automata", -] - -[[package]] -name = "memchr" -version = "2.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", - "simd-adler32", -] - -[[package]] -name = "mio" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" -dependencies = [ - "libc", - "wasi", - "windows-sys 0.61.2", -] - -[[package]] -name = "moq-gst" -version = "0.2.2" -dependencies = [ - "anyhow", - "bytes", - "gst-plugin-version-helper", - "gstreamer", - "hang", - "moq-lite", - "moq-mux", - "moq-native", - "tokio", - "tracing", - "tracing-subscriber", - "url", -] - -[[package]] -name = "moq-lite" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e2b5cbf085a08eca461384c1242a437c4505f41a315e50eec10d538bb910b1" -dependencies = [ - "bytes", - "futures", - "hex", - "num_enum", - "rand 0.9.2", - "serde", - "thiserror 2.0.17", - "tokio", - "tracing", - "web-async", - "web-transport-trait", -] - -[[package]] -name = "moq-msf" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aebd40d255fbed61325c1b2a2a96332b6183755333d95acee4348cd7733fcce1" -dependencies = [ - "serde", - "serde_json", - "serde_with", -] - -[[package]] -name = "moq-mux" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4116c2dc23a07a20c45d3fa54364af190ce678b1d16e93da665589a3735dae0" -dependencies = [ - "anyhow", - "base64", - "buf-list", - "bytes", - "derive_more", - "h264-parser", - "hang", - "m3u8-rs", - "moq-lite", - "moq-msf", - "mp4-atom", - "num_enum", - "reqwest", - "scuffle-av1", - "scuffle-h265", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "moq-native" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5754d77ace0048c8349d76a2f12f25a093d6f9358e7e24cf86f84202c0d2a547" -dependencies = [ - "anyhow", - "clap", - "futures", - "hex", - "humantime", - "humantime-serde", - "moq-lite", - "parking_lot", - "quinn", - "rand 0.9.2", - "rcgen", - "reqwest", - "rustls", - "rustls-native-certs", - "rustls-pemfile", - "rustls-webpki", - "serde", - "serde_with", - "time", - "tokio", - "tracing", - "tracing-subscriber", - "url", - "web-transport-quinn", - "web-transport-ws", -] - -[[package]] -name = "mp4-atom" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e8e949244bbd26ea7eb6d936af3a6a0202be68bcfc9afce700f3c9026860ff7" -dependencies = [ - "bytes", - "derive_more", - "num", - "paste", - "serde", - "thiserror 1.0.69", - "tokio", - "tracing", -] - -[[package]] -name = "muldiv" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956787520e75e9bd233246045d19f42fb73242759cc57fba9611d940ae96d4b0" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "nu-ansi-term" -version = "0.50.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_enum" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" -dependencies = [ - "num_enum_derive", - "rustversion", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "nutype-enum" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e13adea6de269faa0724df58f43f6fe2a81af7094f1dcb8b5b968eb2103cb3" -dependencies = [ - "scuffle-workspace-hack", -] - -[[package]] -name = "object" -version = "0.37.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" - -[[package]] -name = "once_cell_polyfill" -version = "1.70.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "option-operations" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c26d27bb1aeab65138e4bf7666045169d1717febcc9ff870166be8348b223d0" -dependencies = [ - "paste", -] - -[[package]] -name = "parking_lot" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" -dependencies = [ - "backtrace", - "cfg-if", - "libc", - "petgraph", - "redox_syscall", - "smallvec", - "windows-link", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "percent-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" - -[[package]] -name = "petgraph" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" -dependencies = [ - "fixedbitset", - "indexmap 2.12.0", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - -[[package]] -name = "potential_utf" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" -dependencies = [ - "zerovec", -] - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn", -] - -[[package]] -name = "proc-macro-crate" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" -dependencies = [ - "toml_edit", -] - -[[package]] -name = "proc-macro2" -version = "1.0.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e0f6df8eaa422d97d72edcd152e1451618fed47fabbdbd5a8864167b1d4aff7" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quinn" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" -dependencies = [ - "bytes", - "cfg_aliases", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls", - "socket2", - "thiserror 2.0.17", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-proto" -version = "0.11.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" -dependencies = [ - "aws-lc-rs", - "bytes", - "fastbloom", - "getrandom 0.3.4", - "lru-slab", - "rand 0.9.2", - "ring", - "rustc-hash", - "rustls", - "rustls-pki-types", - "rustls-platform-verifier", - "slab", - "thiserror 2.0.17", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2", - "tracing", - "windows-sys 0.52.0", -] - -[[package]] -name = "quote" -version = "1.0.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" -dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.3", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.3", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.16", -] - -[[package]] -name = "rand_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom 0.3.4", -] - -[[package]] -name = "rcgen" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fae430c6b28f1ad601274e78b7dffa0546de0b73b4cd32f46723c0c2a16f7a5" -dependencies = [ - "aws-lc-rs", - "rustls-pki-types", - "time", - "yasna", -] - -[[package]] -name = "redox_syscall" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" -dependencies = [ - "bitflags", -] - -[[package]] -name = "ref-cast" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" -dependencies = [ - "ref-cast-impl", -] - -[[package]] -name = "ref-cast-impl" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "regex" -version = "1.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" - -[[package]] -name = "reqwest" -version = "0.12.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" -dependencies = [ - "async-compression", - "base64", - "bytes", - "futures-core", - "futures-util", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-util", - "js-sys", - "log", - "percent-encoding", - "pin-project-lite", - "quinn", - "rustls", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tokio-rustls", - "tokio-util", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots 1.0.6", -] - -[[package]] -name = "ring" -version = "0.17.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.16", - "libc", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" - -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - -[[package]] -name = "rustls" -version = "0.23.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9586e9ee2b4f8fab52a0048ca7334d7024eef48e2cb9407e3497bb7cab7fa7" -dependencies = [ - "aws-lc-rs", - "log", - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-native-certs" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" -dependencies = [ - "openssl-probe", - "rustls-pki-types", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" -dependencies = [ - "web-time", - "zeroize", -] - -[[package]] -name = "rustls-platform-verifier" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" -dependencies = [ - "core-foundation", - "core-foundation-sys", - "jni", - "log", - "once_cell", - "rustls", - "rustls-native-certs", - "rustls-platform-verifier-android", - "rustls-webpki", - "security-framework", - "security-framework-sys", - "webpki-root-certs", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustls-platform-verifier-android" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" - -[[package]] -name = "rustls-webpki" -version = "0.103.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10b3f4191e8a80e6b43eebabfac91e5dcecebb27a71f04e820c47ec41d314bf" -dependencies = [ - "aws-lc-rs", - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schannel" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "schemars" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" -dependencies = [ - "dyn-clone", - "ref-cast", - "serde", - "serde_json", -] - -[[package]] -name = "schemars" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" -dependencies = [ - "dyn-clone", - "ref-cast", - "serde", - "serde_json", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "scuffle-av1" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028eddc8b17fe9dba817b238c56d3acf03748bdbed4c35783cfb93857ef15955" -dependencies = [ - "byteorder", - "bytes", - "scuffle-bytes-util", - "scuffle-workspace-hack", -] - -[[package]] -name = "scuffle-bytes-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0417748c2a42f4a08d4e634b68b1d64f22a8c24bef2e7ac93df33aa61202a45b" -dependencies = [ - "byteorder", - "bytes", - "bytestring", - "scuffle-workspace-hack", -] - -[[package]] -name = "scuffle-expgolomb" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d21330974c941e4c0aedc1e7255ea809e8cbac51e135209f6d67843ad1b94d" -dependencies = [ - "scuffle-bytes-util", - "scuffle-workspace-hack", -] - -[[package]] -name = "scuffle-h265" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b04b276c2f79846b7968abe6f87cedf951e06fd2a2b72d99c457e85d7e40f3fb" -dependencies = [ - "bitflags", - "byteorder", - "bytes", - "nutype-enum", - "scuffle-bytes-util", - "scuffle-expgolomb", - "scuffle-workspace-hack", -] - -[[package]] -name = "scuffle-workspace-hack" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8028ded836a0d9fabdfa4d713389b76a2098b5153f50a135c8faed7e3a3d5ae2" - -[[package]] -name = "security-framework" -version = "3.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.145" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", - "serde_core", -] - -[[package]] -name = "serde_spanned" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392" -dependencies = [ - "serde_core", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_with" -version = "3.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa66c845eee442168b2c8134fec70ac50dc20e760769c8ba0ad1319ca1959b04" -dependencies = [ - "base64", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.12.0", - "schemars 0.9.0", - "schemars 1.0.4", - "serde_core", - "serde_json", - "serde_with_macros", - "time", -] - -[[package]] -name = "serde_with_macros" -version = "3.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91a903660542fced4e99881aa481bdbaec1634568ee02e0b8bd57c64cb38955" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "sfv" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d471eaefb14f4b30032525bdb124b36e55ba9cb1292080e06f1a236cd10fe87" -dependencies = [ - "base64", - "indexmap 2.12.0", - "ref-cast", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook-registry" -version = "1.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" -dependencies = [ - "libc", -] - -[[package]] -name = "simd-adler32" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" - -[[package]] -name = "siphasher" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" - -[[package]] -name = "slab" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" - -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - -[[package]] -name = "socket2" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" -dependencies = [ - "libc", - "windows-sys 0.60.2", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "syn" -version = "2.0.108" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" -dependencies = [ - "futures-core", -] - -[[package]] -name = "synstructure" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "system-deps" -version = "7.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c236d79f20808ca0084bfcd1a2fd6c686216b7f7a0c4fc39deb0cbf5eaab3713" -dependencies = [ - "cfg-expr", - "heck", - "pkg-config", - "toml", - "version-compare", -] - -[[package]] -name = "target-lexicon" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a" - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" -dependencies = [ - "thiserror-impl 2.0.17", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thread_local" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "time" -version = "0.3.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" - -[[package]] -name = "time-macros" -version = "0.2.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tinystr" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" -dependencies = [ - "displaydoc", - "zerovec", -] - -[[package]] -name = "tinyvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" -dependencies = [ - "bytes", - "libc", - "mio", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.61.2", -] - -[[package]] -name = "tokio-macros" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" -dependencies = [ - "futures-util", - "log", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tungstenite", - "webpki-roots 0.26.11", -] - -[[package]] -name = "tokio-util" -version = "0.7.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "toml" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" -dependencies = [ - "indexmap 2.12.0", - "serde_core", - "serde_spanned", - "toml_datetime", - "toml_parser", - "toml_writer", - "winnow", -] - -[[package]] -name = "toml_datetime" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" -dependencies = [ - "serde_core", -] - -[[package]] -name = "toml_edit" -version = "0.23.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" -dependencies = [ - "indexmap 2.12.0", - "toml_datetime", - "toml_parser", - "winnow", -] - -[[package]] -name = "toml_parser" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" -dependencies = [ - "winnow", -] - -[[package]] -name = "toml_writer" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2" - -[[package]] -name = "tower" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" -dependencies = [ - "futures-core", - "futures-util", - "pin-project-lite", - "sync_wrapper", - "tokio", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-http" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" -dependencies = [ - "bitflags", - "bytes", - "futures-util", - "http", - "http-body", - "iri-string", - "pin-project-lite", - "tower", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tracing" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-core" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex-automata", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "tungstenite" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http", - "httparse", - "log", - "rand 0.8.5", - "rustls", - "rustls-pki-types", - "sha1", - "thiserror 1.0.69", - "utf-8", -] - -[[package]] -name = "typenum" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" - -[[package]] -name = "unicode-ident" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" - -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "url" -version = "2.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[package]] -name = "valuable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" - -[[package]] -name = "version-compare" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - -[[package]] -name = "wasip2" -version = "1.0.1+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" -dependencies = [ - "cfg-if", - "js-sys", - "once_cell", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "web-async" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5414b65d9a5094649bb99987bb74db71febfdfa3677b7954a0a05c99d0424e8" -dependencies = [ - "tokio", - "tracing", - "wasm-bindgen-futures", -] - -[[package]] -name = "web-sys" -version = "0.3.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "web-transport-proto" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5afe275c02f899650c5497b946552fcc04f3f378bd2c3bc1e8005ff915772b97" -dependencies = [ - "bytes", - "http", - "sfv", - "thiserror 2.0.17", - "tokio", - "url", -] - -[[package]] -name = "web-transport-quinn" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d356bedff779480f8d88d94bf50a2eb8dedabb84414442f73c16dfee9db55b8" -dependencies = [ - "bytes", - "futures", - "http", - "quinn", - "rustls", - "rustls-native-certs", - "thiserror 2.0.17", - "tokio", - "tracing", - "url", - "web-transport-proto", - "web-transport-trait", -] - -[[package]] -name = "web-transport-trait" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "802d6aa508f2c63c9050ceabc17265bbf90ed4d6f4e4357e987583883628e79c" -dependencies = [ - "bytes", -] - -[[package]] -name = "web-transport-ws" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7b1cd89c36a28eae759329839e85f7dbca733896f048a6daaf5f8fc80f3bcba" -dependencies = [ - "bytes", - "futures", - "thiserror 2.0.17", - "tokio", - "tokio-tungstenite", - "web-transport-proto", - "web-transport-trait", -] - -[[package]] -name = "webpki-root-certs" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d651ec480de84b762e7be71e6efa7461699c19d9e2c272c8d93455f567786e" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "webpki-roots" -version = "0.26.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" -dependencies = [ - "webpki-roots 1.0.6", -] - -[[package]] -name = "webpki-roots" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "winapi-util" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "windows-core" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-implement" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-interface" -version = "0.59.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-link" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" - -[[package]] -name = "windows-result" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", -] - -[[package]] -name = "windows-sys" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - -[[package]] -name = "winnow" -version = "0.7.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" -dependencies = [ - "memchr", -] - -[[package]] -name = "wit-bindgen" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" - -[[package]] -name = "writeable" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" - -[[package]] -name = "yasna" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" -dependencies = [ - "time", -] - -[[package]] -name = "yoke" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zerocopy" -version = "0.8.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zerofrom" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zeroize" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" - -[[package]] -name = "zerotrie" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", -] - -[[package]] -name = "zerovec" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index 0ac56c6..0000000 --- a/Cargo.toml +++ /dev/null @@ -1,39 +0,0 @@ -[package] -name = "moq-gst" -description = "Media over QUIC - Gstreamer plugin" -authors = ["Luke Curley"] -repository = "https://github.com/moq-dev/gstreamer" -license = "MIT OR Apache-2.0" - -version = "0.2.2" -edition = "2021" -rust-version = "1.80" - -keywords = ["quic", "http3", "webtransport", "media", "live"] -categories = ["multimedia", "network-programming", "web-programming"] - -[lib] -name = "gstmoq" -crate-type = ["cdylib", "rlib"] -path = "src/lib.rs" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -hang = "0.15.0" -moq-mux = "0.3.0" -moq-lite = "0.15.0" -moq-native = "0.13.2" - -anyhow = { version = "1", features = ["backtrace"] } -bytes = "1" -gst = { package = "gstreamer", version = "0.23" } -#gst-app = { package = "gstreamer-app", version = "0.23", features = ["v1_20"] } - -tokio = { version = "1", features = ["full"] } -tracing = "0.1.41" -tracing-subscriber = "0.3.19" -url = "2" - -[build-dependencies] -gst-plugin-version-helper = "0.8" diff --git a/README.md b/README.md index 8b62c72..1f4b570 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@ +> [!WARNING] +> **This repository is deprecated.** Development has moved to [moq-dev/moq](https://github.com/moq-dev/moq) under [`rs/moq-gst`](https://github.com/moq-dev/moq/tree/main/rs/moq-gst). Please use that repository instead. +

Media over QUIC

-A GStreamer plugin for [MoQ (Media over QUIC)](https://github.com/kixelated/moq) that enables publishing and consuming media streams using the MoQ protocol. - -This plugin was originally part of the main MoQ repository but has been separated to avoid requiring GStreamer as a build dependency. +A GStreamer plugin for [MoQ (Media over QUIC)](https://github.com/moq-dev/moq) that enables publishing and consuming media streams using the MoQ protocol. # Usage ## Requirements diff --git a/build.rs b/build.rs deleted file mode 100644 index 6d87290..0000000 --- a/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - gst_plugin_version_helper::info() -} diff --git a/flake.lock b/flake.lock deleted file mode 100644 index f137f66..0000000 --- a/flake.lock +++ /dev/null @@ -1,98 +0,0 @@ -{ - "nodes": { - "crane": { - "locked": { - "lastModified": 1762538466, - "narHash": "sha256-8zrIPl6J+wLm9MH5ksHcW7BUHo7jSNOu0/hA0ohOOaM=", - "owner": "ipetkov", - "repo": "crane", - "rev": "0cea393fffb39575c46b7a0318386467272182fe", - "type": "github" - }, - "original": { - "owner": "ipetkov", - "repo": "crane", - "type": "github" - } - }, - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1762977756, - "narHash": "sha256-4PqRErxfe+2toFJFgcRKZ0UI9NSIOJa+7RXVtBhy4KE=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "c5ae371f1a6a7fd27823bc500d9390b38c05fa55", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "root": { - "inputs": { - "crane": "crane", - "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs", - "rust-overlay": "rust-overlay" - } - }, - "rust-overlay": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1763260832, - "narHash": "sha256-KMEJ9S7bZLvDIfVu2XdEJTZVYAc/arjFt5KnhGqwCOg=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "c3cea2a0ec0d5debbef4aa2a0cfe59bd0fb0aeeb", - "type": "github" - }, - "original": { - "owner": "oxalica", - "repo": "rust-overlay", - "type": "github" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/flake.nix b/flake.nix deleted file mode 100644 index b21770d..0000000 --- a/flake.nix +++ /dev/null @@ -1,90 +0,0 @@ -{ - description = "Media over QUIC - Gstreamer plugin"; - - inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; - flake-utils.url = "github:numtide/flake-utils"; - crane.url = "github:ipetkov/crane"; - rust-overlay = { - url = "github:oxalica/rust-overlay"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - }; - - outputs = { self, nixpkgs, flake-utils, crane, rust-overlay}: - flake-utils.lib.eachDefaultSystem ( - system: - let - pkgs = import nixpkgs { - inherit system; - overlays = [ (import rust-overlay) ]; - }; - rust-toolchain = pkgs.rust-bin.stable.latest.default.override { - extensions = [ - "rust-src" - "rust-analyzer" - ]; - }; - craneLib = (crane.mkLib pkgs).overrideToolchain rust-toolchain; - - # Helper function to get crate info from Cargo.toml - crateInfo = cargoTomlPath: craneLib.crateNameFromCargoToml { cargoToml = cargoTomlPath; }; - - gstreamerLib = with pkgs ; [ - gst_all_1.gstreamer.out - gst_all_1.gst-plugins-base - gst_all_1.gst-plugins-good - gst_all_1.gst-plugins-bad - ]; - gstreamerSearch = with pkgs; [ - gst_all_1.gst-plugins-ugly - gst_all_1.gst-plugins-rs - ] ++ gstreamerLib; - - shell-deps = with pkgs; [ - rust-toolchain - just - pkg-config - glib - cargo-sort - cargo-shear - cargo-edit - gst_all_1.gstreamer - ]; - - gstPluginPath = nixpkgs.lib.makeSearchPath "lib/gstreamer-1.0" gstreamerSearch; - in { - devShells.default = pkgs.mkShell { - packages = shell-deps; - - env = { - GST_PLUGIN_PATH_1_0 = gstPluginPath; - #PKG_CONFIG_PATH = pkgConfigPath; - GST_REGISTRY = "./gst-registry.bin"; - }; - - # if you want zsh instead of bash, uncomment this - #shellHook = '' - # exec zsh - #''; - }; - packages = { - hang-gst = craneLib.buildPackage ( - crateInfo ./Cargo.toml - // { - src = craneLib.cleanCargoSource ./.; - nativeBuildInputs = with pkgs; [ - pkg-config - ]; - buildInputs = with pkgs; [ - glib - glib.dev - gst_all_1.gstreamer.dev - ]; - cargoExtraArgs = "-p hang-gst"; - } - ); - default = self.packages.${system}.hang-gst; - }; - }); -} diff --git a/justfile b/justfile deleted file mode 100644 index 3e03a0d..0000000 --- a/justfile +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env just --justfile - -# Using Just: https://github.com/casey/just?tab=readme-ov-file#installation - -export RUST_BACKTRACE := "1" -export RUST_LOG := env_var_or_default("RUST_LOG", "info") -export URL := "http://localhost:4443/anon" -#export GST_DEBUG:="*:4" - -# List all of the available commands. -default: - just --list - -# Install any required dependencies. -setup: - # Upgrade Rust - rustup update - - # Make sure the right components are installed. - rustup component add rustfmt clippy - - # Install cargo binstall if needed. - cargo install cargo-binstall - - # Install cargo shear if needed. - cargo binstall --no-confirm cargo-shear - -# Download the video and convert it to a fragmented MP4 that we can stream -download name url: - if [ ! -f dev/{{name}}.mp4 ]; then \ - wget {{url}} -O dev/{{name}}.mp4; \ - fi - - if [ ! -f dev/{{name}}.fmp4 ]; then \ - ffmpeg -i dev/{{name}}.mp4 \ - -c copy \ - -f mp4 -movflags cmaf+separate_moof+delay_moov+skip_trailer+frag_every_frame \ - dev/{{name}}.fmp4; \ - fi - -# Publish a video using gstreamer to the localhost relay server -pub broadcast: (download "bbb" "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4") - # Build the plugins - cargo build - - # Run gstreamer and pipe the output to our plugin - GST_PLUGIN_PATH_1_0="${PWD}/target/debug${GST_PLUGIN_PATH_1_0:+:$GST_PLUGIN_PATH_1_0}" \ - gst-launch-1.0 -v -e multifilesrc location="dev/bbb.fmp4" loop=true ! parsebin name=parse \ - parse. ! queue ! identity sync=true ! mux.sink_0 \ - parse. ! queue ! identity sync=true ! mux.sink_1 \ - moqsink name=mux url="$URL" broadcast="{{broadcast}}" tls-disable-verify=true - -# Subscribe to a video using gstreamer -sub broadcast: - # Build the plugins - cargo build - - # Run gstreamer and pipe the output to our plugin - # This will render the video to the screen - GST_PLUGIN_PATH_1_0="${PWD}/target/debug${GST_PLUGIN_PATH_1_0:+:$GST_PLUGIN_PATH_1_0}" \ - gst-launch-1.0 -v -e moqsrc url="$URL" broadcast="{{broadcast}}" tls-disable-verify=true ! decodebin ! videoconvert ! autovideosink - -# Run the CI checks -check $RUSTFLAGS="-D warnings": - cargo check --all-targets - cargo clippy --all-targets -- -D warnings - cargo fmt -- --check - cargo shear # requires: cargo binstall cargo-shear - -# Run any CI tests -test $RUSTFLAGS="-D warnings": - cargo test - -# Automatically fix some issues. -fix: - cargo fix --allow-staged --all-targets --all-features - cargo clippy --fix --allow-staged --all-targets --all-features - cargo fmt --all - cargo shear --fix - -# Upgrade any tooling -upgrade: - rustup upgrade - - # Install cargo-upgrades if needed. - cargo install cargo-upgrades cargo-edit - cargo upgrade - -# Build the plugins -build: - cargo build diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index 69bff0f..0000000 --- a/src/lib.rs +++ /dev/null @@ -1,40 +0,0 @@ -use gst::glib; - -mod sink; -mod source; - -use tracing::level_filters::LevelFilter; -use tracing_subscriber::EnvFilter; - -pub fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { - sink::register(plugin)?; - source::register(plugin)?; - - let filter = EnvFilter::builder() - .with_default_directive(LevelFilter::INFO.into()) - .from_env_lossy() // Allow overriding with RUST_LOG - .add_directive("h2=warn".parse().unwrap()) - .add_directive("quinn=info".parse().unwrap()) - .add_directive("tracing::span=off".parse().unwrap()) - .add_directive("tracing::span::active=off".parse().unwrap()); - - let logger = tracing_subscriber::FmtSubscriber::builder() - .with_writer(std::io::stderr) - .with_env_filter(filter) - .finish(); - - tracing::subscriber::set_global_default(logger).unwrap(); - Ok(()) -} - -gst::plugin_define!( - moq, - env!("CARGO_PKG_DESCRIPTION"), - plugin_init, - concat!(env!("CARGO_PKG_VERSION"), "-", env!("COMMIT_ID")), - "Apache 2.0", - env!("CARGO_PKG_NAME"), - env!("CARGO_PKG_NAME"), - env!("CARGO_PKG_REPOSITORY"), - env!("BUILD_REL_DATE") -); diff --git a/src/sink/imp.rs b/src/sink/imp.rs deleted file mode 100644 index aca9e15..0000000 --- a/src/sink/imp.rs +++ /dev/null @@ -1,467 +0,0 @@ -//! Async-friendly MoqSink that keeps the original dynamic-pad Element -//! behavior while pushing all network setup and CMAF publishing work into -//! a Tokio task. The GLib state change thread never blocks, pads still get -//! requested dynamically, and each pad simply forwards buffers/events to the -//! background worker via an unbounded channel. - -use std::collections::HashMap; -use std::sync::{LazyLock, Mutex}; - -use anyhow::{Context, Result}; -use bytes::Bytes; -use gst::glib; -use gst::prelude::*; -use gst::subclass::prelude::*; -use tokio::sync::mpsc; -use url::Url; - -use hang::moq_lite; - -static RUNTIME: LazyLock = LazyLock::new(|| { - tokio::runtime::Builder::new_multi_thread() - .enable_all() - .build() - .expect("spawn tokio runtime") -}); - -static CAT: LazyLock = LazyLock::new(|| { - gst::DebugCategory::new( - "moq-sink", - gst::DebugColorFlags::empty(), - Some("MoQ Sink (async element)"), - ) -}); - -#[derive(Debug, Clone, Default)] -struct Settings { - url: Option, - broadcast: Option, - tls_disable_verify: bool, -} - -#[derive(Debug, Clone)] -struct ResolvedSettings { - url: Url, - broadcast: String, - tls_disable_verify: bool, -} - -impl TryFrom for ResolvedSettings { - type Error = anyhow::Error; - - fn try_from(value: Settings) -> Result { - Ok(Self { - url: Url::parse(value.url.as_ref().context("url property is required")?)?, - broadcast: value - .broadcast - .as_ref() - .context("broadcast property is required")? - .clone(), - tls_disable_verify: value.tls_disable_verify, - }) - } -} - -#[derive(Debug)] -struct SessionHandle { - sender: mpsc::UnboundedSender, - join: tokio::task::JoinHandle<()>, -} - -impl SessionHandle { - fn stop(self) { - let _ = self.sender.send(ControlMessage::Shutdown); - RUNTIME.spawn(async move { - if let Err(err) = self.join.await { - gst::warning!(CAT, "session task ended with error: {err:?}"); - } - }); - } -} - -struct PadState { - decoder: moq_mux::import::Decoder, - reference_pts: Option, -} - -struct RuntimeState { - #[allow(dead_code)] - session: moq_lite::Session, - broadcast: moq_lite::BroadcastProducer, - catalog: moq_mux::CatalogProducer, - pads: HashMap, -} - -#[derive(Debug)] -enum ControlMessage { - SetCaps { - pad_name: String, - caps: gst::Caps, - }, - Buffer { - pad_name: String, - data: Bytes, - pts: Option, - }, - DropPad { - pad_name: String, - }, - Shutdown, -} - -#[derive(Default)] -pub struct MoqSink { - settings: Mutex, - session: Mutex>, -} - -#[glib::object_subclass] -impl ObjectSubclass for MoqSink { - const NAME: &'static str = "MoqSink"; - type Type = super::MoqSink; - type ParentType = gst::Element; -} - -impl ObjectImpl for MoqSink { - fn properties() -> &'static [glib::ParamSpec] { - static PROPS: LazyLock> = LazyLock::new(|| { - vec![ - glib::ParamSpecString::builder("url") - .nick("Source URL") - .blurb("Connect to the given URL") - .build(), - glib::ParamSpecString::builder("broadcast") - .nick("Broadcast") - .blurb("The name of the broadcast to publish") - .build(), - glib::ParamSpecBoolean::builder("tls-disable-verify") - .nick("TLS disable verify") - .blurb("Disable TLS verification") - .default_value(false) - .build(), - ] - }); - PROPS.as_ref() - } - - fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { - let mut settings = self.settings.lock().unwrap(); - match pspec.name() { - "url" => settings.url = value.get().unwrap(), - "broadcast" => settings.broadcast = value.get().unwrap(), - "tls-disable-verify" => settings.tls_disable_verify = value.get().unwrap(), - _ => unreachable!(), - } - } - - fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { - let settings = self.settings.lock().unwrap(); - match pspec.name() { - "url" => settings.url.to_value(), - "broadcast" => settings.broadcast.to_value(), - "tls-disable-verify" => settings.tls_disable_verify.to_value(), - _ => unreachable!(), - } - } -} - -impl GstObjectImpl for MoqSink {} - -impl ElementImpl for MoqSink { - fn metadata() -> Option<&'static gst::subclass::ElementMetadata> { - static ELEMENT_METADATA: LazyLock = LazyLock::new(|| { - gst::subclass::ElementMetadata::new( - "MoQ Sink (async)", - "Sink/Network/MoQ", - "Transmits media over MoQ", - "Luke Curley , Steve McFarlin ", - ) - }); - Some(&*ELEMENT_METADATA) - } - - fn pad_templates() -> &'static [gst::PadTemplate] { - static PAD_TEMPLATES: LazyLock> = LazyLock::new(|| { - let mut caps = gst::Caps::new_empty(); - caps.merge( - gst::Caps::builder("video/x-h264") - .field("stream-format", "byte-stream") - .field("alignment", "au") - .build(), - ); - caps.merge( - gst::Caps::builder("video/x-h265") - .field("stream-format", "byte-stream") - .field("alignment", "au") - .build(), - ); - caps.merge(gst::Caps::builder("video/x-av1").build()); - caps.merge( - gst::Caps::builder("audio/mpeg") - .field("mpegversion", 4i32) - .field("stream-format", "raw") - .build(), - ); - caps.merge(gst::Caps::builder("audio/x-opus").build()); - - let templ = - gst::PadTemplate::new("sink_%u", gst::PadDirection::Sink, gst::PadPresence::Request, &caps).unwrap(); - vec![templ] - }); - PAD_TEMPLATES.as_ref() - } - - fn request_new_pad( - &self, - templ: &gst::PadTemplate, - name: Option<&str>, - _caps: Option<&gst::Caps>, - ) -> Option { - let pad_builder = gst::Pad::builder_from_template(templ) - .chain_function(|pad, parent, buffer| { - let element = parent - .and_then(|p| p.downcast_ref::()) - .ok_or(gst::FlowError::Error)?; - element.imp().forward_buffer(pad, buffer) - }) - .event_function(|pad, parent, event| { - let Some(element) = parent.and_then(|p| p.downcast_ref::()) else { - return false; - }; - element.imp().forward_event(pad, event) - }); - - let pad = if let Some(name) = name { - pad_builder.name(name).build() - } else { - pad_builder.build() - }; - - self.obj().add_pad(&pad).ok()?; - Some(pad) - } - - fn release_pad(&self, pad: &gst::Pad) { - if let Some(session) = self.session.lock().unwrap().as_ref() { - let _ = session.sender.send(ControlMessage::DropPad { - pad_name: pad.name().to_string(), - }); - } - let _ = self.obj().remove_pad(pad); - } - - fn change_state(&self, transition: gst::StateChange) -> Result { - match transition { - gst::StateChange::ReadyToPaused => { - self.start_session().map_err(|err| { - gst::error!(CAT, obj = self.obj(), "failed to start session: {err:#}"); - gst::StateChangeError - })?; - } - gst::StateChange::PausedToReady => self.stop_session(), - _ => (), - } - - self.parent_change_state(transition) - } -} - -impl MoqSink { - fn start_session(&self) -> Result<()> { - let settings = { - let settings = self.settings.lock().unwrap().clone(); - ResolvedSettings::try_from(settings)? - }; - - let (tx, rx) = mpsc::unbounded_channel::(); - let join = RUNTIME.spawn(async move { - if let Err(err) = run_session(settings, rx).await { - gst::error!(CAT, "session error: {err:#}"); - } - }); - - *self.session.lock().unwrap() = Some(SessionHandle { sender: tx, join }); - Ok(()) - } - - fn stop_session(&self) { - if let Some(handle) = self.session.lock().unwrap().take() { - handle.stop(); - } - } - - fn forward_buffer(&self, pad: &gst::Pad, buffer: gst::Buffer) -> Result { - let sender = self - .session - .lock() - .unwrap() - .as_ref() - .map(|handle| handle.sender.clone()) - .ok_or(gst::FlowError::Flushing)?; - - let map = buffer.map_readable().map_err(|_| gst::FlowError::Error)?; - let pts = buffer.pts(); - let data = Bytes::copy_from_slice(map.as_slice()); - - sender - .send(ControlMessage::Buffer { - pad_name: pad.name().to_string(), - data, - pts, - }) - .map_err(|_| gst::FlowError::Flushing)?; - - Ok(gst::FlowSuccess::Ok) - } - - fn forward_event(&self, pad: &gst::Pad, event: gst::Event) -> bool { - match event.view() { - gst::EventView::Caps(caps) => { - let sender = match self - .session - .lock() - .unwrap() - .as_ref() - .map(|handle| handle.sender.clone()) - { - Some(sender) => sender, - None => return false, - }; - - if sender - .send(ControlMessage::SetCaps { - pad_name: pad.name().to_string(), - caps: caps.caps().to_owned(), - }) - .is_err() - { - return false; - } - - true - } - _ => gst::Pad::event_default(pad, Some(&*self.obj()), event), - } - } -} - -async fn run_session(settings: ResolvedSettings, mut rx: mpsc::UnboundedReceiver) -> Result<()> { - let mut client_config = moq_native::ClientConfig::default(); - client_config.tls.disable_verify = Some(settings.tls_disable_verify); - - let client = client_config.init()?; - - let origin = moq_lite::Origin::produce(); - let mut broadcast = moq_lite::Broadcast::produce(); - let broadcast_consumer = broadcast.consume(); - - let catalog = moq_mux::CatalogProducer::new(&mut broadcast)?; - - anyhow::ensure!( - origin.publish_broadcast(&settings.broadcast, broadcast_consumer), - "failed to publish broadcast {}", - settings.broadcast - ); - - let client = client.with_publish(origin.consume()); - let session = client.connect(settings.url.clone()).await?; - - let mut runtime = RuntimeState { - session, - broadcast, - catalog, - pads: HashMap::new(), - }; - - while let Some(msg) = rx.recv().await { - match msg { - ControlMessage::SetCaps { pad_name, caps } => { - if let Err(err) = handle_caps(&mut runtime, pad_name, caps) { - gst::error!(CAT, "failed to configure pad: {err:#}"); - } - } - ControlMessage::Buffer { pad_name, data, pts } => { - if let Err(err) = handle_buffer(&mut runtime, pad_name, data, pts) { - gst::error!(CAT, "failed to publish buffer: {err:#}"); - } - } - ControlMessage::DropPad { pad_name } => { - runtime.pads.remove(&pad_name); - } - ControlMessage::Shutdown => break, - } - } - - Ok(()) -} - -fn handle_caps(runtime: &mut RuntimeState, pad_name: String, caps: gst::Caps) -> Result<()> { - let structure = caps.structure(0).context("empty caps")?; - let decoder: moq_mux::import::Decoder = match structure.name().as_str() { - "video/x-h264" => { - let mut bytes = Bytes::new(); - new_decoder(runtime, moq_mux::import::DecoderFormat::Avc3, &mut bytes)? - } - "video/x-h265" => { - let mut bytes = Bytes::new(); - new_decoder(runtime, moq_mux::import::DecoderFormat::Hev1, &mut bytes)? - } - "video/x-av1" => { - let mut bytes = Bytes::new(); - new_decoder(runtime, moq_mux::import::DecoderFormat::Av01, &mut bytes)? - } - "audio/mpeg" => { - let codec_data = structure - .get::("codec_data") - .context("AAC caps missing codec_data")?; - let map = codec_data.map_readable().context("failed to map codec_data")?; - let mut data = Bytes::copy_from_slice(map.as_slice()); - new_decoder(runtime, moq_mux::import::DecoderFormat::Aac, &mut data)? - } - "audio/x-opus" => { - let channels: i32 = structure.get("channels").unwrap_or(2); - let rate: i32 = structure.get("rate").unwrap_or(48_000); - let config = moq_mux::import::OpusConfig { - sample_rate: rate as u32, - channel_count: channels as u32, - }; - moq_mux::import::Opus::new(runtime.broadcast.clone(), runtime.catalog.clone(), config)?.into() - } - other => anyhow::bail!("unsupported caps: {}", other), - }; - - runtime.pads.insert( - pad_name, - PadState { - decoder, - reference_pts: None, - }, - ); - Ok(()) -} - -fn new_decoder( - runtime: &mut RuntimeState, - format: moq_mux::import::DecoderFormat, - buf: &mut Bytes, -) -> Result { - let decoder = moq_mux::import::Decoder::new(runtime.broadcast.clone(), runtime.catalog.clone(), format, buf)?; - Ok(decoder) -} - -fn handle_buffer( - runtime: &mut RuntimeState, - pad_name: String, - mut data: Bytes, - pts: Option, -) -> Result<()> { - let pad = runtime.pads.get_mut(&pad_name).context("pad not configured")?; - - let ts = pts.and_then(|pts| { - let reference = *pad.reference_pts.get_or_insert(pts); - let relative = pts.checked_sub(reference)?; - hang::container::Timestamp::from_micros(relative.nseconds() / 1000).ok() - }); - - pad.decoder.decode_frame(&mut data, ts).map_err(|e| anyhow::anyhow!(e)) -} diff --git a/src/sink/mod.rs b/src/sink/mod.rs deleted file mode 100644 index 80d890a..0000000 --- a/src/sink/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -use gst::glib; -use gst::prelude::*; - -mod imp; - -glib::wrapper! { - pub struct MoqSink(ObjectSubclass) @extends gst::Element, gst::Object; -} - -pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { - gst::Element::register(Some(plugin), "moqsink", gst::Rank::NONE, MoqSink::static_type()) -} diff --git a/src/source/imp.rs b/src/source/imp.rs deleted file mode 100644 index b34454f..0000000 --- a/src/source/imp.rs +++ /dev/null @@ -1,659 +0,0 @@ -use std::collections::HashMap; -use std::sync::{LazyLock, Mutex}; -use std::time::Duration; - -use anyhow::{bail, Context, Result}; -use gst::glib; -use gst::prelude::*; -use gst::subclass::prelude::*; -use tokio::sync::{mpsc, oneshot, watch}; - -use hang::moq_lite; - -static CAT: LazyLock = - LazyLock::new(|| gst::DebugCategory::new("moq-src", gst::DebugColorFlags::empty(), Some("MoQ Source Element"))); - -static RUNTIME: LazyLock = LazyLock::new(|| { - tokio::runtime::Builder::new_multi_thread() - .enable_all() - .build() - .expect("spawn tokio runtime") -}); - -#[derive(Debug, Clone, Default)] -struct Settings { - url: Option, - broadcast: Option, - tls_disable_verify: bool, -} - -#[derive(Debug, Clone)] -struct ResolvedSettings { - url: url::Url, - broadcast: String, - tls_disable_verify: bool, -} - -impl TryFrom for ResolvedSettings { - type Error = anyhow::Error; - - fn try_from(value: Settings) -> Result { - Ok(Self { - url: url::Url::parse(value.url.as_ref().context("url property is required")?)?, - broadcast: value - .broadcast - .as_ref() - .context("broadcast property is required")? - .clone(), - tls_disable_verify: value.tls_disable_verify, - }) - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -enum TrackKind { - Video, - Audio, -} - -impl TrackKind { - fn template_name(&self) -> &'static str { - match self { - TrackKind::Video => "video_%u", - TrackKind::Audio => "audio_%u", - } - } -} - -#[derive(Debug, Clone)] -struct TrackDescriptor { - kind: TrackKind, - name: String, -} - -impl TrackDescriptor { - fn pad_name(&self) -> String { - match self.kind { - TrackKind::Video => format!("video_{}", self.name), - TrackKind::Audio => format!("audio_{}", self.name), - } - } -} - -#[derive(Debug)] -enum ControlMessage { - CreatePad { - descriptor: TrackDescriptor, - caps: gst::Caps, - reply: oneshot::Sender, - }, - NoMorePads, - ReportError(anyhow::Error), -} - -#[derive(Debug)] -enum PadMessage { - Buffer(gst::Buffer), - Eos, - Drop, -} - -#[derive(Debug, Clone)] -struct PadEndpoint { - sender: mpsc::UnboundedSender, -} - -impl PadEndpoint { - fn send(&self, msg: PadMessage) -> bool { - self.sender.send(msg).is_ok() - } -} - -struct PadHandle { - sender: mpsc::UnboundedSender, - task: glib::JoinHandle<()>, -} - -struct SessionController { - shutdown: watch::Sender, - join: tokio::task::JoinHandle<()>, -} - -impl SessionController { - fn start(settings: ResolvedSettings, control_tx: mpsc::UnboundedSender) -> Self { - let (shutdown_tx, mut shutdown_rx) = watch::channel(false); - let control_for_error = control_tx.clone(); - let join = RUNTIME.spawn(async move { - let result = run_session(settings, control_tx, &mut shutdown_rx).await; - if let Err(err) = result { - let _ = control_for_error.send(ControlMessage::ReportError(err)); - } - }); - - Self { - shutdown: shutdown_tx, - join, - } - } - - fn stop(self) { - let _ = self.shutdown.send(true); - RUNTIME.spawn(async move { - if let Err(err) = self.join.await { - gst::warning!(CAT, "session task ended with error: {err:?}"); - } - }); - } -} - -#[derive(Default)] -pub struct MoqSrc { - settings: Mutex, - pads: Mutex>, - control_task: Mutex>>, - control_sender: Mutex>>, - session: Mutex>, -} - -#[glib::object_subclass] -impl ObjectSubclass for MoqSrc { - const NAME: &'static str = "MoqSrc"; - type Type = super::MoqSrc; - type ParentType = gst::Element; - - fn new() -> Self { - Self::default() - } -} - -impl ObjectImpl for MoqSrc { - fn properties() -> &'static [glib::ParamSpec] { - static PROPS: LazyLock> = LazyLock::new(|| { - vec![ - glib::ParamSpecString::builder("url") - .nick("Source URL") - .blurb("Connect to the given URL") - .build(), - glib::ParamSpecString::builder("broadcast") - .nick("Broadcast") - .blurb("The broadcast name to subscribe to") - .build(), - glib::ParamSpecBoolean::builder("tls-disable-verify") - .nick("TLS Disable Verify") - .blurb("Disable TLS certificate verification") - .default_value(false) - .build(), - ] - }); - PROPS.as_ref() - } - - fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { - let mut settings = self.settings.lock().unwrap(); - match pspec.name() { - "url" => settings.url = value.get().unwrap(), - "broadcast" => settings.broadcast = value.get().unwrap(), - "tls-disable-verify" => settings.tls_disable_verify = value.get().unwrap(), - _ => unreachable!(), - } - } - - fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { - let settings = self.settings.lock().unwrap(); - match pspec.name() { - "url" => settings.url.to_value(), - "broadcast" => settings.broadcast.to_value(), - "tls-disable-verify" => settings.tls_disable_verify.to_value(), - _ => unreachable!(), - } - } -} - -impl GstObjectImpl for MoqSrc {} -impl ElementImpl for MoqSrc { - fn metadata() -> Option<&'static gst::subclass::ElementMetadata> { - static META: LazyLock = LazyLock::new(|| { - gst::subclass::ElementMetadata::new( - "MoQ Src", - "Source/Network/MoQ", - "Receives media over the network via MoQ", - "Luke Curley , Steve McFarlin ", - ) - }); - Some(&*META) - } - - fn pad_templates() -> &'static [gst::PadTemplate] { - static PAD_TEMPLATES: LazyLock> = LazyLock::new(|| { - vec![ - gst::PadTemplate::new( - "video_%u", - gst::PadDirection::Src, - gst::PadPresence::Sometimes, - &gst::Caps::new_any(), - ) - .unwrap(), - gst::PadTemplate::new( - "audio_%u", - gst::PadDirection::Src, - gst::PadPresence::Sometimes, - &gst::Caps::new_any(), - ) - .unwrap(), - ] - }); - PAD_TEMPLATES.as_ref() - } - - fn change_state(&self, transition: gst::StateChange) -> Result { - match transition { - gst::StateChange::ReadyToPaused => { - if let Err(err) = self.start_session() { - gst::error!(CAT, obj = self.obj(), "failed to start session: {err:?}"); - return Err(gst::StateChangeError); - } - let success = self.parent_change_state(transition)?; - let result = match success { - gst::StateChangeSuccess::Async => gst::StateChangeSuccess::Async, - _ => gst::StateChangeSuccess::NoPreroll, - }; - Ok(result) - } - gst::StateChange::PausedToReady => { - self.stop_session(); - self.parent_change_state(transition) - } - _ => self.parent_change_state(transition), - } - } -} - -impl MoqSrc { - fn start_session(&self) -> Result<()> { - let settings = { - let settings = self.settings.lock().unwrap().clone(); - ResolvedSettings::try_from(settings)? - }; - - let (control_tx, control_rx) = mpsc::unbounded_channel(); - let obj = self.obj(); - let weak = obj.downgrade(); - let context = glib::MainContext::default(); - let control_task = spawn_main_context_forwarder(&context, control_rx, move |msg| { - if let Some(obj) = weak.upgrade() { - obj.imp().handle_control_message(msg); - true - } else { - false - } - }); - - *self.control_task.lock().unwrap() = Some(control_task); - *self.control_sender.lock().unwrap() = Some(control_tx.clone()); - - let session = SessionController::start(settings, control_tx); - *self.session.lock().unwrap() = Some(session); - Ok(()) - } - - fn stop_session(&self) { - if let Some(session) = self.session.lock().unwrap().take() { - session.stop(); - } - - if let Some(control_task) = self.control_task.lock().unwrap().take() { - control_task.abort(); - } - - let handles = self.pads.lock().unwrap().drain().collect::>(); - for (name, handle) in handles { - gst::debug!(CAT, "dropping pad {name}"); - let _ = handle.sender.send(PadMessage::Drop); - handle.task.abort(); - } - - *self.control_sender.lock().unwrap() = None; - } - - fn handle_control_message(&self, msg: ControlMessage) { - match msg { - ControlMessage::CreatePad { - descriptor, - caps, - reply, - } => { - if let Err(err) = self.create_pad(descriptor, caps, reply) { - gst::error!(CAT, obj = self.obj(), "failed to create pad: {err:?}"); - } - } - ControlMessage::NoMorePads => { - self.obj().no_more_pads(); - } - ControlMessage::ReportError(err) => { - gst::element_error!(self.obj(), gst::CoreError::Failed, ("session error"), ["{err:?}"]); - } - } - } - - fn create_pad( - &self, - descriptor: TrackDescriptor, - caps: gst::Caps, - reply: oneshot::Sender, - ) -> Result<()> { - let obj = self.obj(); - let templ = obj - .element_class() - .pad_template(descriptor.kind.template_name()) - .context("missing pad template")?; - - let pad = gst::Pad::builder_from_template(&templ) - .name(descriptor.pad_name()) - .build(); - - pad.set_active(true)?; - - let stream_start = gst::event::StreamStart::builder(&descriptor.name) - .group_id(gst::GroupId::next()) - .build(); - pad.push_event(stream_start); - pad.push_event(gst::event::Caps::new(&caps)); - pad.push_event(gst::event::Segment::new(&gst::FormattedSegment::::new())); - - obj.add_pad(&pad)?; - - let (pad_tx, pad_rx) = mpsc::unbounded_channel(); - let pad_clone = pad.clone(); - let weak = obj.downgrade(); - let context = glib::MainContext::default(); - let task = spawn_main_context_forwarder(&context, pad_rx, move |msg| { - if let Some(obj) = weak.upgrade() { - let imp = obj.imp(); - imp.dispatch_pad_message(&pad_clone, msg) - } else { - false - } - }); - - self.pads.lock().unwrap().insert( - descriptor.pad_name(), - PadHandle { - sender: pad_tx.clone(), - task, - }, - ); - - let _ = reply.send(PadEndpoint { sender: pad_tx }); - Ok(()) - } - - fn dispatch_pad_message(&self, pad: &gst::Pad, msg: PadMessage) -> bool { - match msg { - PadMessage::Buffer(buffer) => { - if let Err(err) = pad.push(buffer) { - gst::warning!(CAT, "failed to push buffer: {err:?}"); - return false; - } - true - } - PadMessage::Eos => { - pad.push_event(gst::event::Eos::builder().build()); - true - } - PadMessage::Drop => { - let _ = pad.set_active(false); - let _ = self.obj().remove_pad(pad); - false - } - } - } -} - -async fn run_session( - settings: ResolvedSettings, - control_tx: mpsc::UnboundedSender, - shutdown: &mut watch::Receiver, -) -> Result<()> { - let mut config = moq_native::ClientConfig::default(); - config.tls.disable_verify = Some(settings.tls_disable_verify); - - let origin = moq_lite::Origin::produce(); - let origin_consumer = origin.consume(); - let client = config.init()?.with_consume(origin); - - let _session = client.connect(settings.url.clone()).await?; - - let broadcast = origin_consumer - .consume_broadcast(&settings.broadcast) - .ok_or_else(|| anyhow::anyhow!("Broadcast '{}' not found", settings.broadcast))?; - - let catalog_track = broadcast.subscribe_track(&hang::catalog::Catalog::default_track())?; - let mut catalog = hang::catalog::CatalogConsumer::new(catalog_track); - let catalog = catalog.next().await?.context("catalog missing")?.clone(); - - let mut tasks = Vec::new(); - - for (track_name, config) in catalog.video.renditions { - let descriptor = TrackDescriptor { - kind: TrackKind::Video, - name: track_name.clone(), - }; - let caps = video_caps(&config)?; - let endpoint = request_pad(&control_tx, descriptor.clone(), caps).await?; - let track_ref = moq_lite::Track::new(&track_name); - let track_consumer = broadcast.subscribe_track(&track_ref)?; - let track = hang::container::OrderedConsumer::new(track_consumer, Duration::from_secs(1)); - tasks.push(spawn_track_pump(track, descriptor, endpoint, shutdown.clone())); - } - - for (track_name, config) in catalog.audio.renditions { - let descriptor = TrackDescriptor { - kind: TrackKind::Audio, - name: track_name.clone(), - }; - let caps = audio_caps(&config)?; - let endpoint = request_pad(&control_tx, descriptor.clone(), caps).await?; - let track_ref = moq_lite::Track::new(&track_name); - let track_consumer = broadcast.subscribe_track(&track_ref)?; - let track = hang::container::OrderedConsumer::new(track_consumer, Duration::from_secs(1)); - tasks.push(spawn_track_pump(track, descriptor, endpoint, shutdown.clone())); - } - - let _ = control_tx.send(ControlMessage::NoMorePads); - - for task in tasks { - let _ = task.await; - } - - Ok(()) -} - -async fn request_pad( - control_tx: &mpsc::UnboundedSender, - descriptor: TrackDescriptor, - caps: gst::Caps, -) -> Result { - let (reply_tx, reply_rx) = oneshot::channel(); - control_tx - .send(ControlMessage::CreatePad { - descriptor, - caps, - reply: reply_tx, - }) - .map_err(|_| anyhow::anyhow!("control plane shut down"))?; - - let endpoint = reply_rx.await.context("pad creation cancelled")?; - Ok(endpoint) -} - -fn spawn_track_pump( - track: hang::container::OrderedConsumer, - descriptor: TrackDescriptor, - pad_endpoint: PadEndpoint, - shutdown: watch::Receiver, -) -> tokio::task::JoinHandle<()> { - RUNTIME.spawn(run_track_pump(track, descriptor, pad_endpoint, shutdown)) -} - -async fn run_track_pump( - mut track: hang::container::OrderedConsumer, - descriptor: TrackDescriptor, - pad_endpoint: PadEndpoint, - mut shutdown: watch::Receiver, -) { - let mut reference_ts = None; - loop { - tokio::select! { - _ = shutdown.changed() => { - pad_endpoint.send(PadMessage::Drop); - break; - } - frame = track.read() => { - match frame { - Ok(Some(frame)) => { - let timestamp = frame.timestamp; - let is_keyframe = frame.is_keyframe(); - let payload = frame.payload; - let mut buffer = gst::Buffer::from_slice(payload.into_iter().flatten().collect::>()); - let buffer_mut = buffer.get_mut().unwrap(); - - let pts = match reference_ts { - Some(reference) => { - let delta: Duration = (timestamp - reference).into(); - gst::ClockTime::from_nseconds(delta.as_nanos() as u64) - } - None => { - reference_ts = Some(timestamp); - gst::ClockTime::ZERO - } - }; - buffer_mut.set_pts(Some(pts)); - - let mut flags = buffer_mut.flags(); - match descriptor.kind { - TrackKind::Video => { - if is_keyframe { - flags.remove(gst::BufferFlags::DELTA_UNIT); - } else { - flags.insert(gst::BufferFlags::DELTA_UNIT); - } - } - TrackKind::Audio => { - flags.remove(gst::BufferFlags::DELTA_UNIT); - } - } - buffer_mut.set_flags(flags); - - if !pad_endpoint.send(PadMessage::Buffer(buffer)) { - break; - } - } - Ok(None) => { - pad_endpoint.send(PadMessage::Eos); - pad_endpoint.send(PadMessage::Drop); - break; - } - Err(err) => { - gst::warning!(CAT, "track {} failed: {err:?}", descriptor.name); - pad_endpoint.send(PadMessage::Drop); - break; - } - } - } - } - } -} - -fn video_caps(config: &hang::catalog::VideoConfig) -> Result { - use hang::catalog::VideoCodec; - - let caps = match &config.codec { - VideoCodec::H264(_) => { - let mut builder = gst::Caps::builder("video/x-h264").field("alignment", "au"); - if let Some(description) = &config.description { - builder = builder - .field("stream-format", "avc") - .field("codec_data", gst::Buffer::from_slice(description.clone())); - } else { - builder = builder.field("stream-format", "annexb"); - } - builder.build() - } - VideoCodec::H265(h265) => { - let mut builder = gst::Caps::builder("video/x-h265").field("alignment", "au"); - match &config.description { - Some(description) => { - let format = if h265.in_band { "hev1" } else { "hvc1" }; - builder = builder - .field("stream-format", format) - .field("codec_data", gst::Buffer::from_slice(description.clone())); - } - None => { - let format = if h265.in_band { "hev1" } else { "byte-stream" }; - builder = builder.field("stream-format", format); - } - } - builder.build() - } - VideoCodec::AV1(_) => { - let mut builder = gst::Caps::builder("video/x-av1"); - if let Some(description) = &config.description { - builder = builder.field("codec_data", gst::Buffer::from_slice(description.clone())); - } - builder.build() - } - other => bail!("unsupported video codec: {other:?}"), - }; - Ok(caps) -} - -fn audio_caps(config: &hang::catalog::AudioConfig) -> Result { - let caps = match &config.codec { - hang::catalog::AudioCodec::AAC(_) => { - let mut builder = gst::Caps::builder("audio/mpeg") - .field("mpegversion", 4) - .field("rate", config.sample_rate) - .field("channels", config.channel_count); - if let Some(description) = &config.description { - builder = builder - .field("codec_data", gst::Buffer::from_slice(description.clone())) - .field("stream-format", "aac"); - } else { - builder = builder.field("stream-format", "adts"); - } - builder.build() - } - hang::catalog::AudioCodec::Opus => { - let mut builder = gst::Caps::builder("audio/x-opus") - .field("rate", config.sample_rate) - .field("channels", config.channel_count); - if let Some(description) = &config.description { - builder = builder - .field("codec_data", gst::Buffer::from_slice(description.clone())) - .field("stream-format", "ogg"); - } - builder.build() - } - other => bail!("unsupported audio codec: {other:?}"), - }; - Ok(caps) -} - -fn spawn_main_context_forwarder( - context: &glib::MainContext, - mut rx: mpsc::UnboundedReceiver, - mut handler: F, -) -> glib::JoinHandle<()> -where - T: Send + 'static, - F: FnMut(T) -> bool + 'static, -{ - let ctx = context.clone(); - ctx.spawn_local(async move { - while let Some(msg) = rx.recv().await { - if !handler(msg) { - break; - } - } - }) -} diff --git a/src/source/mod.rs b/src/source/mod.rs deleted file mode 100644 index f19d1b5..0000000 --- a/src/source/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -use gst::glib; -use gst::prelude::*; - -mod imp; - -glib::wrapper! { - pub struct MoqSrc(ObjectSubclass) @extends gst::Element, gst::Object; -} - -pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { - gst::Element::register(Some(plugin), "moqsrc", gst::Rank::NONE, MoqSrc::static_type()) -}