mp4_atom/moov/trak/mdia/minf/stbl/
ctts.rs1use 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}