Skip to main content

mp4_edit/atom/leaf/stsd/
audio.rs

1use super::StsdExtension;
2
3#[derive(Default, Debug, Clone)]
4pub struct AudioSampleEntry {
5    pub version: u16,
6    pub channel_count: u16,
7    pub sample_size: u16,
8    pub predefined: u16,
9    /// 16.16 fixed point
10    pub sample_rate: f32,
11    pub extensions: Vec<StsdExtension>,
12}
13
14impl AudioSampleEntry {
15    pub fn find_or_create_extension<P, D>(&mut self, pred: P, default_fn: D) -> &mut StsdExtension
16    where
17        P: Fn(&StsdExtension) -> bool,
18        D: FnOnce() -> StsdExtension,
19    {
20        if let Some(index) = self.extensions.iter().position(pred) {
21            return &mut self.extensions[index];
22        }
23        self.extensions.push(default_fn());
24        self.extensions.last_mut().unwrap()
25    }
26}
27
28pub(super) mod serializer {
29    use super::AudioSampleEntry;
30    use crate::atom::{
31        stsd::extension::serializer::serialize_stsd_extensions, util::serializer::fixed_point_16x16,
32    };
33
34    pub fn serialize_audio_sample_entry(audio: AudioSampleEntry) -> Vec<u8> {
35        let mut data = Vec::new();
36        data.extend(audio.version.to_be_bytes());
37        data.extend([0u8; 6]); // reserved
38        data.extend(audio.channel_count.to_be_bytes());
39        data.extend(audio.sample_size.to_be_bytes());
40        data.extend(audio.predefined.to_be_bytes());
41        data.extend([0u8; 2]); // reserved
42        data.extend(fixed_point_16x16(audio.sample_rate));
43        data.extend(serialize_stsd_extensions(audio.extensions));
44        data
45    }
46}
47
48pub(super) mod parser {
49    use winnow::{binary::be_u16, combinator::seq, error::StrContext, ModalResult, Parser};
50
51    use super::AudioSampleEntry;
52    use crate::atom::{
53        stsd::{extension::parser::parse_stsd_extensions, SampleEntryData},
54        util::parser::{byte_array, fixed_point_16x16, Stream},
55    };
56
57    pub fn parse_audio_sample_entry(input: &mut Stream<'_>) -> ModalResult<SampleEntryData> {
58        seq!(AudioSampleEntry {
59            version: be_u16.verify(|v| *v == 0).context(StrContext::Label("version")),
60            _: byte_array::<6>.context(StrContext::Label("reserved")),
61            channel_count: be_u16.context(StrContext::Label("channel_count")),
62            sample_size: be_u16.context(StrContext::Label("sample_size")),
63            predefined: be_u16.context(StrContext::Label("predefined")),
64            _: byte_array::<2>.context(StrContext::Label("reserved")),
65            sample_rate: fixed_point_16x16.context(StrContext::Label("sample_rate")),
66            extensions: parse_stsd_extensions.context(StrContext::Label("extensions")),
67        })
68        .map(SampleEntryData::Audio)
69        .parse_next(input)
70    }
71}