oxideav_core/
capabilities.rs1use std::fmt;
21
22use crate::format::{MediaType, PixelFormat};
23
24pub const DEFAULT_PRIORITY: i32 = 100;
28
29#[derive(Clone, Debug)]
31pub struct CodecCapabilities {
32 pub decode: bool,
33 pub encode: bool,
34 pub media_type: MediaType,
35 pub intra_only: bool,
36 pub lossy: bool,
37 pub lossless: bool,
38 pub hardware_accelerated: bool,
40 pub implementation: String,
42 pub max_width: Option<u32>,
44 pub max_height: Option<u32>,
45 pub max_bitrate: Option<u64>,
46 pub max_sample_rate: Option<u32>,
47 pub max_channels: Option<u16>,
48 pub priority: i32,
50 pub accepted_pixel_formats: Vec<PixelFormat>,
55}
56
57impl CodecCapabilities {
58 pub fn audio(implementation: impl Into<String>) -> Self {
61 Self {
62 decode: false,
63 encode: false,
64 media_type: MediaType::Audio,
65 intra_only: true, lossy: false,
67 lossless: false,
68 hardware_accelerated: false,
69 implementation: implementation.into(),
70 max_width: None,
71 max_height: None,
72 max_bitrate: None,
73 max_sample_rate: None,
74 max_channels: None,
75 priority: DEFAULT_PRIORITY,
76 accepted_pixel_formats: Vec::new(),
77 }
78 }
79
80 pub fn video(implementation: impl Into<String>) -> Self {
81 Self {
82 decode: false,
83 encode: false,
84 media_type: MediaType::Video,
85 intra_only: false,
86 lossy: false,
87 lossless: false,
88 hardware_accelerated: false,
89 implementation: implementation.into(),
90 max_width: None,
91 max_height: None,
92 max_bitrate: None,
93 max_sample_rate: None,
94 max_channels: None,
95 priority: DEFAULT_PRIORITY,
96 accepted_pixel_formats: Vec::new(),
97 }
98 }
99
100 pub fn flag_string(&self) -> String {
103 let mut s = String::with_capacity(6);
104 s.push(if self.decode { 'D' } else { '.' });
105 s.push(if self.encode { 'E' } else { '.' });
106 s.push(match self.media_type {
107 MediaType::Video => 'V',
108 MediaType::Audio => 'A',
109 MediaType::Subtitle => 'S',
110 MediaType::Data => 'D',
111 MediaType::Unknown => '.',
112 });
113 s.push(if self.intra_only { 'I' } else { '.' });
114 s.push(if self.lossy { 'L' } else { '.' });
115 s.push(if self.lossless { 'S' } else { '.' });
116 s
117 }
118
119 pub fn with_decode(mut self) -> Self {
122 self.decode = true;
123 self
124 }
125 pub fn with_encode(mut self) -> Self {
126 self.encode = true;
127 self
128 }
129 pub fn with_intra_only(mut self, v: bool) -> Self {
130 self.intra_only = v;
131 self
132 }
133 pub fn with_lossy(mut self, v: bool) -> Self {
134 self.lossy = v;
135 self
136 }
137 pub fn with_lossless(mut self, v: bool) -> Self {
138 self.lossless = v;
139 self
140 }
141 pub fn with_hardware(mut self, v: bool) -> Self {
142 self.hardware_accelerated = v;
143 self
144 }
145 pub fn with_priority(mut self, p: i32) -> Self {
146 self.priority = p;
147 self
148 }
149 pub fn with_max_size(mut self, w: u32, h: u32) -> Self {
150 self.max_width = Some(w);
151 self.max_height = Some(h);
152 self
153 }
154 pub fn with_max_bitrate(mut self, br: u64) -> Self {
155 self.max_bitrate = Some(br);
156 self
157 }
158 pub fn with_max_sample_rate(mut self, sr: u32) -> Self {
159 self.max_sample_rate = Some(sr);
160 self
161 }
162 pub fn with_max_channels(mut self, ch: u16) -> Self {
163 self.max_channels = Some(ch);
164 self
165 }
166
167 pub fn with_pixel_format(mut self, fmt: PixelFormat) -> Self {
170 self.accepted_pixel_formats.push(fmt);
171 self
172 }
173
174 pub fn with_pixel_formats(mut self, fmts: Vec<PixelFormat>) -> Self {
176 self.accepted_pixel_formats = fmts;
177 self
178 }
179}
180
181impl fmt::Display for CodecCapabilities {
182 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
183 write!(f, "{} {}", self.flag_string(), self.implementation)
184 }
185}
186
187#[derive(Clone, Debug, Default)]
190pub struct CodecPreferences {
191 pub prefer: Vec<String>,
193 pub exclude: Vec<String>,
195 pub no_hardware: bool,
197 pub boost: i32,
199}
200
201impl CodecPreferences {
202 pub fn excludes(&self, caps: &CodecCapabilities) -> bool {
203 self.exclude.iter().any(|n| n == &caps.implementation)
204 || (self.no_hardware && caps.hardware_accelerated)
205 }
206
207 pub fn effective_priority(&self, caps: &CodecCapabilities) -> i32 {
208 if self.prefer.iter().any(|n| n == &caps.implementation) {
209 caps.priority - self.boost.max(0)
210 } else {
211 caps.priority
212 }
213 }
214}