rivet-codec 0.1.3

GPU video decode/encode dispatch (NVDEC/NVENC, AMF, QSV) plus colorspace, tonemap, audio, and probe for the rivet transcoder. Imported as `codec`.
Documentation
[package]

name = "rivet-codec"

version.workspace = true

edition.workspace = true

license-file = "LICENSE.md"

readme = "README.md"

repository.workspace = true

authors.workspace = true

description = "GPU video decode/encode dispatch (NVDEC/NVENC, AMF, QSV) plus colorspace, tonemap, audio, and probe for the rivet transcoder. Imported as `codec`."



[lib]

name = "codec"



[features]

# Default: legacy per-codec stack (openh264 / libde265 / libvpx /

# rav1d / libmpeg2 / libxvidcore / prores / nvdec / vulkan_video).

# No ffmpeg build prerequisites. Everything ships from cargo.

default = []



# `serde`: derive Serialize/Deserialize on the public value types that make

# sense to (de)serialize — currently `filter::VideoFilter` + `FilterSpec`, so a

# YAML/JSON DSL can express a filter chain as structured objects. Off by

# default (keeps the low-level crate lean); rivet's `batch`/`server` enable it.

serde = ["dep:serde"]



# `ffmpeg`: activates the ffmpeg-next primary decoder. Brings the

# full libavcodec catalogue (H.264 / H.265 / VP8 / VP9 / AV1 / MPEG-2 /

# MPEG-4 / ProRes / …) + Vulkan / NVDEC / D3D11 / VAAPI hwaccel

# through one trait-dispatched `FfmpegDecoder`. When enabled, this

# becomes the PRIMARY path — legacy per-codec modules are still

# compiled as fallback but only engage when FfmpegDecoder errors or

# the uniform-plane detector fires.

#

# Build prerequisites (enable ONLY when these are set up):

#   1. FFmpeg ≥7.0 development libraries (headers + .lib / .dylib /

#      .so). On Windows bootstrap via `vendor/ffmpeg/fetch.sh` and

#      set `FFMPEG_DIR=$(pwd)/vendor/ffmpeg/ffmpeg-<ver>-full_build-shared`.

#   2. LLVM / libclang (bindgen dep). On Windows install via winget

#      `LLVM.LLVM` (admin) or download https://github.com/llvm/llvm-project/releases

#      and set `LIBCLANG_PATH=C:\Program Files\LLVM\bin`.

#   3. Runtime DLLs on PATH. Add `$FFMPEG_DIR/bin` before running

#      tests / transcode_one.

#

# Invocation:

#   cargo build --workspace --features codec/ffmpeg

ffmpeg = ["dep:ffmpeg-next"]



# PLATFORM NOTE for the three `shiguredo_*` GPU features below (`nvidia`,

# `amd`, `qsv`): they bindgen the vendor SDK headers at build time (needs

# libclang — set LIBCLANG_PATH). They compile on **Linux** (the production /

# Docker target, `rust:1.86-bookworm`), where clang gives the SDK's

# non-negative C enums the `unsigned int` (→ `u32`) underlying type that the

# crate source expects. They do **NOT** compile on a **Windows MSVC** host:

# the MSVC ABI makes C enums `int` (→ `i32`), producing E0308 mismatches

# inside the shiguredo crates (proven via `_Static_assert((enum E)-1 > 0)` —

# fails on `--target=*-windows-msvc`, passes on `--target=*-linux-gnu`). So

# build these features on Linux / in Docker; on a Windows dev box use the

# `ffmpeg` feature or leave them off. With every feature off, the hardware

# paths compile to construction-erroring stubs and the dispatcher just skips

# that tier.



# `qsv`: Intel QSV AV1 encode via our own hand-rolled oneVPL FFI (`encode/qsv.rs`,

# 8-bit NV12 + 10-bit P010). dlopens libvpl.so.2 / libvpl.dll — no build-time

# link, no bindgen, no header, so it builds on **both Windows MSVC and Linux**.

# Intel Arc / Meteor Lake+.

#   cargo build --features qsv      (Windows or Linux)

qsv = []



# `nvidia`: NVENC AV1 encode + NVDEC decode via our own hand-rolled

# `nvEncodeAPI` / CUVID FFI (`encode/nvenc.rs`, `decode/nvdec.rs`). dlopens the

# NVIDIA runtime at load time — no build-time CUDA link, no bindgen, no header,

# so unlike the shiguredo crates it builds on **both Windows MSVC and Linux**.

# NVENC AV1 needs Ada+; NVDEC decodes H.264/HEVC/AV1/VP8/VP9/MPEG-2/MPEG-4 +

# 10-bit P016.

#   cargo build --features nvidia   (Windows or Linux)

nvidia = []



# `amd`: AMF AV1 encoder via our own hand-rolled AMF FFI (`encode/amf.rs`).

# dlopens amfrt64.dll / libamfrt64.so.1 — no build-time link, no bindgen, no

# header, so it builds on **both Windows MSVC and Linux**. AMD RDNA3+.

#   cargo build --features amd      (Windows or Linux)

amd = []



[dependencies]

anyhow.workspace = true

thiserror.workspace = true

tracing.workspace = true

bytes.workspace = true

serde = { version = "1", features = ["derive"], optional = true }

libloading.workspace = true

# PNG decode for the `overlay` video filter (logo / watermark with alpha).

# png-only so the dep stays small — no other image format is pulled in.

image = { version = "0.25", default-features = false, features = ["png"] }



# mp4 crate is still needed by the container demuxer side; the codec

# crate no longer pulls any CPU codec deps as of 2026-05-08.

mp4.workspace = true



# Audio codecs (Squad-24, Phase 2 audio expansion):

# - minimp3 (MIT) — MP3 decode wrapper around the minimp3 C library

# - lewton (MIT/Apache-2.0) — pure-Rust Vorbis decoder

# - audiopus (ISC) — high-level binding to libopus (BSD); for Opus encode

# - rubato (MIT) — sample-rate conversion for 44.1 → 48 kHz upsample

minimp3 = "0.5"

lewton = "0.10"

audiopus = "0.3.0-rc.0"

rubato = "0.15"



# FFmpeg via ffmpeg-next (2026-04-19 migration):

# - ffmpeg-next (WTFPL-ish — see crate; binds to LGPL-2.1+ FFmpeg)

#   brings the full libavcodec decoder catalogue + Vulkan hwaccel

#   under one trait-dispatched Decoder. Per the 2026-04-19 user

#   directive (memory feedback_ffmpeg_next_migration.md), this is

#   the primary decode path; per-codec modules here (openh264 / rav1d

#   / libde265 / libvpx / libmpeg2 / libxvidcore / prores / nvdec /

#   vulkan_video) are retained as fallback and marked deprecated.

#

# Build requirements: FFmpeg dev libs (headers + .lib + .dll) must be

# on the system. On Windows, bootstrap via `vendor/ffmpeg/fetch.sh` +

# set FFMPEG_DIR. On Linux, install libav*-dev packages. On macOS,

# `brew install ffmpeg pkg-config`.

#

# Feature gate `static` OFF — dynamic linking keeps our source

# licensable separately from LGPL/GPL-licensed FFmpeg.

ffmpeg-next = { version = "7.1", optional = true, default-features = false, features = ["codec", "format", "software-scaling", "software-resampling"] }



# Intel QSV is hand-rolled dlopen oneVPL FFI in-tree (encode/qsv.rs) — no

# external crate, builds on Windows + Linux. The shiguredo_vpl dep was retired

# (Windows MSVC); runtime still needs libvpl + the iHD VA-API driver on Linux.



# NVIDIA NVENC/NVDEC are hand-rolled dlopen FFI in-tree (encode/nvenc.rs,

# decode/nvdec.rs) — no external crate, builds on Windows + Linux. The

# shiguredo_nvcodec dep was retired (it doesn't compile on Windows MSVC).



# AMD AMF is hand-rolled dlopen FFI in-tree (encode/amf.rs) — no external crate,

# builds on Windows + Linux. The shiguredo_amf dep was retired (Windows MSVC).



# NVML (NVIDIA Management Library) wrapper. Used by the Phase 2

# (2026-05-07) richer worker_load surface to read per-GPU utilisation,

# encoder/decoder ASIC busy %, VRAM usage, and temperature on every

# 5 s load tick. NVML loads `libnvidia-ml.so` / `nvml.dll` lazily —

# init failure (no NVIDIA driver installed, hostless dev box) returns

# an Err that the caller folds to "all zeroes" without taking down

# the worker. Same dlopen-shaped runtime contract as the rest of the

# NVIDIA-tier code in this crate.

nvml-wrapper = { workspace = true }



[dev-dependencies]

container = { path = "../container", package = "rivet-container" }

criterion = { workspace = true }

tracing-subscriber = { workspace = true }

serde_json = "1"



[[bench]]

name = "colorspace"

harness = false



[[bench]]

name = "colorspace_601_to_709"

harness = false



[[bench]]

name = "scale"

harness = false



[[bench]]

name = "bilinear"

harness = false



[[bench]]

name = "nvdec_decode"

harness = false



[[bench]]

name = "downsample_444_to_420"

harness = false



[lints.rust]

# `streaming_api_landed` is the post-merge gate flag for the

# streaming-migration #55 QA decoder regression tests

# (`tests/streaming_decoder_equality.rs`). Tests are compile-

# excluded on this branch; flipped on at integration time via

# `RUSTFLAGS="--cfg streaming_api_landed"`. Registering the cfg

# here silences the rust 1.80+ `unexpected_cfgs` warning.

unexpected_cfgs = { level = "warn", check-cfg = ['cfg(streaming_api_landed)'] }