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, Serialize)]
8pub struct MfhdBox {
9 pub version: u8,
10 pub flags: u32,
11 pub sequence_number: u32,
12}
13
14impl Default for MfhdBox {
15 fn default() -> Self {
16 MfhdBox {
17 version: 0,
18 flags: 0,
19 sequence_number: 1,
20 }
21 }
22}
23
24impl MfhdBox {
25 pub fn get_type(&self) -> BoxType {
26 BoxType::MfhdBox
27 }
28
29 pub fn get_size(&self) -> u64 {
30 HEADER_SIZE + HEADER_EXT_SIZE + 4
31 }
32}
33
34impl Mp4Box for MfhdBox {
35 fn box_type(&self) -> BoxType {
36 self.get_type()
37 }
38
39 fn box_size(&self) -> u64 {
40 self.get_size()
41 }
42
43 fn to_json(&self) -> Result<String> {
44 Ok(serde_json::to_string(&self).unwrap())
45 }
46
47 fn summary(&self) -> Result<String> {
48 let s = format!("sequence_number={}", self.sequence_number);
49 Ok(s)
50 }
51}
52
53impl<R: Read + Seek> ReadBox<&mut R> for MfhdBox {
54 fn read_box(reader: &mut R, size: u64) -> Result<Self> {
55 let start = box_start(reader)?;
56
57 let (version, flags) = read_box_header_ext(reader)?;
58 let sequence_number = reader.read_u32::<BigEndian>()?;
59
60 skip_bytes_to(reader, start + size)?;
61
62 Ok(MfhdBox {
63 version,
64 flags,
65 sequence_number,
66 })
67 }
68}
69
70impl<W: Write> WriteBox<&mut W> for MfhdBox {
71 fn write_box(&self, writer: &mut W) -> Result<u64> {
72 let size = self.box_size();
73 BoxHeader::new(self.box_type(), size).write(writer)?;
74
75 write_box_header_ext(writer, self.version, self.flags)?;
76 writer.write_u32::<BigEndian>(self.sequence_number)?;
77
78 Ok(size)
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85 use crate::mp4box::BoxHeader;
86 use std::io::Cursor;
87
88 #[test]
89 fn test_mfhd() {
90 let src_box = MfhdBox {
91 version: 0,
92 flags: 0,
93 sequence_number: 1,
94 };
95 let mut buf = Vec::new();
96 src_box.write_box(&mut buf).unwrap();
97 assert_eq!(buf.len(), src_box.box_size() as usize);
98
99 let mut reader = Cursor::new(&buf);
100 let header = BoxHeader::read(&mut reader).unwrap();
101 assert_eq!(header.name, BoxType::MfhdBox);
102 assert_eq!(src_box.box_size(), header.size);
103
104 let dst_box = MfhdBox::read_box(&mut reader, header.size).unwrap();
105 assert_eq!(src_box, dst_box);
106 }
107}