Skip to main content

codec/encode/tuning/
params.rs

1//! Per-encoder parameter structs, rate-control enums, quality presets,
2//! and associated constants.
3//!
4//! These are the concrete knob-sets that the adapter functions in
5//! `adapters.rs` produce. Each encoder backend (rav1e, NVENC, AMF, QSV)
6//! consumes the matching struct directly.
7
8// ─── rav1e ───────────────────────────────────────────────────────
9
10/// Concrete parameters for rav1e's `EncoderConfig`.
11///
12/// Consumed in `crates/codec/src/encode/rav1e_enc.rs::build_rav1e_config`.
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub struct Rav1eParams {
15    /// rav1e quantizer: 0–255, lower = higher quality. Default 100.
16    pub quantizer: usize,
17    /// rav1e speed preset 0 (slowest/best) – 10 (fastest). Archive=4,
18    /// Standard=6, Draft=8.
19    pub speed_preset: u8,
20    /// Number of tile rows (literal, not log2). Resolution-dependent.
21    pub tile_rows: usize,
22    /// Number of tile columns (literal). Resolution-dependent.
23    pub tile_cols: usize,
24}
25
26// ─── NVENC ───────────────────────────────────────────────────────
27
28/// Concrete parameters for NVENC AV1 (NV_ENC_CONFIG + NV_ENC_RC_PARAMS).
29///
30/// Consumed in `crates/codec/src/encode/nvenc.rs` when populating
31/// `NV_ENC_INITIALIZE_PARAMS.encode_config` (currently null — see
32/// `reviews/codec-review-3.md` issues 1-3).
33///
34/// GUID is returned as its raw 16-byte form so the caller can splat
35/// it into the SDK's `#[repr(C)] Guid { data1: u32, data2: u16,
36/// data3: u16, data4: [u8;8] }` without this module depending on the
37/// FFI struct definitions.
38#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39pub struct NvencAv1Params {
40    /// Rate control mode. Values are the SDK constants
41    /// `NV_ENC_PARAMS_RC_CONSTQP = 0`, `NV_ENC_PARAMS_RC_VBR = 1`,
42    /// `NV_ENC_PARAMS_RC_CBR = 2`. We only emit CONSTQP (archive) or
43    /// VBR+targetQuality (all other tiers) — CBR is never used by
44    /// this service.
45    pub rc_mode: NvencRateControl,
46    /// AV1 CQ target (for VBR mode) or constant QP (for CONSTQP mode).
47    /// Range 0–63 for AV1 (NOT 0-51 — that range is H.264/HEVC).
48    pub cq: u8,
49    /// Preset GUID raw bytes, ready to splat into a `#[repr(C)] Guid`.
50    /// Order: data1 (4 bytes, u32 LE), data2 (2 bytes u16 LE),
51    /// data3 (2 bytes u16 LE), data4 (8 raw bytes).
52    pub preset_guid: [u8; 16],
53    /// `NV_ENC_TUNING_INFO` — always `HIGH_QUALITY (1)` for this
54    /// service; never low-latency.
55    pub tuning_info: u32,
56    /// Adaptive quantization strength 0–15. 0 disables AQ. ~8 is
57    /// a reasonable default under HIGH_QUALITY tuning.
58    pub aq_strength: u8,
59    /// Lookahead depth (frames). 0 disables. Higher = better quality
60    /// bias at cost of latency.
61    pub lookahead_depth: u32,
62    /// `NV_ENC_CONFIG_AV1.numTileColumns`.
63    pub num_tile_columns: u32,
64    /// `NV_ENC_CONFIG_AV1.numTileRows`.
65    pub num_tile_rows: u32,
66    /// `NV_ENC_CONFIG_AV1.outputAnnexBFormat`. Always 0 (LOB) for
67    /// MP4 muxing — AV1-ISOBMFF requires `obu_has_size_field = 1`.
68    pub output_annex_b_format: u32,
69    /// `NV_ENC_CONFIG_AV1.repeatSeqHdr`. Always 1 so every IDR
70    /// carries a sequence header for seeking.
71    pub repeat_seq_hdr: u32,
72}
73
74/// NVENC rate control modes actually used by this service. The numeric
75/// value matches the SDK's `NV_ENC_PARAMS_RC_MODE`.
76#[derive(Debug, Clone, Copy, PartialEq, Eq)]
77#[repr(u32)]
78pub enum NvencRateControl {
79    /// `NV_ENC_PARAMS_RC_CONSTQP = 0`. Every frame gets the same QP.
80    /// Strict archival mode — bitrate floats.
81    ConstQp = 0,
82    /// `NV_ENC_PARAMS_RC_VBR = 1` with `targetQuality` set. NVENC's
83    /// CQ mode — quality-stable across content.
84    VbrTargetQuality = 1,
85}
86
87// ─── AMF ─────────────────────────────────────────────────────────
88
89/// Concrete parameters for AMD AMF AV1 (VCN on RDNA3+).
90///
91/// AMF is property-driven: every knob is set via
92/// `AMFComponent::SetProperty(name, value)` using wide-string names
93/// defined in `vendor/amd/VideoEncoderAV1.h`. The adapter emits integer
94/// ranges that exactly match the property-value ranges the AMF runtime
95/// accepts — out-of-range values return `AMF_INVALID_ARG`.
96///
97/// Consumed in `crates/codec/src/encode/amf.rs::AmfEncoder::new`.
98#[derive(Debug, Clone, Copy, PartialEq, Eq)]
99pub struct AmfAv1Params {
100    /// `AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD`. CQP for archive,
101    /// QVBR (quality-VBR) for the common quality-target tiers.
102    pub rc_mode: AmfRateControl,
103    /// `AMF_VIDEO_ENCODER_AV1_Q_INDEX_INTRA`. AV1 QP index 0..255 (the
104    /// full AV1 quantizer range — NOT 0..63; that's NVENC's scale).
105    pub q_index_intra: u8,
106    /// `AMF_VIDEO_ENCODER_AV1_Q_INDEX_INTER`. Usually +8 on intra so
107    /// P-frames spend fewer bits.
108    pub q_index_inter: u8,
109    /// `AMF_VIDEO_ENCODER_AV1_QVBR_QUALITY_LEVEL`. 1..100 when
110    /// rc_mode == `QualityVbr`; ignored for CQP. Higher = better.
111    pub qvbr_quality: u8,
112    /// `AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET`. Lower = better quality.
113    pub quality_preset: AmfQualityPreset,
114    /// `AMF_VIDEO_ENCODER_AV1_GOP_SIZE`. Frames between keyframes.
115    pub gop_size: u32,
116    /// `AMF_VIDEO_ENCODER_AV1_AQ_MODE`. 0=off, 1=CAQ (content-adaptive).
117    pub aq_mode: u32,
118    /// `AMF_VIDEO_ENCODER_AV1_TILES_PER_FRAME`. AMF picks the grid;
119    /// we specify the total. 1 tile at ≤1080p, 4 at 1080p+, 4 at 4K
120    /// (VCN is less tile-parallel than rav1e — more tiles hurts HQ).
121    pub tiles_per_frame: u32,
122}
123
124/// AMF AV1 quality presets. Values match `AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_*`
125/// constants from the GPUOpen AMF wiki. Lower = better quality / more wall-clock.
126/// The transcode service never picks `Speed` (same rationale as NVENC: no
127/// low-latency presets in this service — see research §2.4).
128#[derive(Debug, Clone, Copy, PartialEq, Eq)]
129#[repr(i64)]
130pub enum AmfQualityPreset {
131    HighQuality = 10,
132    Quality = 30,
133    Balanced = 50,
134    /// Not used by this service; kept in the enum so the mapping table
135    /// stays complete for any future ultra-low-latency path.
136    #[allow(dead_code)]
137    Speed = 70,
138}
139
140/// AMF AV1 rate control modes actually used by this service.
141/// Values match `AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_*`.
142#[derive(Debug, Clone, Copy, PartialEq, Eq)]
143#[repr(i64)]
144pub enum AmfRateControl {
145    /// `AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CQP = 1`. Every
146    /// frame gets the same q-index. Archival.
147    Cqp = 1,
148    /// `AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_QUALITY_VBR = 5`.
149    /// Quality-target VBR — bitrate floats to hit a perceptual level.
150    QualityVbr = 5,
151}
152
153// ─── QSV ─────────────────────────────────────────────────────────
154
155/// Concrete parameters for Intel QSV AV1 (oneVPL on Arc / Meteor Lake+).
156///
157/// oneVPL is struct-driven: `mfxVideoParam` carries every knob in fixed
158/// fields (no property bag). The adapter produces the exact values we
159/// splat into the struct in `crates/codec/src/encode/qsv.rs`.
160#[derive(Debug, Clone, Copy, PartialEq, Eq)]
161pub struct QsvAv1Params {
162    /// `mfxVideoParam.mfx.RateControlMethod`. ICQ for the common
163    /// quality targets; CQP for archive.
164    pub rc_mode: QsvRateControl,
165    /// `mfxVideoParam.mfx.ICQQuality` (ICQ mode) — 1..51 for AV1 per
166    /// oneVPL 2.8+ dispatcher. 1=best, 51=worst. Mapped from libaom CQ.
167    pub icq_quality: u16,
168    /// `mfxVideoParam.mfx.QPI` (CQP mode) — AV1 q-index 0..255.
169    pub qp_i: u16,
170    /// `mfxVideoParam.mfx.QPP` (CQP mode) — inter-frame QP.
171    pub qp_p: u16,
172    /// `mfxVideoParam.mfx.TargetUsage`. 1=best quality, 7=best speed.
173    pub target_usage: u16,
174    /// `mfxVideoParam.mfx.GopPicSize`. Frames between keyframes.
175    pub gop_pic_size: u16,
176    /// Tile grid — `mfxExtAV1TileParam.NumTileColumns` / `NumTileRows`.
177    pub num_tile_columns: u8,
178    pub num_tile_rows: u8,
179    /// `mfxVideoParam.mfx.LowPower`. Always
180    /// `MFX_CODINGOPTION_OFF = 32` for this service — the low-power
181    /// path on older Arc silicon has documented quality regressions;
182    /// leaving it explicitly OFF sidesteps that.
183    pub low_power: u16,
184}
185
186/// oneVPL tri-state option values (from `MFX_CODINGOPTION_*`).
187/// Used for `LowPower` and a handful of other `mfxU16` toggles.
188pub const MFX_CODINGOPTION_OFF: u16 = 32;
189/// Not currently used but named so the value shows up next to `OFF`
190/// whenever a future code path wants explicit on-switching.
191#[allow(dead_code)]
192pub const MFX_CODINGOPTION_ON: u16 = 16;
193
194/// QSV AV1 rate control mode values match `MFX_RATECONTROL_*`
195/// in `oneVPL/include/vpl/mfxstructs.h`.
196#[derive(Debug, Clone, Copy, PartialEq, Eq)]
197#[repr(u16)]
198pub enum QsvRateControl {
199    /// `MFX_RATECONTROL_CQP = 3`.
200    Cqp = 3,
201    /// `MFX_RATECONTROL_ICQ = 8`. Intelligent constant quality — the
202    /// QSV equivalent of CRF. Best match for a perceptual target.
203    Icq = 8,
204}