scuffle_mp4/boxes/types/
ctts.rs1use std::io;
2
3use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
4use bytes::Bytes;
5
6use crate::boxes::header::{BoxHeader, FullBoxHeader};
7use crate::boxes::traits::BoxType;
8
9#[derive(Debug, Clone, PartialEq)]
10pub struct Ctts {
13 pub header: FullBoxHeader,
14 pub entries: Vec<CttsEntry>,
15}
16
17#[derive(Debug, Clone, PartialEq)]
18pub struct CttsEntry {
20 pub sample_count: u32,
21 pub sample_offset: i64,
22}
23
24impl BoxType for Ctts {
25 const NAME: [u8; 4] = *b"ctts";
26
27 fn demux(header: BoxHeader, data: Bytes) -> io::Result<Self> {
28 let mut reader = io::Cursor::new(data);
29
30 let header = FullBoxHeader::demux(header, &mut reader)?;
31
32 let entry_count = reader.read_u32::<BigEndian>()?;
33
34 let mut entries = Vec::with_capacity(entry_count as usize);
35
36 for _ in 0..entry_count {
37 let sample_count = reader.read_u32::<BigEndian>()?;
38 let sample_offset = if header.version == 1 {
39 reader.read_i32::<BigEndian>()? as i64
40 } else {
41 reader.read_u32::<BigEndian>()? as i64
42 };
43
44 entries.push(CttsEntry {
45 sample_count,
46 sample_offset,
47 });
48 }
49
50 Ok(Self { header, entries })
51 }
52
53 fn primitive_size(&self) -> u64 {
54 self.header.size()
55 + 4 + (self.entries.len() as u64 * 8) }
58
59 fn primitive_mux<T: io::Write>(&self, writer: &mut T) -> io::Result<()> {
60 self.header.mux(writer)?;
61
62 writer.write_u32::<BigEndian>(self.entries.len() as u32)?;
63
64 for entry in &self.entries {
65 writer.write_u32::<BigEndian>(entry.sample_count)?;
66
67 if self.header.version == 1 {
68 writer.write_i32::<BigEndian>(entry.sample_offset as i32)?;
69 } else {
70 writer.write_u32::<BigEndian>(entry.sample_offset as u32)?;
71 }
72 }
73
74 Ok(())
75 }
76
77 fn validate(&self) -> io::Result<()> {
78 if self.header.flags != 0 {
79 return Err(io::Error::new(io::ErrorKind::InvalidData, "ctts flags must be 0"));
80 }
81
82 if self.header.version > 1 {
83 return Err(io::Error::new(io::ErrorKind::InvalidData, "ctts version must be 0 or 1"));
84 }
85
86 Ok(())
87 }
88}