scuffle_mp4/boxes/
header.rs1use 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 reader.extract_remaining()
47 } else {
48 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}