1use crate::*;
2
3ext! {
4 name: Tkhd,
5 versions: [0, 1],
6 flags: {
7 track_enabled = 0,
8 track_in_movie = 1,
9 track_in_preview = 2,
10 }
11}
12
13#[derive(Debug, Clone, PartialEq, Eq, Default)]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15pub struct Tkhd {
16 pub creation_time: u64,
17 pub modification_time: u64,
18 pub track_id: u32,
19 pub duration: u64,
20 pub layer: u16,
21 pub alternate_group: u16,
22 pub enabled: bool,
23
24 pub volume: FixedPoint<u8>,
25 pub matrix: Matrix,
26
27 pub width: FixedPoint<u16>,
28 pub height: FixedPoint<u16>,
29}
30
31impl AtomExt for Tkhd {
32 const KIND_EXT: FourCC = FourCC::new(b"tkhd");
33
34 type Ext = TkhdExt;
35
36 fn decode_body_ext<B: Buf>(buf: &mut B, ext: TkhdExt) -> Result<Self> {
37 let (creation_time, modification_time, track_id, _, duration) = match ext.version {
38 TkhdVersion::V1 => (
39 u64::decode(buf)?,
40 u64::decode(buf)?,
41 u32::decode(buf)?,
42 u32::decode(buf)?,
43 u64::decode(buf)?,
44 ),
45 TkhdVersion::V0 => (
46 u32::decode(buf)? as u64,
47 u32::decode(buf)? as u64,
48 u32::decode(buf)?,
49 u32::decode(buf)?,
50 u32::decode(buf)? as u64,
51 ),
52 };
53
54 u64::decode(buf)?; let layer = u16::decode(buf)?;
56 let alternate_group = u16::decode(buf)?;
57 let volume = FixedPoint::decode(buf)?;
58
59 u16::decode(buf)?; let matrix = Matrix::decode(buf)?;
61 let width = FixedPoint::decode(buf)?;
62 let height = FixedPoint::decode(buf)?;
63
64 Ok(Tkhd {
65 creation_time,
66 modification_time,
67 track_id,
68 duration,
69 layer,
70 alternate_group,
71 volume,
72 matrix,
73 width,
74 height,
75 enabled: ext.track_enabled,
76 })
77 }
78
79 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<TkhdExt> {
80 self.creation_time.encode(buf)?;
81 self.modification_time.encode(buf)?;
82 self.track_id.encode(buf)?;
83 0u32.encode(buf)?; self.duration.encode(buf)?;
85
86 0u64.encode(buf)?; self.layer.encode(buf)?;
88 self.alternate_group.encode(buf)?;
89 self.volume.encode(buf)?;
90 0u16.encode(buf)?; self.matrix.encode(buf)?;
92
93 self.width.encode(buf)?;
94 self.height.encode(buf)?;
95
96 Ok(TkhdExt {
97 version: TkhdVersion::V1,
98 track_enabled: self.enabled,
99 ..Default::default()
100 })
101 }
102}
103
104#[derive(Debug, Clone, PartialEq, Eq)]
105#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
106pub struct Matrix {
107 pub a: i32,
108 pub b: i32,
109 pub u: i32,
110 pub c: i32,
111 pub d: i32,
112 pub v: i32,
113 pub x: i32,
114 pub y: i32,
115 pub w: i32,
116}
117
118impl Decode for Matrix {
119 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
120 Ok(Self {
121 a: i32::decode(buf)?,
122 b: i32::decode(buf)?,
123 u: i32::decode(buf)?,
124 c: i32::decode(buf)?,
125 d: i32::decode(buf)?,
126 v: i32::decode(buf)?,
127 x: i32::decode(buf)?,
128 y: i32::decode(buf)?,
129 w: i32::decode(buf)?,
130 })
131 }
132}
133
134impl Encode for Matrix {
135 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
136 self.a.encode(buf)?;
137 self.b.encode(buf)?;
138 self.u.encode(buf)?;
139 self.c.encode(buf)?;
140 self.d.encode(buf)?;
141 self.v.encode(buf)?;
142 self.x.encode(buf)?;
143 self.y.encode(buf)?;
144 self.w.encode(buf)
145 }
146}
147
148impl std::fmt::Display for Matrix {
149 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
150 write!(
151 f,
152 "{:#x} {:#x} {:#x} {:#x} {:#x} {:#x} {:#x} {:#x} {:#x}",
153 self.a, self.b, self.u, self.c, self.d, self.v, self.x, self.y, self.w
154 )
155 }
156}
157
158impl Default for Matrix {
159 fn default() -> Self {
160 Self {
161 a: 0x00010000,
163 b: 0,
164 u: 0,
165 c: 0,
166 d: 0x00010000,
167 v: 0,
168 x: 0,
169 y: 0,
170 w: 0x40000000,
171 }
172 }
173}
174
175#[cfg(test)]
176mod tests {
177 use super::*;
178
179 #[test]
180 fn test_tkhd32() {
181 let expected = Tkhd {
182 creation_time: 100,
183 modification_time: 200,
184 track_id: 1,
185 duration: 634634,
186 layer: 0,
187 alternate_group: 0,
188 volume: 1.into(),
189 matrix: Matrix::default(),
190 width: 512.into(),
191 height: 288.into(),
192 enabled: true,
193 };
194 let mut buf = Vec::new();
195 expected.encode(&mut buf).unwrap();
196
197 let mut buf = buf.as_ref();
198 let decoded = Tkhd::decode(&mut buf).unwrap();
199 assert_eq!(decoded, expected);
200 }
201
202 #[test]
203 fn test_tkhd64() {
204 let expected = Tkhd {
205 creation_time: 100,
206 modification_time: 200,
207 track_id: 1,
208 duration: 634634,
209 layer: 0,
210 alternate_group: 0,
211 volume: 1.into(),
212 matrix: Matrix::default(),
213 width: 512.into(),
214 height: 288.into(),
215 enabled: true,
216 };
217 let mut buf = Vec::new();
218 expected.encode(&mut buf).unwrap();
219
220 let mut buf = buf.as_ref();
221 let decoded = Tkhd::decode(&mut buf).unwrap();
222 assert_eq!(decoded, expected);
223 }
224}