flowly_mp4/mp4box/
vmhd.rs

1use byteorder::{BigEndian, WriteBytesExt};
2use serde::Serialize;
3use std::io::Write;
4
5use crate::mp4box::*;
6
7#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
8pub struct VmhdBox {
9    pub version: u8,
10    pub flags: u32,
11    pub graphics_mode: u16,
12    pub op_color: RgbColor,
13}
14
15#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
16pub struct RgbColor {
17    pub red: u16,
18    pub green: u16,
19    pub blue: u16,
20}
21
22impl VmhdBox {
23    pub fn get_type(&self) -> BoxType {
24        BoxType::VmhdBox
25    }
26
27    pub fn get_size(&self) -> u64 {
28        HEADER_SIZE + HEADER_EXT_SIZE + 8
29    }
30}
31
32impl Mp4Box for VmhdBox {
33    const TYPE: BoxType = BoxType::VmhdBox;
34
35    fn box_size(&self) -> u64 {
36        self.get_size()
37    }
38
39    fn to_json(&self) -> Result<String, Error> {
40        Ok(serde_json::to_string(&self).unwrap())
41    }
42
43    fn summary(&self) -> Result<String, Error> {
44        let s = format!(
45            "graphics_mode={} op_color={}{}{}",
46            self.graphics_mode, self.op_color.red, self.op_color.green, self.op_color.blue
47        );
48        Ok(s)
49    }
50}
51
52impl BlockReader for VmhdBox {
53    fn read_block<'a>(reader: &mut impl Reader<'a>) -> Result<Self, Error> {
54        let (version, flags) = read_box_header_ext(reader);
55        let graphics_mode = reader.get_u16();
56        let op_color = RgbColor {
57            red: reader.get_u16(),
58            green: reader.get_u16(),
59            blue: reader.get_u16(),
60        };
61
62        Ok(VmhdBox {
63            version,
64            flags,
65            graphics_mode,
66            op_color,
67        })
68    }
69
70    fn size_hint() -> usize {
71        12
72    }
73}
74
75impl<W: Write> WriteBox<&mut W> for VmhdBox {
76    fn write_box(&self, writer: &mut W) -> Result<u64, Error> {
77        let size = self.box_size();
78        BoxHeader::new(Self::TYPE, size).write(writer)?;
79
80        write_box_header_ext(writer, self.version, self.flags)?;
81
82        writer.write_u16::<BigEndian>(self.graphics_mode)?;
83        writer.write_u16::<BigEndian>(self.op_color.red)?;
84        writer.write_u16::<BigEndian>(self.op_color.green)?;
85        writer.write_u16::<BigEndian>(self.op_color.blue)?;
86
87        Ok(size)
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94    use crate::mp4box::BoxHeader;
95
96    #[tokio::test]
97    async fn test_vmhd() {
98        let src_box = VmhdBox {
99            version: 0,
100            flags: 1,
101            graphics_mode: 0,
102            op_color: RgbColor {
103                red: 0,
104                green: 0,
105                blue: 0,
106            },
107        };
108        let mut buf = Vec::new();
109        src_box.write_box(&mut buf).unwrap();
110        assert_eq!(buf.len(), src_box.box_size() as usize);
111
112        let mut reader = buf.as_slice();
113        let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
114        assert_eq!(header.kind, BoxType::VmhdBox);
115        assert_eq!(src_box.box_size(), header.size);
116
117        let dst_box = VmhdBox::read_block(&mut reader).unwrap();
118        assert_eq!(src_box, dst_box);
119    }
120}