mp4_atom/meta/
iref.rs

1use crate::*;
2
3// ItemReferenceBox. ISO/IEC 14496-12:2022 Section 8.11.12
4// This is used to work out how the items related to each other
5
6ext! {
7    name: Iref,
8    versions: [0, 1],
9    flags: {}
10}
11
12#[derive(Debug, Clone, PartialEq, Eq)]
13#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
14pub struct Reference {
15    pub reference_type: FourCC,
16    pub from_item_id: u32,
17    pub to_item_ids: Vec<u32>,
18}
19
20#[derive(Debug, Clone, PartialEq, Eq)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
22pub struct Iref {
23    pub references: Vec<Reference>,
24}
25
26impl AtomExt for Iref {
27    type Ext = IrefExt;
28
29    const KIND_EXT: FourCC = FourCC::new(b"iref");
30
31    fn decode_body_ext<B: Buf>(buf: &mut B, ext: IrefExt) -> Result<Self> {
32        let mut bytes_remaining = buf.remaining();
33        let mut references = vec![];
34        while bytes_remaining > 0 {
35            if ext.version == IrefVersion::V0 {
36                let box_len = u32::decode(buf)?;
37                bytes_remaining -= box_len as usize;
38                let reference_type = FourCC::decode(buf)?;
39                let from_item_id: u32 = u16::decode(buf)?.into();
40                let reference_count: u16 = u16::decode(buf)?;
41                let mut to_item_ids: Vec<u32> = vec![];
42                for _ in 0..reference_count {
43                    let to_item_id: u32 = u16::decode(buf)?.into();
44                    to_item_ids.push(to_item_id);
45                }
46                let reference = Reference {
47                    reference_type,
48                    from_item_id,
49                    to_item_ids,
50                };
51                references.push(reference);
52            } else {
53                let box_len = u32::decode(buf)?;
54                bytes_remaining -= box_len as usize;
55                let reference_type = FourCC::decode(buf)?;
56                let from_item_id: u32 = u32::decode(buf)?;
57                let reference_count: u16 = u16::decode(buf)?;
58                let mut to_item_ids: Vec<u32> = vec![];
59                for _ in 0..reference_count {
60                    let to_item_id: u32 = u32::decode(buf)?;
61                    to_item_ids.push(to_item_id);
62                }
63                let reference = Reference {
64                    reference_type,
65                    from_item_id,
66                    to_item_ids,
67                };
68                references.push(reference);
69            }
70        }
71        Ok(Iref { references })
72    }
73
74    fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<IrefExt> {
75        let mut version = IrefVersion::V0;
76        'reference: for reference in &self.references {
77            if reference.from_item_id > (u16::MAX as u32) {
78                version = IrefVersion::V1;
79                break 'reference;
80            }
81            for id in &reference.to_item_ids {
82                if *id > (u16::MAX as u32) {
83                    version = IrefVersion::V1;
84                    break 'reference;
85                }
86            }
87        }
88        if version == IrefVersion::V0 {
89            for reference in &self.references {
90                let size = (4 + 4 + 2 + 2 + 2 * reference.to_item_ids.len()) as u32;
91                size.encode(buf)?;
92                reference.reference_type.encode(buf)?;
93                (reference.from_item_id as u16).encode(buf)?;
94                (reference.to_item_ids.len() as u16).encode(buf)?;
95                for id in &reference.to_item_ids {
96                    (*id as u16).encode(buf)?;
97                }
98            }
99        } else {
100            for reference in &self.references {
101                let size = (4 + 4 + 4 + 2 + 4 * reference.to_item_ids.len()) as u32;
102                size.encode(buf)?;
103                reference.reference_type.encode(buf)?;
104                reference.from_item_id.encode(buf)?;
105                (reference.to_item_ids.len() as u16).encode(buf)?;
106                for id in &reference.to_item_ids {
107                    id.encode(buf)?;
108                }
109            }
110        }
111        Ok(IrefExt { version })
112    }
113}