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 => DataType::Custom(decode_utf8_string(buf)?),
78 _ => {
79 let remaining = buf.remaining();
80 let raw = buf.slice(remaining).to_vec();
81 buf.advance(remaining);
82 DataType::Unknown(namespace, raw)
83 }
84 };
85 Ok(Self { data_type })
86 }
87
88 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
89 match &self.data_type {
90 DataType::WellKnown(code) => {
91 0u32.encode(buf)?;
92 code.encode(buf)
93 }
94 DataType::Custom(name) => {
95 1u32.encode(buf)?;
96 buf.append_slice(name.as_bytes());
97 Ok(())
98 }
99 DataType::Unknown(namespace, raw) => {
100 namespace.encode(buf)?;
101 buf.append_slice(raw);
102 Ok(())
103 }
104 }
105 }
106}
107
108#[derive(Debug, Clone, PartialEq, Eq)]
116#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
117pub struct Loca {
118 pub locale: String,
120}
121
122impl Atom for Loca {
123 const KIND: FourCC = FourCC::new(b"loca");
124
125 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
126 Ok(Self {
127 locale: String::decode(buf)?,
128 })
129 }
130
131 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
132 self.locale.as_str().encode(buf)
133 }
134}
135
136#[derive(Debug, Clone, PartialEq, Eq)]
145#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
146pub struct Setu {
147 pub data: Vec<u8>,
148}
149
150impl Atom for Setu {
151 const KIND: FourCC = FourCC::new(b"setu");
152
153 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
154 Ok(Self {
155 data: Vec::decode(buf)?,
156 })
157 }
158
159 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
160 self.data.encode(buf)
161 }
162}
163
164#[derive(Debug, Clone, PartialEq, Eq)]
175#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
176pub struct MebxKey {
177 pub local_key_id: FourCC,
178 pub keyd: Keyd,
179 pub dtyp: Option<Dtyp>,
180 pub loca: Option<Loca>,
181 pub setu: Option<Setu>,
182}
183
184impl MebxKey {
185 fn decode_maybe<B: Buf>(buf: &mut B) -> Result<Option<Self>> {
186 let Some(header) = Header::decode_maybe(buf)? else {
187 return Ok(None);
188 };
189 if u32::from(header.kind) == 0xFFFF_FFFF {
190 return Err(Error::Reserved);
192 }
193 let size = header.size.unwrap_or(buf.remaining());
194 if size > buf.remaining() {
195 return Ok(None);
196 }
197
198 let mut body = buf.slice(size);
199
200 let mut keyd = None;
201 let mut dtyp = None;
202 let mut loca = None;
203 let mut setu = None;
204 while let Some(atom) = Any::decode_maybe(&mut body)? {
205 match atom {
206 Any::Keyd(atom) => keyd = atom.into(),
207 Any::Dtyp(atom) => dtyp = atom.into(),
208 Any::Loca(atom) => loca = atom.into(),
209 Any::Setu(atom) => setu = atom.into(),
210 unknown => crate::decode_unknown(&unknown, header.kind)?,
211 }
212 }
213 buf.advance(size);
214
215 Ok(Some(Self {
216 local_key_id: header.kind,
217 keyd: keyd.ok_or(Error::MissingBox(Keyd::KIND))?,
218 dtyp,
219 loca,
220 setu,
221 }))
222 }
223
224 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
225 buf.encode_atom(self.local_key_id, |buf| {
226 self.keyd.encode(buf)?;
227 self.dtyp.encode(buf)?;
228 self.loca.encode(buf)?;
229 self.setu.encode(buf)
230 })
231 }
232}
233
234const KEYS_KIND: FourCC = FourCC::new(b"keys");
241
242fn decode_keys<B: Buf>(header: &Header, buf: &mut B) -> Result<Vec<MebxKey>> {
243 let size = header.size.unwrap_or(buf.remaining());
244 let mut body = buf.slice(size);
245
246 let mut keys = Vec::new();
247 while let Some(key) = MebxKey::decode_maybe(&mut body)? {
248 keys.push(key);
249 }
250 buf.advance(size);
251 Ok(keys)
252}
253
254fn encode_keys<B: BufMut>(keys: &[MebxKey], buf: &mut B) -> Result<()> {
255 buf.encode_atom(KEYS_KIND, |buf| {
256 for key in keys {
257 key.encode(buf)?;
258 }
259 Ok(())
260 })
261}
262
263#[derive(Debug, Clone, PartialEq, Eq)]
274#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
275pub struct Mebx {
276 pub metadata: MetaData,
277 pub keys: Vec<MebxKey>,
278 pub btrt: Option<Btrt>,
279}
280
281impl Atom for Mebx {
282 const KIND: FourCC = FourCC::new(b"mebx");
283
284 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
285 let metadata = MetaData::decode(buf)?;
286
287 let mut keys = None;
288 let mut btrt = None;
289 while let Some(header) = Header::decode_maybe(buf)? {
290 let size = header.size.unwrap_or(buf.remaining());
291 if size > buf.remaining() {
292 break;
293 }
294 if header.kind == KEYS_KIND {
295 keys = Some(decode_keys(&header, buf)?);
296 continue;
297 }
298 match Any::decode_atom(&header, buf)? {
299 Any::Btrt(atom) => btrt = Some(atom),
300 unknown => Self::decode_unknown(&unknown)?,
301 }
302 }
303 skip_trailing_padding(buf);
304
305 Ok(Self {
306 metadata,
307 keys: keys.ok_or(Error::MissingBox(KEYS_KIND))?,
308 btrt,
309 })
310 }
311
312 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
313 self.metadata.encode(buf)?;
314 encode_keys(&self.keys, buf)?;
315 self.btrt.encode(buf)?;
316 Ok(())
317 }
318}
319
320#[cfg(test)]
321mod tests {
322 use super::*;
323
324 fn sample_keys() -> Vec<MebxKey> {
325 vec![
326 MebxKey {
327 local_key_id: FourCC::new(b"\0\0\0\x01"),
328 keyd: Keyd {
329 key_namespace: FourCC::new(b"mdta"),
330 key_value: b"com.apple.quicktime.location.ISO6709".to_vec(),
331 },
332 dtyp: Some(Dtyp {
333 data_type: DataType::WellKnown(1), }),
335 loca: None,
336 setu: None,
337 },
338 MebxKey {
339 local_key_id: FourCC::new(b"\0\0\0\x02"),
340 keyd: Keyd {
341 key_namespace: FourCC::new(b"mdta"),
342 key_value: b"com.example.custom-value".to_vec(),
343 },
344 dtyp: Some(Dtyp {
345 data_type: DataType::Custom("com.example.custom-type".into()),
346 }),
347 loca: Some(Loca {
348 locale: "en-US".into(),
349 }),
350 setu: Some(Setu {
351 data: vec![1, 2, 3, 4],
352 }),
353 },
354 ]
355 }
356
357 #[test]
358 fn test_keys_roundtrip() {
359 let keys = sample_keys();
360
361 let mut buf = Vec::new();
362 encode_keys(&keys, &mut buf).unwrap();
363
364 let mut slice = buf.as_slice();
365 let header = Header::decode(&mut slice).unwrap();
366 let decoded = decode_keys(&header, &mut slice).expect("failed to decode keys");
367 assert_eq!(decoded, keys);
368 }
369
370 #[test]
371 fn test_mebx_roundtrip() {
372 let mebx = Mebx {
373 metadata: MetaData {
374 data_reference_index: 1,
375 },
376 keys: sample_keys(),
377 btrt: Some(Btrt {
378 buffer_size_db: 1,
379 max_bitrate: 2000,
380 avg_bitrate: 400,
381 }),
382 };
383
384 let mut buf = Vec::new();
385 mebx.encode(&mut buf).unwrap();
386
387 let decoded = Mebx::decode(&mut buf.as_slice()).expect("failed to decode mebx");
388 assert_eq!(decoded, mebx);
389 }
390
391 #[test]
392 fn test_mebx_roundtrip_no_btrt() {
393 let mebx = Mebx {
394 metadata: MetaData {
395 data_reference_index: 1,
396 },
397 keys: vec![],
398 btrt: None,
399 };
400
401 let mut buf = Vec::new();
402 mebx.encode(&mut buf).unwrap();
403
404 let decoded = Mebx::decode(&mut buf.as_slice()).expect("failed to decode mebx");
405 assert_eq!(decoded, mebx);
406 }
407
408 #[test]
409 fn test_mebx_missing_keys() {
410 let mut buf = Vec::new();
411 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();
416 assert!(matches!(err, Error::MissingBox(kind) if kind == KEYS_KIND));
417 }
418
419 #[test]
420 fn test_mebx_key_rejects_reserved_local_key_id() {
421 let mut buf = Vec::new();
424 8u32.encode(&mut buf).unwrap(); 0xFFFF_FFFFu32.encode(&mut buf).unwrap(); let err = MebxKey::decode_maybe(&mut buf.as_slice()).unwrap_err();
428 assert!(matches!(err, Error::Reserved));
429 }
430
431 #[test]
432 fn test_keyd_non_utf8_key_value_roundtrip() {
433 let keyd = Keyd {
436 key_namespace: FourCC::new(b"uiso"),
437 key_value: b"cprt".to_vec(),
438 };
439
440 let mut buf = Vec::new();
441 keyd.encode(&mut buf).unwrap();
442
443 let decoded = Keyd::decode(&mut buf.as_slice()).expect("failed to decode keyd");
444 assert_eq!(decoded, keyd);
445 }
446
447 #[test]
448 fn test_loca_roundtrip() {
449 let loca = Loca {
450 locale: "fr-FR".into(),
451 };
452
453 let mut buf = Vec::new();
454 loca.encode(&mut buf).unwrap();
455
456 let decoded = Loca::decode(&mut buf.as_slice()).expect("failed to decode loca");
457 assert_eq!(decoded, loca);
458 }
459
460 #[test]
461 fn test_dtyp_well_known_roundtrip() {
462 let dtyp = Dtyp {
463 data_type: DataType::WellKnown(23), };
465
466 let mut buf = Vec::new();
467 dtyp.encode(&mut buf).unwrap();
468
469 let decoded = Dtyp::decode(&mut buf.as_slice()).expect("failed to decode dtyp");
470 assert_eq!(decoded, dtyp);
471 }
472
473 #[test]
474 fn test_dtyp_custom_roundtrip() {
475 let dtyp = Dtyp {
478 data_type: DataType::Custom("com.example.custom-type".into()),
479 };
480
481 let mut buf = Vec::new();
482 dtyp.encode(&mut buf).unwrap();
483
484 let decoded = Dtyp::decode(&mut buf.as_slice()).expect("failed to decode dtyp");
485 assert_eq!(decoded, dtyp);
486 }
487
488 #[test]
489 fn test_dtyp_unknown_namespace_preserves_bytes() {
490 let dtyp = Dtyp {
494 data_type: DataType::Unknown(99, vec![1, 2, 3, 4]),
495 };
496
497 let mut buf = Vec::new();
498 dtyp.encode(&mut buf).unwrap();
499
500 let decoded = Dtyp::decode(&mut buf.as_slice()).expect("failed to decode dtyp");
501 assert_eq!(decoded, dtyp);
502 }
503}