1use crate::TsError;
37
38pub const TS_PACKET_LEN: usize = 188;
40
41pub const TS_SYNC_BYTE: u8 = 0x47;
43
44#[derive(Debug, Clone, Copy)]
46pub struct AdaptationField<'a> {
47 pub length: u8,
51 pub discontinuity_indicator: bool,
53 pub random_access_indicator: bool,
55 pub elementary_stream_priority_indicator: bool,
57 pub pcr_flag: bool,
60 pub opcr_flag: bool,
62 pub splicing_point_flag: bool,
64 pub transport_private_data_flag: bool,
66 pub adaptation_field_extension_flag: bool,
68 pub pcr_base: Option<u64>,
70 pub pcr_extension: Option<u16>,
73 pub opcr_base: Option<u64>,
76 pub opcr_extension: Option<u16>,
79 pub splice_countdown: Option<i8>,
82 pub transport_private_data: Option<&'a [u8]>,
86 pub adaptation_field_extension: Option<AdaptationFieldExtension>,
89 pub raw: &'a [u8],
92}
93
94#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
96pub struct AdaptationFieldExtension {
97 pub length: u8,
100 pub ltw_flag: bool,
102 pub piecewise_rate_flag: bool,
104 pub seamless_splice_flag: bool,
106 pub ltw_valid_flag: Option<bool>,
108 pub ltw_offset: Option<u16>,
111 pub piecewise_rate: Option<u32>,
114 pub splice_type: Option<u8>,
117 pub dts_next_au: Option<u64>,
120}
121
122#[derive(Debug, Clone, Copy)]
124pub struct TsPacket<'a> {
125 pub pid: u16,
128 pub payload_unit_start: bool,
131 pub transport_error: bool,
134 pub transport_priority: bool,
137 pub transport_scrambling_control: u8,
139 pub continuity_counter: u8,
141 pub adaptation_field: Option<AdaptationField<'a>>,
144 pub payload: &'a [u8],
147 pub bytes: &'a [u8],
149}
150
151impl<'a> TsPacket<'a> {
152 pub fn parse(bytes: &'a [u8]) -> Result<Self, TsError> {
157 if bytes.len() < TS_PACKET_LEN {
158 return Err(TsError::Truncated {
159 what: "TS packet",
160 have: bytes.len(),
161 need: TS_PACKET_LEN,
162 });
163 }
164 let bytes = &bytes[..TS_PACKET_LEN];
165 if bytes[0] != TS_SYNC_BYTE {
166 return Err(TsError::BadSyncByte(bytes[0]));
167 }
168
169 let b1 = bytes[1];
170 let b2 = bytes[2];
171 let b3 = bytes[3];
172
173 let transport_error = (b1 & 0b1000_0000) != 0;
174 let payload_unit_start = (b1 & 0b0100_0000) != 0;
175 let transport_priority = (b1 & 0b0010_0000) != 0;
176 let pid = (((b1 & 0b0001_1111) as u16) << 8) | (b2 as u16);
177 let transport_scrambling_control = (b3 >> 6) & 0b11;
178 let adaptation_field_control = (b3 >> 4) & 0b11;
179 let continuity_counter = b3 & 0b1111;
180
181 let has_af = (adaptation_field_control & 0b10) != 0;
182 let has_payload = (adaptation_field_control & 0b01) != 0;
183
184 let mut cursor: usize = 4;
187 let mut adaptation_field = None;
188
189 if has_af {
190 let af_len = bytes[cursor] as usize;
195 let af_total = af_len + 1;
196 let af_end = cursor.checked_add(af_total).ok_or(TsError::Truncated {
197 what: "TS adaptation_field",
198 have: bytes.len() - cursor,
199 need: af_total,
200 })?;
201 if af_end > TS_PACKET_LEN {
202 return Err(TsError::Truncated {
203 what: "TS adaptation_field",
204 have: TS_PACKET_LEN - cursor,
205 need: af_total,
206 });
207 }
208
209 let af_raw = &bytes[cursor..af_end];
210 adaptation_field = Some(parse_adaptation_field(af_raw)?);
211 cursor = af_end;
212 }
213
214 let payload = if has_payload {
215 &bytes[cursor..]
216 } else {
217 &[][..]
218 };
219
220 Ok(Self {
221 pid,
222 payload_unit_start,
223 transport_error,
224 transport_priority,
225 transport_scrambling_control,
226 continuity_counter,
227 adaptation_field,
228 payload,
229 bytes,
230 })
231 }
232}
233
234fn parse_adaptation_field(raw: &[u8]) -> Result<AdaptationField<'_>, TsError> {
235 let length = raw[0];
237 if length == 0 {
238 return Ok(AdaptationField {
239 length: 0,
240 discontinuity_indicator: false,
241 random_access_indicator: false,
242 elementary_stream_priority_indicator: false,
243 pcr_flag: false,
244 opcr_flag: false,
245 splicing_point_flag: false,
246 transport_private_data_flag: false,
247 adaptation_field_extension_flag: false,
248 pcr_base: None,
249 pcr_extension: None,
250 opcr_base: None,
251 opcr_extension: None,
252 splice_countdown: None,
253 transport_private_data: None,
254 adaptation_field_extension: None,
255 raw,
256 });
257 }
258 if raw.len() < 2 {
259 return Err(TsError::Truncated {
260 what: "TS adaptation_field flags",
261 have: raw.len(),
262 need: 2,
263 });
264 }
265 let flags = raw[1];
266 let discontinuity_indicator = (flags & 0b1000_0000) != 0;
267 let random_access_indicator = (flags & 0b0100_0000) != 0;
268 let elementary_stream_priority_indicator = (flags & 0b0010_0000) != 0;
269 let pcr_flag = (flags & 0b0001_0000) != 0;
270 let opcr_flag = (flags & 0b0000_1000) != 0;
271 let splicing_point_flag = (flags & 0b0000_0100) != 0;
272 let transport_private_data_flag = (flags & 0b0000_0010) != 0;
273 let adaptation_field_extension_flag = (flags & 0b0000_0001) != 0;
274
275 let mut cursor = 2usize;
276
277 let (pcr_base, pcr_extension) = if pcr_flag {
279 let (b, e) = parse_clock_reference(raw, cursor, "TS adaptation_field PCR")?;
280 cursor += 6;
281 (Some(b), Some(e))
282 } else {
283 (None, None)
284 };
285
286 let (opcr_base, opcr_extension) = if opcr_flag {
288 let (b, e) = parse_clock_reference(raw, cursor, "TS adaptation_field OPCR")?;
289 cursor += 6;
290 (Some(b), Some(e))
291 } else {
292 (None, None)
293 };
294
295 let splice_countdown = if splicing_point_flag {
297 if cursor + 1 > raw.len() {
298 return Err(TsError::Truncated {
299 what: "TS adaptation_field splice_countdown",
300 have: raw.len() - cursor,
301 need: 1,
302 });
303 }
304 let v = raw[cursor] as i8;
305 cursor += 1;
306 Some(v)
307 } else {
308 None
309 };
310
311 let transport_private_data = if transport_private_data_flag {
313 if cursor + 1 > raw.len() {
314 return Err(TsError::Truncated {
315 what: "TS adaptation_field transport_private_data_length",
316 have: raw.len() - cursor,
317 need: 1,
318 });
319 }
320 let n = raw[cursor] as usize;
321 cursor += 1;
322 let end = cursor.checked_add(n).ok_or(TsError::Truncated {
323 what: "TS adaptation_field private_data",
324 have: raw.len() - cursor,
325 need: n,
326 })?;
327 if end > raw.len() {
328 return Err(TsError::Truncated {
329 what: "TS adaptation_field private_data",
330 have: raw.len() - cursor,
331 need: n,
332 });
333 }
334 let slice = &raw[cursor..end];
335 cursor = end;
336 Some(slice)
337 } else {
338 None
339 };
340
341 let adaptation_field_extension = if adaptation_field_extension_flag {
344 Some(parse_extension(raw, &mut cursor)?)
345 } else {
346 None
347 };
348
349 let _ = cursor;
352
353 Ok(AdaptationField {
354 length,
355 discontinuity_indicator,
356 random_access_indicator,
357 elementary_stream_priority_indicator,
358 pcr_flag,
359 opcr_flag,
360 splicing_point_flag,
361 transport_private_data_flag,
362 adaptation_field_extension_flag,
363 pcr_base,
364 pcr_extension,
365 opcr_base,
366 opcr_extension,
367 splice_countdown,
368 transport_private_data,
369 adaptation_field_extension,
370 raw,
371 })
372}
373
374fn parse_clock_reference(
377 raw: &[u8],
378 cursor: usize,
379 what: &'static str,
380) -> Result<(u64, u16), TsError> {
381 if cursor + 6 > raw.len() {
382 return Err(TsError::Truncated {
383 what,
384 have: raw.len() - cursor,
385 need: 6,
386 });
387 }
388 let p = &raw[cursor..cursor + 6];
389 let base: u64 = ((p[0] as u64) << 25)
390 | ((p[1] as u64) << 17)
391 | ((p[2] as u64) << 9)
392 | ((p[3] as u64) << 1)
393 | (((p[4] >> 7) & 0b1) as u64);
394 let ext: u16 = (((p[4] & 0b0000_0001) as u16) << 8) | (p[5] as u16);
395 Ok((base, ext))
396}
397
398fn parse_extension(raw: &[u8], cursor: &mut usize) -> Result<AdaptationFieldExtension, TsError> {
399 if *cursor + 1 > raw.len() {
400 return Err(TsError::Truncated {
401 what: "TS adaptation_field_extension_length",
402 have: raw.len() - *cursor,
403 need: 1,
404 });
405 }
406 let ext_len = raw[*cursor] as usize;
407 *cursor += 1;
408 let ext_end = cursor.checked_add(ext_len).ok_or(TsError::Truncated {
409 what: "TS adaptation_field_extension body",
410 have: raw.len() - *cursor,
411 need: ext_len,
412 })?;
413 if ext_end > raw.len() {
414 return Err(TsError::Truncated {
415 what: "TS adaptation_field_extension body",
416 have: raw.len() - *cursor,
417 need: ext_len,
418 });
419 }
420 if ext_len < 1 {
422 return Ok(AdaptationFieldExtension {
425 length: 0,
426 ..Default::default()
427 });
428 }
429 let flags = raw[*cursor];
430 *cursor += 1;
431 let body_end = ext_end; let ltw_flag = (flags & 0b1000_0000) != 0;
433 let piecewise_rate_flag = (flags & 0b0100_0000) != 0;
434 let seamless_splice_flag = (flags & 0b0010_0000) != 0;
435
436 let (ltw_valid_flag, ltw_offset) = if ltw_flag {
437 if *cursor + 2 > body_end {
438 return Err(TsError::Truncated {
439 what: "TS adaptation_field ltw",
440 have: body_end - *cursor,
441 need: 2,
442 });
443 }
444 let b0 = raw[*cursor];
445 let b1 = raw[*cursor + 1];
446 *cursor += 2;
447 let valid = (b0 & 0b1000_0000) != 0;
448 let offset = (((b0 & 0b0111_1111) as u16) << 8) | (b1 as u16);
449 (Some(valid), Some(offset))
450 } else {
451 (None, None)
452 };
453
454 let piecewise_rate = if piecewise_rate_flag {
455 if *cursor + 3 > body_end {
456 return Err(TsError::Truncated {
457 what: "TS adaptation_field piecewise_rate",
458 have: body_end - *cursor,
459 need: 3,
460 });
461 }
462 let p0 = raw[*cursor] & 0b0011_1111;
463 let p1 = raw[*cursor + 1];
464 let p2 = raw[*cursor + 2];
465 *cursor += 3;
466 Some(((p0 as u32) << 16) | ((p1 as u32) << 8) | (p2 as u32))
467 } else {
468 None
469 };
470
471 let (splice_type, dts_next_au) = if seamless_splice_flag {
472 if *cursor + 5 > body_end {
473 return Err(TsError::Truncated {
474 what: "TS adaptation_field seamless_splice",
475 have: body_end - *cursor,
476 need: 5,
477 });
478 }
479 let b0 = raw[*cursor];
485 let b1 = raw[*cursor + 1];
486 let b2 = raw[*cursor + 2];
487 let b3 = raw[*cursor + 3];
488 let b4 = raw[*cursor + 4];
489 *cursor += 5;
490 let stype = (b0 >> 4) & 0b1111;
491 let dts: u64 = (((b0 >> 1) & 0b0000_0111) as u64) << 30
492 | (b1 as u64) << 22
493 | (((b2 >> 1) & 0b0111_1111) as u64) << 15
494 | (b3 as u64) << 7
495 | (((b4 >> 1) & 0b0111_1111) as u64);
496 (Some(stype), Some(dts))
497 } else {
498 (None, None)
499 };
500
501 *cursor = body_end;
503
504 Ok(AdaptationFieldExtension {
505 length: ext_len as u8,
506 ltw_flag,
507 piecewise_rate_flag,
508 seamless_splice_flag,
509 ltw_valid_flag,
510 ltw_offset,
511 piecewise_rate,
512 splice_type,
513 dts_next_au,
514 })
515}
516
517#[derive(Debug)]
519pub struct TsPacketIter<'a> {
520 rest: &'a [u8],
521 halted: bool,
522}
523
524impl<'a> Iterator for TsPacketIter<'a> {
525 type Item = Result<TsPacket<'a>, TsError>;
526
527 fn next(&mut self) -> Option<Self::Item> {
528 if self.halted || self.rest.len() < TS_PACKET_LEN {
529 return None;
530 }
531 let (head, tail) = self.rest.split_at(TS_PACKET_LEN);
532 self.rest = tail;
533 match TsPacket::parse(head) {
534 Ok(pkt) => Some(Ok(pkt)),
535 Err(e) => {
536 self.halted = true;
540 Some(Err(e))
541 }
542 }
543 }
544}
545
546pub fn iter_packets(bytes: &[u8]) -> TsPacketIter<'_> {
552 TsPacketIter {
553 rest: bytes,
554 halted: false,
555 }
556}
557
558#[cfg(test)]
559mod tests {
560 use super::*;
561
562 fn make_packet(header: [u8; 4], tail: &[u8]) -> Vec<u8> {
565 assert!(tail.len() <= 184);
566 let mut v = Vec::with_capacity(TS_PACKET_LEN);
567 v.extend_from_slice(&header);
568 v.extend_from_slice(tail);
569 v.resize(TS_PACKET_LEN, 0xFF);
570 v
571 }
572
573 #[test]
574 fn bare_audio_packet_payload_only() {
575 let header = [
578 0x47,
579 0b0100_0001, 0x00, 0b0001_0101, ];
583 let payload = [0xAA, 0xBB, 0xCC, 0xDD];
584 let bytes = make_packet(header, &payload);
585 let pkt = TsPacket::parse(&bytes).unwrap();
586 assert_eq!(pkt.pid, 0x0100);
587 assert!(pkt.payload_unit_start);
588 assert!(!pkt.transport_error);
589 assert_eq!(pkt.continuity_counter, 5);
590 assert!(pkt.adaptation_field.is_none());
591 assert_eq!(pkt.payload.len(), 184);
593 assert_eq!(&pkt.payload[..4], &payload);
594 }
595
596 #[test]
597 fn packet_with_adaptation_field_and_pcr() {
598 let base: u64 = 0x1_2345_6789;
602 let ext: u16 = 0x0AB;
603 let p0 = ((base >> 25) & 0xFF) as u8;
606 let p1 = ((base >> 17) & 0xFF) as u8;
607 let p2 = ((base >> 9) & 0xFF) as u8;
608 let p3 = ((base >> 1) & 0xFF) as u8;
609 let p4 = (((base & 0b1) as u8) << 7) | 0b0111_1110 | (((ext >> 8) & 0b1) as u8);
610 let p5 = (ext & 0xFF) as u8;
611
612 let af_len: u8 = 1 + 6;
615 let af = [af_len, 0b0101_0000, p0, p1, p2, p3, p4, p5];
616
617 let header = [0x47, 0x01, 0x00, 0b0011_1010];
620
621 let mut tail = Vec::new();
623 tail.extend_from_slice(&af);
624 tail.extend_from_slice(&[0x00, 0x00, 0x01, 0xE0]);
625
626 let bytes = make_packet(header, &tail);
627 let pkt = TsPacket::parse(&bytes).unwrap();
628 assert_eq!(pkt.pid, 0x0100);
629 assert!(!pkt.payload_unit_start);
630 assert_eq!(pkt.continuity_counter, 0xA);
631 let af = pkt.adaptation_field.expect("af present");
632 assert_eq!(af.length, 7);
633 assert!(af.random_access_indicator);
634 assert!(af.pcr_flag);
635 assert_eq!(af.pcr_base, Some(base));
636 assert_eq!(af.pcr_extension, Some(ext));
637 assert_eq!(pkt.payload.len(), TS_PACKET_LEN - 4 - 8);
639 assert_eq!(&pkt.payload[..4], &[0x00, 0x00, 0x01, 0xE0]);
640 }
641
642 #[test]
643 fn af_only_packet_has_empty_payload() {
644 let header = [0x47, 0x01, 0x00, 0b0010_0000];
647 let mut tail = Vec::new();
649 tail.push(183);
650 tail.push(0);
651 tail.extend(std::iter::repeat(0xFF).take(182));
652 let bytes = make_packet(header, &tail);
653 let pkt = TsPacket::parse(&bytes).unwrap();
654 assert!(pkt.adaptation_field.is_some());
655 assert_eq!(pkt.adaptation_field.unwrap().length, 183);
656 assert!(pkt.payload.is_empty());
657 }
658
659 #[test]
660 fn wrong_sync_byte_iterator_halts() {
661 let good_header = [0x47, 0x01, 0x00, 0b0001_0000];
662 let good = make_packet(good_header, &[]);
663 let mut bad = good.clone();
664 bad[0] = 0x48; let mut buf = Vec::new();
666 buf.extend_from_slice(&good);
667 buf.extend_from_slice(&bad);
668 buf.extend_from_slice(&good);
669
670 let mut it = iter_packets(&buf);
671 let first = it.next().unwrap().unwrap();
672 assert_eq!(first.pid, 0x0100);
673 let second = it.next().unwrap();
674 match second {
675 Err(TsError::BadSyncByte(0x48)) => {}
676 other => panic!("expected BadSyncByte(0x48), got {other:?}"),
677 }
678 assert!(it.next().is_none());
680 }
681
682 #[test]
683 fn truncated_tail_yields_nothing_extra() {
684 let good_header = [0x47, 0x00, 0x00, 0b0001_0000];
685 let good = make_packet(good_header, &[]);
686 let mut buf = Vec::new();
687 buf.extend_from_slice(&good);
688 buf.extend_from_slice(&[0x47, 0x00]); let mut it = iter_packets(&buf);
690 assert!(it.next().unwrap().is_ok());
691 assert!(it.next().is_none());
692 }
693
694 fn encode_clock_reference(base: u64, ext: u16) -> [u8; 6] {
697 let b0 = ((base >> 25) & 0xFF) as u8;
698 let b1 = ((base >> 17) & 0xFF) as u8;
699 let b2 = ((base >> 9) & 0xFF) as u8;
700 let b3 = ((base >> 1) & 0xFF) as u8;
701 let b4 = (((base & 0b1) as u8) << 7) | 0b0111_1110 | (((ext >> 8) & 0b1) as u8);
702 let b5 = (ext & 0xFF) as u8;
703 [b0, b1, b2, b3, b4, b5]
704 }
705
706 fn ts_packet_with_af(af_flags: u8, af_tail: &[u8]) -> Vec<u8> {
709 let af_len = (1 + af_tail.len()) as u8;
711 let header = [0x47, 0x01, 0x00, 0b0011_0000];
712 let mut tail = Vec::new();
713 tail.push(af_len);
714 tail.push(af_flags);
715 tail.extend_from_slice(af_tail);
716 make_packet(header, &tail)
717 }
718
719 #[test]
720 fn af_opcr_unpacked() {
721 let pcr_base: u64 = 0x0_0000_0001;
723 let pcr_ext: u16 = 0x000;
724 let opcr_base: u64 = 0x1_FEDC_BA98;
725 let opcr_ext: u16 = 0x1FE;
726 let mut tail = Vec::new();
727 tail.extend_from_slice(&encode_clock_reference(pcr_base, pcr_ext));
728 tail.extend_from_slice(&encode_clock_reference(opcr_base, opcr_ext));
729 let bytes = ts_packet_with_af(0b0001_1000, &tail);
731 let pkt = TsPacket::parse(&bytes).unwrap();
732 let af = pkt.adaptation_field.expect("af");
733 assert_eq!(af.pcr_base, Some(pcr_base));
734 assert_eq!(af.pcr_extension, Some(pcr_ext));
735 assert_eq!(af.opcr_base, Some(opcr_base));
736 assert_eq!(af.opcr_extension, Some(opcr_ext));
737 }
738
739 #[test]
740 fn af_splice_countdown_signed() {
741 let bytes = ts_packet_with_af(0b0000_0100, &[(-3i8) as u8]);
743 let pkt = TsPacket::parse(&bytes).unwrap();
744 let af = pkt.adaptation_field.expect("af");
745 assert!(af.splicing_point_flag);
746 assert_eq!(af.splice_countdown, Some(-3));
747 }
748
749 #[test]
750 fn af_transport_private_data() {
751 let payload: &[u8] = &[0xDE, 0xAD, 0xBE, 0xEF];
753 let mut tail = Vec::new();
754 tail.push(payload.len() as u8);
755 tail.extend_from_slice(payload);
756 let bytes = ts_packet_with_af(0b0000_0010, &tail);
757 let pkt = TsPacket::parse(&bytes).unwrap();
758 let af = pkt.adaptation_field.expect("af");
759 assert!(af.transport_private_data_flag);
760 assert_eq!(af.transport_private_data, Some(payload));
761 }
762
763 #[test]
764 fn af_extension_with_ltw_and_piecewise_rate() {
765 let ltw_offset: u16 = 0x1234;
769 let b0 = 0b1000_0000 | ((ltw_offset >> 8) & 0x7F) as u8;
770 let b1 = (ltw_offset & 0xFF) as u8;
771 let pwr: u32 = 0x2A_3B4C;
772 let p0 = ((pwr >> 16) & 0x3F) as u8 | 0b1100_0000; let p1 = ((pwr >> 8) & 0xFF) as u8;
774 let p2 = (pwr & 0xFF) as u8;
775 let tail = vec![
776 6, 0b1100_0000, b0,
779 b1,
780 p0,
781 p1,
782 p2,
783 ];
784 let bytes = ts_packet_with_af(0b0000_0001, &tail);
786 let pkt = TsPacket::parse(&bytes).unwrap();
787 let af = pkt.adaptation_field.expect("af");
788 let ext = af.adaptation_field_extension.expect("ext");
789 assert_eq!(ext.length, 6);
790 assert!(ext.ltw_flag);
791 assert!(ext.piecewise_rate_flag);
792 assert!(!ext.seamless_splice_flag);
793 assert_eq!(ext.ltw_valid_flag, Some(true));
794 assert_eq!(ext.ltw_offset, Some(0x1234));
795 assert_eq!(ext.piecewise_rate, Some(0x2A_3B4C));
796 assert_eq!(ext.splice_type, None);
797 assert_eq!(ext.dts_next_au, None);
798 }
799
800 #[test]
801 fn af_extension_seamless_splice_dts() {
802 let dts: u64 = 0x1_2345_6789;
805 let splice_type: u8 = 5;
806 let b0 = (splice_type << 4) | (((dts >> 30) & 0b0111) as u8) << 1 | 0b1;
807 let b1 = ((dts >> 22) & 0xFF) as u8;
808 let b2 = (((dts >> 15) & 0b0111_1111) as u8) << 1 | 0b1;
809 let b3 = ((dts >> 7) & 0xFF) as u8;
810 let b4 = (((dts & 0b0111_1111) as u8) << 1) | 0b1;
811 let mut tail = Vec::new();
812 tail.push(6); tail.push(0b0010_0000); tail.extend_from_slice(&[b0, b1, b2, b3, b4]);
815 let bytes = ts_packet_with_af(0b0000_0001, &tail);
816 let pkt = TsPacket::parse(&bytes).unwrap();
817 let ext = pkt
818 .adaptation_field
819 .unwrap()
820 .adaptation_field_extension
821 .expect("ext");
822 assert!(ext.seamless_splice_flag);
823 assert_eq!(ext.splice_type, Some(splice_type));
824 assert_eq!(ext.dts_next_au, Some(dts));
825 }
826
827 #[test]
828 fn af_extension_with_reserved_padding_is_accepted() {
829 let ltw_offset: u16 = 0x0ABC;
832 let b0 = ((ltw_offset >> 8) & 0x7F) as u8; let b1 = (ltw_offset & 0xFF) as u8;
834 let tail = vec![
835 4, 0b1000_0000, b0,
838 b1,
839 0xFF, ];
841 let bytes = ts_packet_with_af(0b0000_0001, &tail);
842 let pkt = TsPacket::parse(&bytes).unwrap();
843 let ext = pkt
844 .adaptation_field
845 .unwrap()
846 .adaptation_field_extension
847 .expect("ext");
848 assert_eq!(ext.length, 4);
849 assert!(ext.ltw_flag);
850 assert_eq!(ext.ltw_valid_flag, Some(false));
851 assert_eq!(ext.ltw_offset, Some(0x0ABC));
852 }
853
854 #[test]
855 fn af_all_optional_subfields_together() {
856 let pcr_base: u64 = 100;
861 let pcr_ext: u16 = 50;
862 let opcr_base: u64 = 200;
863 let opcr_ext: u16 = 60;
864 let priv_data: &[u8] = &[0xAB, 0xCD];
865 let mut tail = Vec::new();
866 tail.extend_from_slice(&encode_clock_reference(pcr_base, pcr_ext));
867 tail.extend_from_slice(&encode_clock_reference(opcr_base, opcr_ext));
868 tail.push(7i8 as u8); tail.push(priv_data.len() as u8); tail.extend_from_slice(priv_data);
871 tail.push(3);
874 tail.push(0b1000_0000);
875 tail.push(0x00);
876 tail.push(0x00);
877 let bytes = ts_packet_with_af(0b0001_1111, &tail);
878 let pkt = TsPacket::parse(&bytes).unwrap();
879 let af = pkt.adaptation_field.expect("af");
880 assert_eq!(af.pcr_base, Some(pcr_base));
881 assert_eq!(af.opcr_base, Some(opcr_base));
882 assert_eq!(af.opcr_extension, Some(opcr_ext));
883 assert_eq!(af.splice_countdown, Some(7));
884 assert_eq!(af.transport_private_data, Some(priv_data));
885 let ext = af.adaptation_field_extension.expect("ext");
886 assert_eq!(ext.length, 3);
887 assert_eq!(ext.ltw_valid_flag, Some(false));
888 assert_eq!(ext.ltw_offset, Some(0));
889 }
890
891 #[test]
892 fn af_extension_truncated_body_errors() {
893 let tail = vec![
895 5, 0b1000_0000, 0x00, ];
899 let af_len = (1 + tail.len()) as u8;
900 let header = [0x47, 0x01, 0x00, 0b0011_0000];
901 let mut packet_tail = Vec::new();
902 packet_tail.push(af_len);
903 packet_tail.push(0b0000_0001);
904 packet_tail.extend_from_slice(&tail);
905 let bytes = make_packet(header, &packet_tail);
906 let err = TsPacket::parse(&bytes).unwrap_err();
907 match err {
908 TsError::Truncated { .. } => {}
909 other => panic!("expected Truncated, got {other:?}"),
910 }
911 }
912}