1pub mod adaptation_field;
4pub mod header;
5pub mod payload;
6
7use adaptation_field::AdaptationField;
8use adaptation_field::StuffingAdaptationField;
9#[cfg(feature = "tracing")]
10use tracing::trace;
11
12use crate::ErrorKind;
13use crate::packet::adaptation_field::DataAdaptationField;
14use crate::packet::header::TsHeader;
15use crate::packet::payload::TsPayload;
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, ErrorKind> {
39 let buffer_length = buf.len();
40 let header_bytes = Box::from(buf[0..HEADER_SIZE as usize].to_vec());
41
42 #[cfg(feature = "tracing")]
43 trace!("Parsing TSPacket from raw bytes: {:02X?}", buf);
44
45 let header = TsHeader::from_bytes(&header_bytes)?;
46
47 let mut read_idx: usize = HEADER_SIZE as usize;
51
52 let adaptation_field = if header.has_adaptation_field() {
55 #[cfg(feature = "tracing")]
56 trace!("Adaptation field exists for TSPacket");
57
58 let length = buf[read_idx];
61
62 if length != 0 {
63 let af = DataAdaptationField::from_bytes(
64 &mut buf[read_idx..buffer_length],
65 );
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 = "tracing")]
84 trace!("Payload exists for TSPacket");
85
86 let payload_bytes = &buf[read_idx..buf.len()];
87
88 let remainder = (PACKET_SIZE - read_idx) as u8;
89 if header.pusi() && payload_bytes[0] > remainder {
90 return Err(ErrorKind::InvalidPayloadPointer {
91 pointer: payload_bytes[0],
92 remainder,
93 });
94 }
95
96 Some(TsPayload::from_bytes(
97 header.pusi(),
98 header.continuity_counter(),
99 payload_bytes,
100 ))
101 } else {
102 None
103 };
104
105 let packet = TsPacket { header, adaptation_field, payload };
107
108 Ok(packet)
109 }
110
111 pub fn header(&self) -> TsHeader {
113 self.header
114 }
115
116 pub fn has_adaptation_field(&self) -> bool {
118 self.header.has_adaptation_field()
119 }
120
121 pub fn has_payload(&self) -> bool {
123 self.header.has_payload()
124 }
125
126 pub fn adaptation_field(&self) -> Option<AdaptationField> {
128 self.adaptation_field.clone()
129 }
130
131 pub fn payload(&self) -> &Option<TsPayload> {
133 &self.payload
134 }
135
136 pub fn to_payload(self) -> Option<TsPayload> {
138 self.payload
139 }
140}
141
142#[cfg(test)]
143mod tests {
144 use test_case::test_case;
145
146 use super::*;
147 use crate::AdaptationFieldControl;
148
149 fn packet_1() -> (Box<[u8]>, AdaptationFieldControl, Box<[u8]>) {
153 let packet = [
154 0x47, 0x41, 0x02, 0x10, 0x00, 0x00, 0x01, 0xFC, 0x01, 0x10, 0x84, 0x80, 0x05, 0x21, 0x02, 0x95,
157 0x32, 0x6F, 0x00, 0x00, 0xDF, 0x01, 0x03, 0x06, 0x0E, 0x2B, 0x34,
158 0x02, 0x0B, 0x01, 0x01, 0x0E, 0x01, 0x03, 0x01, 0x01, 0x00, 0x00,
159 0x00, 0x81, 0xF1, 0x02, 0x08, 0x00, 0x04, 0xCA, 0x14, 0x28, 0x06,
160 0x0E, 0xEA, 0x03, 0x15, 0x45, 0x53, 0x52, 0x49, 0x5F, 0x4D, 0x65,
161 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5F, 0x43, 0x6F, 0x6C, 0x6C,
162 0x65, 0x63, 0x74, 0x04, 0x06, 0x4E, 0x39, 0x37, 0x38, 0x32, 0x36,
163 0x05, 0x02, 0x70, 0x12, 0x06, 0x02, 0x15, 0xB3, 0x07, 0x02, 0xEF,
164 0x62, 0x0A, 0x05, 0x43, 0x32, 0x30, 0x38, 0x42, 0x0B, 0x00, 0x0C,
165 0x00, 0x0D, 0x04, 0x3A, 0x72, 0x80, 0x98, 0x0E, 0x04, 0xB5, 0x6C,
166 0xF5, 0xB9, 0x0F, 0x02, 0x31, 0x4F, 0x10, 0x02, 0x04, 0x5C, 0x11,
167 0x02, 0x02, 0x73, 0x12, 0x04, 0xB4, 0xCC, 0xCC, 0xCE, 0x13, 0x04,
168 0xF1, 0x81, 0x6C, 0x17, 0x14, 0x04, 0x00, 0x00, 0x00, 0x00, 0x15,
169 0x04, 0x00, 0x1E, 0x0A, 0x4F, 0x16, 0x02, 0x00, 0x00, 0x17, 0x04,
170 0x3A, 0x76, 0x87, 0xAF, 0x18, 0x04, 0xB5, 0x70, 0x74, 0xF2, 0x19,
171 0x02, 0x23, 0x99, 0x1A, 0x02, 0x01, 0x7B, 0x1B, 0x02, 0x00, 0x75,
172 0x1C, 0x02, 0xFF, 0xF1, 0x1D, 0x02, 0x02, ];
174 (
175 Box::new(packet),
176 crate::AdaptationFieldControl::Payload,
177 Box::new([0x00, 0x01, 0xFC, 0x01]),
178 )
179 }
180
181 fn packet_2() -> (Box<[u8]>, AdaptationFieldControl, Box<[u8]>) {
182 let packet = [
183 0x47, 0x01, 0x02, 0x31, 0x59, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
185 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
186 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
187 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
188 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
189 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
190 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
191 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
192 0xFF, 0xFF, 0x03, 0x1E, 0x02, 0xFE, 0x9B, 0x1F, 0x02, 0xFF, 0x93, 0x20, 0x02,
194 0x00, 0x0F, 0x21, 0x02, 0xFE, 0x1B, 0x2F, 0x01, 0x00, 0x30, 0x2A,
195 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03, 0x04, 0x2F, 0x2F, 0x43,
196 0x41, 0x04, 0x00, 0x05, 0x00, 0x06, 0x02, 0x43, 0x41, 0x15, 0x10,
197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x02, 0x00, 0x05, 0x38, 0x01,
199 0x00, 0x3B, 0x08, 0x46, 0x69, 0x72, 0x65, 0x62, 0x69, 0x72, 0x64,
200 0x41, 0x01, 0x01, 0x48, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201 0x00, 0x00, 0x01, 0x02, 0xF9, 0x05, ];
203
204 (
205 Box::new(packet),
206 crate::AdaptationFieldControl::AdaptationAndPayload,
207 Box::new([0x03, 0x1E, 0x02, 0xFE]),
208 )
209 }
210
211 #[test_case(packet_2)]
212 #[test_case(packet_1)]
213 fn from_bytes(
214 packet: fn() -> (Box<[u8]>, AdaptationFieldControl, Box<[u8]>),
215 ) {
216 let (mut buf, adaptation_field_control, first_packet_bytes) = packet();
217 let packet = TsPacket::from_bytes(&mut buf).unwrap();
218
219 assert_eq!(
220 packet.header().adaptation_field_control(),
221 adaptation_field_control,
222 "Transport Error Indicator is incorrect"
223 );
224
225 match packet.payload().clone().unwrap().get_payload_data() {
226 payload::TsPayloadData::StartData(start, _end) => assert!(
227 start.iter().eq(first_packet_bytes.iter()),
228 "First payload bytes are incorrect: {:02X?}",
229 start
230 ),
231 _ => panic!(),
232 };
233 }
234}