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