Skip to main content

mp4/mp4box/
trex.rs

1use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
2use serde::Serialize;
3use std::io::{Read, Seek, Write};
4
5use crate::mp4box::*;
6
7#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
8pub struct TrexBox {
9    pub version: u8,
10    pub flags: u32,
11    pub track_id: u32,
12    pub default_sample_description_index: u32,
13    pub default_sample_duration: u32,
14    pub default_sample_size: u32,
15    pub default_sample_flags: u32,
16}
17
18impl TrexBox {
19    pub fn get_type(&self) -> BoxType {
20        BoxType::TrexBox
21    }
22
23    pub fn get_size(&self) -> u64 {
24        HEADER_SIZE + HEADER_EXT_SIZE + 20
25    }
26}
27
28impl Mp4Box for TrexBox {
29    fn box_type(&self) -> BoxType {
30        self.get_type()
31    }
32
33    fn box_size(&self) -> u64 {
34        self.get_size()
35    }
36
37    fn to_json(&self) -> Result<String> {
38        Ok(serde_json::to_string(&self).unwrap())
39    }
40
41    fn summary(&self) -> Result<String> {
42        let s = format!(
43            "track_id={} default_sample_duration={}",
44            self.track_id, self.default_sample_duration
45        );
46        Ok(s)
47    }
48}
49
50impl<R: Read + Seek> ReadBox<&mut R> for TrexBox {
51    fn read_box(reader: &mut R, size: u64) -> Result<Self> {
52        let start = box_start(reader)?;
53
54        let (version, flags) = read_box_header_ext(reader)?;
55
56        let track_id = reader.read_u32::<BigEndian>()?;
57        let default_sample_description_index = reader.read_u32::<BigEndian>()?;
58        let default_sample_duration = reader.read_u32::<BigEndian>()?;
59        let default_sample_size = reader.read_u32::<BigEndian>()?;
60        let default_sample_flags = reader.read_u32::<BigEndian>()?;
61
62        skip_bytes_to(reader, start + size)?;
63
64        Ok(TrexBox {
65            version,
66            flags,
67            track_id,
68            default_sample_description_index,
69            default_sample_duration,
70            default_sample_size,
71            default_sample_flags,
72        })
73    }
74}
75
76impl<W: Write> WriteBox<&mut W> for TrexBox {
77    fn write_box(&self, writer: &mut W) -> Result<u64> {
78        let size = self.box_size();
79        BoxHeader::new(self.box_type(), size).write(writer)?;
80
81        write_box_header_ext(writer, self.version, self.flags)?;
82
83        writer.write_u32::<BigEndian>(self.track_id)?;
84        writer.write_u32::<BigEndian>(self.default_sample_description_index)?;
85        writer.write_u32::<BigEndian>(self.default_sample_duration)?;
86        writer.write_u32::<BigEndian>(self.default_sample_size)?;
87        writer.write_u32::<BigEndian>(self.default_sample_flags)?;
88
89        Ok(size)
90    }
91}
92
93#[cfg(test)]
94mod tests {
95    use super::*;
96    use crate::mp4box::BoxHeader;
97    use std::io::Cursor;
98
99    #[test]
100    fn test_trex() {
101        let src_box = TrexBox {
102            version: 0,
103            flags: 0,
104            track_id: 1,
105            default_sample_description_index: 1,
106            default_sample_duration: 1000,
107            default_sample_size: 0,
108            default_sample_flags: 65536,
109        };
110        let mut buf = Vec::new();
111        src_box.write_box(&mut buf).unwrap();
112        assert_eq!(buf.len(), src_box.box_size() as usize);
113
114        let mut reader = Cursor::new(&buf);
115        let header = BoxHeader::read(&mut reader).unwrap();
116        assert_eq!(header.name, BoxType::TrexBox);
117        assert_eq!(src_box.box_size(), header.size);
118
119        let dst_box = TrexBox::read_box(&mut reader, header.size).unwrap();
120        assert_eq!(src_box, dst_box);
121    }
122}