mp4_atom/moov/trak/mdia/minf/stbl/stsd/
mebx.rs1use crate::*;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct Keyd {
12 pub key_namespace: FourCC,
13 pub key_value: Vec<u8>,
14}
15
16impl Atom for Keyd {
17 const KIND: FourCC = FourCC::new(b"keyd");
18
19 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
20 let key_namespace = FourCC::decode(buf)?;
21 let key_value = Vec::decode(buf)?;
22 Ok(Self {
23 key_namespace,
24 key_value,
25 })
26 }
27
28 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
29 self.key_namespace.encode(buf)?;
30 self.key_value.encode(buf)
31 }
32}
33
34#[derive(Debug, Clone, PartialEq, Eq)]
36#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
37pub enum DataType {
38 WellKnown(u32),
42 Custom(String),
46 Unknown(u32, Vec<u8>),
50}
51
52#[derive(Debug, Clone, PartialEq, Eq)]
63#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
64pub struct Dtyp {
65 pub data_type: DataType,
66}
67
68impl Atom for Dtyp {
69 const KIND: FourCC = FourCC::new(b"dtyp");
70
71 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
72 let namespace = u32::decode(buf)?;
73 let data_type = match namespace {
74 0 => DataType::WellKnown(u32::decode(buf)?),
75 1 => {
78 let remaining = buf.remaining();
79 let bytes = buf.slice(remaining).to_vec();
80 buf.advance(remaining);
81 DataType::Custom(
82 String::from_utf8(bytes)
83 .map_err(|err| Error::InvalidString(err.to_string()))?,
84 )
85 }
86 _ => {
87 let remaining = buf.remaining();
88 let raw = buf.slice(remaining).to_vec();
89 buf.advance(remaining);
90 DataType::Unknown(namespace, raw)
91 }
92 };
93 Ok(Self { data_type })
94 }
95
96 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
97 match &self.data_type {
98 DataType::WellKnown(code) => {
99 0u32.encode(buf)?;
100 code.encode(buf)
101 }
102 DataType::Custom(name) => {
103 1u32.encode(buf)?;
104 buf.append_slice(name.as_bytes());
105 Ok(())
106 }
107 DataType::Unknown(namespace, raw) => {
108 namespace.encode(buf)?;
109 buf.append_slice(raw);
110 Ok(())
111 }
112 }
113 }
114}
115
116#[derive(Debug, Clone, PartialEq, Eq)]
124#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
125pub struct Loca {
126 pub locale: String,
128}
129
130impl Atom for Loca {
131 const KIND: FourCC = FourCC::new(b"loca");
132
133 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
134 Ok(Self {
135 locale: String::decode(buf)?,
136 })
137 }
138
139 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
140 self.locale.as_str().encode(buf)
141 }
142}
143
144#[derive(Debug, Clone, PartialEq, Eq)]
153#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
154pub struct Setu {
155 pub data: Vec<u8>,
156}
157
158impl Atom for Setu {
159 const KIND: FourCC = FourCC::new(b"setu");
160
161 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
162 Ok(Self {
163 data: Vec::decode(buf)?,
164 })
165 }
166
167 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
168 self.data.encode(buf)
169 }
170}
171
172#[derive(Debug, Clone, PartialEq, Eq)]
183#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
184pub struct MebxKey {
185 pub local_key_id: FourCC,
186 pub keyd: Keyd,
187 pub dtyp: Option<Dtyp>,
188 pub loca: Option<Loca>,
189 pub setu: Option<Setu>,
190}
191
192impl MebxKey {
193 fn decode_maybe<B: Buf>(buf: &mut B) -> Result<Option<Self>> {
194 let Some(header) = Header::decode_maybe(buf)? else {
195 return Ok(None);
196 };
197 if u32::from(header.kind) == 0xFFFF_FFFF {
198 return Err(Error::Reserved);
200 }
201 let size = header.size.unwrap_or(buf.remaining());
202 if size > buf.remaining() {
203 return Ok(None);
204 }
205
206 let mut body = buf.slice(size);
207
208 let mut keyd = None;
209 let mut dtyp = None;
210 let mut loca = None;
211 let mut setu = None;
212 while let Some(atom) = Any::decode_maybe(&mut body)? {
213 match atom {
214 Any::Keyd(atom) => keyd = atom.into(),
215 Any::Dtyp(atom) => dtyp = atom.into(),
216 Any::Loca(atom) => loca = atom.into(),
217 Any::Setu(atom) => setu = atom.into(),
218 unknown => crate::decode_unknown(&unknown, header.kind)?,
219 }
220 }
221 buf.advance(size);
222
223 Ok(Some(Self {
224 local_key_id: header.kind,
225 keyd: keyd.ok_or(Error::MissingBox(Keyd::KIND))?,
226 dtyp,
227 loca,
228 setu,
229 }))
230 }
231
232 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
233 buf.encode_atom(self.local_key_id, |buf| {
234 self.keyd.encode(buf)?;
235 self.dtyp.encode(buf)?;
236 self.loca.encode(buf)?;
237 self.setu.encode(buf)
238 })
239 }
240}
241
242const KEYS_KIND: FourCC = FourCC::new(b"keys");
249
250fn decode_keys<B: Buf>(header: &Header, buf: &mut B) -> Result<Vec<MebxKey>> {
251 let size = header.size.unwrap_or(buf.remaining());
252 let mut body = buf.slice(size);
253
254 let mut keys = Vec::new();
255 while let Some(key) = MebxKey::decode_maybe(&mut body)? {
256 keys.push(key);
257 }
258 buf.advance(size);
259 Ok(keys)
260}
261
262fn encode_keys<B: BufMut>(keys: &[MebxKey], buf: &mut B) -> Result<()> {
263 buf.encode_atom(KEYS_KIND, |buf| {
264 for key in keys {
265 key.encode(buf)?;
266 }
267 Ok(())
268 })
269}
270
271#[derive(Debug, Clone, PartialEq, Eq)]
282#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
283pub struct Mebx {
284 pub metadata: MetaData,
285 pub keys: Vec<MebxKey>,
286 pub btrt: Option<Btrt>,
287}
288
289impl Atom for Mebx {
290 const KIND: FourCC = FourCC::new(b"mebx");
291
292 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
293 let metadata = MetaData::decode(buf)?;
294
295 let mut keys = None;
296 let mut btrt = None;
297 while let Some(header) = Header::decode_maybe(buf)? {
298 let size = header.size.unwrap_or(buf.remaining());
299 if size > buf.remaining() {
300 break;
301 }
302 if header.kind == KEYS_KIND {
303 keys = Some(decode_keys(&header, buf)?);
304 continue;
305 }
306 match Any::decode_atom(&header, buf)? {
307 Any::Btrt(atom) => btrt = Some(atom),
308 unknown => Self::decode_unknown(&unknown)?,
309 }
310 }
311 skip_trailing_padding(buf);
312
313 Ok(Self {
314 metadata,
315 keys: keys.ok_or(Error::MissingBox(KEYS_KIND))?,
316 btrt,
317 })
318 }
319
320 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
321 self.metadata.encode(buf)?;
322 encode_keys(&self.keys, buf)?;
323 self.btrt.encode(buf)?;
324 Ok(())
325 }
326}
327
328#[cfg(test)]
329mod tests {
330 use super::*;
331
332 fn sample_keys() -> Vec<MebxKey> {
333 vec![
334 MebxKey {
335 local_key_id: FourCC::new(b"\0\0\0\x01"),
336 keyd: Keyd {
337 key_namespace: FourCC::new(b"mdta"),
338 key_value: b"com.apple.quicktime.location.ISO6709".to_vec(),
339 },
340 dtyp: Some(Dtyp {
341 data_type: DataType::WellKnown(1), }),
343 loca: None,
344 setu: None,
345 },
346 MebxKey {
347 local_key_id: FourCC::new(b"\0\0\0\x02"),
348 keyd: Keyd {
349 key_namespace: FourCC::new(b"mdta"),
350 key_value: b"com.example.custom-value".to_vec(),
351 },
352 dtyp: Some(Dtyp {
353 data_type: DataType::Custom("com.example.custom-type".into()),
354 }),
355 loca: Some(Loca {
356 locale: "en-US".into(),
357 }),
358 setu: Some(Setu {
359 data: vec![1, 2, 3, 4],
360 }),
361 },
362 ]
363 }
364
365 #[test]
366 fn test_keys_roundtrip() {
367 let keys = sample_keys();
368
369 let mut buf = Vec::new();
370 encode_keys(&keys, &mut buf).unwrap();
371
372 let mut slice = buf.as_slice();
373 let header = Header::decode(&mut slice).unwrap();
374 let decoded = decode_keys(&header, &mut slice).expect("failed to decode keys");
375 assert_eq!(decoded, keys);
376 }
377
378 #[test]
379 fn test_mebx_roundtrip() {
380 let mebx = Mebx {
381 metadata: MetaData {
382 data_reference_index: 1,
383 },
384 keys: sample_keys(),
385 btrt: Some(Btrt {
386 buffer_size_db: 1,
387 max_bitrate: 2000,
388 avg_bitrate: 400,
389 }),
390 };
391
392 let mut buf = Vec::new();
393 mebx.encode(&mut buf).unwrap();
394
395 let decoded = Mebx::decode(&mut buf.as_slice()).expect("failed to decode mebx");
396 assert_eq!(decoded, mebx);
397 }
398
399 #[test]
400 fn test_mebx_roundtrip_no_btrt() {
401 let mebx = Mebx {
402 metadata: MetaData {
403 data_reference_index: 1,
404 },
405 keys: vec![],
406 btrt: None,
407 };
408
409 let mut buf = Vec::new();
410 mebx.encode(&mut buf).unwrap();
411
412 let decoded = Mebx::decode(&mut buf.as_slice()).expect("failed to decode mebx");
413 assert_eq!(decoded, mebx);
414 }
415
416 #[test]
417 fn test_mebx_missing_keys() {
418 let mut buf = Vec::new();
419 0u32.encode(&mut buf).unwrap(); 0u16.encode(&mut buf).unwrap(); 1u16.encode(&mut buf).unwrap(); let err = Mebx::decode_body(&mut buf.as_slice()).unwrap_err();
424 assert!(matches!(err, Error::MissingBox(kind) if kind == KEYS_KIND));
425 }
426
427 #[test]
428 fn test_mebx_key_rejects_reserved_local_key_id() {
429 let mut buf = Vec::new();
432 8u32.encode(&mut buf).unwrap(); 0xFFFF_FFFFu32.encode(&mut buf).unwrap(); let err = MebxKey::decode_maybe(&mut buf.as_slice()).unwrap_err();
436 assert!(matches!(err, Error::Reserved));
437 }
438
439 #[test]
440 fn test_keyd_non_utf8_key_value_roundtrip() {
441 let keyd = Keyd {
444 key_namespace: FourCC::new(b"uiso"),
445 key_value: b"cprt".to_vec(),
446 };
447
448 let mut buf = Vec::new();
449 keyd.encode(&mut buf).unwrap();
450
451 let decoded = Keyd::decode(&mut buf.as_slice()).expect("failed to decode keyd");
452 assert_eq!(decoded, keyd);
453 }
454
455 #[test]
456 fn test_loca_roundtrip() {
457 let loca = Loca {
458 locale: "fr-FR".into(),
459 };
460
461 let mut buf = Vec::new();
462 loca.encode(&mut buf).unwrap();
463
464 let decoded = Loca::decode(&mut buf.as_slice()).expect("failed to decode loca");
465 assert_eq!(decoded, loca);
466 }
467
468 #[test]
469 fn test_dtyp_well_known_roundtrip() {
470 let dtyp = Dtyp {
471 data_type: DataType::WellKnown(23), };
473
474 let mut buf = Vec::new();
475 dtyp.encode(&mut buf).unwrap();
476
477 let decoded = Dtyp::decode(&mut buf.as_slice()).expect("failed to decode dtyp");
478 assert_eq!(decoded, dtyp);
479 }
480
481 #[test]
482 fn test_dtyp_custom_roundtrip() {
483 let dtyp = Dtyp {
486 data_type: DataType::Custom("com.example.custom-type".into()),
487 };
488
489 let mut buf = Vec::new();
490 dtyp.encode(&mut buf).unwrap();
491
492 let decoded = Dtyp::decode(&mut buf.as_slice()).expect("failed to decode dtyp");
493 assert_eq!(decoded, dtyp);
494 }
495
496 #[test]
497 fn test_dtyp_unknown_namespace_preserves_bytes() {
498 let dtyp = Dtyp {
502 data_type: DataType::Unknown(99, vec![1, 2, 3, 4]),
503 };
504
505 let mut buf = Vec::new();
506 dtyp.encode(&mut buf).unwrap();
507
508 let decoded = Dtyp::decode(&mut buf.as_slice()).expect("failed to decode dtyp");
509 assert_eq!(decoded, dtyp);
510 }
511}