Skip to main content

mp4_edit/atom/leaf/
gmin.rs

1use crate::{
2    atom::{util::ColorRgb, FourCC},
3    parser::ParseAtomData,
4    writer::SerializeAtom,
5    ParseError,
6};
7
8pub const GMIN: FourCC = FourCC::new(b"gmin");
9
10#[derive(Debug, Clone)]
11pub struct BaseMediaInfoAtom {
12    pub version: u8,
13    pub flags: [u8; 3],
14    pub graphics_mode: u16,
15    pub op_color: ColorRgb,
16    /// fixed point 8x8
17    pub balance: f32,
18    // reserved: 2 bytes
19}
20
21impl Default for BaseMediaInfoAtom {
22    fn default() -> Self {
23        Self {
24            version: 0,
25            flags: [0, 0, 0],
26            graphics_mode: 64,
27            op_color: ColorRgb {
28                red: 32768,
29                green: 32768,
30                blue: 32768,
31            },
32            balance: 0.0,
33        }
34    }
35}
36
37impl ParseAtomData for BaseMediaInfoAtom {
38    fn parse_atom_data(atom_type: FourCC, input: &[u8]) -> Result<Self, ParseError> {
39        crate::atom::util::parser::assert_atom_type!(atom_type, GMIN);
40        use crate::atom::util::parser::stream;
41        use winnow::Parser;
42        Ok(parser::parse_gmin_data.parse(stream(input))?)
43    }
44}
45
46impl SerializeAtom for BaseMediaInfoAtom {
47    fn atom_type(&self) -> FourCC {
48        GMIN
49    }
50
51    fn into_body_bytes(self) -> Vec<u8> {
52        serializer::serialize_gmin_data(self)
53    }
54}
55
56mod serializer {
57    use crate::atom::{
58        gmin::BaseMediaInfoAtom,
59        util::serializer::{color_rgb, fixed_point_8x8},
60    };
61
62    pub fn serialize_gmin_data(gmin: BaseMediaInfoAtom) -> Vec<u8> {
63        let mut data = Vec::new();
64        data.push(gmin.version);
65        data.extend(gmin.flags);
66        data.extend(gmin.graphics_mode.to_be_bytes());
67        data.extend(color_rgb(gmin.op_color));
68        data.extend(fixed_point_8x8(gmin.balance));
69        data.extend([0u8; 2]); // reserved
70        data
71    }
72}
73
74mod parser {
75    use crate::atom::{
76        gmin::BaseMediaInfoAtom,
77        util::parser::{byte_array, color_rgb, fixed_point_8x8, flags3, version, Stream},
78    };
79    use winnow::{binary::be_u16, combinator::seq, error::StrContext, ModalResult, Parser};
80
81    pub fn parse_gmin_data(input: &mut Stream<'_>) -> ModalResult<BaseMediaInfoAtom> {
82        seq!(BaseMediaInfoAtom {
83            version: version,
84            flags: flags3,
85            graphics_mode: be_u16.context(StrContext::Label("graphics_mode")),
86            op_color: color_rgb.context(StrContext::Label("op_color")),
87            balance: fixed_point_8x8.context(StrContext::Label("balance")),
88            _: byte_array::<2>.context(StrContext::Label("reserved")),
89        })
90        .parse_next(input)
91    }
92}
93
94#[cfg(test)]
95mod tests {
96    use super::*;
97    use crate::atom::test_utils::test_atom_roundtrip;
98
99    /// Test round-trip for all available gmin test data files
100    #[test]
101    fn test_gmin_roundtrip() {
102        test_atom_roundtrip::<BaseMediaInfoAtom>(GMIN);
103    }
104}