scuffle_mp4/boxes/types/
trex.rs

1use 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)]
10/// Track Extends Box
11/// ISO/IEC 14496-12:2022(E) - 8.8.3
12pub struct Trex {
13    pub header: FullBoxHeader,
14    pub track_id: u32,
15    pub default_sample_description_index: u32,
16    pub default_sample_duration: u32,
17    pub default_sample_size: u32,
18    pub default_sample_flags: u32,
19}
20
21impl Trex {
22    pub fn new(track_id: u32) -> Self {
23        Self {
24            header: FullBoxHeader::new(Self::NAME, 0, 0),
25            track_id,
26            default_sample_description_index: 1,
27            default_sample_duration: 0,
28            default_sample_size: 0,
29            default_sample_flags: 0,
30        }
31    }
32}
33
34impl BoxType for Trex {
35    const NAME: [u8; 4] = *b"trex";
36
37    fn demux(header: BoxHeader, data: Bytes) -> io::Result<Self> {
38        let mut reader = io::Cursor::new(data);
39
40        let header = FullBoxHeader::demux(header, &mut reader)?;
41
42        let track_id = reader.read_u32::<BigEndian>()?;
43        let default_sample_description_index = reader.read_u32::<BigEndian>()?;
44        let default_sample_duration = reader.read_u32::<BigEndian>()?;
45        let default_sample_size = reader.read_u32::<BigEndian>()?;
46        let default_sample_flags = reader.read_u32::<BigEndian>()?;
47
48        Ok(Self {
49            header,
50
51            track_id,
52            default_sample_description_index,
53            default_sample_duration,
54            default_sample_size,
55            default_sample_flags,
56        })
57    }
58
59    fn primitive_size(&self) -> u64 {
60        let size = self.header.size();
61        let size = size + 4; // track_id
62        let size = size + 4; // default_sample_description_index
63        let size = size + 4; // default_sample_duration
64        let size = size + 4; // default_sample_size
65        // default_sample_flags
66        size + 4
67    }
68
69    fn primitive_mux<T: io::Write>(&self, writer: &mut T) -> io::Result<()> {
70        self.header.mux(writer)?;
71
72        writer.write_u32::<BigEndian>(self.track_id)?;
73        writer.write_u32::<BigEndian>(self.default_sample_description_index)?;
74        writer.write_u32::<BigEndian>(self.default_sample_duration)?;
75        writer.write_u32::<BigEndian>(self.default_sample_size)?;
76        writer.write_u32::<BigEndian>(self.default_sample_flags)?;
77
78        Ok(())
79    }
80
81    fn validate(&self) -> io::Result<()> {
82        if self.header.version != 0 {
83            return Err(io::Error::new(io::ErrorKind::InvalidData, "trex version must be 0"));
84        }
85
86        if self.header.flags != 0 {
87            return Err(io::Error::new(io::ErrorKind::InvalidData, "trex flags must be 0"));
88        }
89
90        Ok(())
91    }
92}