Skip to main content

iso_bmff/isobmff/
header.rs

1//! Box header parse / write.
2
3#![forbid(unsafe_code)]
4
5use super::buf::ByteSource;
6use super::fourcc::FourCc;
7
8/// Parsed ISOBMFF box header.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct Header {
11    /// Box type.
12    pub typ: FourCc,
13    /// Total size including header.
14    pub size: usize,
15    /// Header length (8 or 16).
16    pub header_len: usize,
17}
18
19/// Parse a box header at the start of `data`.
20#[must_use]
21pub fn parse_header(data: &[u8]) -> Option<Header> {
22    let mut src = ByteSource::new(data);
23    let size32 = src.u32()? as usize;
24    let typ = FourCc([src.u8()?, src.u8()?, src.u8()?, src.u8()?]);
25    if size32 == 1 {
26        let size64 = src.u64()? as usize;
27        Some(Header {
28            typ,
29            size: size64,
30            header_len: 16,
31        })
32    } else if size32 == 0 {
33        None
34    } else {
35        Some(Header {
36            typ,
37            size: size32,
38            header_len: 8,
39        })
40    }
41}
42
43/// Write a box: placeholder size, `body`, then patch size.
44pub fn write_box(buf: &mut Vec<u8>, typ: FourCc, body: impl FnOnce(&mut Vec<u8>)) {
45    let start = buf.len();
46    buf.extend_from_slice(&0u32.to_be_bytes());
47    buf.extend_from_slice(&typ.0);
48    body(buf);
49    let size = u32::try_from(buf.len().saturating_sub(start)).unwrap_or(u32::MAX);
50    if let Some(slot) = buf.get_mut(start..start + 4) {
51        slot.copy_from_slice(&size.to_be_bytes());
52    }
53}