mp4_atom/moov/trak/mdia/minf/stbl/stsd/
evte.rs1use crate::*;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct Evte {
12 pub metadata: MetaData,
13 pub btrt: Option<Btrt>,
14 pub silb: Option<Silb>,
15}
16
17impl Atom for Evte {
18 const KIND: FourCC = FourCC::new(b"evte");
19
20 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
21 let metadata = MetaData::decode(buf)?;
22
23 let mut btrt = None;
24 let mut silb = None;
25 while let Some(atom) = Any::decode_maybe(buf)? {
26 match atom {
27 Any::Btrt(atom) => btrt = atom.into(),
28 Any::Silb(atom) => silb = atom.into(),
29 unknown => Self::decode_unknown(&unknown)?,
30 }
31 }
32 skip_trailing_padding(buf);
33
34 Ok(Self {
35 metadata,
36 btrt,
37 silb,
38 })
39 }
40
41 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
42 self.metadata.encode(buf)?;
43 self.btrt.encode(buf)?;
44 self.silb.encode(buf)?;
45 Ok(())
46 }
47}
48
49#[derive(Debug, Clone, PartialEq, Eq)]
51#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
52pub struct SchemeIdEntry {
53 pub scheme_id_uri: String,
54 pub value: String,
55 pub atleast_once: bool,
57}
58
59#[derive(Debug, Clone, PartialEq, Eq)]
64#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
65pub struct Silb {
66 pub schemes: Vec<SchemeIdEntry>,
67 pub other_schemes: bool,
69}
70
71impl AtomExt for Silb {
72 type Ext = ();
73
74 const KIND_EXT: FourCC = FourCC::new(b"silb");
75
76 fn decode_body_ext<B: Buf>(buf: &mut B, _ext: ()) -> Result<Self> {
77 let number_of_schemes = u32::decode(buf)?;
78 if number_of_schemes as u64 > buf.remaining() as u64 / 3 {
82 return Err(Error::OutOfBounds);
83 }
84
85 let mut schemes = Vec::with_capacity((number_of_schemes as usize).min(16));
86 for _ in 0..number_of_schemes {
87 let scheme_id_uri = String::decode(buf)?;
88 let value = String::decode(buf)?;
89 let flags = u8::decode(buf)?;
90 schemes.push(SchemeIdEntry {
91 scheme_id_uri,
92 value,
93 atleast_once: flags & 0x1 != 0,
94 });
95 }
96
97 let other_schemes_byte = u8::decode(buf)?;
98
99 Ok(Self {
100 schemes,
101 other_schemes: other_schemes_byte & 0x1 != 0,
102 })
103 }
104
105 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<()> {
106 (self.schemes.len() as u32).encode(buf)?;
107 for scheme in &self.schemes {
108 scheme.scheme_id_uri.as_str().encode(buf)?;
109 scheme.value.as_str().encode(buf)?;
110 let flags: u8 = if scheme.atleast_once { 0x1 } else { 0 };
111 flags.encode(buf)?;
112 }
113
114 let other_schemes_byte: u8 = if self.other_schemes { 0x1 } else { 0 };
115 other_schemes_byte.encode(buf)?;
116
117 Ok(())
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124
125 const ENCODED_EVTE: &[u8] = &[
128 0x00, 0x00, 0x00, 0x10, 0x65, 0x76, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129 0x01,
130 ];
131
132 fn decoded_evte() -> Evte {
133 Evte {
134 metadata: MetaData {
135 data_reference_index: 1,
136 },
137 btrt: None,
138 silb: None,
139 }
140 }
141
142 #[test]
143 fn test_evte_decode() {
144 let buf = &mut std::io::Cursor::new(ENCODED_EVTE);
145 let evte = Evte::decode(buf).expect("failed to decode evte");
146 assert_eq!(evte, decoded_evte());
147 }
148
149 #[test]
150 fn test_evte_encode() {
151 let mut buf = Vec::new();
152 decoded_evte().encode(&mut buf).unwrap();
153 assert_eq!(buf.as_slice(), ENCODED_EVTE);
154 }
155
156 #[test]
157 fn test_evte_via_codec() {
158 let evte = decoded_evte();
159
160 let mut buf = Vec::new();
161 Codec::from(evte.clone()).encode(&mut buf).unwrap();
162 assert_eq!(buf.as_slice(), ENCODED_EVTE);
163
164 let decoded = Codec::decode(&mut buf.as_slice()).expect("failed to decode evte codec");
165 assert_eq!(decoded, Codec::Evte(evte));
166 }
167
168 #[test]
169 fn test_silb_roundtrip() {
170 let silb = Silb {
171 schemes: vec![
172 SchemeIdEntry {
173 scheme_id_uri: "urn:scte:scte35:2014:xml+bin".into(),
174 value: "1".into(),
175 atleast_once: true,
176 },
177 SchemeIdEntry {
178 scheme_id_uri: "urn:mpeg:dash:event:2012".into(),
179 value: "".into(),
180 atleast_once: false,
181 },
182 ],
183 other_schemes: true,
184 };
185
186 let mut buf = Vec::new();
187 silb.encode(&mut buf).unwrap();
188
189 let decoded = Silb::decode(&mut buf.as_slice()).expect("failed to decode silb");
190 assert_eq!(decoded, silb);
191 }
192
193 #[test]
194 fn test_evte_with_btrt_and_silb_roundtrip() {
195 let evte = Evte {
196 metadata: MetaData {
197 data_reference_index: 1,
198 },
199 btrt: Some(Btrt {
200 buffer_size_db: 0,
201 max_bitrate: 1000,
202 avg_bitrate: 500,
203 }),
204 silb: Some(Silb {
205 schemes: vec![SchemeIdEntry {
206 scheme_id_uri: "urn:mpeg:dash:event:2012".into(),
207 value: "".into(),
208 atleast_once: true,
209 }],
210 other_schemes: false,
211 }),
212 };
213
214 let mut buf = Vec::new();
215 evte.encode(&mut buf).unwrap();
216
217 let decoded = Evte::decode(&mut buf.as_slice()).expect("failed to decode evte");
218 assert_eq!(decoded, evte);
219 }
220
221 #[test]
225 fn test_silb_huge_count() {
226 let mut buf = Vec::new();
227 u32::MAX.encode(&mut buf).unwrap(); assert!(matches!(
230 Silb::decode_body_ext(&mut buf.as_slice(), ()),
231 Err(Error::OutOfBounds)
232 ));
233 }
234}