flowly_mp4/mp4box/
vp09.rs

1use crate::mp4box::vpcc::VpccBox;
2use crate::mp4box::*;
3use crate::Mp4Box;
4use serde::Serialize;
5
6#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
7pub struct Vp09Box {
8    pub version: u8,
9    pub flags: u32,
10    pub start_code: u16,
11    pub data_reference_index: u16,
12    pub reserved0: [u8; 16],
13    pub width: u16,
14    pub height: u16,
15    pub horizresolution: (u16, u16),
16    pub vertresolution: (u16, u16),
17    pub reserved1: [u8; 4],
18    pub frame_count: u16,
19    pub compressorname: [u8; 32],
20    pub depth: u16,
21    pub end_code: u16,
22    pub vpcc: VpccBox,
23}
24
25impl Vp09Box {
26    pub const DEFAULT_START_CODE: u16 = 0;
27    pub const DEFAULT_END_CODE: u16 = 0xFFFF;
28    pub const DEFAULT_DATA_REFERENCE_INDEX: u16 = 1;
29    pub const DEFAULT_HORIZRESOLUTION: (u16, u16) = (0x48, 0x00);
30    pub const DEFAULT_VERTRESOLUTION: (u16, u16) = (0x48, 0x00);
31    pub const DEFAULT_FRAME_COUNT: u16 = 1;
32    pub const DEFAULT_COMPRESSORNAME: [u8; 32] = [0; 32];
33    pub const DEFAULT_DEPTH: u16 = 24;
34
35    pub fn new(config: &Vp9Config) -> Self {
36        Vp09Box {
37            version: 0,
38            flags: 0,
39            start_code: Vp09Box::DEFAULT_START_CODE,
40            data_reference_index: Vp09Box::DEFAULT_DATA_REFERENCE_INDEX,
41            reserved0: Default::default(),
42            width: config.width,
43            height: config.height,
44            horizresolution: Vp09Box::DEFAULT_HORIZRESOLUTION,
45            vertresolution: Vp09Box::DEFAULT_VERTRESOLUTION,
46            reserved1: Default::default(),
47            frame_count: Vp09Box::DEFAULT_FRAME_COUNT,
48            compressorname: Vp09Box::DEFAULT_COMPRESSORNAME,
49            depth: Vp09Box::DEFAULT_DEPTH,
50            end_code: Vp09Box::DEFAULT_END_CODE,
51            vpcc: VpccBox {
52                version: VpccBox::DEFAULT_VERSION,
53                flags: 0,
54                profile: 0,
55                level: 0x1F,
56                bit_depth: VpccBox::DEFAULT_BIT_DEPTH,
57                chroma_subsampling: 0,
58                video_full_range_flag: false,
59                color_primaries: 0,
60                transfer_characteristics: 0,
61                matrix_coefficients: 0,
62                codec_initialization_data_size: 0,
63            },
64        }
65    }
66}
67
68impl Mp4Box for Vp09Box {
69    const TYPE: BoxType = BoxType::Vp09Box;
70
71    fn box_size(&self) -> u64 {
72        0x6A
73    }
74
75    fn to_json(&self) -> Result<String, Error> {
76        Ok(serde_json::to_string(&self).unwrap())
77    }
78
79    fn summary(&self) -> Result<String, Error> {
80        Ok(format!("{self:?}"))
81    }
82}
83
84impl BlockReader for Vp09Box {
85    fn read_block<'a>(reader: &mut impl Reader<'a>) -> Result<Self, Error> {
86        let (version, flags) = read_box_header_ext(reader);
87
88        let start_code: u16 = reader.get_u16();
89        let data_reference_index: u16 = reader.get_u16();
90        let reserved0: [u8; 16] = {
91            let mut buf = [0u8; 16];
92            reader.copy_to_slice(&mut buf)?;
93            buf
94        };
95
96        let width: u16 = reader.get_u16();
97        let height: u16 = reader.get_u16();
98        let horizresolution: (u16, u16) = (reader.get_u16(), reader.get_u16());
99        let vertresolution: (u16, u16) = (reader.get_u16(), reader.get_u16());
100        let reserved1: [u8; 4] = {
101            let mut buf = [0u8; 4];
102            reader.copy_to_slice(&mut buf)?;
103            buf
104        };
105
106        let frame_count: u16 = reader.get_u16();
107        let compressorname: [u8; 32] = {
108            let mut buf = [0u8; 32];
109            reader.copy_to_slice(&mut buf)?;
110            buf
111        };
112
113        let depth: u16 = reader.get_u16();
114        let end_code: u16 = reader.get_u16();
115
116        Ok(Self {
117            version,
118            flags,
119            start_code,
120            data_reference_index,
121            reserved0,
122            width,
123            height,
124            horizresolution,
125            vertresolution,
126            reserved1,
127            frame_count,
128            compressorname,
129            depth,
130            end_code,
131            vpcc: reader.find_box::<VpccBox>()?,
132        })
133    }
134
135    fn size_hint() -> usize {
136        78
137    }
138}
139
140impl<W: Write> WriteBox<&mut W> for Vp09Box {
141    fn write_box(&self, writer: &mut W) -> Result<u64, Error> {
142        let size = self.box_size();
143        BoxHeader::new(Self::TYPE, size).write(writer)?;
144
145        write_box_header_ext(writer, self.version, self.flags)?;
146
147        writer.write_u16::<BigEndian>(self.start_code)?;
148        writer.write_u16::<BigEndian>(self.data_reference_index)?;
149        writer.write_all(&self.reserved0)?;
150        writer.write_u16::<BigEndian>(self.width)?;
151        writer.write_u16::<BigEndian>(self.height)?;
152        writer.write_u16::<BigEndian>(self.horizresolution.0)?;
153        writer.write_u16::<BigEndian>(self.horizresolution.1)?;
154        writer.write_u16::<BigEndian>(self.vertresolution.0)?;
155        writer.write_u16::<BigEndian>(self.vertresolution.1)?;
156        writer.write_all(&self.reserved1)?;
157        writer.write_u16::<BigEndian>(self.frame_count)?;
158        writer.write_all(&self.compressorname)?;
159        writer.write_u16::<BigEndian>(self.depth)?;
160        writer.write_u16::<BigEndian>(self.end_code)?;
161        VpccBox::write_box(&self.vpcc, writer)?;
162
163        Ok(size)
164    }
165}
166
167#[cfg(test)]
168mod tests {
169    use super::*;
170    use crate::mp4box::BoxHeader;
171
172    #[tokio::test]
173    async fn test_vpcc() {
174        let src_box = Vp09Box::new(&Vp9Config {
175            width: 1920,
176            height: 1080,
177        });
178        let mut buf = Vec::new();
179        src_box.write_box(&mut buf).unwrap();
180        assert_eq!(buf.len(), src_box.box_size() as usize);
181
182        let mut reader = buf.as_slice();
183        let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
184        assert_eq!(header.kind, BoxType::Vp09Box);
185        assert_eq!(src_box.box_size(), header.size);
186
187        let dst_box = Vp09Box::read_block(&mut reader).unwrap();
188        assert_eq!(src_box, dst_box);
189    }
190}