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 let start = buf.len();
234 0u32.encode(buf)?; self.local_key_id.encode(buf)?;
236 self.keyd.encode(buf)?;
237 self.dtyp.encode(buf)?;
238 self.loca.encode(buf)?;
239 self.setu.encode(buf)?;
240
241 let size: u32 = (buf.len() - start)
242 .try_into()
243 .map_err(|_| Error::TooLarge(self.local_key_id))?;
244 buf.set_slice(start, &size.to_be_bytes());
245 Ok(())
246 }
247}
248
249const KEYS_KIND: FourCC = FourCC::new(b"keys");
256
257fn decode_keys<B: Buf>(header: &Header, buf: &mut B) -> Result<Vec<MebxKey>> {
258 let size = header.size.unwrap_or(buf.remaining());
259 let mut body = buf.slice(size);
260
261 let mut keys = Vec::new();
262 while let Some(key) = MebxKey::decode_maybe(&mut body)? {
263 keys.push(key);
264 }
265 buf.advance(size);
266 Ok(keys)
267}
268
269fn encode_keys<B: BufMut>(keys: &[MebxKey], buf: &mut B) -> Result<()> {
270 let start = buf.len();
271 0u32.encode(buf)?; KEYS_KIND.encode(buf)?;
273 for key in keys {
274 key.encode(buf)?;
275 }
276
277 let size: u32 = (buf.len() - start)
278 .try_into()
279 .map_err(|_| Error::TooLarge(KEYS_KIND))?;
280 buf.set_slice(start, &size.to_be_bytes());
281 Ok(())
282}
283
284#[derive(Debug, Clone, PartialEq, Eq)]
295#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
296pub struct Mebx {
297 pub metadata: MetaData,
298 pub keys: Vec<MebxKey>,
299 pub btrt: Option<Btrt>,
300}
301
302impl Atom for Mebx {
303 const KIND: FourCC = FourCC::new(b"mebx");
304
305 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
306 let metadata = MetaData::decode(buf)?;
307
308 let mut keys = None;
309 let mut btrt = None;
310 while let Some(header) = Header::decode_maybe(buf)? {
311 let size = header.size.unwrap_or(buf.remaining());
312 if size > buf.remaining() {
313 break;
314 }
315 if header.kind == KEYS_KIND {
316 keys = Some(decode_keys(&header, buf)?);
317 continue;
318 }
319 match Any::decode_atom(&header, buf)? {
320 Any::Btrt(atom) => btrt = Some(atom),
321 unknown => Self::decode_unknown(&unknown)?,
322 }
323 }
324 skip_trailing_padding(buf);
325
326 Ok(Self {
327 metadata,
328 keys: keys.ok_or(Error::MissingBox(KEYS_KIND))?,
329 btrt,
330 })
331 }
332
333 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
334 self.metadata.encode(buf)?;
335 encode_keys(&self.keys, buf)?;
336 self.btrt.encode(buf)?;
337 Ok(())
338 }
339}
340
341#[cfg(test)]
342mod tests {
343 use super::*;
344
345 fn sample_keys() -> Vec<MebxKey> {
346 vec![
347 MebxKey {
348 local_key_id: FourCC::new(b"\0\0\0\x01"),
349 keyd: Keyd {
350 key_namespace: FourCC::new(b"mdta"),
351 key_value: b"com.apple.quicktime.location.ISO6709".to_vec(),
352 },
353 dtyp: Some(Dtyp {
354 data_type: DataType::WellKnown(1), }),
356 loca: None,
357 setu: None,
358 },
359 MebxKey {
360 local_key_id: FourCC::new(b"\0\0\0\x02"),
361 keyd: Keyd {
362 key_namespace: FourCC::new(b"mdta"),
363 key_value: b"com.example.custom-value".to_vec(),
364 },
365 dtyp: Some(Dtyp {
366 data_type: DataType::Custom("com.example.custom-type".into()),
367 }),
368 loca: Some(Loca {
369 locale: "en-US".into(),
370 }),
371 setu: Some(Setu {
372 data: vec![1, 2, 3, 4],
373 }),
374 },
375 ]
376 }
377
378 #[test]
379 fn test_keys_roundtrip() {
380 let keys = sample_keys();
381
382 let mut buf = Vec::new();
383 encode_keys(&keys, &mut buf).unwrap();
384
385 let mut slice = buf.as_slice();
386 let header = Header::decode(&mut slice).unwrap();
387 let decoded = decode_keys(&header, &mut slice).expect("failed to decode keys");
388 assert_eq!(decoded, keys);
389 }
390
391 #[test]
392 fn test_mebx_roundtrip() {
393 let mebx = Mebx {
394 metadata: MetaData {
395 data_reference_index: 1,
396 },
397 keys: sample_keys(),
398 btrt: Some(Btrt {
399 buffer_size_db: 1,
400 max_bitrate: 2000,
401 avg_bitrate: 400,
402 }),
403 };
404
405 let mut buf = Vec::new();
406 mebx.encode(&mut buf).unwrap();
407
408 let decoded = Mebx::decode(&mut buf.as_slice()).expect("failed to decode mebx");
409 assert_eq!(decoded, mebx);
410 }
411
412 #[test]
413 fn test_mebx_roundtrip_no_btrt() {
414 let mebx = Mebx {
415 metadata: MetaData {
416 data_reference_index: 1,
417 },
418 keys: vec![],
419 btrt: None,
420 };
421
422 let mut buf = Vec::new();
423 mebx.encode(&mut buf).unwrap();
424
425 let decoded = Mebx::decode(&mut buf.as_slice()).expect("failed to decode mebx");
426 assert_eq!(decoded, mebx);
427 }
428
429 #[test]
430 fn test_mebx_missing_keys() {
431 let mut buf = Vec::new();
432 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();
437 assert!(matches!(err, Error::MissingBox(kind) if kind == KEYS_KIND));
438 }
439
440 #[test]
441 fn test_mebx_key_rejects_reserved_local_key_id() {
442 let mut buf = Vec::new();
445 8u32.encode(&mut buf).unwrap(); 0xFFFF_FFFFu32.encode(&mut buf).unwrap(); let err = MebxKey::decode_maybe(&mut buf.as_slice()).unwrap_err();
449 assert!(matches!(err, Error::Reserved));
450 }
451
452 #[test]
453 fn test_keyd_non_utf8_key_value_roundtrip() {
454 let keyd = Keyd {
457 key_namespace: FourCC::new(b"uiso"),
458 key_value: b"cprt".to_vec(),
459 };
460
461 let mut buf = Vec::new();
462 keyd.encode(&mut buf).unwrap();
463
464 let decoded = Keyd::decode(&mut buf.as_slice()).expect("failed to decode keyd");
465 assert_eq!(decoded, keyd);
466 }
467
468 #[test]
469 fn test_loca_roundtrip() {
470 let loca = Loca {
471 locale: "fr-FR".into(),
472 };
473
474 let mut buf = Vec::new();
475 loca.encode(&mut buf).unwrap();
476
477 let decoded = Loca::decode(&mut buf.as_slice()).expect("failed to decode loca");
478 assert_eq!(decoded, loca);
479 }
480
481 #[test]
482 fn test_dtyp_well_known_roundtrip() {
483 let dtyp = Dtyp {
484 data_type: DataType::WellKnown(23), };
486
487 let mut buf = Vec::new();
488 dtyp.encode(&mut buf).unwrap();
489
490 let decoded = Dtyp::decode(&mut buf.as_slice()).expect("failed to decode dtyp");
491 assert_eq!(decoded, dtyp);
492 }
493
494 #[test]
495 fn test_dtyp_custom_roundtrip() {
496 let dtyp = Dtyp {
499 data_type: DataType::Custom("com.example.custom-type".into()),
500 };
501
502 let mut buf = Vec::new();
503 dtyp.encode(&mut buf).unwrap();
504
505 let decoded = Dtyp::decode(&mut buf.as_slice()).expect("failed to decode dtyp");
506 assert_eq!(decoded, dtyp);
507 }
508
509 #[test]
510 fn test_dtyp_unknown_namespace_preserves_bytes() {
511 let dtyp = Dtyp {
515 data_type: DataType::Unknown(99, vec![1, 2, 3, 4]),
516 };
517
518 let mut buf = Vec::new();
519 dtyp.encode(&mut buf).unwrap();
520
521 let decoded = Dtyp::decode(&mut buf.as_slice()).expect("failed to decode dtyp");
522 assert_eq!(decoded, dtyp);
523 }
524}