1use serde::Serialize;
2use std::io::{Read, Seek, Write};
3
4use crate::mp4box::*;
5use crate::mp4box::{mfhd::MfhdBox, traf::TrafBox};
6
7#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
8pub struct MoofBox {
9 pub mfhd: MfhdBox,
10
11 #[serde(rename = "traf")]
12 pub trafs: Vec<TrafBox>,
13}
14
15impl MoofBox {
16 pub fn get_type(&self) -> BoxType {
17 BoxType::MoofBox
18 }
19
20 pub fn get_size(&self) -> u64 {
21 let mut size = HEADER_SIZE + self.mfhd.box_size();
22 for traf in self.trafs.iter() {
23 size += traf.box_size();
24 }
25 size
26 }
27}
28
29impl Mp4Box for MoofBox {
30 fn box_type(&self) -> BoxType {
31 self.get_type()
32 }
33
34 fn box_size(&self) -> u64 {
35 self.get_size()
36 }
37
38 fn to_json(&self) -> Result<String> {
39 Ok(serde_json::to_string(&self).unwrap())
40 }
41
42 fn summary(&self) -> Result<String> {
43 let s = format!("trafs={}", self.trafs.len());
44 Ok(s)
45 }
46}
47
48impl<R: Read + Seek> ReadBox<&mut R> for MoofBox {
49 fn read_box(reader: &mut R, size: u64) -> Result<Self> {
50 let start = box_start(reader)?;
51
52 let mut mfhd = None;
53 let mut trafs = Vec::new();
54
55 let mut current = reader.stream_position()?;
56 let end = start + size;
57 while current < end {
58 let header = BoxHeader::read(reader)?;
60 let BoxHeader { name, size: s } = header;
61 if s > size {
62 return Err(Error::InvalidData(
63 "moof box contains a box with a larger size than it",
64 ));
65 }
66
67 match name {
68 BoxType::MfhdBox => {
69 mfhd = Some(MfhdBox::read_box(reader, s)?);
70 }
71 BoxType::TrafBox => {
72 let traf = TrafBox::read_box(reader, s)?;
73 trafs.push(traf);
74 }
75 _ => {
76 skip_box(reader, s)?;
78 }
79 }
80 current = reader.stream_position()?;
81 }
82
83 if mfhd.is_none() {
84 return Err(Error::BoxNotFound(BoxType::MfhdBox));
85 }
86
87 skip_bytes_to(reader, start + size)?;
88
89 Ok(MoofBox {
90 mfhd: mfhd.unwrap(),
91 trafs,
92 })
93 }
94}
95
96impl<W: Write> WriteBox<&mut W> for MoofBox {
97 fn write_box(&self, writer: &mut W) -> Result<u64> {
98 let size = self.box_size();
99 BoxHeader::new(self.box_type(), size).write(writer)?;
100
101 self.mfhd.write_box(writer)?;
102 for traf in self.trafs.iter() {
103 traf.write_box(writer)?;
104 }
105 Ok(0)
106 }
107}