va_ts/
pes.rs

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
10/// ISO/IEC 13818-1
11pub 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    /// 90kHz
25    pub fn value(&self) -> u64 {
26        ((u64::from(self.buf[0]) & 0b0000_1110) << 29) // (>> 1 (<< 30))
27            | (u64::from(self.buf[1]) << 22)
28            | (u64::from(self.buf[2] & 0b1111_1110) << 14) // (>> 1 (<< 15))
29            | (u64::from(self.buf[3]) << 7)
30            | u64::from((self.buf[4] & 0b1111_1110) >> 1)
31    }
32
33    /// nanoseconds
34    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/// ISO/IEC 13818-1
76#[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    /// if (stream_id != program_stream_map
105    /// && stream_id != padding_stream
106    /// && stream_id != private_stream_2
107    /// && stream_id != ECM
108    /// && stream_id != EMM
109    /// && stream_id != program_stream_directory
110    /// && stream_id != DSMCC_stream
111    /// && stream_id != ITU-T Rec. H.222.1 type E stream)
112    #[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    /// if ( stream_id == program_stream_map
125    /// || stream_id == private_stream_2
126    /// || stream_id == ECM
127    /// || stream_id == EMM
128    /// || stream_id == program_stream_directory
129    /// || stream_id == DSMCC_stream
130    /// || stream_id == ITU-T Rec. H.222.1 type E stream)
131    #[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    /// if ( stream_id == padding_stream)
143    #[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/// ISO/IEC 13818-1
210#[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/// ISO/IEC 13818-1
227#[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
248/// ISO/IEC 13818-1
249///
250/// http://dvd.sourceforge.net/dvdinfo/pes-hdr.html
251pub 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}