Skip to main content

mp4_atom/sample/
evte.rs

1use std::borrow::Borrow;
2
3use crate::*;
4
5/// The content of a single sample in an Event Message track (the
6/// [`Evte`](crate::Evte) sample entry).
7///
8/// Sample content lives inside `mdat` and isn't walked automatically by this
9/// crate (it isn't part of the structural box tree, and [`Emib`]/[`Emeb`]
10/// aren't registered in [`Any`] since they only ever appear here, as sample
11/// data) -- decode it explicitly via [`EvteSample::decode`].
12///
13/// See ISO/IEC 23001-18:2022 Section 6.
14#[derive(Debug, Clone, PartialEq, Eq)]
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16pub struct EvteSample;
17
18impl EvteSample {
19    pub fn decode<B: Buf>(buf: &mut B) -> Result<Vec<Emib>> {
20        let mut emibs = Vec::new();
21        let mut emeb = None;
22
23        while let Some(header) = Header::decode_maybe(buf)? {
24            let size = header.size.unwrap_or(buf.remaining());
25            if size > buf.remaining() {
26                return Err(Error::OutOfBounds);
27            }
28            let mut body = buf.slice(size);
29
30            match header.kind {
31                Emib::KIND if emeb.is_none() => emibs.push(Emib::decode_body(&mut body)?),
32                Emeb::KIND if emeb.is_none() && emibs.is_empty() => {
33                    emeb = Some(Emeb::decode_body(&mut body)?)
34                }
35                kind => return Err(Error::UnexpectedBox(kind)),
36            }
37
38            if body.has_remaining() {
39                return Err(Error::UnderDecode(header.kind));
40            }
41            buf.advance(size);
42        }
43
44        if buf.has_remaining() {
45            Err(Error::ShortRead)
46        } else if emeb.is_none() && emibs.is_empty() {
47            Err(Error::UnexpectedEof)
48        } else {
49            Ok(emibs)
50        }
51    }
52
53    pub fn encode<B: BufMut>(
54        emibs: impl IntoIterator<Item = impl Borrow<Emib>>,
55        buf: &mut B,
56    ) -> Result<()> {
57        let mut wrote_atom = false;
58        for emib in emibs {
59            emib.borrow().encode(buf)?;
60            wrote_atom = true;
61        }
62        if wrote_atom {
63            Ok(())
64        } else {
65            Emeb.encode(buf)
66        }
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73
74    fn sample_emib(id: u32) -> Emib {
75        Emib {
76            presentation_time_delta: 0,
77            event_duration: 1000,
78            id,
79            scheme_id_uri: "urn:mpeg:dash:event:2012".into(),
80            value: "".into(),
81            message_data: vec![1, 2, 3],
82        }
83    }
84
85    #[test]
86    fn test_evte_sample_no_emib_roundtrip() {
87        let sample = vec![];
88
89        let mut buf = Vec::new();
90        EvteSample::encode(&sample, &mut buf).unwrap();
91
92        let decoded = EvteSample::decode(&mut buf.as_slice()).expect("failed to decode sample");
93        assert_eq!(decoded, sample);
94    }
95
96    #[test]
97    fn test_evte_sample_single_emib_roundtrip() {
98        let sample = vec![sample_emib(1)];
99
100        let mut buf = Vec::new();
101        EvteSample::encode(&sample, &mut buf).unwrap();
102
103        let decoded = EvteSample::decode(&mut buf.as_slice()).expect("failed to decode sample");
104        assert_eq!(decoded, sample);
105    }
106
107    #[test]
108    fn test_evte_sample_multiple_emib_roundtrip() {
109        // A sample may concatenate multiple concurrent event instances.
110        let sample = vec![sample_emib(1), sample_emib(2), sample_emib(3)];
111
112        let mut buf = Vec::new();
113        EvteSample::encode(&sample, &mut buf).unwrap();
114
115        let decoded = EvteSample::decode(&mut buf.as_slice()).expect("failed to decode sample");
116        assert_eq!(decoded, sample);
117    }
118
119    #[test]
120    fn test_evte_sample_empty_is_error() {
121        let err = EvteSample::decode(&mut [].as_slice()).unwrap_err();
122        assert!(matches!(err, Error::UnexpectedEof));
123    }
124
125    #[test]
126    fn test_evte_sample_short_read() {
127        let err = EvteSample::decode(&mut [1, 2].as_slice()).unwrap_err();
128        assert!(matches!(err, Error::ShortRead));
129    }
130
131    #[test]
132    fn test_evte_sample_emeb_after_emib_is_error() {
133        // `emeb` means "no event"; it must not be mixed with `emib`s.
134        let mut buf = Vec::new();
135        sample_emib(1).encode(&mut buf).unwrap();
136        Emeb.encode(&mut buf).unwrap();
137
138        let err = EvteSample::decode(&mut buf.as_slice()).unwrap_err();
139        assert!(matches!(err, Error::UnexpectedBox(kind) if kind == Emeb::KIND));
140    }
141
142    #[test]
143    fn test_evte_sample_invalid_emeb_is_error() {
144        let mut buf = Vec::new();
145
146        let header = Header {
147            kind: Emeb::KIND,
148            size: Some(size_of::<u32>()),
149        };
150        header.encode(&mut buf).unwrap();
151        0u32.encode(&mut buf).unwrap(); // invalid `emeb` body
152
153        let err = EvteSample::decode(&mut buf.as_slice()).unwrap_err();
154        assert!(matches!(err, Error::UnderDecode(kind) if kind == Emeb::KIND));
155    }
156}