scuffle_mp4/boxes/types/
mehd.rs1use std::io;
2
3use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
4use bytes::Bytes;
5
6use crate::boxes::header::{BoxHeader, FullBoxHeader};
7use crate::boxes::traits::BoxType;
8
9#[derive(Debug, Clone, PartialEq)]
10pub struct Mehd {
13 pub header: FullBoxHeader,
14 pub fragment_duration: u64,
15}
16
17impl BoxType for Mehd {
18 const NAME: [u8; 4] = *b"mehd";
19
20 fn demux(header: BoxHeader, data: Bytes) -> io::Result<Self> {
21 let mut reader = io::Cursor::new(data);
22
23 let header = FullBoxHeader::demux(header, &mut reader)?;
24
25 let fragment_duration = if header.version == 1 {
26 reader.read_u64::<BigEndian>()?
27 } else {
28 reader.read_u32::<BigEndian>()? as u64
29 };
30
31 Ok(Self {
32 header,
33 fragment_duration,
34 })
35 }
36
37 fn primitive_size(&self) -> u64 {
38 self.header.size()
39 + if self.header.version == 1 {
40 8 } else {
42 4 }
44 }
45
46 fn primitive_mux<T: io::Write>(&self, writer: &mut T) -> io::Result<()> {
47 self.header.mux(writer)?;
48
49 if self.header.version == 1 {
50 writer.write_u64::<BigEndian>(self.fragment_duration)?;
51 } else {
52 writer.write_u32::<BigEndian>(self.fragment_duration as u32)?;
53 }
54
55 Ok(())
56 }
57
58 fn validate(&self) -> io::Result<()> {
59 if self.header.version > 1 {
60 return Err(io::Error::new(io::ErrorKind::InvalidData, "mehd version must be 0 or 1"));
61 }
62
63 if self.header.version == 0 && self.fragment_duration > u32::MAX as u64 {
64 return Err(io::Error::new(
65 io::ErrorKind::InvalidData,
66 "mehd fragment_duration must be less than 2^32",
67 ));
68 }
69
70 Ok(())
71 }
72}