1use crate::es::StreamId;
2use crate::time::{ClockReference, Timestamp};
3use crate::{track_io, util};
4use crate::{ErrorKind, Result};
5use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
6use std::io::{Read, Write};
7use trackable::{track, track_assert, track_assert_eq, track_assert_ne};
8
9const PACKET_START_CODE_PREFIX: u64 = 0x00_0001;
10
11#[allow(missing_docs)]
13#[derive(Debug, Clone)]
14pub struct PesPacket<B> {
15 pub header: PesHeader,
16 pub data: B,
17}
18
19#[allow(missing_docs)]
23#[derive(Debug, Clone, PartialEq, Eq, Hash)]
24pub struct PesHeader {
25 pub stream_id: StreamId,
26 pub priority: bool,
27
28 pub data_alignment_indicator: bool,
31
32 pub copyright: bool,
34
35 pub original_or_copy: bool,
37
38 pub pts: Option<Timestamp>,
39 pub dts: Option<Timestamp>,
40
41 pub escr: Option<ClockReference>,
43}
44impl PesHeader {
45 pub(super) fn optional_header_len(&self) -> u16 {
46 3 + self.pts.map_or(0, |_| 5) + self.dts.map_or(0, |_| 5) + self.escr.map_or(0, |_| 6)
47 }
48
49 pub(crate) fn read_from<R: Read>(mut reader: R) -> Result<(Self, u16, u8)> {
50 let packet_start_code_prefix = track_io!(reader.read_uint::<BigEndian>(3))?;
51 track_assert_eq!(
52 packet_start_code_prefix,
53 PACKET_START_CODE_PREFIX,
54 ErrorKind::InvalidInput
55 );
56
57 let stream_id = StreamId::new(track_io!(reader.read_u8())?);
58
59 let packet_len = track_io!(reader.read_u16::<BigEndian>())?;
60
61 let b = track_io!(reader.read_u8())?;
62 track_assert_eq!(
63 b & 0b1100_0000,
64 0b1000_0000,
65 ErrorKind::InvalidInput,
66 "Unexpected marker bits"
67 );
68 let scrambling_control = (b & 0b0011_0000) >> 4;
69 let priority = (b & 0b0000_1000) != 0;
70 let data_alignment_indicator = (b & 0b0000_0100) != 0;
71 let copyright = (b & 0b0000_0010) != 0;
72 let original_or_copy = (b & 0b0000_0001) != 0;
73 track_assert_eq!(scrambling_control, 0, ErrorKind::Unsupported);
74
75 let b = track_io!(reader.read_u8())?;
76 let pts_flag = (b & 0b1000_0000) != 0;
77 let dts_flag = (b & 0b0100_0000) != 0;
78 track_assert_ne!((pts_flag, dts_flag), (false, true), ErrorKind::InvalidInput);
79
80 let escr_flag = (b & 0b0010_0000) != 0;
81 let es_rate_flag = (b & 0b0001_0000) != 0;
82 let dsm_trick_mode_flag = (b & 0b0000_1000) != 0;
83 let additional_copy_info_flag = (b & 0b0000_0100) != 0;
84 let crc_flag = (b & 0b0000_0010) != 0;
85 let extension_flag = (b & 0b0000_0001) != 0;
86 track_assert!(!es_rate_flag, ErrorKind::Unsupported);
87 track_assert!(!dsm_trick_mode_flag, ErrorKind::Unsupported);
88 track_assert!(!additional_copy_info_flag, ErrorKind::Unsupported);
89 track_assert!(!crc_flag, ErrorKind::Unsupported);
90 track_assert!(!extension_flag, ErrorKind::Unsupported);
91
92 let pes_header_len = track_io!(reader.read_u8())?;
93
94 let mut reader = reader.take(u64::from(pes_header_len));
95 let pts = if pts_flag {
96 let check_bits = if dts_flag { 3 } else { 2 };
97 Some(track!(Timestamp::read_from(&mut reader, check_bits))?)
98 } else {
99 None
100 };
101 let dts = if dts_flag {
102 let check_bits = 1;
103 Some(track!(Timestamp::read_from(&mut reader, check_bits))?)
104 } else {
105 None
106 };
107 let escr = if escr_flag {
108 Some(track!(ClockReference::read_escr_from(&mut reader))?)
109 } else {
110 None
111 };
112 track!(util::consume_stuffing_bytes(reader))?;
113
114 let header = PesHeader {
115 stream_id,
116 priority,
117 data_alignment_indicator,
118 copyright,
119 original_or_copy,
120 pts,
121 dts,
122 escr,
123 };
124 Ok((header, packet_len, pes_header_len))
125 }
126
127 pub(crate) fn write_to<W: Write>(&self, mut writer: W, pes_header_len: u16) -> Result<()> {
128 track_io!(writer.write_uint::<BigEndian>(PACKET_START_CODE_PREFIX, 3))?;
129 track_io!(writer.write_u8(self.stream_id.as_u8()))?;
130 track_io!(writer.write_u16::<BigEndian>(pes_header_len))?;
131
132 let n = 0b1000_0000
133 | ((self.priority as u8) << 3)
134 | ((self.data_alignment_indicator as u8) << 2)
135 | ((self.copyright as u8) << 1)
136 | self.original_or_copy as u8;
137 track_io!(writer.write_u8(n))?;
138
139 if self.dts.is_some() {
140 track_assert!(self.pts.is_some(), ErrorKind::InvalidInput);
141 }
142 let n = ((self.pts.is_some() as u8) << 7)
143 | ((self.dts.is_some() as u8) << 6)
144 | ((self.escr.is_some() as u8) << 5);
145 track_io!(writer.write_u8(n))?;
146
147 let pes_header_len = self.optional_header_len() as u8 - 3;
148 track_io!(writer.write_u8(pes_header_len))?;
149 if let Some(x) = self.pts {
150 let check_bits = if self.dts.is_some() { 3 } else { 2 };
151 track!(x.write_to(&mut writer, check_bits))?;
152 }
153 if let Some(x) = self.dts {
154 let check_bits = 1;
155 track!(x.write_to(&mut writer, check_bits))?;
156 }
157 if let Some(x) = self.escr {
158 track!(x.write_escr_to(&mut writer))?;
159 }
160
161 Ok(())
162 }
163}