1use crate::*;
2
3#[derive(Debug, Clone, PartialEq, Eq, Default)]
4#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5pub struct Cslg {
6 pub composition_to_dts_shift: i64,
7 pub least_decode_to_display_shift: i64,
8 pub greatest_decode_to_display_delta: i64,
9 pub composition_start_time: i64,
10 pub composition_end_time: i64,
11}
12
13ext! {
14 name: Cslg,
15 versions: [0, 1],
16 flags: {}
17}
18
19impl AtomExt for Cslg {
20 type Ext = CslgExt;
21
22 const KIND_EXT: FourCC = FourCC::new(b"cslg");
23
24 fn decode_body_ext<B: Buf>(buf: &mut B, ext: CslgExt) -> Result<Self> {
25 if ext.version == CslgVersion::V0 {
26 Ok(Cslg {
27 composition_to_dts_shift: i32::decode(buf)?.into(),
28 least_decode_to_display_shift: i32::decode(buf)?.into(),
29 greatest_decode_to_display_delta: i32::decode(buf)?.into(),
30 composition_start_time: i32::decode(buf)?.into(),
31 composition_end_time: i32::decode(buf)?.into(),
32 })
33 } else {
34 Ok(Cslg {
35 composition_to_dts_shift: i64::decode(buf)?,
36 least_decode_to_display_shift: i64::decode(buf)?,
37 greatest_decode_to_display_delta: i64::decode(buf)?,
38 composition_start_time: i64::decode(buf)?,
39 composition_end_time: i64::decode(buf)?,
40 })
41 }
42 }
43
44 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<CslgExt> {
45 match (
46 i32::try_from(self.composition_to_dts_shift),
47 i32::try_from(self.least_decode_to_display_shift),
48 i32::try_from(self.greatest_decode_to_display_delta),
49 i32::try_from(self.composition_start_time),
50 i32::try_from(self.composition_end_time),
51 ) {
52 (
53 Ok(composition_to_dts_shift),
54 Ok(least_decode_to_display_shift),
55 Ok(greatest_decode_to_display_delta),
56 Ok(composition_start_time),
57 Ok(composition_end_time),
58 ) => {
59 composition_to_dts_shift.encode(buf)?;
60 least_decode_to_display_shift.encode(buf)?;
61 greatest_decode_to_display_delta.encode(buf)?;
62 composition_start_time.encode(buf)?;
63 composition_end_time.encode(buf)?;
64 Ok(CslgExt {
65 version: CslgVersion::V0,
66 })
67 }
68 _ => {
69 self.composition_to_dts_shift.encode(buf)?;
70 self.least_decode_to_display_shift.encode(buf)?;
71 self.greatest_decode_to_display_delta.encode(buf)?;
72 self.composition_start_time.encode(buf)?;
73 self.composition_end_time.encode(buf)?;
74 Ok(CslgExt {
75 version: CslgVersion::V1,
76 })
77 }
78 }
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 const ENCODED_CSLG_V0: &[u8] = &[
88 0x00, 0x00, 0x00, 0x20, 0x63, 0x73, 0x6c, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 0x08, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90 0x13, 0x88,
91 ];
92
93 const ENCODED_CSLG_V1: &[u8] = &[
95 0x00, 0x00, 0x00, 0x34, b'c', b's', b'l', b'g', 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
97 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F,
98 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
99 ];
100
101 const ENCODED_CSLG_V1_VARIANT: &[u8] = &[
103 0x00, 0x00, 0x00, 0x34, b'c', b's', b'l', b'g', 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
105 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F,
106 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
107 ];
108
109 #[test]
110 fn test_cslg_v0() {
111 let buf: &mut std::io::Cursor<&&[u8]> = &mut std::io::Cursor::new(&ENCODED_CSLG_V0);
112
113 let cslg = Cslg::decode(buf).expect("failed to decode cslg");
114
115 assert_eq!(
116 cslg,
117 Cslg {
118 composition_to_dts_shift: 8,
119 least_decode_to_display_shift: -8,
120 greatest_decode_to_display_delta: 8,
121 composition_start_time: 0,
122 composition_end_time: 5000
123 },
124 );
125
126 let mut buf = Vec::new();
127 cslg.encode(&mut buf).unwrap();
128
129 assert_eq!(buf.as_slice(), ENCODED_CSLG_V0);
130 }
131
132 #[test]
133 fn test_cslg_v1_encode() {
134 let cslg = Cslg {
135 composition_to_dts_shift: 2147483648,
136 least_decode_to_display_shift: -2147483649,
137 greatest_decode_to_display_delta: 8,
138 composition_start_time: i64::MIN,
139 composition_end_time: i64::MAX,
140 };
141
142 let mut buf = Vec::new();
143 cslg.encode(&mut buf).unwrap();
144
145 assert_eq!(buf.as_slice(), ENCODED_CSLG_V1);
146 }
147
148 #[test]
149 fn test_cslg_v1_decode() {
150 let buf: &mut std::io::Cursor<&&[u8]> = &mut std::io::Cursor::new(&ENCODED_CSLG_V1);
151
152 let cslg = Cslg::decode(buf).expect("failed to decode cslg");
153
154 assert_eq!(
155 cslg,
156 Cslg {
157 composition_to_dts_shift: 2147483648,
158 least_decode_to_display_shift: -2147483649,
159 greatest_decode_to_display_delta: 8,
160 composition_start_time: i64::MIN,
161 composition_end_time: i64::MAX,
162 },
163 );
164 }
165
166 #[test]
167 fn test_cslg_v1_encode_variant() {
168 let cslg = Cslg {
169 composition_to_dts_shift: 2147483647,
170 least_decode_to_display_shift: -2147483649,
171 greatest_decode_to_display_delta: 8,
172 composition_start_time: i64::MIN,
173 composition_end_time: i64::MAX,
174 };
175
176 let mut buf = Vec::new();
177 cslg.encode(&mut buf).unwrap();
178
179 assert_eq!(buf.as_slice(), ENCODED_CSLG_V1_VARIANT);
180 }
181}