1use std::collections::HashMap;
6
7use oxideav_core::{CodecCapabilities, CodecId, CodecParameters, CodecPreferences, Error, Result};
8
9use crate::{Decoder, DecoderFactory, Encoder, EncoderFactory};
10
11#[derive(Clone)]
15pub struct CodecImplementation {
16 pub caps: CodecCapabilities,
17 pub make_decoder: Option<DecoderFactory>,
18 pub make_encoder: Option<EncoderFactory>,
19}
20
21#[derive(Default)]
22pub struct CodecRegistry {
23 impls: HashMap<CodecId, Vec<CodecImplementation>>,
24}
25
26impl CodecRegistry {
27 pub fn new() -> Self {
28 Self::default()
29 }
30
31 pub fn register(&mut self, id: CodecId, implementation: CodecImplementation) {
35 self.impls.entry(id).or_default().push(implementation);
36 }
37
38 pub fn register_decoder_impl(
41 &mut self,
42 id: CodecId,
43 caps: CodecCapabilities,
44 factory: DecoderFactory,
45 ) {
46 self.register(
47 id,
48 CodecImplementation {
49 caps: caps.with_decode(),
50 make_decoder: Some(factory),
51 make_encoder: None,
52 },
53 );
54 }
55
56 pub fn register_encoder_impl(
58 &mut self,
59 id: CodecId,
60 caps: CodecCapabilities,
61 factory: EncoderFactory,
62 ) {
63 self.register(
64 id,
65 CodecImplementation {
66 caps: caps.with_encode(),
67 make_decoder: None,
68 make_encoder: Some(factory),
69 },
70 );
71 }
72
73 pub fn register_both(
76 &mut self,
77 id: CodecId,
78 caps: CodecCapabilities,
79 decode: DecoderFactory,
80 encode: EncoderFactory,
81 ) {
82 self.register(
83 id,
84 CodecImplementation {
85 caps: caps.with_decode().with_encode(),
86 make_decoder: Some(decode),
87 make_encoder: Some(encode),
88 },
89 );
90 }
91
92 pub fn register_decoder(&mut self, id: CodecId, factory: DecoderFactory) {
95 let caps = CodecCapabilities::audio(id.as_str()).with_decode();
96 self.register_decoder_impl(id, caps, factory);
97 }
98
99 pub fn register_encoder(&mut self, id: CodecId, factory: EncoderFactory) {
102 let caps = CodecCapabilities::audio(id.as_str()).with_encode();
103 self.register_encoder_impl(id, caps, factory);
104 }
105
106 pub fn has_decoder(&self, id: &CodecId) -> bool {
107 self.impls
108 .get(id)
109 .map(|v| v.iter().any(|i| i.make_decoder.is_some()))
110 .unwrap_or(false)
111 }
112
113 pub fn has_encoder(&self, id: &CodecId) -> bool {
114 self.impls
115 .get(id)
116 .map(|v| v.iter().any(|i| i.make_encoder.is_some()))
117 .unwrap_or(false)
118 }
119
120 pub fn make_decoder_with(
125 &self,
126 params: &CodecParameters,
127 prefs: &CodecPreferences,
128 ) -> Result<Box<dyn Decoder>> {
129 let candidates = self
130 .impls
131 .get(¶ms.codec_id)
132 .ok_or_else(|| Error::CodecNotFound(params.codec_id.to_string()))?;
133 let mut ranked: Vec<&CodecImplementation> = candidates
134 .iter()
135 .filter(|i| i.make_decoder.is_some() && !prefs.excludes(&i.caps))
136 .filter(|i| caps_fit_params(&i.caps, params, false))
137 .collect();
138 ranked.sort_by_key(|i| prefs.effective_priority(&i.caps));
139 let mut last_err: Option<Error> = None;
140 for imp in ranked {
141 match (imp.make_decoder.unwrap())(params) {
142 Ok(d) => return Ok(d),
143 Err(e) => last_err = Some(e),
144 }
145 }
146 Err(last_err.unwrap_or_else(|| {
147 Error::CodecNotFound(format!(
148 "no decoder for {} accepts the requested parameters",
149 params.codec_id
150 ))
151 }))
152 }
153
154 pub fn make_encoder_with(
156 &self,
157 params: &CodecParameters,
158 prefs: &CodecPreferences,
159 ) -> Result<Box<dyn Encoder>> {
160 let candidates = self
161 .impls
162 .get(¶ms.codec_id)
163 .ok_or_else(|| Error::CodecNotFound(params.codec_id.to_string()))?;
164 let mut ranked: Vec<&CodecImplementation> = candidates
165 .iter()
166 .filter(|i| i.make_encoder.is_some() && !prefs.excludes(&i.caps))
167 .filter(|i| caps_fit_params(&i.caps, params, true))
168 .collect();
169 ranked.sort_by_key(|i| prefs.effective_priority(&i.caps));
170 let mut last_err: Option<Error> = None;
171 for imp in ranked {
172 match (imp.make_encoder.unwrap())(params) {
173 Ok(e) => return Ok(e),
174 Err(e) => last_err = Some(e),
175 }
176 }
177 Err(last_err.unwrap_or_else(|| {
178 Error::CodecNotFound(format!(
179 "no encoder for {} accepts the requested parameters",
180 params.codec_id
181 ))
182 }))
183 }
184
185 pub fn make_decoder(&self, params: &CodecParameters) -> Result<Box<dyn Decoder>> {
187 self.make_decoder_with(params, &CodecPreferences::default())
188 }
189
190 pub fn make_encoder(&self, params: &CodecParameters) -> Result<Box<dyn Encoder>> {
192 self.make_encoder_with(params, &CodecPreferences::default())
193 }
194
195 pub fn decoder_ids(&self) -> impl Iterator<Item = &CodecId> {
197 self.impls
198 .iter()
199 .filter(|(_, v)| v.iter().any(|i| i.make_decoder.is_some()))
200 .map(|(id, _)| id)
201 }
202
203 pub fn encoder_ids(&self) -> impl Iterator<Item = &CodecId> {
204 self.impls
205 .iter()
206 .filter(|(_, v)| v.iter().any(|i| i.make_encoder.is_some()))
207 .map(|(id, _)| id)
208 }
209
210 pub fn implementations(&self, id: &CodecId) -> &[CodecImplementation] {
212 self.impls.get(id).map(|v| v.as_slice()).unwrap_or(&[])
213 }
214
215 pub fn all_implementations(&self) -> impl Iterator<Item = (&CodecId, &CodecImplementation)> {
218 self.impls
219 .iter()
220 .flat_map(|(id, v)| v.iter().map(move |i| (id, i)))
221 }
222}
223
224fn caps_fit_params(caps: &CodecCapabilities, p: &CodecParameters, for_encode: bool) -> bool {
228 let _ = for_encode; if let (Some(max), Some(w)) = (caps.max_width, p.width) {
230 if w > max {
231 return false;
232 }
233 }
234 if let (Some(max), Some(h)) = (caps.max_height, p.height) {
235 if h > max {
236 return false;
237 }
238 }
239 if let (Some(max), Some(br)) = (caps.max_bitrate, p.bit_rate) {
240 if br > max {
241 return false;
242 }
243 }
244 if let (Some(max), Some(sr)) = (caps.max_sample_rate, p.sample_rate) {
245 if sr > max {
246 return false;
247 }
248 }
249 if let (Some(max), Some(ch)) = (caps.max_channels, p.channels) {
250 if ch > max {
251 return false;
252 }
253 }
254 true
255}