ts_analyzer/
packet.rs

1//! Holds all the information regarding a given packet from the transport stream.
2pub mod payload;
3pub mod header;
4pub mod adaptation_field;
5
6use crate::errors::invalid_payload_pointer::InvalidPayloadPointer;
7use crate::packet::adaptation_field::DataAdaptationField;
8use crate::packet::header::TSHeader;
9use adaptation_field::{AdaptationField, StuffingAdaptationField};
10use bitvec::prelude::*;
11use std::error::Error;
12
13use crate::packet::payload::TSPayload;
14#[cfg(feature = "log")]
15use log::trace;
16
17pub(crate) const PACKET_SIZE: usize = 188;
18
19/// The length of a transport stream packet is 4 bytes in size.
20pub const HEADER_SIZE: u8 = 4;
21
22/// All of this information is shamelessly stolen from wikipedia, my lord and savior.
23/// This [article](https://en.wikipedia.org/wiki/MPEG_transport_stream) in particular. Please donate
24/// to wikipedia if you have the means.
25pub struct TSPacket {
26    /// Header object which tracks header attributes of the packet
27    header: TSHeader,
28    /// Adaptation field data. This field will be `None` when the adaptation field control field has
29    /// a `0` in the MSB place.
30    adaptation_field: Option<AdaptationField>,
31    /// Payload field data. This field will be `None` when the adaptation field control field has
32    /// a `0` in the LSB place.
33    payload: Option<TSPayload>,
34}
35
36impl TSPacket {
37    /// Create a TSPacket from a byte array.
38    pub fn from_bytes(buf: &mut [u8]) -> Result<TSPacket, Box<dyn Error>> {
39        let buffer_length = buf.len();
40        let header_bytes = Box::from(buf[0..HEADER_SIZE as usize].to_vec());
41
42        #[cfg(feature = "log")]
43        trace!("Parsing TSPacket from raw bytes: {:02X?}", buf);
44
45        let header = match TSHeader::from_bytes(&header_bytes) {
46            Ok(header) => header,
47            Err(e) => return Err(e),
48        };
49
50        // This number comes from the fact that the TS header is always 4 bytes wide and the
51        // adaptation field always comes directly after the header if it is present.
52        let mut read_idx: usize = HEADER_SIZE as usize;
53
54        // If the adaptation field is present we need to determine it's size as we want to ignore
55        // it entirely.
56        let adaptation_field = if header.has_adaptation_field() {
57            #[cfg(feature = "log")]
58            trace!("Adaptation field exists for TSPacket");
59
60            // Get the length of the adaptation field. If it's `0` then this is a stuffing
61            // adaptation field.
62            let length = buf[read_idx];
63
64            if length != 0 {
65                let af = DataAdaptationField::from_bytes(&mut buf[read_idx..buffer_length]);
66
67                // Add 1 because the adaptation field length is 1 byte long
68                read_idx += af.adaptation_field_length() as usize + 1;
69    
70                Some(AdaptationField::Data(af))
71            } else {
72                let af = StuffingAdaptationField::new();
73
74                read_idx += af.adaptation_field_length() as usize;
75
76                Some(AdaptationField::Stuffing(af))
77            }
78        } else {
79            None
80        };
81
82        let payload = if header.has_payload() {
83            #[cfg(feature = "log")]
84            trace!("Payload exists for TSPacket");
85
86            let payload_bytes: Box<[u8]> = Box::from(
87                BitVec::<u8, Msb0>::from_slice(&buf[read_idx..buf.len()]).as_raw_slice()
88            );
89
90            let remainder = (PACKET_SIZE - read_idx) as u8;
91            if header.pusi() && payload_bytes[0] > remainder {
92                return Err(Box::new(InvalidPayloadPointer { pointer: payload_bytes[0], remainder }))
93            }
94
95            Some(TSPayload::from_bytes(header.pusi(), header.continuity_counter(), payload_bytes))
96        } else {
97            None
98        };
99
100        // Payload data should now start at the read_idx.
101        let packet = TSPacket {
102            header,
103            adaptation_field,
104            payload,
105        };
106
107        Ok(packet)
108    }
109
110    /// Returns the header object of this packet
111    pub fn header(&self) -> TSHeader {
112        self.header.clone()
113    }
114
115    /// Returns if the packet has adaptation field data.
116    pub fn has_adaptation_field(&self) -> bool {
117        self.header.has_adaptation_field()
118    }
119
120    /// Returns if the packet has payload field data.
121    pub fn has_payload(&self) -> bool {
122        self.header.has_payload()
123    }
124
125    /// Return the adaptation field data.
126    pub fn adaptation_field(&self) -> Option<AdaptationField> {
127        self.adaptation_field.clone()
128    }
129
130    /// Return the payload data
131    pub fn payload(&self) -> Option<TSPayload> {
132        self.payload.clone()
133    }
134}
135
136#[cfg(test)]
137mod tests {
138    use crate::AdaptationFieldControl;
139
140    use super::*;
141    use test_case::test_case;
142
143    // The original error I got from this packet was: `range end index 224 out of range for slice of
144    // length 24`. Want to keep it as a historical test case.
145    fn packet_1() -> (Box<[u8]>, AdaptationFieldControl, Box<[u8]>) {
146        let packet = [
147            0x47, 0x41, 0x02, 0x10, // Header
148            0x00, 0x00, 0x01, 0xFC, 0x01, 0x10, 0x84, 0x80, 0x05, 0x21, 0x02, 0x95, 0x32, 0x6F,
149            0x00, 0x00, 0xDF, 0x01, 0x03, 0x06, 0x0E, 0x2B, 0x34, 0x02, 0x0B, 0x01, 0x01, 0x0E,
150            0x01, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x81, 0xF1, 0x02, 0x08, 0x00, 0x04, 0xCA,
151            0x14, 0x28, 0x06, 0x0E, 0xEA, 0x03, 0x15, 0x45, 0x53, 0x52, 0x49, 0x5F, 0x4D, 0x65,
152            0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5F, 0x43, 0x6F, 0x6C, 0x6C, 0x65, 0x63, 0x74,
153            0x04, 0x06, 0x4E, 0x39, 0x37, 0x38, 0x32, 0x36, 0x05, 0x02, 0x70, 0x12, 0x06, 0x02,
154            0x15, 0xB3, 0x07, 0x02, 0xEF, 0x62, 0x0A, 0x05, 0x43, 0x32, 0x30, 0x38, 0x42, 0x0B,
155            0x00, 0x0C, 0x00, 0x0D, 0x04, 0x3A, 0x72, 0x80, 0x98, 0x0E, 0x04, 0xB5, 0x6C, 0xF5,
156            0xB9, 0x0F, 0x02, 0x31, 0x4F, 0x10, 0x02, 0x04, 0x5C, 0x11, 0x02, 0x02, 0x73, 0x12,
157            0x04, 0xB4, 0xCC, 0xCC, 0xCE, 0x13, 0x04, 0xF1, 0x81, 0x6C, 0x17, 0x14, 0x04, 0x00,
158            0x00, 0x00, 0x00, 0x15, 0x04, 0x00, 0x1E, 0x0A, 0x4F, 0x16, 0x02, 0x00, 0x00, 0x17,
159            0x04, 0x3A, 0x76, 0x87, 0xAF, 0x18, 0x04, 0xB5, 0x70, 0x74, 0xF2, 0x19, 0x02, 0x23,
160            0x99, 0x1A, 0x02, 0x01, 0x7B, 0x1B, 0x02, 0x00, 0x75, 0x1C, 0x02, 0xFF, 0xF1, 0x1D,
161            0x02, 0x02 // Payload
162        ];
163        return (Box::new(packet), crate::AdaptationFieldControl::Payload, Box::new([0x00, 0x00, 0x01, 0xFC]));
164    }
165
166    fn packet_2() -> (Box<[u8]>, AdaptationFieldControl, Box<[u8]>) {
167        let packet = [
168            0x47, 0x01, 0x02, 0x31, // Header
169            0x59, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
170            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
171            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
172            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
173            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
174            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
175            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Adaptation field
176            0x03, 0x1E, 0x02, 0xFE, 0x9B, 0x1F, 0x02, 0xFF, 0x93, 0x20, 0x02, 0x00, 0x0F, 0x21, 
177            0x02, 0xFE, 0x1B, 0x2F, 0x01, 0x00, 0x30, 0x2A, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 
178            0x03, 0x04, 0x2F, 0x2F, 0x43, 0x41, 0x04, 0x00, 0x05, 0x00, 0x06, 0x02, 0x43, 0x41, 
179            0x15, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
180            0x00, 0x00, 0x00, 0x00, 0x16, 0x02, 0x00, 0x05, 0x38, 0x01, 0x00, 0x3B, 0x08, 0x46, 
181            0x69, 0x72, 0x65, 0x62, 0x69, 0x72, 0x64, 0x41, 0x01, 0x01, 0x48, 0x08, 0x00, 0x00, 
182            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0xF9, 0x05 // Payload
183        ];
184
185        return (Box::new(packet), crate::AdaptationFieldControl::AdaptationAndPayload, Box::new([0x03, 0x1E, 0x02, 0xFE]));
186    }
187
188    #[test_case(packet_2)]
189    #[test_case(packet_1)]
190    fn from_bytes(packet: fn() -> (Box<[u8]>, AdaptationFieldControl, Box<[u8]>)) {
191        let (mut buf, adaptation_field_control, first_packet_bytes) = packet();
192        let packet = TSPacket::from_bytes(&mut buf).unwrap();
193        
194        assert_eq!(packet.header().adaptation_field_control(), adaptation_field_control, "Transport Error Indicator is incorrect");
195
196        let real_first_bytes: Box<[u8]> = packet.payload().unwrap().data()[0..first_packet_bytes.len()].into();
197        assert!(real_first_bytes.iter().eq(first_packet_bytes.iter()), "First payload bytes are incorrect: {:02X?}", real_first_bytes);
198    }
199}