Skip to main content

rav1d_safe/
lib.rs

1//! AV1 decoding through a native Rust API.
2//!
3//! Import [`Decoder`], [`Settings`], [`Frame`], and [`Planes`] directly from this
4//! crate. Default features select checked Rust SIMD; Rust callers do not need
5//! the optional C FFI or assembly features.
6//!
7//! Feed raw AV1 OBU data, such as packets emitted by zenrav1e. For complete AVIF
8//! files and RGB output, use zenavif, which wraps this decoder with container
9//! handling and color conversion. Decoded [`Frame`] values expose borrowed YUV
10//! plane views and own the storage that keeps those views alive.
11//!
12//! ```no_run
13//! use rav1d_safe::{Decoder, Frame};
14//!
15//! fn decode_still(obu: &[u8]) -> rav1d_safe::Result<Vec<Frame>> {
16//!     let mut decoder = Decoder::new()?;
17//!     let mut frames = Vec::new();
18//!     if let Some(frame) = decoder.decode(obu)? {
19//!         frames.push(frame);
20//!     }
21//!     frames.extend(decoder.flush()?);
22//!     Ok(frames)
23//! }
24//! ```
25
26#![allow(non_upper_case_globals)]
27#![cfg_attr(target_arch = "arm", feature(stdarch_arm_feature_detection))]
28#![cfg_attr(
29    any(target_arch = "riscv32", target_arch = "riscv64"),
30    feature(stdarch_riscv_feature_detection)
31)]
32// Crate-wide forbid(unsafe_code) unless `asm`, `c-ffi`, or `unchecked` is enabled.
33// All unsafe must live in separate crates (rav1d-disjoint-mut, rav1d-align, etc.)
34// or be gated behind cfg(feature = "asm") / cfg(feature = "c-ffi").
35// forbid cannot be overridden by #[allow] — any unsafe in the default build is a hard error.
36#![cfg_attr(
37    not(any(feature = "asm", feature = "c-ffi", feature = "unchecked")),
38    forbid(unsafe_code)
39)]
40#![cfg_attr(any(feature = "asm", feature = "c-ffi"), deny(unsafe_op_in_unsafe_fn))]
41// Clippy lint policy: suppress pervasive C-port patterns at crate level,
42// enable everything else. Each lint has a reason and warning count.
43//
44// Pervasive C-port patterns (too many to fix individually):
45#![allow(clippy::precedence)] // 652: C-style arithmetic
46#![allow(clippy::too_many_arguments)] // 282: C function signatures
47#![allow(clippy::unnecessary_cast)] // 189: generic/bitdepth code
48#![allow(clippy::identity_op)] // 156: readability in transforms
49#![allow(clippy::needless_range_loop)] // 143: C-port loop idiom
50#![allow(clippy::explicit_auto_deref)] // 85: deref style
51#![allow(clippy::erasing_op)] // 53: generic transform constants
52#![allow(clippy::needless_return)] // 24: C-port return style
53#![allow(clippy::nonminimal_bool)] // 23: C-port booleans
54#![allow(clippy::needless_borrow)] // 19: borrow style
55#![allow(clippy::doc_overindented_list_items)] // 16: doc formatting
56#![allow(clippy::zero_prefixed_literal)] // 12: decimal C constants
57#![allow(clippy::collapsible_if)] // 11: nested ifs from C
58#![allow(clippy::needless_late_init)] // 10: C-style init
59//
60// Structural C-port patterns (changing would obscure correspondence):
61#![allow(clippy::upper_case_acronyms)] // 9: AV1 spec names
62#![allow(clippy::type_complexity)] // 4: internal C-port types
63#![allow(clippy::misrefactored_assign_op)] // 4: boundary clamping
64#![allow(clippy::neg_multiply)] // 4: C-style negation
65//
66// Intentional patterns (deny-by-default, false positives here):
67#![allow(clippy::eq_op)] // 2: intentional 2-2
68#![allow(clippy::overly_complex_bool_expr)] // 2: debug gates
69#![allow(clippy::let_underscore_lock)] // 2: lock drop via take()
70//
71// Informational lints not worth acting on:
72#![allow(clippy::module_inception)] // 1: dav1d::dav1d
73#![allow(clippy::large_enum_variant)] // 1: internal enum
74//
75// Newer clippy lints (1.87+) firing on C-port patterns:
76#![allow(clippy::duplicated_attributes)] // new in clippy 1.87+: repeated cfg_attr
77#![allow(clippy::manual_is_multiple_of)] // new in clippy 1.87+: x % n == 0 patterns
78#![allow(clippy::let_and_return)] // new in clippy 1.87+: C-port let-then-return
79#![allow(clippy::unnecessary_map_on_constructor)] // new in clippy 1.87+: Option/Result::map on constructor
80#![allow(clippy::clone_on_copy)] // new in clippy 1.87+: explicit .clone() on Copy types
81#![allow(clippy::option_map_unit_fn)] // new in clippy 1.87+: .map(|x| side_effect)
82#![allow(clippy::unnecessary_lazy_evaluations)] // new in clippy 1.87+: .unwrap_or_else(|| val)
83#![cfg_attr(
84    any(feature = "asm", feature = "c-ffi"),
85    deny(clippy::undocumented_unsafe_blocks)
86)]
87#![cfg_attr(
88    any(feature = "asm", feature = "c-ffi"),
89    deny(clippy::missing_safety_doc)
90)]
91
92#[cfg(not(any(feature = "bitdepth_8", feature = "bitdepth_16")))]
93compile_error!(
94    "No bitdepths enabled. Enable one or more of the following features: `bitdepth_8`, `bitdepth_16`"
95);
96
97pub mod include {
98    pub mod common {
99        pub(crate) mod attributes;
100        pub(crate) mod bitdepth;
101        pub(crate) mod dump;
102        pub(crate) mod intops;
103        pub(crate) mod validate;
104    } // mod common
105    #[cfg_attr(feature = "c-ffi", allow(unsafe_code))]
106    pub mod dav1d {
107        pub mod common;
108        pub mod data;
109        pub mod dav1d;
110        pub mod headers;
111        pub mod picture;
112    } // mod dav1d
113} // mod include
114pub mod src {
115    // === Module Safety Annotations ===
116    // - Modules with zero unsafe use forbid(unsafe_code) internally
117    // - Modules with isolated unsafe items use item-level #[allow(unsafe_code)]
118    // - Modules that need unsafe only for c-ffi use cfg_attr(feature, allow)
119    // - safe_simd sub-modules set their own forbid/deny (no parent blanket allow)
120
121    // Per-kernel SIMD ablation switch (measurement infrastructure). Compiles to
122    // a constant `false` guard unless the `__ablate` feature is on; `pub` so the
123    // ablation harness in `examples/` can drive it.
124    pub mod ablate;
125
126    // Core primitives
127    pub(crate) mod align;
128    #[cfg(feature = "c-ffi")]
129    pub(crate) mod assume;
130    #[cfg_attr(feature = "c-ffi", allow(unsafe_code))]
131    pub(crate) mod c_arc;
132    #[cfg_attr(feature = "c-ffi", allow(unsafe_code))]
133    pub(crate) mod c_box;
134    // `pub` ONLY under the measurement probe, so `examples/x86_tier_census.rs`
135    // can read `cpu::tier_census`. A default build keeps it `pub(crate)` — the
136    // public API is unchanged (`docs/public-api/` snapshots are taken without
137    // probe features).
138    #[cfg(feature = "__probe_x86tier")]
139    pub mod cpu;
140    #[cfg(not(feature = "__probe_x86tier"))]
141    pub(crate) mod cpu;
142    pub(crate) mod disjoint_mut;
143    mod ffi_safe;
144    mod in_range;
145    pub(super) mod internal;
146    mod intra_edge;
147    #[cfg_attr(not(feature = "c-ffi"), deny(unsafe_code))]
148    #[cfg_attr(feature = "c-ffi", allow(unsafe_code))]
149    pub(crate) mod log;
150    pub(crate) mod pixels;
151    #[cfg(any(feature = "asm", feature = "c-ffi"))]
152    #[allow(unsafe_code)]
153    pub mod send_sync_non_null;
154    mod tables;
155
156    // Data/picture management
157    mod data;
158    #[cfg_attr(not(feature = "c-ffi"), deny(unsafe_code))]
159    #[cfg_attr(feature = "c-ffi", allow(unsafe_code))]
160    mod picture;
161    // LAYOUT-NOISE CONTROL, measurement only: see src/text_pad.rs.
162    #[cfg(feature = "__pad_far")]
163    pub(crate) mod text_pad;
164
165    // DSP dispatch modules (contain _erased functions and fn ptr dispatch)
166    mod cdef;
167    mod filmgrain;
168    mod ipred;
169    mod itx;
170    mod lf_mask;
171    mod loopfilter;
172    mod looprestoration;
173    mod mc;
174    mod pal;
175    mod recon;
176    #[cfg_attr(feature = "asm", allow(unsafe_code))]
177    mod refmvs;
178
179    // Entropy coding (inline SIMD, safe on both x86_64 and aarch64 when asm off)
180    #[cfg_attr(feature = "asm", allow(unsafe_code))]
181    mod msac;
182
183    // Safe SIMD implementations (internal, not part of the public API)
184    #[cfg(not(feature = "asm"))]
185    pub(crate) mod safe_simd;
186
187    // Rust core API (rav1d_open, rav1d_send_data, etc.)
188    #[cfg_attr(not(feature = "c-ffi"), deny(unsafe_code))]
189    #[cfg_attr(feature = "c-ffi", allow(unsafe_code))]
190    pub(crate) mod lib;
191
192    // C FFI wrappers (dav1d_* extern "C" functions)
193    #[cfg(feature = "c-ffi")]
194    #[allow(unsafe_code)]
195    pub mod dav1d_api;
196
197    // === Modules WITHOUT unsafe_code (enforced by deny) ===
198    #[cfg(all(feature = "asm", any(target_arch = "arm", target_arch = "aarch64")))]
199    mod arm_asm_offsets;
200    mod cdef_apply;
201    mod cdf;
202    mod const_fn;
203    mod ctx;
204    mod cursor;
205    mod decode;
206    mod dequant_tables;
207    pub(crate) mod enum_map;
208    mod env;
209    pub(crate) mod error;
210    mod extensions;
211    mod fg_apply;
212    mod getbits;
213    mod ipred_prepare;
214    mod iter;
215    mod itx_1d;
216    pub(crate) mod levels;
217    mod lf_apply;
218    mod lr_apply;
219    pub(crate) mod mem;
220    mod obu;
221    pub(crate) mod owned_recon;
222    pub(crate) mod pic_or_buf;
223    /// THROWAWAY P1 measurement probe. Never merge.
224    #[cfg(feature = "__probe_tasktime")]
225    pub mod probe_tasktime;
226    mod qm;
227    pub(crate) mod relaxed_atomic;
228    mod scan;
229    pub(crate) mod strided;
230    // Public ONLY under the private test feature, for the induced-worker-panic
231    // hook (tests/worker_panic_recovery.rs); crate-private otherwise.
232    #[cfg(feature = "__test_induce_worker_panic")]
233    pub mod thread_task;
234    #[cfg(not(feature = "__test_induce_worker_panic"))]
235    mod thread_task;
236    mod warpmv;
237    mod wedge;
238    pub(crate) mod with_offset;
239    pub(crate) mod wrap_fn_ptr;
240
241    #[cfg(test)]
242    mod decode_test;
243
244    // === Managed Safe API ===
245    /// 100% safe Rust API for AV1 decoding
246    ///
247    /// This module provides a fully safe, zero-copy API wrapping rav1d's internal decoder.
248    pub mod managed;
249} // mod src
250
251// Re-export the managed API at the crate root for convenience.
252// Users can write `rav1d_safe::Decoder` instead of `rav1d_safe::src::managed::Decoder`.
253pub use src::managed::{
254    ColorInfo, ColorPrimaries, ColorRange, ContentLightLevel, CpuLevel, DecodeFrameType, Decoder,
255    Error, Frame, InloopFilters, MasteringDisplay, MatrixCoefficients, PixelLayout, PlaneView8,
256    PlaneView16, Planes, Planes8, Planes16, Result, Settings, Strictness, TransferCharacteristics,
257    enabled_features,
258};