1pub 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
19pub const HEADER_SIZE: u8 = 4;
21
22pub struct TSPacket {
26 header: TSHeader,
28 adaptation_field: Option<AdaptationField>,
31 payload: Option<TSPayload>,
34}
35
36impl TSPacket {
37 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 let mut read_idx: usize = HEADER_SIZE as usize;
53
54 let adaptation_field = if header.has_adaptation_field() {
57 #[cfg(feature = "log")]
58 trace!("Adaptation field exists for TSPacket");
59
60 let length = buf[read_idx];
63
64 if length != 0 {
65 let af = DataAdaptationField::from_bytes(&mut buf[read_idx..buffer_length]);
66
67 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 let packet = TSPacket {
102 header,
103 adaptation_field,
104 payload,
105 };
106
107 Ok(packet)
108 }
109
110 pub fn header(&self) -> TSHeader {
112 self.header.clone()
113 }
114
115 pub fn has_adaptation_field(&self) -> bool {
117 self.header.has_adaptation_field()
118 }
119
120 pub fn has_payload(&self) -> bool {
122 self.header.has_payload()
123 }
124
125 pub fn adaptation_field(&self) -> Option<AdaptationField> {
127 self.adaptation_field.clone()
128 }
129
130 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 fn packet_1() -> (Box<[u8]>, AdaptationFieldControl, Box<[u8]>) {
146 let packet = [
147 0x47, 0x41, 0x02, 0x10, 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 ];
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, 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, 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 ];
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}