tpt_kinetix_core/encode.rs
1//! Shared encoder configuration types.
2//!
3//! Encoders across the Kinetix engine (currently the `rav1e`-backed AV1 encoder
4//! in `tpt-kinetix-av1`) accept their tuning parameters through the codec-agnostic
5//! [`EncodeConfig`] defined here, so that higher layers (pipeline, CLI) can
6//! express encode intent without depending on any specific codec crate.
7//!
8//! The [`RateControl`] enum captures the two rate-control strategies supported
9//! by the initial release, and [`SpeedPreset`] maps human-friendly presets onto
10//! the numeric speed knobs used by real encoders.
11
12use serde::{Deserialize, Serialize};
13
14/// How the encoder should allocate bits.
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
16pub enum RateControl {
17 /// Constant-quality mode driven by a quantizer value (0 = best quality,
18 /// 255 = worst quality). This is `rav1e`'s CQP mode.
19 ConstantQuality {
20 /// Quantizer index (0..=255).
21 quantizer: u8,
22 },
23 /// Target-bitrate mode in bits per second.
24 Bitrate {
25 /// Target bitrate in bits per second.
26 bits_per_second: u32,
27 },
28}
29
30impl Default for RateControl {
31 fn default() -> Self {
32 RateControl::ConstantQuality { quantizer: 100 }
33 }
34}
35
36/// Human-friendly speed / quality trade-off preset.
37///
38/// Presets map onto a numeric speed value via [`SpeedPreset::to_speed`], where
39/// `0` is the slowest / highest quality and `10` is the fastest.
40#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
41pub enum SpeedPreset {
42 /// Highest quality, slowest encode (speed 0).
43 Slowest,
44 /// Balanced default (speed 6).
45 #[default]
46 Medium,
47 /// Fastest encode, lowest quality (speed 10).
48 Fastest,
49 /// An explicit numeric speed value (clamped to 0..=10).
50 Custom(u8),
51}
52
53impl SpeedPreset {
54 /// Map the preset to a numeric speed value in the range `0..=10`.
55 ///
56 /// # Examples
57 ///
58 /// ```
59 /// use tpt_kinetix_core::encode::SpeedPreset;
60 ///
61 /// assert_eq!(SpeedPreset::Slowest.to_speed(), 0);
62 /// assert_eq!(SpeedPreset::Medium.to_speed(), 6);
63 /// assert_eq!(SpeedPreset::Fastest.to_speed(), 10);
64 /// assert_eq!(SpeedPreset::Custom(20).to_speed(), 10); // clamped
65 /// ```
66 pub fn to_speed(self) -> u8 {
67 match self {
68 SpeedPreset::Slowest => 0,
69 SpeedPreset::Medium => 6,
70 SpeedPreset::Fastest => 10,
71 SpeedPreset::Custom(v) => v.min(10),
72 }
73 }
74}
75
76/// Codec-agnostic video encode configuration.
77///
78/// Codec-specific encoders translate this into their own configuration type.
79///
80/// # Examples
81///
82/// ```
83/// use tpt_kinetix_core::encode::{EncodeConfig, RateControl, SpeedPreset};
84///
85/// let cfg = EncodeConfig {
86/// width: 1920,
87/// height: 1080,
88/// rate_control: RateControl::Bitrate { bits_per_second: 6_000_000 },
89/// speed: SpeedPreset::Medium,
90/// keyframe_interval: 240,
91/// };
92/// assert_eq!(cfg.speed.to_speed(), 6);
93/// ```
94#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
95pub struct EncodeConfig {
96 /// Frame width in pixels.
97 pub width: u32,
98 /// Frame height in pixels.
99 pub height: u32,
100 /// Rate-control strategy.
101 pub rate_control: RateControl,
102 /// Speed / quality preset.
103 pub speed: SpeedPreset,
104 /// Maximum interval between keyframes, in frames.
105 pub keyframe_interval: u64,
106}
107
108impl Default for EncodeConfig {
109 fn default() -> Self {
110 Self {
111 width: 640,
112 height: 480,
113 rate_control: RateControl::default(),
114 speed: SpeedPreset::default(),
115 keyframe_interval: 240,
116 }
117 }
118}
119
120impl EncodeConfig {
121 /// Returns the quantizer to use, defaulting sensibly when in bitrate mode.
122 pub fn quantizer(&self) -> u8 {
123 match self.rate_control {
124 RateControl::ConstantQuality { quantizer } => quantizer,
125 // rav1e uses the quantizer as an upper bound in bitrate mode; a
126 // neutral mid value is a safe default.
127 RateControl::Bitrate { .. } => 100,
128 }
129 }
130
131 /// Returns the target bitrate in bits per second (0 in constant-quality mode).
132 pub fn bitrate(&self) -> u32 {
133 match self.rate_control {
134 RateControl::ConstantQuality { .. } => 0,
135 RateControl::Bitrate { bits_per_second } => bits_per_second,
136 }
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143
144 #[test]
145 fn defaults_are_constant_quality() {
146 let cfg = EncodeConfig::default();
147 assert_eq!(cfg.bitrate(), 0);
148 assert_eq!(cfg.quantizer(), 100);
149 assert_eq!(cfg.speed.to_speed(), 6);
150 }
151
152 #[test]
153 fn bitrate_mode_reports_bitrate() {
154 let cfg = EncodeConfig {
155 rate_control: RateControl::Bitrate {
156 bits_per_second: 5_000_000,
157 },
158 ..Default::default()
159 };
160 assert_eq!(cfg.bitrate(), 5_000_000);
161 }
162
163 #[test]
164 fn custom_speed_clamps() {
165 assert_eq!(SpeedPreset::Custom(255).to_speed(), 10);
166 assert_eq!(SpeedPreset::Custom(3).to_speed(), 3);
167 }
168}