mpeg2ts_reader/
packet.rs

1//! A [`Packet`](./struct.Packet.html) struct and associated infrastructure to read an MPEG Transport Stream packet
2
3use crate::pes;
4use log::warn;
5use std::cmp::Ordering;
6use std::convert::TryFrom;
7use std::fmt;
8use std::fmt::{Debug, Formatter};
9use std::num::NonZeroU8;
10
11/// Representation of the `adaptation_field_control` field from the Transport Stream packet header.
12/// The methods on this type indicate whether a `Packet`'s `adaptation_field()` and `payload()`
13/// methods will return `Some` or `None`.
14#[derive(Eq, PartialEq, Debug)]
15pub struct AdaptationControl(u8);
16
17impl AdaptationControl {
18    /// Construct a new `AdaptationControl` given the fourth byte from a Transport Stream packet's
19    /// header.  The `adaptation_field_control` field that this type represents is derived from
20    /// just two bits within the given byte - all the other bits are ignored
21    #[inline(always)]
22    fn new(header_byte: u8) -> AdaptationControl {
23        AdaptationControl(header_byte)
24    }
25
26    /// True if the `adaptation_field_control` indicates that the packet will have a payload
27    #[inline(always)]
28    pub fn has_payload(&self) -> bool {
29        self.0 & 0b00010000 != 0
30    }
31
32    /// True if the `adaptation_field_control` field indicates that the packet will have an
33    /// adaptation field.
34    #[inline(always)]
35    pub fn has_adaptation_field(&self) -> bool {
36        self.0 & 0b00100000 != 0
37    }
38}
39
40/// Indicates content scrambling in use, if any.
41///
42/// Actual content scrambling schemes, are undefined in the main TS spec (left to be described
43/// by other specifications).
44#[derive(Eq, PartialEq)]
45pub struct TransportScramblingControl(u8);
46
47impl TransportScramblingControl {
48    /// creates a new instance from the fourth byte of a TS packet's header
49    #[inline]
50    fn from_byte_four(val: u8) -> TransportScramblingControl {
51        TransportScramblingControl(val)
52    }
53
54    /// If the `transport_scrambling_control` field in the Transport Stream data has the value
55    /// `00`, then return `false`, returns true if `transport_scrambling_control` has any other
56    /// values.
57    #[inline]
58    pub fn is_scrambled(&self) -> bool {
59        self.0 & 0b11000000 != 0
60    }
61
62    /// Returns the value of the  `transport_scrambling_control` field, or `None` if the field
63    /// indicates this packet payload is not scrambled.
64    pub fn scheme(&self) -> Option<NonZeroU8> {
65        let scheme = self.0 >> 6;
66        NonZeroU8::new(scheme)
67    }
68}
69impl Debug for TransportScramblingControl {
70    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
71        f.debug_struct("TransportScramblingControl")
72            .field("scheme", &self.scheme())
73            .finish()
74    }
75}
76
77/// A _Clock Reference_ is used to represent the values of PCR and ESCR fields within the transport
78/// stream data.
79///
80/// A _Clock Reference_ includes a 33-bit, 90kHz `base` component, together with another 9-bit,
81/// high-resolution `extension` component.
82///
83/// Together these can be viewed as a 42-bit, 27MHz quantity (e.g. `let full_value = pcr as u64`).
84/// Since the clock reference is limited to 33-bits, at a rate of 90kHz a continuously increasing
85/// clock value will wrap-around approximately every 26.5 hours.
86#[derive(Copy, Clone)]
87pub struct ClockRef {
88    base: u64,
89    extension: u16,
90}
91
92impl PartialEq for ClockRef {
93    fn eq(&self, other: &ClockRef) -> bool {
94        self.base == other.base && self.extension == other.extension
95    }
96}
97
98impl From<ClockRef> for u64 {
99    fn from(pcr: ClockRef) -> u64 {
100        pcr.base * 300 + u64::from(pcr.extension)
101    }
102}
103
104impl fmt::Debug for ClockRef {
105    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
106        write!(f, "PCR{{{:08x}:{:04x}}}", self.base, self.extension)
107    }
108}
109impl ClockRef {
110    /// Panics if `data` is shorter than 5 bytes
111    pub fn from_slice(data: &[u8]) -> ClockRef {
112        ClockRef {
113            base: u64::from(data[0]) << 25
114                | u64::from(data[1]) << 17
115                | u64::from(data[2]) << 9
116                | u64::from(data[3]) << 1
117                | u64::from(data[4]) >> 7,
118            //reserved: (data[4] >> 1) & 0b00111111,
119            extension: (u16::from(data[4]) & 0b1) << 8 | u16::from(data[5]),
120        }
121    }
122    /// Panics if the `base` is greater than 2^33-1 or the `extension` is greater than 2^9-1
123    pub fn from_parts(base: u64, extension: u16) -> ClockRef {
124        assert!(base < (1 << 33));
125        assert!(extension < (1 << 9));
126        ClockRef { base, extension }
127    }
128
129    /// get the 33-bit, 90kHz 'base' component of the timestamp
130    pub fn base(&self) -> u64 {
131        self.base
132    }
133
134    /// get the 9-bit 'extension' component of the timestamp, measured in 300ths of the 90kHz base
135    /// clockrate (i.e. 27MHz)
136    pub fn extension(&self) -> u16 {
137        self.extension
138    }
139}
140
141/// Some error encountered while parsing adaptation field syntax
142#[derive(Debug, PartialEq, Eq)]
143pub enum AdaptationFieldError {
144    /// The an optional field's value was requested, but the field is not actually present
145    FieldNotPresent,
146    /// There is a syntactic problem in the adaptation field being parsed, and not enough data
147    /// is present in the stream to hold the requested component which is supposed to be present.
148    NotEnoughData,
149    /// The `seamless_splice()` function found a syntax error is the adaptation field data holding
150    /// the _seamless_splice_ field.
151    SpliceTimestampError(pes::TimestampError),
152}
153
154/// A collection of fields that may optionally appear within the header of a transport stream
155/// `Packet`.
156///
157/// As returned by [`Packet::adaptation_field()`](struct.Packet.html#method.adaptation_field)
158pub struct AdaptationField<'buf> {
159    buf: &'buf [u8],
160}
161
162impl<'buf> AdaptationField<'buf> {
163    // TODO: just eager-load all this stuff in new()?  would be simpler!
164
165    /// Create a new structure to parse the adaptation field data held within the given slice.
166    ///
167    /// Panics if the slice is empty.
168    pub fn new(buf: &'buf [u8]) -> AdaptationField<'buf> {
169        assert!(!buf.is_empty());
170        AdaptationField { buf }
171    }
172
173    /// Get the value of the _discontinuity_indicator_ field which might have been written into
174    /// the transport stream by some 'upstream' processor on discovering that there was a break
175    /// in the data.
176    pub fn discontinuity_indicator(&self) -> bool {
177        self.buf[0] & 0b1000_0000 != 0
178    }
179    /// Get the value of the _random_access_indicator_ field.
180    pub fn random_access_indicator(&self) -> bool {
181        self.buf[0] & 0b0100_0000 != 0
182    }
183    /// Get the value of the _elementary_stream_priority_indicator_ field.
184    pub fn elementary_stream_priority_indicator(&self) -> u8 {
185        (self.buf[0] & 0b10_0000) >> 5
186    }
187    fn pcr_flag(&self) -> bool {
188        self.buf[0] & 0b1_0000 != 0
189    }
190    fn opcr_flag(&self) -> bool {
191        self.buf[0] & 0b1000 != 0
192    }
193    fn splicing_point_flag(&self) -> bool {
194        self.buf[0] & 0b100 != 0
195    }
196    fn transport_private_data_flag(&self) -> bool {
197        self.buf[0] & 0b10 != 0
198    }
199    fn adaptation_field_extension_flag(&self) -> bool {
200        self.buf[0] & 0b1 != 0
201    }
202    fn slice(&self, from: usize, to: usize) -> Result<&'buf [u8], AdaptationFieldError> {
203        if to > self.buf.len() {
204            Err(AdaptationFieldError::NotEnoughData)
205        } else {
206            Ok(&self.buf[from..to])
207        }
208    }
209    const PCR_SIZE: usize = 6;
210    /// Get the _Program Clock Reference_ field,
211    /// or `AdaptationFieldError::FieldNotPresent` if absent
212    pub fn pcr(&self) -> Result<ClockRef, AdaptationFieldError> {
213        if self.pcr_flag() {
214            Ok(ClockRef::from_slice(self.slice(1, 1 + Self::PCR_SIZE)?))
215        } else {
216            Err(AdaptationFieldError::FieldNotPresent)
217        }
218    }
219    fn opcr_offset(&self) -> usize {
220        if self.pcr_flag() {
221            1 + Self::PCR_SIZE
222        } else {
223            1
224        }
225    }
226    /// Returns the 'Original Program Clock Reference' value,
227    /// or `AdaptationFieldError::FieldNotPresent` if absent
228    pub fn opcr(&self) -> Result<ClockRef, AdaptationFieldError> {
229        if self.opcr_flag() {
230            let off = self.opcr_offset();
231            Ok(ClockRef::from_slice(self.slice(off, off + Self::PCR_SIZE)?))
232        } else {
233            Err(AdaptationFieldError::FieldNotPresent)
234        }
235    }
236    fn splice_countdown_offset(&self) -> usize {
237        self.opcr_offset() + if self.opcr_flag() { Self::PCR_SIZE } else { 0 }
238    }
239    /// Get the value of the _splice_countdown_ field,
240    /// or `AdaptationFieldError::FieldNotPresent` if absent
241    pub fn splice_countdown(&self) -> Result<u8, AdaptationFieldError> {
242        if self.splicing_point_flag() {
243            let off = self.splice_countdown_offset();
244            Ok(self.slice(off, off + 1)?[0])
245        } else {
246            Err(AdaptationFieldError::FieldNotPresent)
247        }
248    }
249    fn transport_private_data_offset(&self) -> usize {
250        self.splice_countdown_offset() + usize::from(self.splicing_point_flag())
251    }
252    /// Borrow a slice of the underlying buffer containing private data,
253    /// or `AdaptationFieldError::FieldNotPresent` if absent
254    pub fn transport_private_data(&self) -> Result<&[u8], AdaptationFieldError> {
255        if self.transport_private_data_flag() {
256            let off = self.transport_private_data_offset();
257            let len = self.slice(off, off + 1)?[0] as usize;
258            Ok(self.slice(off + 1, off + 1 + len)?)
259        } else {
260            Err(AdaptationFieldError::FieldNotPresent)
261        }
262    }
263    fn adaptation_field_extension_offset(&self) -> Result<usize, AdaptationFieldError> {
264        let off = self.transport_private_data_offset();
265        Ok(off
266            + if self.transport_private_data_flag() {
267                let len = self.slice(off, off + 1)?[0] as usize;
268                len + 1
269            } else {
270                0
271            })
272    }
273    /// Returns extended adaptation fields, or `AdaptationFieldError::FieldNotPresent` if absent
274    pub fn adaptation_field_extension(
275        &self,
276    ) -> Result<AdaptationFieldExtension<'buf>, AdaptationFieldError> {
277        if self.adaptation_field_extension_flag() {
278            let off = self.adaptation_field_extension_offset()?;
279            let len = self.slice(off, off + 1)?[0] as usize;
280            AdaptationFieldExtension::new(self.slice(off + 1, off + 1 + len)?)
281        } else {
282            Err(AdaptationFieldError::FieldNotPresent)
283        }
284    }
285}
286
287impl<'buf> fmt::Debug for AdaptationField<'buf> {
288    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
289        let mut d = f.debug_struct("AdaptationField");
290        d.field("discontinuity_indicator", &self.discontinuity_indicator());
291        d.field("random_access_indicator", &self.random_access_indicator());
292        d.field(
293            "elementary_stream_priority_indicator",
294            &self.elementary_stream_priority_indicator(),
295        );
296        d.field("pcr", &self.pcr());
297        d.field("opcr", &self.opcr());
298        d.field("splice_countdown", &self.splice_countdown());
299        d.field("transport_private_data", &self.transport_private_data());
300        d.field(
301            "adaptation_field_extension",
302            &self.adaptation_field_extension(),
303        );
304        d.finish()
305    }
306}
307
308/// Optional extensions within an [`AdaptationField`](struct.AdaptationField.html).
309///
310/// As returned by
311/// [`AdaptationField::adaptation_field_extension()`](struct.AdaptationField.html#method.adaptation_field_extension).
312pub struct AdaptationFieldExtension<'buf> {
313    buf: &'buf [u8],
314}
315impl<'buf> AdaptationFieldExtension<'buf> {
316    /// Create a new structure to parse the adaptation field extension data held within the given
317    /// slice.
318    pub fn new(buf: &'buf [u8]) -> Result<AdaptationFieldExtension<'buf>, AdaptationFieldError> {
319        if buf.is_empty() {
320            Err(AdaptationFieldError::NotEnoughData)
321        } else {
322            Ok(AdaptationFieldExtension { buf })
323        }
324    }
325
326    fn slice(&self, from: usize, to: usize) -> Result<&'buf [u8], AdaptationFieldError> {
327        if to > self.buf.len() {
328            Err(AdaptationFieldError::NotEnoughData)
329        } else {
330            Ok(&self.buf[from..to])
331        }
332    }
333
334    fn ltw_flag(&self) -> bool {
335        self.buf[0] & 0b1000_0000 != 0
336    }
337    fn piecewise_rate_flag(&self) -> bool {
338        self.buf[0] & 0b0100_0000 != 0
339    }
340    fn seamless_splice_flag(&self) -> bool {
341        self.buf[0] & 0b0010_0000 != 0
342    }
343    /// Returns the 'Legal time window offset', if any.
344    pub fn ltw_offset(&self) -> Result<Option<u16>, AdaptationFieldError> {
345        if self.ltw_flag() {
346            let dat = self.slice(1, 3)?;
347            let ltw_valid_flag = dat[0] & 0b1000_0000 != 0;
348            Ok(if ltw_valid_flag {
349                Some(u16::from(dat[0] & 0b0111_1111) << 8 | u16::from(dat[1]))
350            } else {
351                None
352            })
353        } else {
354            Err(AdaptationFieldError::FieldNotPresent)
355        }
356    }
357    fn piecewise_rate_offset(&self) -> usize {
358        1 + if self.ltw_flag() { 2 } else { 0 }
359    }
360    /// Get the value of the _piecewise_rate_ field,
361    /// or `AdaptationFieldError::FieldNotPresent` if absent
362    pub fn piecewise_rate(&self) -> Result<u32, AdaptationFieldError> {
363        if self.piecewise_rate_flag() {
364            let off = self.piecewise_rate_offset();
365            let dat = self.slice(off, off + 3)?;
366            Ok(u32::from(dat[0] & 0b0011_1111) << 16 | u32::from(dat[1]) << 8 | u32::from(dat[2]))
367        } else {
368            Err(AdaptationFieldError::FieldNotPresent)
369        }
370    }
371    fn seamless_splice_offset(&self) -> usize {
372        self.piecewise_rate_offset() + if self.piecewise_rate_flag() { 3 } else { 0 }
373    }
374    /// Get the value of the _seamless_splice_ field,
375    /// or `AdaptationFieldError::FieldNotPresent` if absent
376    pub fn seamless_splice(&self) -> Result<SeamlessSplice, AdaptationFieldError> {
377        if self.seamless_splice_flag() {
378            let off = self.seamless_splice_offset();
379            let dat = self.slice(off, off + 5)?;
380            Ok(SeamlessSplice {
381                splice_type: dat[0] >> 4,
382                dts_next_au: pes::Timestamp::from_bytes(dat)
383                    .map_err(AdaptationFieldError::SpliceTimestampError)?,
384            })
385        } else {
386            Err(AdaptationFieldError::FieldNotPresent)
387        }
388    }
389}
390
391impl<'buf> fmt::Debug for AdaptationFieldExtension<'buf> {
392    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
393        let mut d = f.debug_struct("AdaptationFieldExtension");
394        d.field("ltw_offset", &self.ltw_offset());
395        d.field("piecewise_rate", &self.piecewise_rate());
396        d.field("seamless_splice", &self.seamless_splice());
397        d.finish()
398    }
399}
400
401/// Value of the _seamless_splice_ field, as returned by
402/// [`AdaptationFieldExtension::seamless_splice()`](struct.AdaptationFieldExtension.html#method.seamless_splice)
403/// method
404#[derive(Debug, PartialEq, Eq)]
405pub struct SeamlessSplice {
406    /// see _ISO/IEC 13818-1 : 2000_, Table 2-7 through Table 2-16
407    pub splice_type: u8,
408    /// The DTS of the access unit after the splice-point.
409    pub dts_next_au: pes::Timestamp,
410}
411
412/// A counter value used within a transport stream to detect discontinuities in a sequence of packets.
413/// The continuity counter should increase by one for each packet with a given PID for which
414/// `adaptation_control` indicates that a payload should be present.
415///
416/// See [`Packet.continuity_counter()`](struct.Packet.html#method.continuity_counter)
417#[derive(PartialEq, Eq, Debug, Clone, Copy)]
418pub struct ContinuityCounter {
419    val: u8,
420}
421
422impl From<u8> for ContinuityCounter {
423    #[inline]
424    fn from(count: u8) -> ContinuityCounter {
425        ContinuityCounter::new(count)
426    }
427}
428
429impl ContinuityCounter {
430    /// Panics if the given value is greater than 15.
431    #[inline]
432    pub fn new(count: u8) -> ContinuityCounter {
433        assert!(count < 0b10000);
434        ContinuityCounter { val: count }
435    }
436
437    /// Returns this counter's value, which will be between 0 and 15 inclusive.
438    #[inline]
439    pub fn count(self) -> u8 {
440        self.val
441    }
442
443    /// true iff the given `ContinuityCounter` value follows this one.  Note that the maximum counter
444    /// value is 15, and the counter 'wraps around':
445    ///
446    /// ```rust
447    /// # use mpeg2ts_reader::packet::ContinuityCounter;
448    /// let a = ContinuityCounter::new(0);
449    /// let b = ContinuityCounter::new(15);
450    /// assert!(a.follows(b));  // after 15, counter wraps around to 0
451    /// ```
452    #[inline]
453    pub fn follows(self, other: ContinuityCounter) -> bool {
454        (other.val + 1) & 0b1111 == self.val
455    }
456}
457
458/// A Packet Identifier value, between `0x0000` and `0x1fff`.
459///
460/// PID values identify a particular sub-stream within the overall Transport Stream.
461///
462/// As returned by the [`Packet::pid`](struct.Packet.html#method.pid) method for example.
463#[derive(Copy, Clone, PartialEq, Eq, Hash)]
464pub struct Pid(u16);
465impl Pid {
466    /// The largest possible PID value, `0x1fff`.
467    pub const MAX_VALUE: u16 = 0x1fff;
468
469    /// The total number of distinct PID values, `0x2000` (equal to `MAX_VALUE` + 1)
470    pub const PID_COUNT: usize = (Self::MAX_VALUE + 1) as usize;
471
472    #[doc(hidden)]
473    /// Use mpeg2ts_reader::psi::pat::PAT_PID instead of this
474    pub const PAT: Pid = Pid::new(0);
475    #[doc(hidden)]
476    /// Use mpeg2ts_reader::STUFFING_PID instead of this
477    pub const STUFFING: Pid = Pid::new(0x1fff);
478
479    /// Panics if the given value is greater than `Pid::MAX_VALUE`.
480    pub const fn new(pid: u16) -> Pid {
481        assert!(pid <= 0x1fff);
482        Pid(pid)
483    }
484}
485impl TryFrom<u16> for Pid {
486    type Error = ();
487
488    fn try_from(value: u16) -> Result<Self, Self::Error> {
489        if value <= Pid::MAX_VALUE {
490            Ok(Pid(value))
491        } else {
492            Err(())
493        }
494    }
495}
496impl From<Pid> for u16 {
497    #[inline]
498    fn from(pid: Pid) -> Self {
499        pid.0
500    }
501}
502impl From<Pid> for usize {
503    #[inline]
504    fn from(pid: Pid) -> Self {
505        pid.0 as usize
506    }
507}
508impl fmt::Debug for Pid {
509    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
510        write!(f, "Pid({:04x})", self.0)
511    }
512}
513
514/// A transport stream `Packet` is a wrapper around a byte slice which allows the bytes to be
515/// interpreted as a packet structure per _ISO/IEC 13818-1, Section 2.4.3.3_.
516pub struct Packet<'buf> {
517    buf: &'buf [u8],
518}
519
520const FIXED_HEADER_SIZE: usize = 4;
521// when AF present, a 1-byte 'length' field precedes the content,
522const ADAPTATION_FIELD_OFFSET: usize = FIXED_HEADER_SIZE + 1;
523
524impl<'buf> Packet<'buf> {
525    /// The value `0x47`, which must appear in the first byte of every transport stream packet.
526    pub const SYNC_BYTE: u8 = 0x47;
527
528    /// The fixed 188 byte size of a transport stream packet.
529    pub const SIZE: usize = 188;
530
531    /// returns `true` if the given value is a valid synchronisation byte, the value `Packet::SYNC_BYTE` (0x47), which
532    /// must appear at the start of every transport stream packet.
533    #[inline(always)]
534    pub fn is_sync_byte(b: u8) -> bool {
535        b == Self::SYNC_BYTE
536    }
537
538    /// Panics if the given buffer is less than 188 bytes, or if the initial sync-byte does not
539    /// have the correct value (`0x47`).  Calling code is expected to have already checked those
540    /// conditions.
541    ///
542    /// Panics if the buffer size is not exactly `Packet::SIZE` (188) bytes, or if the first
543    /// byte value is not equal to `Packet::SYNC_BYTE` (0x47).
544    #[inline(always)]
545    pub fn new(buf: &'buf [u8]) -> Packet<'buf> {
546        assert_eq!(buf.len(), Self::SIZE);
547        assert!(Packet::is_sync_byte(buf[0]));
548        Packet { buf }
549    }
550
551    /// Like `new()`, but returns `None` if the sync-byte has incorrect value (still panics if the
552    /// buffer size is not 188 bytes).
553    #[inline(always)]
554    pub fn try_new(buf: &'buf [u8]) -> Option<Packet<'buf>> {
555        assert_eq!(buf.len(), Self::SIZE);
556        if Packet::is_sync_byte(buf[0]) {
557            Some(Packet { buf })
558        } else {
559            None
560        }
561    }
562
563    /// *May* have been set if some previous processing of this TS data detected at least
564    /// 1 uncorrectable bit error in this TS packet.
565    #[inline]
566    pub fn transport_error_indicator(&self) -> bool {
567        self.buf[1] & 0b1000_0000 != 0
568    }
569
570    /// a structure larger than a single packet payload needs to be split across multiple packets,
571    /// `payload_unit_start()` indicates if this packet payload contains the start of the
572    /// structure.  If `false`, this packets payload is a continuation of a structure which began
573    /// in an earlier packet within the transport stream.
574    #[inline]
575    pub fn payload_unit_start_indicator(&self) -> bool {
576        self.buf[1] & 0b0100_0000 != 0
577    }
578
579    /// When `1`, this TS packet has higher priority than other packets of the the same PID having
580    /// PID `0`.
581    pub fn transport_priority(&self) -> bool {
582        self.buf[1] & 0b0010_0000 != 0
583    }
584
585    /// The sub-stream to which a particular packet belongs is indicated by this Packet Identifier
586    /// value.
587    #[inline]
588    pub fn pid(&self) -> Pid {
589        Pid(u16::from(self.buf[1] & 0b0001_1111) << 8 | u16::from(self.buf[2]))
590    }
591
592    /// Value of the _transport_scrambling_control_ field.
593    #[inline]
594    pub fn transport_scrambling_control(&self) -> TransportScramblingControl {
595        TransportScramblingControl::from_byte_four(self.buf[3])
596    }
597
598    /// The returned enum value indicates if `adaptation_field()`, `payload()` or both will return
599    /// something.
600    #[inline]
601    pub fn adaptation_control(&self) -> AdaptationControl {
602        AdaptationControl::new(self.buf[3])
603    }
604
605    /// Each packet with a given `pid()` value within a transport stream should have a continuity
606    /// counter value which increases by 1 from the last counter value seen.  Unexpected continuity
607    /// counter values allow the receiver of the transport stream to detect discontinuities in the
608    /// stream (e.g. due to data loss during transmission).
609    #[inline]
610    pub fn continuity_counter(&self) -> ContinuityCounter {
611        ContinuityCounter::new(self.buf[3] & 0b0000_1111)
612    }
613
614    fn adaptation_field_length(&self) -> usize {
615        self.buf[4] as usize
616    }
617
618    /// An `AdaptationField` contains additional packet headers that may be present in the packet.
619    pub fn adaptation_field(&self) -> Option<AdaptationField<'buf>> {
620        let ac = self.adaptation_control();
621        if ac.has_adaptation_field() {
622            if ac.has_payload() {
623                let len = self.adaptation_field_length();
624                if len > 182 {
625                    warn!(
626                        "invalid adaptation_field_length for AdaptationFieldAndPayload: {}",
627                        len
628                    );
629                    // TODO: Option<Result<AdaptationField>> instead?
630                    return None;
631                }
632                if len == 0 {
633                    return None;
634                }
635                Some(self.mk_af(len))
636            } else {
637                let len = self.adaptation_field_length();
638                if len != (Self::SIZE - ADAPTATION_FIELD_OFFSET) {
639                    warn!(
640                        "invalid adaptation_field_length for AdaptationFieldOnly: {}",
641                        len
642                    );
643                    // TODO: Option<Result<AdaptationField>> instead?
644                    return None;
645                }
646                Some(self.mk_af(len))
647            }
648        } else {
649            None
650        }
651    }
652
653    fn mk_af(&self, len: usize) -> AdaptationField<'buf> {
654        AdaptationField::new(&self.buf[ADAPTATION_FIELD_OFFSET..ADAPTATION_FIELD_OFFSET + len])
655    }
656
657    /// The data contained within the packet, not including the packet headers.
658    /// Not all packets have a payload, and `None` is returned if `adaptation_control()` indicates
659    /// that no payload is present.  None may also be returned if the packet is malformed.
660    /// If `Some` payload is returned, it is guaranteed not to be an empty slice.
661    #[inline(always)]
662    pub fn payload(&self) -> Option<&'buf [u8]> {
663        if self.adaptation_control().has_payload() {
664            self.mk_payload()
665        } else {
666            None
667        }
668    }
669
670    #[inline]
671    fn mk_payload(&self) -> Option<&'buf [u8]> {
672        let offset = self.content_offset();
673        let len = self.buf.len();
674        match offset.cmp(&len) {
675            Ordering::Equal => {
676                warn!("no payload data present");
677                None
678            }
679            Ordering::Greater => {
680                warn!(
681                    "adaptation_field_length {} too large",
682                    self.adaptation_field_length()
683                );
684                None
685            }
686            Ordering::Less => Some(&self.buf[offset..]),
687        }
688    }
689
690    /// borrow a reference to the underlying buffer of this packet
691    pub fn buffer(&self) -> &'buf [u8] {
692        self.buf
693    }
694
695    #[inline]
696    fn content_offset(&self) -> usize {
697        if self.adaptation_control().has_adaptation_field() {
698            ADAPTATION_FIELD_OFFSET + self.adaptation_field_length()
699        } else {
700            FIXED_HEADER_SIZE
701        }
702    }
703}
704
705#[cfg(test)]
706mod test {
707    use crate::demultiplex::test::NullDemuxContext;
708    use crate::demultiplex::{NullPacketFilter, PacketFilter};
709    use crate::packet::*;
710    use crate::pes;
711
712    #[test]
713    fn pid() {
714        assert!(Pid::try_from(0x2000).is_err());
715    }
716
717    #[test]
718    #[should_panic]
719    fn zero_len() {
720        let buf = [0u8; 0];
721        Packet::new(&buf[..]);
722    }
723
724    #[test]
725    fn test_xmas_tree() {
726        let mut buf = [0xffu8; Packet::SIZE];
727        buf[0] = Packet::SYNC_BYTE;
728        buf[4] = 28; // adaptation_field_length
729        buf[19] = 1; // transport_private_data_length
730        buf[21] = 11; // adaptation_field_extension_length
731        let pk = Packet::new(&buf[..]);
732        assert_eq!(u16::from(pk.pid()), 0b1111111111111u16);
733        assert!(pk.transport_error_indicator());
734        assert!(pk.payload_unit_start_indicator());
735        assert!(pk.transport_priority());
736        assert!(pk.transport_scrambling_control().is_scrambled());
737        assert_eq!(
738            pk.transport_scrambling_control().scheme(),
739            NonZeroU8::new(3)
740        );
741        assert!(pk.adaptation_control().has_payload());
742        assert!(pk.adaptation_control().has_adaptation_field());
743        assert_eq!(pk.continuity_counter().count(), 0b1111);
744        assert!(pk.adaptation_field().is_some());
745        let ad = pk.adaptation_field().unwrap();
746        assert!(ad.discontinuity_indicator());
747        assert_eq!(
748            ad.pcr(),
749            Ok(ClockRef::from_parts(
750                0b1_1111_1111_1111_1111_1111_1111_1111_1111,
751                0b1_1111_1111
752            ))
753        );
754        assert_eq!(1234 * 300 + 56, u64::from(ClockRef::from_parts(1234, 56)));
755        assert_eq!(
756            ad.opcr(),
757            Ok(ClockRef::from_parts(
758                0b1_1111_1111_1111_1111_1111_1111_1111_1111,
759                0b1_1111_1111
760            ))
761        );
762        assert_eq!(ad.splice_countdown(), Ok(0b11111111));
763        let expected_data = [0xff];
764        assert_eq!(ad.transport_private_data(), Ok(&expected_data[..]));
765        let ext = ad.adaptation_field_extension().unwrap();
766        assert_eq!(ext.ltw_offset(), Ok(Some(0b0111_1111_1111_1111)));
767        assert_eq!(ext.piecewise_rate(), Ok(0b0011_1111_1111_1111_1111_1111));
768        assert_eq!(
769            ext.seamless_splice(),
770            Ok(SeamlessSplice {
771                splice_type: 0b1111,
772                dts_next_au: pes::Timestamp::from_u64(0b1_1111_1111_1111_1111_1111_1111_1111_1111)
773            })
774        );
775        assert!(!format!("{:?}", pk.adaptation_field()).is_empty())
776    }
777
778    #[test]
779    fn empty_adaptation_field() {
780        let mut buf = [0xffu8; Packet::SIZE];
781        buf[0] = Packet::SYNC_BYTE;
782        buf[4] = 0; // adaptation_field_length
783        let pk = Packet::new(&buf[..]);
784        assert!(pk.adaptation_control().has_payload());
785        assert!(pk.adaptation_control().has_adaptation_field());
786        assert!(pk.adaptation_field().is_none());
787    }
788
789    #[test]
790    fn empty_adaptation_field_extension() {
791        assert!(AdaptationFieldExtension::new(b"").is_err());
792    }
793
794    #[test]
795    fn should_do_nothing() {
796        let mut ctx = NullDemuxContext::new();
797        let mut data = vec![0; 188];
798        data[0] = 0x47;
799        let pkt = Packet::new(&data);
800        NullPacketFilter::default().consume(&mut ctx, &pkt);
801    }
802}