mp4_atom/moov/trak/mdia/minf/stbl/
ctts.rs

1use crate::*;
2
3#[derive(Debug, Clone, PartialEq, Eq, Default)]
4#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5pub struct Ctts {
6    pub entries: Vec<CttsEntry>,
7}
8
9#[derive(Debug, Clone, PartialEq, Eq, Default)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct CttsEntry {
12    pub sample_count: u32,
13    pub sample_offset: i32,
14}
15
16impl AtomExt for Ctts {
17    type Ext = ();
18
19    const KIND_EXT: FourCC = FourCC::new(b"ctts");
20
21    fn decode_body_ext<B: Buf>(buf: &mut B, _ext: ()) -> Result<Self> {
22        let entry_count = u32::decode(buf)?;
23
24        let mut entries = Vec::new();
25        for _ in 0..entry_count {
26            let entry = CttsEntry {
27                sample_count: u32::decode(buf)?,
28                sample_offset: i32::decode(buf)?,
29            };
30            entries.push(entry);
31        }
32
33        Ok(Ctts { entries })
34    }
35
36    fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<()> {
37        (self.entries.len() as u32).encode(buf)?;
38        for entry in self.entries.iter() {
39            (entry.sample_count).encode(buf)?;
40            (entry.sample_offset).encode(buf)?;
41        }
42
43        Ok(())
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use super::*;
50
51    #[test]
52    fn test_ctts() {
53        let expected = Ctts {
54            entries: vec![
55                CttsEntry {
56                    sample_count: 1,
57                    sample_offset: 200,
58                },
59                CttsEntry {
60                    sample_count: 2,
61                    sample_offset: -100,
62                },
63            ],
64        };
65        let mut buf = Vec::new();
66        expected.encode(&mut buf).unwrap();
67
68        let mut buf = buf.as_ref();
69        let decoded = Ctts::decode(&mut buf).unwrap();
70        assert_eq!(decoded, expected);
71    }
72}