mpeg2ps/pes/
packet.rs

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/// PES packet.
12#[allow(missing_docs)]
13#[derive(Debug, Clone)]
14pub struct PesPacket<B> {
15    pub header: PesHeader,
16    pub data: B,
17}
18
19/// PES packet header.
20///
21/// Note that `PesHeader` contains the fields that belong to the optional PES header.
22#[allow(missing_docs)]
23#[derive(Debug, Clone, PartialEq, Eq, Hash)]
24pub struct PesHeader {
25    pub stream_id: StreamId,
26    pub priority: bool,
27
28    /// `true` indicates that the PES packet header is immediately followed by
29    /// the video start code or audio syncword.
30    pub data_alignment_indicator: bool,
31
32    /// `true` implies copyrighted.
33    pub copyright: bool,
34
35    /// `true` implies original.
36    pub original_or_copy: bool,
37
38    pub pts: Option<Timestamp>,
39    pub dts: Option<Timestamp>,
40
41    /// Elementary stream clock reference.
42    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}