mp4_edit/atom/leaf/stsd/
audio.rs1use 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 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]); 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]); 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}