1use alloc::vec::Vec;
9
10use crate::error::{Error, Result};
11use broadcast_common::{Parse, Serialize};
12
13pub const SYSTEM_HEADER_START_CODE: u32 = 0x0000_01BB;
15
16const EXT_STREAM_ID: u8 = 0xB7;
18
19pub(crate) const PREFIX_LEN: usize = 6;
21const RESERVED_BITS_MASK: u8 = 0x7F;
23
24#[derive(Debug, Clone, PartialEq, Eq)]
26#[cfg_attr(feature = "serde", derive(serde::Serialize))]
27pub struct StdBufferBound {
28 pub stream_id: u8,
30 pub stream_id_extension: Option<u8>,
33 pub buffer_bound_scale: bool,
35 pub buffer_size_bound: u16,
37}
38
39#[derive(Debug, Clone, PartialEq, Eq)]
41#[cfg_attr(feature = "serde", derive(serde::Serialize))]
42pub struct SystemHeader {
43 pub rate_bound: u32,
45 pub audio_bound: u8,
47 pub fixed_flag: bool,
49 pub csps_flag: bool,
51 pub system_audio_lock_flag: bool,
53 pub system_video_lock_flag: bool,
55 pub video_bound: u8,
57 pub packet_rate_restriction_flag: bool,
59 pub reserved_bits: u8,
64 pub std_buffer_bounds: Vec<StdBufferBound>,
66}
67
68fn stream_loop_len(system_header: &SystemHeader) -> usize {
76 let mut len: usize = 0;
77 for b in &system_header.std_buffer_bounds {
78 if b.stream_id_extension.is_some() {
79 len += 6;
80 } else {
81 len += 3;
82 }
83 }
84 len
85}
86
87impl<'a> Parse<'a> for SystemHeader {
88 type Error = Error;
89
90 fn parse(b: &'a [u8]) -> Result<Self> {
91 if b.len() < PREFIX_LEN {
92 return Err(Error::BufferTooShort {
93 need: PREFIX_LEN,
94 have: b.len(),
95 what: "system_header prefix",
96 });
97 }
98
99 if u32::from_be_bytes([b[0], b[1], b[2], b[3]]) != SYSTEM_HEADER_START_CODE {
100 return Err(Error::BadSystemHeaderStartCode(u32::from_be_bytes([
101 b[0], b[1], b[2], b[3],
102 ])));
103 }
104
105 let header_length = u16::from_be_bytes([b[4], b[5]]) as usize;
106 let body_end = PREFIX_LEN + header_length;
107 if b.len() < body_end {
108 return Err(Error::HeaderLengthOverflow {
109 header_length,
110 available: b.len().saturating_sub(PREFIX_LEN),
111 });
112 }
113 let body = &b[PREFIX_LEN..body_end];
114
115 if body.len() < 6 {
124 return Err(Error::BufferTooShort {
125 need: 6 + PREFIX_LEN,
126 have: b.len(),
127 what: "system_header fixed body",
128 });
129 }
130
131 if body[0] & 0x80 == 0 {
133 return Err(Error::BadMarker("system_header rate_bound marker 1"));
134 }
135 if body[2] & 0x01 == 0 {
136 return Err(Error::BadMarker("system_header rate_bound marker 2"));
137 }
138 if body[4] & 0x20 == 0 {
139 return Err(Error::BadMarker("system_header video_bound marker"));
140 }
141
142 let rate_bound = ((u32::from(body[0] & 0x7F) << 15)
144 | (u32::from(body[1]) << 7)
145 | u32::from(body[2] >> 1))
146 & 0x3F_FFFF;
147
148 let audio_bound = (body[3] >> 2) & 0x3F;
150 let fixed_flag = body[3] & 0x02 != 0;
151 let csps_flag = body[3] & 0x01 != 0;
152
153 let system_audio_lock_flag = body[4] & 0x80 != 0;
155 let system_video_lock_flag = body[4] & 0x40 != 0;
156 let video_bound = body[4] & 0x1F;
161
162 let packet_rate_restriction_flag = body[5] & 0x80 != 0;
164 let reserved_bits = body[5] & RESERVED_BITS_MASK;
165
166 let mut pos = 6;
168 let mut std_buffer_bounds = Vec::new();
169 while pos < body.len() && body[pos] & 0x80 != 0 {
170 let stream_id = body[pos];
171 if stream_id == EXT_STREAM_ID {
172 if pos + 6 > body.len() {
174 return Err(Error::BufferTooShort {
175 need: pos + 6,
176 have: body.len(),
177 what: "system_header extended stream entry",
178 });
179 }
180 if body[pos + 1] & 0xC0 != 0xC0 {
182 return Err(Error::BadStreamIdExtensionPrefix(body[pos + 1]));
183 }
184 let stream_id_extension = body[pos + 2] & 0x7F;
186 if body[pos + 3] != 0xB6 {
188 return Err(Error::BadStreamIdExtensionPrefix(body[pos + 3]));
189 }
190 if body[pos + 4] & 0xC0 != 0xC0 {
192 return Err(Error::BadMarker("P-STD_buffer_bound_scale prefix (ext)"));
193 }
194 let buffer_bound_scale = body[pos + 4] & 0x20 != 0;
195 let buffer_size_bound =
198 (u16::from(body[pos + 4] & 0x1F) << 8) | u16::from(body[pos + 5]);
199 std_buffer_bounds.push(StdBufferBound {
200 stream_id,
201 stream_id_extension: Some(stream_id_extension),
202 buffer_bound_scale,
203 buffer_size_bound,
204 });
205 pos += 6;
206 } else {
207 if pos + 3 > body.len() {
209 return Err(Error::BufferTooShort {
210 need: pos + 3,
211 have: body.len(),
212 what: "system_header stream entry",
213 });
214 }
215 if body[pos + 1] & 0xC0 != 0xC0 {
217 return Err(Error::BadMarker("P-STD_buffer_bound_scale prefix"));
218 }
219 let buffer_bound_scale = body[pos + 1] & 0x20 != 0;
220 let buffer_size_bound =
222 (u16::from(body[pos + 1] & 0x1F) << 8) | u16::from(body[pos + 2]);
223 std_buffer_bounds.push(StdBufferBound {
224 stream_id,
225 stream_id_extension: None,
226 buffer_bound_scale,
227 buffer_size_bound,
228 });
229 pos += 3;
230 }
231 }
232
233 Ok(SystemHeader {
234 rate_bound,
235 audio_bound,
236 fixed_flag,
237 csps_flag,
238 system_audio_lock_flag,
239 system_video_lock_flag,
240 video_bound,
241 packet_rate_restriction_flag,
242 reserved_bits,
243 std_buffer_bounds,
244 })
245 }
246}
247
248impl Serialize for SystemHeader {
249 type Error = Error;
250
251 fn serialized_len(&self) -> usize {
252 PREFIX_LEN + 6 + stream_loop_len(self)
253 }
254
255 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
256 let total = self.serialized_len();
257 if buf.len() < total {
258 return Err(Error::BufferTooShort {
259 need: total,
260 have: buf.len(),
261 what: "system_header serialize output",
262 });
263 }
264
265 buf[0..4].copy_from_slice(&SYSTEM_HEADER_START_CODE.to_be_bytes());
267
268 let header_length = broadcast_common::len::fit_u16(
270 6 + stream_loop_len(self),
271 "system_header.header_length",
272 )?;
273 buf[4..6].copy_from_slice(&header_length.to_be_bytes());
274
275 let rate_bound = self.rate_bound & 0x3F_FFFF;
276 buf[6] = 0x80 | ((rate_bound >> 15) & 0x7F) as u8;
278 buf[7] = ((rate_bound >> 7) & 0xFF) as u8;
280 buf[8] = (((rate_bound & 0x7F) as u8) << 1) | 0x01;
282 buf[9] = (self.audio_bound & 0x3F) << 2
284 | (u8::from(self.fixed_flag) << 1)
285 | u8::from(self.csps_flag);
286 buf[10] = (u8::from(self.system_audio_lock_flag) << 7)
288 | (u8::from(self.system_video_lock_flag) << 6)
289 | 0x20 | (self.video_bound & 0x1F);
291 buf[11] = (u8::from(self.packet_rate_restriction_flag) << 7)
293 | (self.reserved_bits & RESERVED_BITS_MASK);
294
295 let mut pos = 12;
297 for bound in &self.std_buffer_bounds {
298 if let Some(ext) = bound.stream_id_extension {
299 buf[pos] = bound.stream_id;
300 buf[pos + 1] = 0xC0;
301 buf[pos + 2] = ext & 0x7F;
302 buf[pos + 3] = 0xB6;
303 buf[pos + 4] = 0xC0
304 | (u8::from(bound.buffer_bound_scale) << 5)
305 | ((bound.buffer_size_bound >> 8) & 0x1F) as u8;
306 buf[pos + 5] = (bound.buffer_size_bound & 0xFF) as u8;
307 pos += 6;
308 } else {
309 buf[pos] = bound.stream_id;
310 buf[pos + 1] = 0xC0
311 | (u8::from(bound.buffer_bound_scale) << 5)
312 | ((bound.buffer_size_bound >> 8) & 0x1F) as u8;
313 buf[pos + 2] = (bound.buffer_size_bound & 0xFF) as u8;
314 pos += 3;
315 }
316 }
317
318 Ok(total)
319 }
320}
321
322#[cfg(test)]
323mod tests {
324 use super::*;
325 use alloc::vec;
326
327 #[test]
328 fn system_header_round_trip_no_streams() {
329 let bytes = vec![
330 0x00, 0x00, 0x01, 0xBB, 0x00, 0x06, 0x80, 0x00, 0x01, 0x04, 0x20, 0xFF, ];
337 let h = SystemHeader::parse(&bytes).unwrap();
338 assert_eq!(h.rate_bound, 0);
339 assert_eq!(h.audio_bound, 1);
340 assert!(!h.fixed_flag);
341 assert!(!h.csps_flag);
342 assert!(!h.system_audio_lock_flag);
343 assert!(!h.system_video_lock_flag);
344 assert_eq!(h.video_bound, 0);
345 assert!(h.packet_rate_restriction_flag);
346 assert!(h.std_buffer_bounds.is_empty());
347
348 let mut out = vec![0u8; h.serialized_len()];
349 h.serialize_into(&mut out).unwrap();
350 assert_eq!(&out[..], &bytes[..]);
351
352 let h2 = SystemHeader::parse(&out).unwrap();
353 assert_eq!(h, h2);
354 }
355
356 #[test]
361 fn video_bound_bit_4_round_trips() {
362 let bytes = vec![
363 0x00,
364 0x00,
365 0x01,
366 0xBB, 0x00,
368 0x06, 0x80,
370 0x00,
371 0x01, 0x04, 0x20 | 0x1F, 0xFF,
375 ];
376 let h = SystemHeader::parse(&bytes).unwrap();
377 assert_eq!(
378 h.video_bound, 31,
379 "bit 4 of video_bound must not be dropped"
380 );
381
382 let mut out = vec![0u8; h.serialized_len()];
383 h.serialize_into(&mut out).unwrap();
384 assert_eq!(&out[..], &bytes[..]);
385 }
386
387 #[test]
388 fn system_header_round_trip_with_streams() {
389 let bytes = vec![
390 0x00, 0x00, 0x01, 0xBB, 0x00,
391 0x0C, 0x80, 0x00, 0x01, 0x04, 0x20, 0xFF,
393 0xE0, 0xFF, 0xFF, 0xC0, 0xC1, 0x00,
396 ];
397 let h = SystemHeader::parse(&bytes).unwrap();
398 assert_eq!(h.std_buffer_bounds.len(), 2);
399 assert_eq!(h.std_buffer_bounds[0].stream_id, 0xE0);
400 assert!(h.std_buffer_bounds[0].stream_id_extension.is_none());
401 assert!(h.std_buffer_bounds[0].buffer_bound_scale);
402 assert_eq!(h.std_buffer_bounds[0].buffer_size_bound, 0x1FFF);
403
404 assert_eq!(h.std_buffer_bounds[1].stream_id, 0xC0);
405 assert!(h.std_buffer_bounds[1].stream_id_extension.is_none());
406 assert!(!h.std_buffer_bounds[1].buffer_bound_scale);
407 assert_eq!(h.std_buffer_bounds[1].buffer_size_bound, 0x0100);
408
409 let mut out = vec![0u8; h.serialized_len()];
410 h.serialize_into(&mut out).unwrap();
411 assert_eq!(&out[..], &bytes[..]);
412
413 let h2 = SystemHeader::parse(&out).unwrap();
414 assert_eq!(h, h2);
415
416 let h_mut = SystemHeader {
418 rate_bound: 12345,
419 ..h.clone()
420 };
421 let mut out2 = vec![0u8; h_mut.serialized_len()];
422 h_mut.serialize_into(&mut out2).unwrap();
423 assert_ne!(&out[..], &out2[..]);
424 }
425
426 #[test]
429 fn non_conventional_reserved_bits_round_trip() {
430 let bytes = vec![
431 0x00, 0x00, 0x01, 0xBB, 0x00, 0x06, 0x80, 0x00, 0x01, 0x04, 0x20, 0x2A, ];
438 let h = SystemHeader::parse(&bytes).unwrap();
439 assert_eq!(h.reserved_bits, 0x2A);
440 assert!(!h.packet_rate_restriction_flag);
441 let mut out = vec![0u8; h.serialized_len()];
442 h.serialize_into(&mut out).unwrap();
443 assert_eq!(out, bytes);
444 }
445
446 #[test]
458 fn many_bounds_past_old_u16_overflow_point_errs_not_panics() {
459 let std_buffer_bounds = (0..11_000)
460 .map(|_| StdBufferBound {
461 stream_id: EXT_STREAM_ID,
462 stream_id_extension: Some(0x05),
463 buffer_bound_scale: false,
464 buffer_size_bound: 0,
465 })
466 .collect::<Vec<_>>();
467 let h = SystemHeader {
468 rate_bound: 0,
469 audio_bound: 0,
470 fixed_flag: false,
471 csps_flag: false,
472 system_audio_lock_flag: false,
473 system_video_lock_flag: false,
474 video_bound: 0,
475 packet_rate_restriction_flag: false,
476 reserved_bits: RESERVED_BITS_MASK,
477 std_buffer_bounds,
478 };
479 let mut buf = vec![0u8; h.serialized_len()];
483 assert!(h.serialize_into(&mut buf).is_err());
484 }
485
486 #[test]
489 fn header_length_over_u16_is_rejected_not_wrapped() {
490 let std_buffer_bounds = (0..25_000)
491 .map(|_| StdBufferBound {
492 stream_id: 0xC0,
493 stream_id_extension: None,
494 buffer_bound_scale: false,
495 buffer_size_bound: 0,
496 })
497 .collect::<Vec<_>>();
498 let h = SystemHeader {
499 rate_bound: 0,
500 audio_bound: 0,
501 fixed_flag: false,
502 csps_flag: false,
503 system_audio_lock_flag: false,
504 system_video_lock_flag: false,
505 video_bound: 0,
506 packet_rate_restriction_flag: false,
507 reserved_bits: RESERVED_BITS_MASK,
508 std_buffer_bounds,
509 };
510 let mut buf = vec![0u8; h.serialized_len()];
511 assert!(h.serialize_into(&mut buf).is_err());
512 }
513
514 #[test]
517 fn many_bounds_within_u16_header_length_round_trips() {
518 let std_buffer_bounds = (0..1000)
519 .map(|_| StdBufferBound {
520 stream_id: 0xC0,
521 stream_id_extension: None,
522 buffer_bound_scale: false,
523 buffer_size_bound: 0x0100,
524 })
525 .collect::<Vec<_>>();
526 let h = SystemHeader {
527 rate_bound: 0,
528 audio_bound: 0,
529 fixed_flag: false,
530 csps_flag: false,
531 system_audio_lock_flag: false,
532 system_video_lock_flag: false,
533 video_bound: 0,
534 packet_rate_restriction_flag: false,
535 reserved_bits: RESERVED_BITS_MASK,
536 std_buffer_bounds,
537 };
538 let mut buf = vec![0u8; h.serialized_len()];
539 h.serialize_into(&mut buf).unwrap();
540 let back = SystemHeader::parse(&buf).unwrap();
541 assert_eq!(back.std_buffer_bounds.len(), 1000);
542 }
543
544 #[test]
545 fn system_header_round_trip_extended_stream_id() {
546 let bytes = vec![
547 0x00, 0x00, 0x01, 0xBB, 0x00, 0x0C, 0x80, 0x00, 0x01, 0x04, 0x20, 0xFF,
549 0xB7, 0xC0, 0x05, 0xB6, 0xE1, 0x00,
551 ];
552 let h = SystemHeader::parse(&bytes).unwrap();
553 assert_eq!(h.std_buffer_bounds.len(), 1);
554 assert_eq!(h.std_buffer_bounds[0].stream_id, 0xB7);
555 assert_eq!(h.std_buffer_bounds[0].stream_id_extension, Some(0x05));
556 assert!(h.std_buffer_bounds[0].buffer_bound_scale);
557 assert_eq!(h.std_buffer_bounds[0].buffer_size_bound, 0x100);
558
559 let mut out = vec![0u8; h.serialized_len()];
560 h.serialize_into(&mut out).unwrap();
561 assert_eq!(&out[..], &bytes[..]);
562 }
563}