scuffle_mp4/boxes/types/
hdlr.rs

1use std::io::{
2    Read, {self},
3};
4
5use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
6use bytes::Bytes;
7
8use crate::boxes::header::{BoxHeader, FullBoxHeader};
9use crate::boxes::traits::BoxType;
10
11#[derive(Debug, Clone, PartialEq)]
12/// Handler Reference Box
13/// ISO/IEC 14496-12:2022(E) - 8.4.3
14pub struct Hdlr {
15    pub header: FullBoxHeader,
16    pub pre_defined: u32,
17    pub handler_type: HandlerType,
18    pub reserved: [u32; 3],
19    pub name: String,
20}
21
22impl Hdlr {
23    pub fn new(handler_type: HandlerType, name: String) -> Self {
24        Self {
25            header: FullBoxHeader::new(Self::NAME, 0, 0),
26            pre_defined: 0,
27            handler_type,
28            reserved: [0; 3],
29            name,
30        }
31    }
32}
33
34#[derive(Debug, Clone, PartialEq)]
35/// The handler type indicates the media type of the media in the track.
36/// The handler type is a 32-bit value composed of a 4-character code.
37pub enum HandlerType {
38    Vide,
39    Soun,
40    Hint,
41    Meta,
42    Unknown([u8; 4]),
43}
44
45impl HandlerType {
46    pub fn to_bytes(&self) -> [u8; 4] {
47        match self {
48            Self::Vide => *b"vide",
49            Self::Soun => *b"soun",
50            Self::Hint => *b"hint",
51            Self::Meta => *b"meta",
52            Self::Unknown(b) => *b,
53        }
54    }
55}
56
57impl From<[u8; 4]> for HandlerType {
58    fn from(v: [u8; 4]) -> Self {
59        match &v {
60            b"vide" => Self::Vide,
61            b"soun" => Self::Soun,
62            b"hint" => Self::Hint,
63            b"meta" => Self::Meta,
64            _ => Self::Unknown(v),
65        }
66    }
67}
68
69impl BoxType for Hdlr {
70    const NAME: [u8; 4] = *b"hdlr";
71
72    fn demux(header: BoxHeader, data: Bytes) -> io::Result<Self> {
73        let mut reader = io::Cursor::new(data);
74
75        let header = FullBoxHeader::demux(header, &mut reader)?;
76
77        let pre_defined = reader.read_u32::<BigEndian>()?;
78
79        let mut handler_type = [0; 4];
80        reader.read_exact(&mut handler_type)?;
81
82        let mut reserved = [0; 3];
83        for v in reserved.iter_mut() {
84            *v = reader.read_u32::<BigEndian>()?;
85        }
86
87        let mut name = String::new();
88        loop {
89            let c = reader.read_u8()?;
90            if c == 0 {
91                break;
92            }
93
94            name.push(c as char);
95        }
96
97        Ok(Self {
98            header,
99            pre_defined,
100            handler_type: handler_type.into(),
101            reserved,
102            name,
103        })
104    }
105
106    fn primitive_size(&self) -> u64 {
107        self.header.size()
108        + 4 // pre_defined
109        + 4 // handler_type
110        + 3 * 4 // reserved
111        + self.name.len() as u64 + 1 // name + null terminator
112    }
113
114    fn primitive_mux<T: io::Write>(&self, writer: &mut T) -> io::Result<()> {
115        self.header.mux(writer)?;
116
117        writer.write_u32::<BigEndian>(self.pre_defined)?;
118
119        writer.write_all(&self.handler_type.to_bytes())?;
120
121        for v in self.reserved.iter() {
122            writer.write_u32::<BigEndian>(*v)?;
123        }
124
125        writer.write_all(self.name.as_bytes())?;
126        writer.write_u8(0)?;
127
128        Ok(())
129    }
130
131    fn validate(&self) -> io::Result<()> {
132        if self.header.version != 0 {
133            return Err(io::Error::new(io::ErrorKind::InvalidData, "hdlr version must be 0"));
134        }
135
136        if self.header.flags != 0 {
137            return Err(io::Error::new(io::ErrorKind::InvalidData, "hdlr flags must be 0"));
138        }
139
140        if self.reserved != [0; 3] {
141            return Err(io::Error::new(io::ErrorKind::InvalidData, "hdlr reserved must be 0"));
142        }
143
144        if self.pre_defined != 0 {
145            return Err(io::Error::new(io::ErrorKind::InvalidData, "hdlr pre_defined must be 0"));
146        }
147
148        Ok(())
149    }
150}