1use crate::{TsError, TsPacket};
50
51fn has_optional_pes_header(stream_id: u8) -> bool {
58 !matches!(
59 stream_id,
60 0xBC | 0xBE | 0xBF | 0xF0 | 0xF1 | 0xFF | 0xF2 | 0xF8 )
69}
70
71#[derive(Debug, Clone)]
81pub struct PesPacket {
82 pub stream_id: u8,
84 pub pes_scrambling_control: u8,
86 pub pes_priority: bool,
88 pub data_alignment_indicator: bool,
91 pub copyright: bool,
93 pub original_or_copy: bool,
96 pub pts_90k: Option<u64>,
98 pub dts_90k: Option<u64>,
100 pub escr_27mhz: Option<u64>,
104 pub es_rate_50bps: Option<u32>,
107 pub dsm_trick_mode: Option<u8>,
110 pub additional_copy_info: Option<u8>,
112 pub previous_pes_packet_crc: Option<u16>,
114 pub pes_extension: Option<PesExtension>,
119 pub payload: Vec<u8>,
121}
122
123#[derive(Debug, Clone, PartialEq, Eq, Default)]
142pub struct PesExtension {
143 pub private_data: Option<[u8; 16]>,
147 pub pack_header: Option<Vec<u8>>,
152 pub program_packet_sequence_counter: Option<ProgramPacketSequenceCounter>,
154 pub p_std_buffer: Option<PStdBuffer>,
156 pub extension_field_2: Option<Vec<u8>>,
160}
161
162#[derive(Debug, Clone, Copy, PartialEq, Eq)]
167pub struct ProgramPacketSequenceCounter {
168 pub counter: u8,
171 pub mpeg1_mpeg2_identifier: bool,
175 pub original_stuff_length: u8,
179}
180
181#[derive(Debug, Clone, Copy, PartialEq, Eq)]
186pub struct PStdBuffer {
187 pub scale: bool,
191 pub size: u16,
193}
194
195impl PStdBuffer {
196 pub fn size_bytes(&self) -> u32 {
199 u32::from(self.size) * if self.scale { 1024 } else { 128 }
200 }
201}
202
203impl PesPacket {
204 pub fn parse(bytes: &[u8]) -> Result<Self, TsError> {
209 if bytes.len() < 6 {
210 return Err(TsError::Truncated {
211 what: "PES header",
212 have: bytes.len(),
213 need: 6,
214 });
215 }
216 if bytes[0] != 0x00 || bytes[1] != 0x00 || bytes[2] != 0x01 {
217 return Err(TsError::BadPesStartCode([bytes[0], bytes[1], bytes[2]]));
218 }
219 let stream_id = bytes[3];
220 let _pes_packet_length = u16::from_be_bytes([bytes[4], bytes[5]]);
221
222 if !has_optional_pes_header(stream_id) {
223 return Ok(Self {
224 stream_id,
225 pes_scrambling_control: 0,
226 pes_priority: false,
227 data_alignment_indicator: false,
228 copyright: false,
229 original_or_copy: false,
230 pts_90k: None,
231 dts_90k: None,
232 escr_27mhz: None,
233 es_rate_50bps: None,
234 dsm_trick_mode: None,
235 additional_copy_info: None,
236 previous_pes_packet_crc: None,
237 pes_extension: None,
238 payload: bytes[6..].to_vec(),
239 });
240 }
241 if bytes.len() < 9 {
242 return Err(TsError::Truncated {
243 what: "PES optional header",
244 have: bytes.len(),
245 need: 9,
246 });
247 }
248 let flags1 = bytes[6];
254 let pes_scrambling_control = (flags1 >> 4) & 0b11;
255 let pes_priority = (flags1 & 0b0000_1000) != 0;
256 let data_alignment_indicator = (flags1 & 0b0000_0100) != 0;
257 let copyright = (flags1 & 0b0000_0010) != 0;
258 let original_or_copy = (flags1 & 0b0000_0001) != 0;
259
260 let flags2 = bytes[7];
261 let pts_dts_flags = (flags2 >> 6) & 0b11;
262 let escr_flag = (flags2 & 0b0010_0000) != 0;
263 let es_rate_flag = (flags2 & 0b0001_0000) != 0;
264 let dsm_trick_mode_flag = (flags2 & 0b0000_1000) != 0;
265 let additional_copy_info_flag = (flags2 & 0b0000_0100) != 0;
266 let pes_crc_flag = (flags2 & 0b0000_0010) != 0;
267 let pes_extension_flag = (flags2 & 0b0000_0001) != 0;
268
269 let pes_header_data_length = bytes[8] as usize;
270 let header_end = 9 + pes_header_data_length;
271 if bytes.len() < header_end {
272 return Err(TsError::Truncated {
273 what: "PES optional header body",
274 have: bytes.len(),
275 need: header_end,
276 });
277 }
278 let mut pts_90k = None;
279 let mut dts_90k = None;
280 let mut escr_27mhz = None;
281 let mut es_rate_50bps = None;
282 let mut dsm_trick_mode = None;
283 let mut additional_copy_info = None;
284 let mut previous_pes_packet_crc = None;
285 let opt = &bytes[9..header_end];
286 let mut cursor = 0usize;
287 match pts_dts_flags {
288 0b10 => {
289 if opt.len() < cursor + 5 {
291 return Err(TsError::Truncated {
292 what: "PES PTS",
293 have: opt.len(),
294 need: cursor + 5,
295 });
296 }
297 pts_90k = Some(decode_timestamp(&opt[cursor..cursor + 5])?);
298 cursor += 5;
299 }
300 0b11 => {
301 if opt.len() < cursor + 10 {
302 return Err(TsError::Truncated {
303 what: "PES PTS+DTS",
304 have: opt.len(),
305 need: cursor + 10,
306 });
307 }
308 pts_90k = Some(decode_timestamp(&opt[cursor..cursor + 5])?);
309 dts_90k = Some(decode_timestamp(&opt[cursor + 5..cursor + 10])?);
310 cursor += 10;
311 }
312 0b00 => { }
313 _ => return Err(TsError::Unsupported("PES PTS_DTS_flags = 0b01")),
315 }
316 if escr_flag {
317 if opt.len() < cursor + 6 {
318 return Err(TsError::Truncated {
319 what: "PES ESCR",
320 have: opt.len(),
321 need: cursor + 6,
322 });
323 }
324 escr_27mhz = Some(decode_escr(&opt[cursor..cursor + 6])?);
325 cursor += 6;
326 }
327 if es_rate_flag {
328 if opt.len() < cursor + 3 {
329 return Err(TsError::Truncated {
330 what: "PES ES_rate",
331 have: opt.len(),
332 need: cursor + 3,
333 });
334 }
335 let b0 = opt[cursor] as u32;
339 let b1 = opt[cursor + 1] as u32;
340 let b2 = opt[cursor + 2] as u32;
341 let es_rate = ((b0 & 0x7F) << 15) | (b1 << 7) | ((b2 >> 1) & 0x7F);
342 es_rate_50bps = Some(es_rate);
343 cursor += 3;
344 }
345 if dsm_trick_mode_flag {
346 if opt.len() < cursor + 1 {
347 return Err(TsError::Truncated {
348 what: "PES DSM_trick_mode",
349 have: opt.len(),
350 need: cursor + 1,
351 });
352 }
353 dsm_trick_mode = Some(opt[cursor]);
354 cursor += 1;
355 }
356 if additional_copy_info_flag {
357 if opt.len() < cursor + 1 {
358 return Err(TsError::Truncated {
359 what: "PES additional_copy_info",
360 have: opt.len(),
361 need: cursor + 1,
362 });
363 }
364 additional_copy_info = Some(opt[cursor] & 0x7F);
366 cursor += 1;
367 }
368 if pes_crc_flag {
369 if opt.len() < cursor + 2 {
370 return Err(TsError::Truncated {
371 what: "PES previous_PES_packet_CRC",
372 have: opt.len(),
373 need: cursor + 2,
374 });
375 }
376 previous_pes_packet_crc = Some(u16::from_be_bytes([opt[cursor], opt[cursor + 1]]));
377 cursor += 2;
378 }
379 let pes_extension = if pes_extension_flag {
383 let (ext, used) = PesExtension::parse(&opt[cursor..])?;
384 cursor += used;
385 Some(ext)
386 } else {
387 None
388 };
389 let _ = cursor;
390
391 Ok(Self {
392 stream_id,
393 pes_scrambling_control,
394 pes_priority,
395 data_alignment_indicator,
396 copyright,
397 original_or_copy,
398 pts_90k,
399 dts_90k,
400 escr_27mhz,
401 es_rate_50bps,
402 dsm_trick_mode,
403 additional_copy_info,
404 previous_pes_packet_crc,
405 pes_extension,
406 payload: bytes[header_end..].to_vec(),
407 })
408 }
409}
410
411impl PesExtension {
412 fn parse(b: &[u8]) -> Result<(Self, usize), TsError> {
417 if b.is_empty() {
418 return Err(TsError::Truncated {
419 what: "PES extension flags",
420 have: 0,
421 need: 1,
422 });
423 }
424 let flags = b[0];
428 let private_data_flag = (flags & 0b1000_0000) != 0;
429 let pack_header_field_flag = (flags & 0b0100_0000) != 0;
430 let ppsc_flag = (flags & 0b0010_0000) != 0;
431 let p_std_buffer_flag = (flags & 0b0001_0000) != 0;
432 let extension_flag_2 = (flags & 0b0000_0001) != 0;
433 let mut cursor = 1usize;
434
435 let mut ext = Self::default();
436 if private_data_flag {
437 if b.len() < cursor + 16 {
438 return Err(TsError::Truncated {
439 what: "PES_private_data",
440 have: b.len(),
441 need: cursor + 16,
442 });
443 }
444 let mut pd = [0u8; 16];
445 pd.copy_from_slice(&b[cursor..cursor + 16]);
446 ext.private_data = Some(pd);
447 cursor += 16;
448 }
449 if pack_header_field_flag {
450 if b.len() < cursor + 1 {
451 return Err(TsError::Truncated {
452 what: "pack_field_length",
453 have: b.len(),
454 need: cursor + 1,
455 });
456 }
457 let pack_field_length = b[cursor] as usize;
458 cursor += 1;
459 if b.len() < cursor + pack_field_length {
460 return Err(TsError::Truncated {
461 what: "pack_header",
462 have: b.len(),
463 need: cursor + pack_field_length,
464 });
465 }
466 ext.pack_header = Some(b[cursor..cursor + pack_field_length].to_vec());
467 cursor += pack_field_length;
468 }
469 if ppsc_flag {
470 if b.len() < cursor + 2 {
471 return Err(TsError::Truncated {
472 what: "program_packet_sequence_counter",
473 have: b.len(),
474 need: cursor + 2,
475 });
476 }
477 ext.program_packet_sequence_counter = Some(ProgramPacketSequenceCounter {
481 counter: b[cursor] & 0x7F,
482 mpeg1_mpeg2_identifier: (b[cursor + 1] & 0b0100_0000) != 0,
483 original_stuff_length: b[cursor + 1] & 0x3F,
484 });
485 cursor += 2;
486 }
487 if p_std_buffer_flag {
488 if b.len() < cursor + 2 {
489 return Err(TsError::Truncated {
490 what: "P-STD_buffer",
491 have: b.len(),
492 need: cursor + 2,
493 });
494 }
495 ext.p_std_buffer = Some(PStdBuffer {
497 scale: (b[cursor] & 0b0010_0000) != 0,
498 size: (u16::from(b[cursor] & 0x1F) << 8) | u16::from(b[cursor + 1]),
499 });
500 cursor += 2;
501 }
502 if extension_flag_2 {
503 if b.len() < cursor + 1 {
504 return Err(TsError::Truncated {
505 what: "PES_extension_field_length",
506 have: b.len(),
507 need: cursor + 1,
508 });
509 }
510 let len = (b[cursor] & 0x7F) as usize;
513 cursor += 1;
514 if b.len() < cursor + len {
515 return Err(TsError::Truncated {
516 what: "PES_extension_field",
517 have: b.len(),
518 need: cursor + len,
519 });
520 }
521 ext.extension_field_2 = Some(b[cursor..cursor + len].to_vec());
522 cursor += len;
523 }
524 Ok((ext, cursor))
525 }
526}
527
528fn decode_escr(b: &[u8]) -> Result<u64, TsError> {
542 if b.len() < 6 {
543 return Err(TsError::Truncated {
544 what: "ESCR",
545 have: b.len(),
546 need: 6,
547 });
548 }
549 let base_32_30 = ((b[0] >> 3) & 0b0000_0111) as u64;
560 let base_29_15 = (((b[0] as u64) & 0b0000_0011) << 13)
561 | ((b[1] as u64) << 5)
562 | (((b[2] as u64) >> 3) & 0b0001_1111);
563 let base_14_0 = (((b[2] as u64) & 0b0000_0011) << 13)
564 | ((b[3] as u64) << 5)
565 | (((b[4] as u64) >> 3) & 0b0001_1111);
566 let escr_ext = (((b[4] as u64) & 0b0000_0011) << 7) | (((b[5] as u64) >> 1) & 0x7F);
567
568 let base = (base_32_30 << 30) | (base_29_15 << 15) | base_14_0;
569 Ok(base * 300 + escr_ext)
570}
571
572fn decode_timestamp(b: &[u8]) -> Result<u64, TsError> {
574 if b.len() < 5 {
575 return Err(TsError::Truncated {
576 what: "PTS/DTS",
577 have: b.len(),
578 need: 5,
579 });
580 }
581 let t32_30 = ((b[0] >> 1) & 0b0000_0111) as u64;
585 let t29_22 = b[1] as u64;
586 let t21_15 = ((b[2] >> 1) & 0b0111_1111) as u64;
587 let t14_7 = b[3] as u64;
588 let t6_0 = ((b[4] >> 1) & 0b0111_1111) as u64;
589 let ts = (t32_30 << 30) | (t29_22 << 22) | (t21_15 << 15) | (t14_7 << 7) | t6_0;
590 Ok(ts)
591}
592
593#[derive(Debug, Default)]
599pub struct PesReassembler {
600 buf: Vec<u8>,
602 started: bool,
604}
605
606impl PesReassembler {
607 pub fn new() -> Self {
609 Self::default()
610 }
611
612 pub fn feed(&mut self, ts: &TsPacket<'_>) -> Result<Option<PesPacket>, TsError> {
616 if ts.payload_unit_start {
617 let finished = if self.started {
620 Some(PesPacket::parse(&self.buf)?)
621 } else {
622 None
623 };
624 self.buf.clear();
625 self.buf.extend_from_slice(ts.payload);
626 self.started = true;
627 Ok(finished)
628 } else if self.started {
629 self.buf.extend_from_slice(ts.payload);
630 Ok(None)
631 } else {
632 Ok(None)
635 }
636 }
637
638 pub fn flush(&mut self) -> Result<Option<PesPacket>, TsError> {
640 if !self.started {
641 return Ok(None);
642 }
643 let buf = std::mem::take(&mut self.buf);
644 self.started = false;
645 Ok(Some(PesPacket::parse(&buf)?))
646 }
647}
648
649#[cfg(test)]
650mod tests {
651 use super::*;
652 use crate::packet::{TS_PACKET_LEN, TS_SYNC_BYTE};
653
654 fn encode_timestamp(prefix: u8, ts: u64) -> [u8; 5] {
657 let t = ts & 0x1_FFFF_FFFF;
659 let t32_30 = ((t >> 30) & 0b0111) as u8;
660 let t29_15 = ((t >> 15) & 0x7FFF) as u16;
661 let t14_0 = (t & 0x7FFF) as u16;
662 [
663 (prefix << 4) | (t32_30 << 1) | 0b1,
664 ((t29_15 >> 7) & 0xFF) as u8,
665 (((t29_15 & 0x7F) << 1) as u8) | 0b1,
666 ((t14_0 >> 7) & 0xFF) as u8,
667 (((t14_0 & 0x7F) << 1) as u8) | 0b1,
668 ]
669 }
670
671 fn build_pes(stream_id: u8, pts: u64, payload: &[u8]) -> Vec<u8> {
674 let pts_bytes = encode_timestamp(0b0010, pts);
675 let mut v = Vec::new();
676 v.extend_from_slice(&[0x00, 0x00, 0x01, stream_id]);
677 let pes_packet_length: u16 = (3 + 5 + payload.len()) as u16;
679 v.extend_from_slice(&pes_packet_length.to_be_bytes());
680 v.push(0b1000_0000);
683 v.push(0b1000_0000);
685 v.push(5);
687 v.extend_from_slice(&pts_bytes);
688 v.extend_from_slice(payload);
689 v
690 }
691
692 fn pes_into_ts(pid: u16, pes: &[u8], chunk_len: usize) -> Vec<u8> {
701 assert!(chunk_len > 0 && chunk_len <= 184);
702 let mut out = Vec::new();
703 let mut cursor = 0;
704 let mut first = true;
705 let mut cc: u8 = 0;
706 while cursor < pes.len() {
707 let pusi = if first { 0b0100_0000 } else { 0 };
708 let pid_hi = ((pid >> 8) & 0x1F) as u8;
709 let pid_lo = (pid & 0xFF) as u8;
710 let remaining = pes.len() - cursor;
711 let take = remaining.min(chunk_len).min(184);
712 let af_total = 184 - take;
718 let af_control: u8 = if af_total > 0 { 0b11 } else { 0b01 };
719 let b3 = (af_control << 4) | (cc & 0x0F);
720 let mut pkt = vec![TS_SYNC_BYTE, pusi | pid_hi, pid_lo, b3];
721 if af_total > 0 {
722 pkt.push((af_total - 1) as u8);
724 if af_total >= 2 {
730 pkt.push(0); pkt.extend(std::iter::repeat(0xFF).take(af_total - 2));
732 }
733 }
736 pkt.extend_from_slice(&pes[cursor..cursor + take]);
737 cursor += take;
738 assert_eq!(pkt.len(), TS_PACKET_LEN);
739 out.extend_from_slice(&pkt);
740 cc = (cc + 1) & 0x0F;
741 first = false;
742 }
743 out
744 }
745
746 #[test]
747 fn decode_timestamp_round_trip() {
748 for ts in [0u64, 1, 90_000, 0x1_FFFF_FFFF] {
749 let enc = encode_timestamp(0b0010, ts);
750 let dec = decode_timestamp(&enc).unwrap();
751 assert_eq!(dec, ts);
752 }
753 }
754
755 #[test]
756 fn parse_complete_pes_packet_pts_only() {
757 let pes = build_pes(0xE0, 90_000, b"hello world");
758 let parsed = PesPacket::parse(&pes).unwrap();
759 assert_eq!(parsed.stream_id, 0xE0);
760 assert_eq!(parsed.pts_90k, Some(90_000));
761 assert_eq!(parsed.dts_90k, None);
762 assert_eq!(parsed.payload, b"hello world");
763 }
764
765 #[test]
766 fn parse_complete_pes_packet_pts_dts() {
767 let pts_bytes = encode_timestamp(0b0011, 200_000);
768 let dts_bytes = encode_timestamp(0b0001, 180_000);
769 let payload = b"AVCdata";
770 let mut v = Vec::new();
771 v.extend_from_slice(&[0x00, 0x00, 0x01, 0xE0]);
772 let pes_packet_length: u16 = (3 + 10 + payload.len()) as u16;
773 v.extend_from_slice(&pes_packet_length.to_be_bytes());
774 v.push(0b1000_0000);
775 v.push(0b1100_0000); v.push(10);
777 v.extend_from_slice(&pts_bytes);
778 v.extend_from_slice(&dts_bytes);
779 v.extend_from_slice(payload);
780 let parsed = PesPacket::parse(&v).unwrap();
781 assert_eq!(parsed.pts_90k, Some(200_000));
782 assert_eq!(parsed.dts_90k, Some(180_000));
783 assert_eq!(parsed.payload, payload);
784 }
785
786 #[test]
787 fn reassemble_pes_split_across_three_ts_packets() {
788 let payload: Vec<u8> = (0..400u32).map(|i| (i & 0xFF) as u8).collect();
789 let pes = build_pes(0xE0, 12345, &payload);
790 let ts_buf = pes_into_ts(0x100, &pes, 150);
792 let next_pes = build_pes(0xE0, 67890, b"X");
795 let next_ts = pes_into_ts(0x100, &next_pes, 184);
796 let mut full = ts_buf;
797 full.extend_from_slice(&next_ts);
798
799 let mut r = PesReassembler::new();
800 let mut packets = Vec::new();
801 for pkt in crate::iter_packets(&full) {
802 let pkt = pkt.unwrap();
803 if let Some(done) = r.feed(&pkt).unwrap() {
804 packets.push(done);
805 }
806 }
807 if let Some(done) = r.flush().unwrap() {
808 packets.push(done);
809 }
810
811 assert_eq!(packets.len(), 2);
812 assert_eq!(packets[0].pts_90k, Some(12345));
813 assert_eq!(&packets[0].payload[..payload.len()], &payload[..]);
821 assert_eq!(packets[1].pts_90k, Some(67890));
822 }
823
824 #[test]
825 fn pusi_starts_new_packet_and_emits_previous() {
826 let pes1 = build_pes(0xC0, 1000, b"first");
827 let pes2 = build_pes(0xC0, 2000, b"second");
828 let ts1 = pes_into_ts(0x101, &pes1, 184);
829 let ts2 = pes_into_ts(0x101, &pes2, 184);
830
831 let mut r = PesReassembler::new();
832 let mut emitted = Vec::new();
833 for buf in [&ts1, &ts2] {
834 for pkt in crate::iter_packets(buf) {
835 let pkt = pkt.unwrap();
836 if let Some(done) = r.feed(&pkt).unwrap() {
837 emitted.push(done);
838 }
839 }
840 }
841 assert_eq!(emitted.len(), 1);
844 assert_eq!(emitted[0].pts_90k, Some(1000));
845 assert_eq!(&emitted[0].payload[..5], b"first");
846 let flushed = r.flush().unwrap().expect("buffered pes2");
847 assert_eq!(flushed.pts_90k, Some(2000));
848 assert_eq!(&flushed.payload[..6], b"second");
849 }
850
851 #[test]
852 fn padding_stream_has_no_optional_header() {
853 let mut v = Vec::new();
855 v.extend_from_slice(&[0x00, 0x00, 0x01, 0xBE]);
856 let payload = [0xFFu8; 12];
857 let len: u16 = payload.len() as u16;
858 v.extend_from_slice(&len.to_be_bytes());
859 v.extend_from_slice(&payload);
860 let p = PesPacket::parse(&v).unwrap();
861 assert_eq!(p.stream_id, 0xBE);
862 assert_eq!(p.pts_90k, None);
863 assert_eq!(p.dts_90k, None);
864 assert_eq!(p.payload, &payload);
865 }
866
867 #[test]
868 fn bad_pes_start_code_rejected() {
869 let mut v = vec![0x00, 0x00, 0x02, 0xE0, 0, 0];
870 v.extend_from_slice(&[0u8; 3]);
871 let err = PesPacket::parse(&v).unwrap_err();
872 match err {
873 TsError::BadPesStartCode(_) => {}
874 other => panic!("expected BadPesStartCode, got {other:?}"),
875 }
876 }
877
878 fn encode_escr(escr_42: u64) -> [u8; 6] {
880 let base = (escr_42 / 300) & 0x1_FFFF_FFFF;
881 let ext = (escr_42 % 300) & 0x1FF;
882 let base_32_30 = ((base >> 30) & 0b111) as u8;
883 let base_29_15 = ((base >> 15) & 0x7FFF) as u32;
884 let base_14_0 = (base & 0x7FFF) as u32;
885 let ext = ext as u32;
886 let b0 = 0b1100_0000 | (base_32_30 << 3)
888 | 0b0000_0100 | (((base_29_15 >> 13) & 0b11) as u8);
890 let b1 = ((base_29_15 >> 5) & 0xFF) as u8;
891 let b2 = (((base_29_15 & 0x1F) as u8) << 3)
892 | 0b0000_0100 | (((base_14_0 >> 13) & 0b11) as u8);
894 let b3 = ((base_14_0 >> 5) & 0xFF) as u8;
895 let b4 = (((base_14_0 & 0x1F) as u8) << 3)
896 | 0b0000_0100 | (((ext >> 7) & 0b11) as u8);
898 let b5 = (((ext & 0x7F) as u8) << 1) | 0b0000_0001; [b0, b1, b2, b3, b4, b5]
900 }
901
902 fn encode_es_rate(rate: u32) -> [u8; 3] {
904 let r = rate & 0x3F_FFFF;
905 [
906 0b1000_0000 | ((r >> 15) as u8 & 0x7F),
907 ((r >> 7) & 0xFF) as u8,
908 (((r & 0x7F) << 1) as u8) | 0x01,
909 ]
910 }
911
912 #[test]
913 fn escr_round_trip_round_numbers() {
914 let max_escr: u64 = (((1u64 << 33) - 1) * 300) + 299;
918 for &target in &[0u64, 1, 299, 300, 27_000_000, 27_000_001, max_escr] {
919 let enc = encode_escr(target);
920 let dec = decode_escr(&enc).unwrap();
921 assert_eq!(dec, target, "target {target:#x} encoded {enc:02X?}");
922 }
923 }
924
925 #[test]
926 fn parse_pes_with_every_optional_field() {
927 let pts_bytes = encode_timestamp(0b0011, 300_000);
931 let dts_bytes = encode_timestamp(0b0001, 240_000);
932 let escr_bytes = encode_escr(27_000_123);
933 let es_rate_bytes = encode_es_rate(123_456);
934 let dsm_byte: u8 = 0b010_00000; let aci_byte: u8 = 0x80 | 0x42; let pes_crc_bytes: [u8; 2] = [0xCA, 0xFE];
937 let pes_ext_flags: u8 = 0b0000_0000;
941 let optional: Vec<u8> = [
942 pts_bytes.as_slice(),
943 dts_bytes.as_slice(),
944 escr_bytes.as_slice(),
945 es_rate_bytes.as_slice(),
946 std::slice::from_ref(&dsm_byte),
947 std::slice::from_ref(&aci_byte),
948 pes_crc_bytes.as_slice(),
949 std::slice::from_ref(&pes_ext_flags),
950 ]
951 .concat();
952 let payload = b"\x01\x02\x03\x04";
953 let mut v = Vec::new();
954 v.extend_from_slice(&[0x00, 0x00, 0x01, 0xE0]);
955 let pes_packet_length: u16 = (3 + optional.len() + payload.len()) as u16;
956 v.extend_from_slice(&pes_packet_length.to_be_bytes());
957 v.push(0b1000_1111);
960 v.push(0b1111_1111);
963 v.push(optional.len() as u8);
964 v.extend_from_slice(&optional);
965 v.extend_from_slice(payload);
966 let p = PesPacket::parse(&v).unwrap();
967 assert_eq!(p.stream_id, 0xE0);
968 assert_eq!(p.pes_scrambling_control, 0);
969 assert!(p.pes_priority);
970 assert!(p.data_alignment_indicator);
971 assert!(p.copyright);
972 assert!(p.original_or_copy);
973 assert_eq!(p.pts_90k, Some(300_000));
974 assert_eq!(p.dts_90k, Some(240_000));
975 assert_eq!(p.escr_27mhz, Some(27_000_123));
976 assert_eq!(p.es_rate_50bps, Some(123_456));
977 assert_eq!(p.dsm_trick_mode, Some(0b010_00000));
978 assert_eq!(p.additional_copy_info, Some(0x42));
979 assert_eq!(p.previous_pes_packet_crc, Some(0xCAFE));
980 assert_eq!(p.pes_extension, Some(PesExtension::default()));
983 assert_eq!(p.payload, payload);
984 }
985
986 #[test]
987 fn parse_pes_no_optional_fields_defaults() {
988 let pes = build_pes(0xE0, 90_000, b"abcd");
990 let p = PesPacket::parse(&pes).unwrap();
991 assert_eq!(p.pts_90k, Some(90_000));
992 assert_eq!(p.escr_27mhz, None);
993 assert_eq!(p.es_rate_50bps, None);
994 assert_eq!(p.dsm_trick_mode, None);
995 assert_eq!(p.additional_copy_info, None);
996 assert_eq!(p.previous_pes_packet_crc, None);
997 assert!(p.pes_extension.is_none());
998 assert!(!p.pes_priority);
1000 assert!(!p.copyright);
1001 assert_eq!(p.pes_scrambling_control, 0);
1002 }
1003
1004 fn build_pes_with_extension(ext_body: &[u8]) -> Vec<u8> {
1008 let payload = b"data";
1009 let mut v = Vec::new();
1010 v.extend_from_slice(&[0x00, 0x00, 0x01, 0xE0]);
1011 let pes_packet_length: u16 = (3 + ext_body.len() + payload.len()) as u16;
1012 v.extend_from_slice(&pes_packet_length.to_be_bytes());
1013 v.push(0b1000_0000); v.push(0b0000_0001); v.push(ext_body.len() as u8);
1016 v.extend_from_slice(ext_body);
1017 v.extend_from_slice(payload);
1018 v
1019 }
1020
1021 #[test]
1022 fn parse_pes_extension_every_sub_field() {
1023 let mut ext = vec![0b1111_1111u8];
1026 let private: [u8; 16] = *b"0123456789ABCDEF";
1027 ext.extend_from_slice(&private);
1028 ext.extend_from_slice(&[3, 0xAA, 0xBB, 0xCC]);
1030 ext.push(0b1101_0101);
1032 ext.push(0b1110_0001);
1033 ext.push(0b0111_0010);
1035 ext.push(0x34);
1036 ext.push(0b1000_0010);
1038 ext.extend_from_slice(&[0xDE, 0xAD]);
1039
1040 let pes = build_pes_with_extension(&ext);
1041 let p = PesPacket::parse(&pes).unwrap();
1042 let e = p.pes_extension.expect("extension present");
1043 assert_eq!(e.private_data, Some(private));
1044 assert_eq!(e.pack_header.as_deref(), Some(&[0xAA, 0xBB, 0xCC][..]));
1045 let ppsc = e.program_packet_sequence_counter.unwrap();
1046 assert_eq!(ppsc.counter, 0x55);
1047 assert!(ppsc.mpeg1_mpeg2_identifier);
1048 assert_eq!(ppsc.original_stuff_length, 0x21);
1049 let pstd = e.p_std_buffer.unwrap();
1050 assert!(pstd.scale);
1051 assert_eq!(pstd.size, 0x1234);
1052 assert_eq!(pstd.size_bytes(), 0x1234 * 1024);
1053 assert_eq!(e.extension_field_2.as_deref(), Some(&[0xDE, 0xAD][..]));
1054 assert_eq!(p.payload, b"data");
1055 }
1056
1057 #[test]
1058 fn parse_pes_extension_p_std_scale_clear_units_128() {
1059 let ext = [0b0001_0000u8, 0b0100_0000, 10];
1061 let pes = build_pes_with_extension(&ext);
1062 let p = PesPacket::parse(&pes).unwrap();
1063 let pstd = p.pes_extension.unwrap().p_std_buffer.unwrap();
1064 assert!(!pstd.scale);
1065 assert_eq!(pstd.size, 10);
1066 assert_eq!(pstd.size_bytes(), 1280);
1067 }
1068
1069 #[test]
1070 fn parse_pes_extension_truncated_private_data_rejected() {
1071 let ext = [0b1000_0000u8, 1, 2, 3, 4];
1073 let pes = build_pes_with_extension(&ext);
1074 let err = PesPacket::parse(&pes).unwrap_err();
1075 match err {
1076 TsError::Truncated { what, .. } => assert_eq!(what, "PES_private_data"),
1077 other => panic!("expected Truncated, got {other:?}"),
1078 }
1079 }
1080
1081 #[test]
1082 fn parse_pes_extension_truncated_field_2_rejected() {
1083 let ext = [0b0000_0001u8, 0b1000_0101];
1085 let pes = build_pes_with_extension(&ext);
1086 let err = PesPacket::parse(&pes).unwrap_err();
1087 match err {
1088 TsError::Truncated { what, .. } => assert_eq!(what, "PES_extension_field"),
1089 other => panic!("expected Truncated, got {other:?}"),
1090 }
1091 }
1092
1093 #[test]
1094 fn parse_pes_truncated_optional_body_rejected() {
1095 let mut v = Vec::new();
1098 v.extend_from_slice(&[0x00, 0x00, 0x01, 0xE0]);
1099 v.extend_from_slice(&8u16.to_be_bytes());
1101 v.push(0b1000_0000);
1102 v.push(0b1100_0000);
1103 v.push(5); v.extend_from_slice(&[0u8; 5]);
1105 let err = PesPacket::parse(&v).unwrap_err();
1106 match err {
1107 TsError::Truncated { what, .. } => {
1108 assert_eq!(what, "PES PTS+DTS");
1109 }
1110 other => panic!("expected Truncated, got {other:?}"),
1111 }
1112 }
1113}