1use alloc::vec::Vec;
9
10use crate::error::{Error, Result};
11use dvb_common::{Parse, Serialize};
12
13pub const SYSTEM_HEADER_START_CODE: u32 = 0x0000_01BB;
15
16const EXT_STREAM_ID: u8 = 0xB7;
18
19const PREFIX_LEN: usize = 6;
21
22#[derive(Debug, Clone, PartialEq, Eq)]
24#[cfg_attr(feature = "serde", derive(serde::Serialize))]
25pub struct StdBufferBound {
26 pub stream_id: u8,
28 pub stream_id_extension: Option<u8>,
31 pub buffer_bound_scale: bool,
33 pub buffer_size_bound: u16,
35}
36
37#[derive(Debug, Clone, PartialEq, Eq)]
39#[cfg_attr(feature = "serde", derive(serde::Serialize))]
40pub struct SystemHeader {
41 pub rate_bound: u32,
43 pub audio_bound: u8,
45 pub fixed_flag: bool,
47 pub csps_flag: bool,
49 pub system_audio_lock_flag: bool,
51 pub system_video_lock_flag: bool,
53 pub video_bound: u8,
55 pub packet_rate_restriction_flag: bool,
57 pub std_buffer_bounds: Vec<StdBufferBound>,
59}
60
61fn stream_loop_len(system_header: &SystemHeader) -> u16 {
62 let mut len: u16 = 0;
63 for b in &system_header.std_buffer_bounds {
64 if b.stream_id_extension.is_some() {
65 len += 6;
66 } else {
67 len += 3;
68 }
69 }
70 len
71}
72
73impl<'a> Parse<'a> for SystemHeader {
74 type Error = Error;
75
76 fn parse(b: &'a [u8]) -> Result<Self> {
77 if b.len() < PREFIX_LEN {
78 return Err(Error::BufferTooShort {
79 need: PREFIX_LEN,
80 have: b.len(),
81 what: "system_header prefix",
82 });
83 }
84
85 if u32::from_be_bytes([b[0], b[1], b[2], b[3]]) != SYSTEM_HEADER_START_CODE {
86 return Err(Error::BadSystemHeaderStartCode(u32::from_be_bytes([
87 b[0], b[1], b[2], b[3],
88 ])));
89 }
90
91 let header_length = u16::from_be_bytes([b[4], b[5]]) as usize;
92 let body_end = PREFIX_LEN + header_length;
93 if b.len() < body_end {
94 return Err(Error::HeaderLengthOverflow {
95 header_length,
96 available: b.len().saturating_sub(PREFIX_LEN),
97 });
98 }
99 let body = &b[PREFIX_LEN..body_end];
100
101 if body.len() < 6 {
110 return Err(Error::BufferTooShort {
111 need: 6 + PREFIX_LEN,
112 have: b.len(),
113 what: "system_header fixed body",
114 });
115 }
116
117 if body[0] & 0x80 == 0 {
119 return Err(Error::BadMarker("system_header rate_bound marker 1"));
120 }
121 if body[2] & 0x01 == 0 {
122 return Err(Error::BadMarker("system_header rate_bound marker 2"));
123 }
124 if body[4] & 0x20 == 0 {
125 return Err(Error::BadMarker("system_header video_bound marker"));
126 }
127
128 let rate_bound = ((u32::from(body[0] & 0x7F) << 15)
130 | (u32::from(body[1]) << 7)
131 | u32::from(body[2] >> 1))
132 & 0x3F_FFFF;
133
134 let audio_bound = (body[3] >> 2) & 0x3F;
136 let fixed_flag = body[3] & 0x02 != 0;
137 let csps_flag = body[3] & 0x01 != 0;
138
139 let system_audio_lock_flag = body[4] & 0x80 != 0;
141 let system_video_lock_flag = body[4] & 0x40 != 0;
142 let video_bound = body[4] & 0x0F;
143
144 let packet_rate_restriction_flag = body[5] & 0x80 != 0;
146
147 let mut pos = 6;
149 let mut std_buffer_bounds = Vec::new();
150 while pos < body.len() && body[pos] & 0x80 != 0 {
151 let stream_id = body[pos];
152 if stream_id == EXT_STREAM_ID {
153 if pos + 6 > body.len() {
155 return Err(Error::BufferTooShort {
156 need: pos + 6,
157 have: body.len(),
158 what: "system_header extended stream entry",
159 });
160 }
161 if body[pos + 1] & 0xC0 != 0xC0 {
163 return Err(Error::BadStreamIdExtensionPrefix(body[pos + 1]));
164 }
165 let stream_id_extension = body[pos + 2] & 0x7F;
167 if body[pos + 3] != 0xB6 {
169 return Err(Error::BadStreamIdExtensionPrefix(body[pos + 3]));
170 }
171 if body[pos + 4] & 0xC0 != 0xC0 {
173 return Err(Error::BadMarker("P-STD_buffer_bound_scale prefix (ext)"));
174 }
175 let buffer_bound_scale = body[pos + 4] & 0x20 != 0;
176 let buffer_size_bound =
186 (u16::from(body[pos + 4] & 0x1F) << 8) | u16::from(body[pos + 5]);
187 std_buffer_bounds.push(StdBufferBound {
188 stream_id,
189 stream_id_extension: Some(stream_id_extension),
190 buffer_bound_scale,
191 buffer_size_bound,
192 });
193 pos += 6;
194 } else {
195 if pos + 3 > body.len() {
197 return Err(Error::BufferTooShort {
198 need: pos + 3,
199 have: body.len(),
200 what: "system_header stream entry",
201 });
202 }
203 if body[pos + 1] & 0xC0 != 0xC0 {
205 return Err(Error::BadMarker("P-STD_buffer_bound_scale prefix"));
206 }
207 let buffer_bound_scale = body[pos + 1] & 0x20 != 0;
208 let buffer_size_bound =
211 (u16::from(body[pos + 1] & 0x1F) << 8) | u16::from(body[pos + 2]);
212 std_buffer_bounds.push(StdBufferBound {
213 stream_id,
214 stream_id_extension: None,
215 buffer_bound_scale,
216 buffer_size_bound,
217 });
218 pos += 3;
219 }
220 }
221
222 Ok(SystemHeader {
223 rate_bound,
224 audio_bound,
225 fixed_flag,
226 csps_flag,
227 system_audio_lock_flag,
228 system_video_lock_flag,
229 video_bound,
230 packet_rate_restriction_flag,
231 std_buffer_bounds,
232 })
233 }
234}
235
236impl Serialize for SystemHeader {
237 type Error = Error;
238
239 fn serialized_len(&self) -> usize {
240 PREFIX_LEN + 6 + stream_loop_len(self) as usize
241 }
242
243 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
244 let total = self.serialized_len();
245 if buf.len() < total {
246 return Err(Error::BufferTooShort {
247 need: total,
248 have: buf.len(),
249 what: "system_header serialize output",
250 });
251 }
252
253 buf[0..4].copy_from_slice(&SYSTEM_HEADER_START_CODE.to_be_bytes());
255
256 let header_length = 6 + stream_loop_len(self);
258 buf[4..6].copy_from_slice(&header_length.to_be_bytes());
259
260 let rate_bound = self.rate_bound & 0x3F_FFFF;
261 buf[6] = 0x80 | ((rate_bound >> 15) & 0x7F) as u8;
263 buf[7] = ((rate_bound >> 7) & 0xFF) as u8;
265 buf[8] = (((rate_bound & 0x7F) as u8) << 1) | 0x01;
267 buf[9] = (self.audio_bound & 0x3F) << 2
269 | (u8::from(self.fixed_flag) << 1)
270 | u8::from(self.csps_flag);
271 buf[10] = (u8::from(self.system_audio_lock_flag) << 7)
273 | (u8::from(self.system_video_lock_flag) << 6)
274 | 0x20 | (self.video_bound & 0x1F);
276 buf[11] = (u8::from(self.packet_rate_restriction_flag) << 7) | 0x7F;
278
279 let mut pos = 12;
281 for bound in &self.std_buffer_bounds {
282 if let Some(ext) = bound.stream_id_extension {
283 buf[pos] = bound.stream_id;
284 buf[pos + 1] = 0xC0;
285 buf[pos + 2] = ext & 0x7F;
286 buf[pos + 3] = 0xB6;
287 buf[pos + 4] = 0xC0
288 | (u8::from(bound.buffer_bound_scale) << 5)
289 | ((bound.buffer_size_bound >> 8) & 0x1F) as u8;
290 buf[pos + 5] = (bound.buffer_size_bound & 0xFF) as u8;
291 pos += 6;
292 } else {
293 buf[pos] = bound.stream_id;
294 buf[pos + 1] = 0xC0
295 | (u8::from(bound.buffer_bound_scale) << 5)
296 | ((bound.buffer_size_bound >> 8) & 0x1F) as u8;
297 buf[pos + 2] = (bound.buffer_size_bound & 0xFF) as u8;
298 pos += 3;
299 }
300 }
301
302 Ok(total)
303 }
304}
305
306#[cfg(test)]
307mod tests {
308 use super::*;
309 use alloc::vec;
310
311 #[test]
312 fn system_header_round_trip_no_streams() {
313 let bytes = vec![
314 0x00, 0x00, 0x01, 0xBB, 0x00, 0x06, 0x80, 0x00, 0x01, 0x04, 0x20, 0xFF, ];
321 let h = SystemHeader::parse(&bytes).unwrap();
322 assert_eq!(h.rate_bound, 0);
323 assert_eq!(h.audio_bound, 1);
324 assert!(!h.fixed_flag);
325 assert!(!h.csps_flag);
326 assert!(!h.system_audio_lock_flag);
327 assert!(!h.system_video_lock_flag);
328 assert_eq!(h.video_bound, 0);
329 assert!(h.packet_rate_restriction_flag);
330 assert!(h.std_buffer_bounds.is_empty());
331
332 let mut out = vec![0u8; h.serialized_len()];
333 h.serialize_into(&mut out).unwrap();
334 assert_eq!(&out[..], &bytes[..]);
335
336 let h2 = SystemHeader::parse(&out).unwrap();
337 assert_eq!(h, h2);
338 }
339
340 #[test]
341 fn system_header_round_trip_with_streams() {
342 let bytes = vec![
343 0x00, 0x00, 0x01, 0xBB, 0x00,
344 0x0C, 0x80, 0x00, 0x01, 0x04, 0x20, 0xFF,
346 0xE0, 0xFF, 0xFF, 0xC0, 0xC1, 0x00,
349 ];
350 let h = SystemHeader::parse(&bytes).unwrap();
351 assert_eq!(h.std_buffer_bounds.len(), 2);
352 assert_eq!(h.std_buffer_bounds[0].stream_id, 0xE0);
353 assert!(h.std_buffer_bounds[0].stream_id_extension.is_none());
354 assert!(h.std_buffer_bounds[0].buffer_bound_scale);
355 assert_eq!(h.std_buffer_bounds[0].buffer_size_bound, 0x1FFF);
356
357 assert_eq!(h.std_buffer_bounds[1].stream_id, 0xC0);
358 assert!(h.std_buffer_bounds[1].stream_id_extension.is_none());
359 assert!(!h.std_buffer_bounds[1].buffer_bound_scale);
360 assert_eq!(h.std_buffer_bounds[1].buffer_size_bound, 0x0100);
361
362 let mut out = vec![0u8; h.serialized_len()];
363 h.serialize_into(&mut out).unwrap();
364 assert_eq!(&out[..], &bytes[..]);
365
366 let h2 = SystemHeader::parse(&out).unwrap();
367 assert_eq!(h, h2);
368
369 let h_mut = SystemHeader {
371 rate_bound: 12345,
372 ..h.clone()
373 };
374 let mut out2 = vec![0u8; h_mut.serialized_len()];
375 h_mut.serialize_into(&mut out2).unwrap();
376 assert_ne!(&out[..], &out2[..]);
377 }
378
379 #[test]
380 fn system_header_round_trip_extended_stream_id() {
381 let bytes = vec![
382 0x00, 0x00, 0x01, 0xBB, 0x00, 0x0C, 0x80, 0x00, 0x01, 0x04, 0x20, 0xFF,
384 0xB7, 0xC0, 0x05, 0xB6, 0xE1, 0x00,
386 ];
387 let h = SystemHeader::parse(&bytes).unwrap();
388 assert_eq!(h.std_buffer_bounds.len(), 1);
389 assert_eq!(h.std_buffer_bounds[0].stream_id, 0xB7);
390 assert_eq!(h.std_buffer_bounds[0].stream_id_extension, Some(0x05));
391 assert!(h.std_buffer_bounds[0].buffer_bound_scale);
392 assert_eq!(h.std_buffer_bounds[0].buffer_size_bound, 0x100);
393
394 let mut out = vec![0u8; h.serialized_len()];
395 h.serialize_into(&mut out).unwrap();
396 assert_eq!(&out[..], &bytes[..]);
397 }
398}