Skip to main content

media_codec/
codec.rs

1use std::{
2    collections::HashMap,
3    marker::PhantomData,
4    sync::{Arc, LazyLock, RwLock},
5};
6
7use media_codec_types::{CodecBuilder, CodecID, CodecSpec};
8use media_core::{invalid_error, not_found_error, Result};
9
10pub(crate) struct CodecList<S: CodecSpec, B: ?Sized + CodecBuilder<S> = dyn CodecBuilder<S>> {
11    pub(crate) codecs: HashMap<CodecID, Vec<Arc<B>>>,
12    pub(crate) _marker: PhantomData<S>,
13}
14
15pub(crate) type LazyCodecList<S, B = dyn CodecBuilder<S>> = LazyLock<RwLock<CodecList<S, B>>>;
16
17pub(crate) fn register_codec<S, B>(codec_list: &LazyCodecList<S, B>, builder: Arc<B>, default: bool) -> Result<()>
18where
19    S: CodecSpec,
20    B: ?Sized + CodecBuilder<S>,
21{
22    let mut codec_list = codec_list.write().map_err(|err| invalid_error!(err.to_string()))?;
23    for &id in builder.ids() {
24        let list = codec_list.codecs.entry(id).or_default();
25
26        if default {
27            list.insert(0, builder.clone());
28        } else {
29            list.push(builder.clone());
30        }
31    }
32
33    Ok(())
34}
35
36pub(crate) fn find_codec<S, B>(codec_list: &LazyCodecList<S, B>, id: CodecID) -> Result<Arc<B>>
37where
38    S: CodecSpec,
39    B: ?Sized + CodecBuilder<S>,
40{
41    let codec_list = codec_list.read().map_err(|err| invalid_error!(err.to_string()))?;
42
43    if let Some(builders) = codec_list.codecs.get(&id) {
44        if let Some(builder) = builders.first() {
45            return Ok(builder.clone());
46        }
47    }
48
49    Err(not_found_error!(format!("codec: {:?}", id)))
50}
51
52pub(crate) fn find_codec_by_name<S, B>(codec_list: &LazyCodecList<S, B>, name: &str) -> Result<Arc<B>>
53where
54    S: CodecSpec,
55    B: ?Sized + CodecBuilder<S>,
56{
57    let codec_list = codec_list.read().map_err(|err| invalid_error!(err.to_string()))?;
58
59    for builders in codec_list.codecs.values() {
60        for builder in builders {
61            if builder.name() == name {
62                return Ok(builder.clone());
63            }
64        }
65    }
66
67    Err(not_found_error!(format!("codec: {}", name)))
68}