1use std::fmt;
2use std::time::Duration;
3
4use crate::duration_fmt::DurationFmt;
5use crate::error::{Error, Kind as ErrorKind};
6use crate::rational;
7use crate::rational::Rational;
8use crate::result::Result;
9
10pub struct Timestamp<'buf> {
12 buf: &'buf [u8],
13}
14
15impl<'buf> Timestamp<'buf> {
16 const SZ: usize = 5;
17 const TB: Rational = rational::TB_90KHZ;
18
19 #[inline(always)]
20 fn new(buf: &'buf [u8]) -> Timestamp<'buf> {
21 Timestamp { buf }
22 }
23
24 pub fn value(&self) -> u64 {
26 ((u64::from(self.buf[0]) & 0b0000_1110) << 29) | (u64::from(self.buf[1]) << 22)
28 | (u64::from(self.buf[2] & 0b1111_1110) << 14) | (u64::from(self.buf[3]) << 7)
30 | u64::from((self.buf[4] & 0b1111_1110) >> 1)
31 }
32
33 pub fn ns(&self) -> u64 {
35 rational::rescale(self.value(), Self::TB, rational::TB_1NS)
36 }
37}
38
39impl<'buf> From<&Timestamp<'buf>> for Duration {
40 fn from(t: &Timestamp) -> Self {
41 Duration::from_nanos(t.ns())
42 }
43}
44
45impl<'buf> From<Timestamp<'buf>> for Duration {
46 fn from(t: Timestamp) -> Self {
47 Duration::from(&t)
48 }
49}
50
51impl<'buf> From<&Timestamp<'buf>> for DurationFmt {
52 fn from(t: &Timestamp) -> Self {
53 DurationFmt::from_nanos(t.ns())
54 }
55}
56
57impl<'buf> fmt::Debug for Timestamp<'buf> {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 write!(
60 f,
61 ":v(90kHz) {} :v(ns) {} :duration {}",
62 self.value(),
63 self.ns(),
64 DurationFmt::from(self)
65 )
66 }
67}
68
69impl<'buf> fmt::Display for Timestamp<'buf> {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 DurationFmt::from(self).fmt(f)
72 }
73}
74
75#[derive(Debug, PartialEq)]
77pub enum StreamID {
78 ProgramStreamMap,
79 PrivateStream1,
80 PaddingStream,
81 PrivateStream2,
82 AudioStreamNumber(u8),
83 VideoStreamNumber(u8),
84 ECMStream,
85 EMMStream,
86 DSMCCStream,
87 ISOIEC13522Stream,
88 TypeA,
89 TypeB,
90 TypeC,
91 TypeD,
92 TypeE,
93 AncillaryStream,
94 SLPacketizedStream,
95 FlexMuxStream,
96 MetadataStream,
97 ExtendedStreamId,
98 ReservedDataStream,
99 ProgramStreamDirectory,
100 Other(u8),
101}
102
103impl StreamID {
104 #[inline(always)]
113 pub fn is1(self) -> bool {
114 self != StreamID::ProgramStreamMap
115 && self != StreamID::PaddingStream
116 && self != StreamID::PrivateStream2
117 && self != StreamID::ECMStream
118 && self != StreamID::EMMStream
119 && self != StreamID::ProgramStreamDirectory
120 && self != StreamID::DSMCCStream
121 && self != StreamID::TypeE
122 }
123
124 #[inline(always)]
132 pub fn is2(self) -> bool {
133 self == StreamID::ProgramStreamMap
134 || self == StreamID::PrivateStream2
135 || self == StreamID::ECMStream
136 || self == StreamID::EMMStream
137 || self == StreamID::ProgramStreamDirectory
138 || self == StreamID::DSMCCStream
139 || self == StreamID::TypeE
140 }
141
142 #[inline(always)]
144 pub fn is3(self) -> bool {
145 self == StreamID::PaddingStream
146 }
147}
148
149impl From<u8> for StreamID {
150 fn from(d: u8) -> Self {
151 match d {
152 0b1011_1100 => StreamID::ProgramStreamMap,
153 0b1011_1101 => StreamID::PrivateStream1,
154 0b1011_1110 => StreamID::PaddingStream,
155 0b1011_1111 => StreamID::PrivateStream2,
156 0b1100_0000..=0b1101_1111 => StreamID::AudioStreamNumber(d),
157 0b1110_0000..=0b1110_1111 => StreamID::VideoStreamNumber(d),
158 0b1111_0000 => StreamID::ECMStream,
159 0b1111_0001 => StreamID::EMMStream,
160 0b1111_0010 => StreamID::DSMCCStream,
161 0b1111_0011 => StreamID::ISOIEC13522Stream,
162 0b1111_0100 => StreamID::TypeA,
163 0b1111_0101 => StreamID::TypeB,
164 0b1111_0110 => StreamID::TypeC,
165 0b1111_0111 => StreamID::TypeD,
166 0b1111_1000 => StreamID::TypeE,
167 0b1111_1001 => StreamID::AncillaryStream,
168 0b1111_1010 => StreamID::SLPacketizedStream,
169 0b1111_1011 => StreamID::FlexMuxStream,
170 0b1111_1100 => StreamID::MetadataStream,
171 0b1111_1101 => StreamID::ExtendedStreamId,
172 0b1111_1110 => StreamID::ReservedDataStream,
173 0b1111_1111 => StreamID::ProgramStreamDirectory,
174 _ => StreamID::Other(d),
175 }
176 }
177}
178
179impl From<StreamID> for u8 {
180 fn from(sid: StreamID) -> u8 {
181 match sid {
182 StreamID::ProgramStreamMap => 0b1011_1100,
183 StreamID::PrivateStream1 => 0b1011_1101,
184 StreamID::PaddingStream => 0b1011_1110,
185 StreamID::PrivateStream2 => 0b1011_1111,
186 StreamID::AudioStreamNumber(d) => d,
187 StreamID::VideoStreamNumber(d) => d,
188 StreamID::ECMStream => 0b1111_0000,
189 StreamID::EMMStream => 0b1111_0001,
190 StreamID::DSMCCStream => 0b1111_0010,
191 StreamID::ISOIEC13522Stream => 0b1111_0011,
192 StreamID::TypeA => 0b1111_0100,
193 StreamID::TypeB => 0b1111_0101,
194 StreamID::TypeC => 0b1111_0110,
195 StreamID::TypeD => 0b1111_0111,
196 StreamID::TypeE => 0b1111_1000,
197 StreamID::AncillaryStream => 0b1111_1001,
198 StreamID::SLPacketizedStream => 0b1111_1010,
199 StreamID::FlexMuxStream => 0b1111_1011,
200 StreamID::MetadataStream => 0b1111_1100,
201 StreamID::ExtendedStreamId => 0b1111_1101,
202 StreamID::ReservedDataStream => 0b1111_1110,
203 StreamID::ProgramStreamDirectory => 0b1111_1111,
204 StreamID::Other(d) => d,
205 }
206 }
207}
208
209#[derive(Clone, Copy, Debug, PartialEq)]
211pub enum ScramblingControl {
212 NotScrabled,
213 UserDefined(u8),
214}
215
216impl From<u8> for ScramblingControl {
217 #[inline(always)]
218 fn from(d: u8) -> Self {
219 match d {
220 0b00 => ScramblingControl::NotScrabled,
221 _ => ScramblingControl::UserDefined(d),
222 }
223 }
224}
225
226#[derive(Clone, Copy, Debug, PartialEq)]
228pub enum PtsDtsFlag {
229 No,
230 Pts,
231 PtsDts,
232 Forbidden,
233}
234
235impl From<u8> for PtsDtsFlag {
236 #[inline(always)]
237 fn from(d: u8) -> Self {
238 match d {
239 0b00 => PtsDtsFlag::No,
240 0b10 => PtsDtsFlag::Pts,
241 0b11 => PtsDtsFlag::PtsDts,
242
243 _ => PtsDtsFlag::Forbidden,
244 }
245 }
246}
247
248pub struct PES<'buf> {
252 buf: &'buf [u8],
253}
254
255impl<'buf> PES<'buf> {
256 const HEADER_SZ: usize = 6;
257 const HEADER_SZ_1: usize = 3;
258 const START_CODE: u32 = 0x0000_0001;
259 const PTS_OFFSET_LFT: usize = 9;
260 const PTS_OFFSET_RGHT: usize = Self::PTS_OFFSET_LFT + Timestamp::SZ;
261 const DTS_OFFSET_LFT: usize = Self::PTS_OFFSET_RGHT;
262 const DTS_OFFSET_RGHT: usize = Self::DTS_OFFSET_LFT + Timestamp::SZ;
263
264 #[inline(always)]
265 pub fn new(buf: &'buf [u8]) -> PES<'buf> {
266 PES { buf }
267 }
268
269 #[inline(always)]
270 pub fn try_new(buf: &'buf [u8]) -> Result<PES<'buf>> {
271 let p = PES::new(buf);
272 p.validate()?;
273 Ok(p)
274 }
275
276 #[inline(always)]
277 pub fn validate(&self) -> Result<()> {
278 let sz1 = || PES::HEADER_SZ + PES::HEADER_SZ_1 + (self.pes_header_data_length() as usize);
279
280 if self.buf.len() < Self::HEADER_SZ {
281 Err(Error::new(ErrorKind::Buf(self.buf.len(), Self::HEADER_SZ)))
282 } else if self.start_code() != Self::START_CODE {
283 Err(Error::new(ErrorKind::PESStartCode(self.start_code())))
284 } else if self.stream_id().is1() && self.buf.len() < sz1() {
285 Err(Error::new(ErrorKind::Buf(self.buf.len(), sz1())))
286 } else {
287 Ok(())
288 }
289 }
290
291 #[inline(always)]
292 fn start_code(&self) -> u32 {
293 (u32::from(self.buf[0]) << 16) | (u32::from(self.buf[1]) << 8) | u32::from(self.buf[2])
294 }
295
296 #[inline(always)]
297 fn stream_id(&self) -> StreamID {
298 StreamID::from(self.buf[3])
299 }
300
301 #[inline(always)]
302 #[allow(dead_code)]
303 fn packet_length(&self) -> u16 {
304 u16::from(self.buf[4]) << 8 | u16::from(self.buf[5])
305 }
306
307 #[inline(always)]
308 fn pts_dts_flag(&self) -> Option<PtsDtsFlag> {
309 if self.stream_id().is1() {
310 Some(PtsDtsFlag::from((self.buf[7] & 0b1100_0000) >> 6))
311 } else {
312 None
313 }
314 }
315
316 #[inline(always)]
317 fn pes_header_data_length(&self) -> usize {
318 usize::from(self.buf[8])
319 }
320
321 #[inline(always)]
322 pub fn pts(&self) -> Option<Timestamp> {
323 self.pts_dts_flag().and_then(|flag| match flag {
324 PtsDtsFlag::Pts | PtsDtsFlag::PtsDts => Some(Timestamp::new(
325 &self.buf[Self::PTS_OFFSET_LFT..Self::PTS_OFFSET_RGHT],
326 )),
327 _ => None,
328 })
329 }
330
331 #[inline(always)]
332 pub fn dts(&self) -> Option<Timestamp> {
333 self.pts_dts_flag().and_then(|flag| match flag {
334 PtsDtsFlag::PtsDts => Some(Timestamp::new(
335 &self.buf[Self::DTS_OFFSET_LFT..Self::DTS_OFFSET_RGHT],
336 )),
337 _ => None,
338 })
339 }
340
341 #[inline(always)]
342 pub fn buf_seek_payload(&self) -> &'buf [u8] {
343 if self.stream_id().is1() {
344 &self.buf[(Self::HEADER_SZ + Self::HEADER_SZ_1)..]
345 } else {
346 &self.buf[Self::HEADER_SZ..]
347 }
348 }
349}
350
351impl<'buf> fmt::Debug for PES<'buf> {
352 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
353 write!(f, ":PES (")?;
354
355 if let Some(pts) = self.pts() {
356 write!(f, ":pts {}", pts)?;
357 }
358
359 if let Some(dts) = self.dts() {
360 write!(f, " :dts {}", dts)?;
361 }
362
363 write!(f, ")")
364 }
365}