1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
//! Decoder configuration
/// Configuration for AVIF decoding
#[derive(Debug, Clone)]
pub struct DecoderConfig {
/// Number of threads to use for decoding (0 = auto)
pub(crate) threads: u32,
/// Whether to apply film grain synthesis
pub(crate) apply_grain: bool,
/// Maximum frame size limit in pixels (0 = no limit)
pub(crate) frame_size_limit: u32,
/// CPU feature flags mask (bitwise AND with detected features).
/// Use to disable SIMD paths for testing. Default: all enabled.
/// x86_64: bit 3 = AVX2, bit 2 = SSE4.1, bit 1 = SSSE3, bit 0 = SSE2
pub(crate) cpu_flags_mask: u32,
/// Parser peak memory limit in bytes (forwarded to zenavif-parse).
pub(crate) parser_peak_memory_limit: Option<u64>,
/// Parser total megapixels limit (forwarded to zenavif-parse).
pub(crate) parser_total_megapixels_limit: Option<u32>,
/// Parser max animation frames (forwarded to zenavif-parse).
pub(crate) parser_max_animation_frames: Option<u32>,
/// When true, 10/12-bit AV1 content is downscaled to 8-bit RGB output.
/// Most AVIF encoders (including zenravif) default to 10-bit encoding
/// even for 8-bit input. This option returns 8-bit output for those files.
pub(crate) prefer_8bit: bool,
}
impl Default for DecoderConfig {
fn default() -> Self {
Self {
// Default to auto-detect threads. For single-frame AVIF, rav1d
// auto-derives max_frame_delay=1, giving tile parallelism without
// frame threading overhead.
threads: 0,
apply_grain: true,
frame_size_limit: 0,
cpu_flags_mask: u32::MAX,
parser_peak_memory_limit: None,
parser_total_megapixels_limit: None,
parser_max_animation_frames: None,
prefer_8bit: false,
}
}
}
impl DecoderConfig {
/// Create a new decoder configuration with default settings
pub fn new() -> Self {
Self::default()
}
/// Set the number of threads for decoding
///
/// 0 means automatic (use available cores)
pub fn threads(mut self, threads: u32) -> Self {
self.threads = threads;
self
}
/// Enable or disable film grain synthesis
///
/// When enabled (default), film grain specified in the AV1 stream
/// will be synthesized and applied to the decoded image.
pub fn apply_grain(mut self, apply: bool) -> Self {
self.apply_grain = apply;
self
}
/// Set maximum frame size limit in total pixels
///
/// If width * height exceeds this limit, decoding will fail.
/// 0 means no limit.
pub fn frame_size_limit(mut self, limit: u32) -> Self {
self.frame_size_limit = limit;
self
}
/// Set CPU feature flags mask.
///
/// Controls which SIMD code paths are used by masking detected CPU features.
/// Default is `u32::MAX` (all features enabled).
///
/// # x86_64 flag bits
/// - `1 << 0` = SSE2
/// - `1 << 1` = SSSE3
/// - `1 << 2` = SSE4.1
/// - `1 << 3` = AVX2
/// - `1 << 4` = AVX-512 ICL
///
/// Setting to `0` forces scalar-only decode. Setting to `0b0111` (7) allows
/// up to SSE4.1 but disables AVX2.
pub fn cpu_flags_mask(mut self, mask: u32) -> Self {
self.cpu_flags_mask = mask;
self
}
/// Downscale 10/12-bit AV1 output to 8-bit RGB.
///
/// Default: `false`. Enable when decoding files encoded at 10-bit from
/// 8-bit sources and you want 8-bit output without an external conversion.
pub fn prefer_8bit(mut self, prefer: bool) -> Self {
self.prefer_8bit = prefer;
self
}
}