1use super::descriptor_body;
7use crate::error::{Error, Result};
8use dvb_common::{Parse, Serialize};
9
10pub const TAG: u8 = 0x30;
12const HEADER_LEN: usize = 2;
13const BODY_LEN: u8 = 13;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize))]
18pub struct SvcExtensionDescriptor {
19 pub width: u16,
21 pub height: u16,
23 pub frame_rate: u16,
25 pub average_bitrate: u16,
27 pub maximum_bitrate: u16,
29 pub dependency_id: u8,
31 pub quality_id_start: u8,
33 pub quality_id_end: u8,
35 pub temporal_id_start: u8,
37 pub temporal_id_end: u8,
39 pub no_sei_nal_unit_present: bool,
41}
42
43impl<'a> Parse<'a> for SvcExtensionDescriptor {
44 type Error = crate::error::Error;
45
46 fn parse(bytes: &'a [u8]) -> Result<Self> {
47 let body = descriptor_body(
48 bytes,
49 TAG,
50 "SvcExtensionDescriptor",
51 "unexpected tag for SVC_extension_descriptor",
52 )?;
53 if body.len() != BODY_LEN as usize {
54 return Err(Error::InvalidDescriptor {
55 tag: TAG,
56 reason: "SVC_extension_descriptor length must equal 13",
57 });
58 }
59 let width = u16::from_be_bytes([body[0], body[1]]);
60 let height = u16::from_be_bytes([body[2], body[3]]);
61 let frame_rate = u16::from_be_bytes([body[4], body[5]]);
62 let average_bitrate = u16::from_be_bytes([body[6], body[7]]);
63 let maximum_bitrate = u16::from_be_bytes([body[8], body[9]]);
64 let b10 = body[10];
65 let dependency_id = (b10 >> 5) & 0x07;
66 let b11 = body[11];
68 let quality_id_start = (b11 >> 4) & 0x0F;
69 let quality_id_end = b11 & 0x0F;
70 let b12 = body[12];
71 let temporal_id_start = (b12 >> 5) & 0x07;
72 let temporal_id_end = (b12 >> 2) & 0x07;
73 let no_sei_nal_unit_present = (b12 & 0x02) != 0;
74 Ok(Self {
76 width,
77 height,
78 frame_rate,
79 average_bitrate,
80 maximum_bitrate,
81 dependency_id,
82 quality_id_start,
83 quality_id_end,
84 temporal_id_start,
85 temporal_id_end,
86 no_sei_nal_unit_present,
87 })
88 }
89}
90
91impl Serialize for SvcExtensionDescriptor {
92 type Error = crate::error::Error;
93
94 fn serialized_len(&self) -> usize {
95 HEADER_LEN + BODY_LEN as usize
96 }
97
98 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
99 let len = self.serialized_len();
100 if buf.len() < len {
101 return Err(Error::OutputBufferTooSmall {
102 need: len,
103 have: buf.len(),
104 });
105 }
106 buf[0] = TAG;
107 buf[1] = BODY_LEN;
108 buf[HEADER_LEN..HEADER_LEN + 2].copy_from_slice(&self.width.to_be_bytes());
109 buf[HEADER_LEN + 2..HEADER_LEN + 4].copy_from_slice(&self.height.to_be_bytes());
110 buf[HEADER_LEN + 4..HEADER_LEN + 6].copy_from_slice(&self.frame_rate.to_be_bytes());
111 buf[HEADER_LEN + 6..HEADER_LEN + 8].copy_from_slice(&self.average_bitrate.to_be_bytes());
112 buf[HEADER_LEN + 8..HEADER_LEN + 10].copy_from_slice(&self.maximum_bitrate.to_be_bytes());
113 buf[HEADER_LEN + 10] = (self.dependency_id & 0x07) << 5;
114 buf[HEADER_LEN + 11] = ((self.quality_id_start & 0x0F) << 4) | (self.quality_id_end & 0x0F);
115 buf[HEADER_LEN + 12] = ((self.temporal_id_start & 0x07) << 5)
116 | ((self.temporal_id_end & 0x07) << 2)
117 | ((self.no_sei_nal_unit_present as u8) << 1);
118 Ok(len)
119 }
120}
121impl<'a> crate::traits::DescriptorDef<'a> for SvcExtensionDescriptor {
122 const TAG: u8 = TAG;
123 const NAME: &'static str = "SVC_EXTENSION";
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129
130 #[test]
131 fn parse_extracts_fields() {
132 let bytes = [
133 TAG, 13, 0x07, 0x80, 0x04, 0x38, 0x00, 0x3C, 0x00, 0x64, 0x00, 0xC8, 0x20, 0x01, 0x06, ];
142 let d = SvcExtensionDescriptor::parse(&bytes).unwrap();
143 assert_eq!(d.width, 1920);
144 assert_eq!(d.height, 1080);
145 assert_eq!(d.frame_rate, 60);
146 assert_eq!(d.average_bitrate, 100);
147 assert_eq!(d.maximum_bitrate, 200);
148 assert_eq!(d.dependency_id, 1);
149 assert_eq!(d.quality_id_start, 0);
150 assert_eq!(d.quality_id_end, 1);
151 assert_eq!(d.temporal_id_start, 0);
152 assert_eq!(d.temporal_id_end, 1);
153 assert!(d.no_sei_nal_unit_present);
154 }
155
156 #[test]
157 fn parse_max_bit_fields() {
158 let bytes = [
159 TAG, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xE0, 0xFF, 0xFE, ];
163 let d = SvcExtensionDescriptor::parse(&bytes).unwrap();
164 assert_eq!(d.dependency_id, 7);
165 assert_eq!(d.quality_id_start, 15);
166 assert_eq!(d.quality_id_end, 15);
167 assert_eq!(d.temporal_id_start, 7);
168 assert_eq!(d.temporal_id_end, 7);
169 assert!(d.no_sei_nal_unit_present);
170 }
171
172 #[test]
173 fn parse_rejects_wrong_tag() {
174 let err = SvcExtensionDescriptor::parse(&[0x02, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
175 .unwrap_err();
176 assert!(matches!(err, Error::InvalidDescriptor { tag: 0x02, .. }));
177 }
178
179 #[test]
180 fn parse_rejects_wrong_length() {
181 let err = SvcExtensionDescriptor::parse(&[TAG, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
182 .unwrap_err();
183 assert!(matches!(err, Error::InvalidDescriptor { .. }));
184 }
185
186 #[test]
187 fn serialize_round_trip() {
188 let d = SvcExtensionDescriptor {
189 width: 1280,
190 height: 720,
191 frame_rate: 50,
192 average_bitrate: 5000,
193 maximum_bitrate: 10000,
194 dependency_id: 2,
195 quality_id_start: 3,
196 quality_id_end: 5,
197 temporal_id_start: 1,
198 temporal_id_end: 3,
199 no_sei_nal_unit_present: false,
200 };
201 let mut buf = vec![0u8; d.serialized_len()];
202 d.serialize_into(&mut buf).unwrap();
203 let reparsed = SvcExtensionDescriptor::parse(&buf).unwrap();
204 assert_eq!(d, reparsed);
205 }
206
207 #[test]
208 fn serialize_round_trip_reserved_preserved() {
209 let bytes_with_reserved = [
214 TAG, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1F, 0x00, 0x01, ];
217 let d = SvcExtensionDescriptor::parse(&bytes_with_reserved).unwrap();
218 let mut buf = vec![0u8; d.serialized_len()];
219 d.serialize_into(&mut buf).unwrap();
220 let reparsed = SvcExtensionDescriptor::parse(&buf).unwrap();
222 let mut buf2 = vec![0u8; reparsed.serialized_len()];
223 reparsed.serialize_into(&mut buf2).unwrap();
224 assert_eq!(buf, buf2);
225 }
226
227 #[test]
228 fn serialize_rejects_small_buffer() {
229 let d = SvcExtensionDescriptor {
230 width: 0,
231 height: 0,
232 frame_rate: 0,
233 average_bitrate: 0,
234 maximum_bitrate: 0,
235 dependency_id: 0,
236 quality_id_start: 0,
237 quality_id_end: 0,
238 temporal_id_start: 0,
239 temporal_id_end: 0,
240 no_sei_nal_unit_present: false,
241 };
242 let mut tiny = vec![0u8; 5];
243 let err = d.serialize_into(&mut tiny).unwrap_err();
244 assert!(matches!(err, Error::OutputBufferTooSmall { .. }));
245 }
246}