Skip to main content

mp4/mp4box/
vmhd.rs

1use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
2use serde::Serialize;
3use std::io::{Read, Seek, 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    fn box_type(&self) -> BoxType {
34        self.get_type()
35    }
36
37    fn box_size(&self) -> u64 {
38        self.get_size()
39    }
40
41    fn to_json(&self) -> Result<String> {
42        Ok(serde_json::to_string(&self).unwrap())
43    }
44
45    fn summary(&self) -> Result<String> {
46        let s = format!(
47            "graphics_mode={} op_color={}{}{}",
48            self.graphics_mode, self.op_color.red, self.op_color.green, self.op_color.blue
49        );
50        Ok(s)
51    }
52}
53
54impl<R: Read + Seek> ReadBox<&mut R> for VmhdBox {
55    fn read_box(reader: &mut R, size: u64) -> Result<Self> {
56        let start = box_start(reader)?;
57
58        let (version, flags) = read_box_header_ext(reader)?;
59
60        let graphics_mode = reader.read_u16::<BigEndian>()?;
61        let op_color = RgbColor {
62            red: reader.read_u16::<BigEndian>()?,
63            green: reader.read_u16::<BigEndian>()?,
64            blue: reader.read_u16::<BigEndian>()?,
65        };
66
67        skip_bytes_to(reader, start + size)?;
68
69        Ok(VmhdBox {
70            version,
71            flags,
72            graphics_mode,
73            op_color,
74        })
75    }
76}
77
78impl<W: Write> WriteBox<&mut W> for VmhdBox {
79    fn write_box(&self, writer: &mut W) -> Result<u64> {
80        let size = self.box_size();
81        BoxHeader::new(self.box_type(), size).write(writer)?;
82
83        write_box_header_ext(writer, self.version, self.flags)?;
84
85        writer.write_u16::<BigEndian>(self.graphics_mode)?;
86        writer.write_u16::<BigEndian>(self.op_color.red)?;
87        writer.write_u16::<BigEndian>(self.op_color.green)?;
88        writer.write_u16::<BigEndian>(self.op_color.blue)?;
89
90        Ok(size)
91    }
92}
93
94#[cfg(test)]
95mod tests {
96    use super::*;
97    use crate::mp4box::BoxHeader;
98    use std::io::Cursor;
99
100    #[test]
101    fn test_vmhd() {
102        let src_box = VmhdBox {
103            version: 0,
104            flags: 1,
105            graphics_mode: 0,
106            op_color: RgbColor {
107                red: 0,
108                green: 0,
109                blue: 0,
110            },
111        };
112        let mut buf = Vec::new();
113        src_box.write_box(&mut buf).unwrap();
114        assert_eq!(buf.len(), src_box.box_size() as usize);
115
116        let mut reader = Cursor::new(&buf);
117        let header = BoxHeader::read(&mut reader).unwrap();
118        assert_eq!(header.name, BoxType::VmhdBox);
119        assert_eq!(src_box.box_size(), header.size);
120
121        let dst_box = VmhdBox::read_box(&mut reader, header.size).unwrap();
122        assert_eq!(src_box, dst_box);
123    }
124}