scuffle_mp4/boxes/
header.rs

1use std::fmt::{Debug, Formatter};
2use std::io::{
3    Read, {self},
4};
5
6use byteorder::{ReadBytesExt, WriteBytesExt};
7use bytes::Bytes;
8use scuffle_bytes_util::BytesCursorExt;
9
10#[derive(Clone, PartialEq)]
11pub struct BoxHeader {
12    pub box_type: [u8; 4],
13}
14
15impl BoxHeader {
16    pub fn new(box_type: [u8; 4]) -> Self {
17        Self { box_type }
18    }
19}
20
21impl Debug for BoxHeader {
22    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
23        f.debug_struct("BoxHeader")
24            .field("box_type", &Bytes::from(self.box_type[..].to_vec()))
25            .finish()
26    }
27}
28
29impl BoxHeader {
30    pub fn demux(reader: &mut io::Cursor<Bytes>) -> Result<(Self, Bytes), io::Error> {
31        let size = reader.read_u32::<byteorder::BigEndian>()? as u64;
32
33        let mut box_type: [u8; 4] = [0; 4];
34        reader.read_exact(&mut box_type)?;
35
36        let offset = if size == 1 { 16 } else { 8 };
37
38        let size = if size == 1 {
39            reader.read_u64::<byteorder::BigEndian>()?
40        } else {
41            size
42        };
43
44        let data = if size == 0 {
45            // As per spec this means the box extends to the end of the file.
46            reader.extract_remaining()
47        } else {
48            // We already read 8 bytes, so we need to subtract that from the size.
49            reader.extract_bytes((size - offset) as usize)?
50        };
51
52        Ok((Self { box_type }, data))
53    }
54}
55
56#[derive(Debug, Clone, PartialEq)]
57pub struct FullBoxHeader {
58    pub header: BoxHeader,
59    pub version: u8,
60    pub flags: u32,
61}
62
63impl FullBoxHeader {
64    pub fn new(box_type: [u8; 4], version: u8, flags: u32) -> Self {
65        Self {
66            header: BoxHeader::new(box_type),
67            version,
68            flags,
69        }
70    }
71
72    pub fn demux(header: BoxHeader, reader: &mut io::Cursor<Bytes>) -> io::Result<Self> {
73        let version = reader.read_u8()?;
74        let flags = reader.read_u24::<byteorder::BigEndian>()?;
75        Ok(Self { header, version, flags })
76    }
77
78    pub fn mux<T: io::Write>(&self, writer: &mut T) -> io::Result<()> {
79        writer.write_u8(self.version)?;
80        writer.write_u24::<byteorder::BigEndian>(self.flags)?;
81        Ok(())
82    }
83
84    pub const fn size(&self) -> u64 {
85        1 + 3
86    }
87}