mp4_atom/moov/
mvhd.rs

1use crate::*;
2
3ext! {
4    name: Mvhd,
5    versions: [0,1],
6    flags: {}
7}
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct Mvhd {
12    pub creation_time: u64,
13    pub modification_time: u64,
14    pub timescale: u32,
15    pub duration: u64,
16
17    pub rate: FixedPoint<u16>,
18    pub volume: FixedPoint<u8>,
19
20    pub matrix: Matrix,
21    pub next_track_id: u32,
22}
23
24impl AtomExt for Mvhd {
25    const KIND_EXT: FourCC = FourCC::new(b"mvhd");
26
27    type Ext = MvhdExt;
28
29    fn decode_body_ext<B: Buf>(buf: &mut B, ext: MvhdExt) -> Result<Self> {
30        let (creation_time, modification_time, timescale, duration) = match ext.version {
31            MvhdVersion::V1 => (
32                u64::decode(buf)?,
33                u64::decode(buf)?,
34                u32::decode(buf)?,
35                u64::decode(buf)?,
36            ),
37            MvhdVersion::V0 => (
38                u32::decode(buf)? as u64,
39                u32::decode(buf)? as u64,
40                u32::decode(buf)?,
41                u32::decode(buf)? as u64,
42            ),
43        };
44
45        let rate = FixedPoint::decode(buf)?;
46        let volume = FixedPoint::decode(buf)?;
47
48        u16::decode(buf)?; // reserved
49        u64::decode(buf)?; // reserved
50
51        let matrix = Matrix::decode(buf)?;
52
53        <[u8; 24]>::decode(buf)?; // pre_defined = 0
54
55        let next_track_id = u32::decode(buf)?;
56
57        Ok(Mvhd {
58            creation_time,
59            modification_time,
60            timescale,
61            duration,
62            rate,
63            volume,
64            matrix,
65            next_track_id,
66        })
67    }
68
69    fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<MvhdExt> {
70        self.creation_time.encode(buf)?;
71        self.modification_time.encode(buf)?;
72        self.timescale.encode(buf)?;
73        self.duration.encode(buf)?;
74
75        self.rate.encode(buf)?;
76        self.volume.encode(buf)?;
77
78        0u16.encode(buf)?; // reserved
79        0u64.encode(buf)?; // reserved
80
81        self.matrix.encode(buf)?;
82
83        [0u8; 24].encode(buf)?; // pre_defined = 0
84
85        self.next_track_id.encode(buf)?;
86
87        Ok(MvhdVersion::V1.into())
88    }
89}
90
91impl Default for Mvhd {
92    fn default() -> Self {
93        Mvhd {
94            creation_time: 0,
95            modification_time: 0,
96            timescale: 1000,
97            duration: 0,
98            rate: Default::default(),
99            matrix: Default::default(),
100            volume: Default::default(),
101            next_track_id: 1,
102        }
103    }
104}
105
106#[cfg(test)]
107mod tests {
108    use super::*;
109
110    #[test]
111    fn test_mvhd32() {
112        let expected = Mvhd {
113            creation_time: 100,
114            modification_time: 200,
115            timescale: 1000,
116            duration: 634634,
117            rate: 1.into(),
118            volume: 1.into(),
119            matrix: Matrix::default(),
120            next_track_id: 1,
121        };
122
123        let mut buf = Vec::new();
124        expected.encode(&mut buf).unwrap();
125
126        let mut buf = buf.as_ref();
127        let decoded = Mvhd::decode(&mut buf).unwrap();
128        assert_eq!(decoded, expected);
129    }
130
131    #[test]
132    fn test_mvhd64() {
133        let expected = Mvhd {
134            creation_time: 100,
135            modification_time: 200,
136            timescale: 1000,
137            duration: 634634,
138            rate: 1.into(),
139            volume: 1.into(),
140            matrix: Matrix::default(),
141            next_track_id: 1,
142        };
143
144        let mut buf = Vec::new();
145        expected.encode(&mut buf).unwrap();
146
147        let mut buf = buf.as_ref();
148        let output = Mvhd::decode(&mut buf).unwrap();
149        assert_eq!(output, expected);
150    }
151}