scuffle_mp4/boxes/types/
hdlr.rs1use 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)]
12pub 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)]
35pub 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 + 4 + 3 * 4 + self.name.len() as u64 + 1 }
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}