Skip to main content

ez_ffmpeg/wgpu_filter/
mod.rs

1//! GPU-accelerated frame filtering backed by [wgpu](https://wgpu.rs)
2//! (Vulkan/Metal/DX12/GL). Successor to the deprecated `opengl` module.
3//!
4//! Compared to the OpenGL filter, this module:
5//! - runs headless (no X11/Wayland/display connection required),
6//! - converts YUV<->RGB on the GPU with the correct color matrix
7//!   (BT.601/BT.709, limited/full range) instead of `sws_scale` on the CPU,
8//! - supports output resizing, live parameter updates, and per-stage timing
9//!   statistics,
10//! - overlaps GPU work with CPU work by default (up to two frames in
11//!   flight; see `WgpuFrameFilterBuilder::frames_in_flight`) while always
12//!   preserving output order,
13//! - is `Send` without unsafe: all wgpu handles are thread-safe.
14//!
15//! # Example
16//!
17//! ```rust,ignore
18//! use ez_ffmpeg::wgpu_filter::WgpuFrameFilter;
19//! use ez_ffmpeg::filter::frame_pipeline_builder::FramePipelineBuilder;
20//! use ez_ffmpeg::AVMediaType;
21//!
22//! let shader = r#"
23//!     @group(0) @binding(0) var texture1: texture_2d<f32>;
24//!     @group(0) @binding(1) var sampler1: sampler;
25//!     struct EzUniforms { play_time: f32, width: f32, height: f32, _pad: f32 };
26//!     @group(0) @binding(2) var<uniform> ez: EzUniforms;
27//!
28//!     @fragment
29//!     fn fs_main(@location(0) tex_coord: vec2<f32>) -> @location(0) vec4<f32> {
30//!         let color = textureSample(texture1, sampler1, tex_coord);
31//!         let gray = dot(color.rgb, vec3<f32>(0.299, 0.587, 0.114));
32//!         return vec4<f32>(vec3<f32>(gray), 1.0);
33//!     }
34//! "#;
35//!
36//! let filter = WgpuFrameFilter::new_simple(shader)?;
37//! let pipeline: FramePipelineBuilder = AVMediaType::AVMEDIA_TYPE_VIDEO.into();
38//! let pipeline = pipeline.filter("wgpu", Box::new(filter));
39//! // output.add_frame_pipeline(pipeline);
40//! ```
41//!
42//! **Feature flag**: only available with the `wgpu` feature.
43//!
44//! **Input formats**: YUV420P, YUV422P, YUV444P (plus their full-range J
45//! variants) and NV12 CPU frames. Hardware frames (e.g.
46//! `set_hwaccel_output_format("vaapi")`) are downloaded to system memory
47//! automatically, or imported zero-copy over DRM PRIME dmabufs when
48//! `WgpuFrameFilterBuilder::hw_zero_copy_input` is enabled (Linux/Vulkan,
49//! experimental). Other formats need a `format=yuv420p` conversion in
50//! `filter_desc` first. Output is always YUV420P (4:2:2/4:4:4 inputs are
51//! chroma-downsampled on the GPU).
52
53pub mod wgpu_frame_filter;
54
55mod frame_io;
56mod gpu_state;
57mod hw_interop;
58mod params;
59pub(crate) mod shaders;
60#[cfg(test)]
61mod tests;
62
63pub use params::{WgpuFilterStats, WgpuParamsHandle};
64pub use wgpu_frame_filter::{WgpuFrameFilter, WgpuFrameFilterBuilder};