1use crate::errors::invalid_first_byte::InvalidFirstByte;
5use crate::AdaptationFieldControl::{AdaptationAndPayload, AdaptationField, Payload};
6use crate::TransportScramblingControl::{EvenKey, NoScrambling, OddKey};
7use crate::{AdaptationFieldControl, TransportScramblingControl};
8use std::error::Error;
9use std::fmt::{Display, Formatter};
10use bitvec::macros::internal::funty::Fundamental;
11use bitvec::field::BitField;
12use bitvec::order::Msb0;
13use bitvec::vec::BitVec;
14#[cfg(feature = "log")]
15use log::trace;
16
17pub const SYNC_BYTE: u8 = 0x47;
19
20#[derive(Clone, Copy, Debug)]
24pub struct TSHeader {
25 tei: bool,
28 pusi: bool,
31 transport_priority: bool,
34 pid: u16,
36 tsc: TransportScramblingControl,
43 adaptation_field_control: AdaptationFieldControl,
50 continuity_counter: u8,
52}
53
54impl TSHeader {
55 pub fn new(
57 tei: bool,
58 pusi: bool,
59 transport_priority: bool,
60 pid: u16,
61 tsc: u8,
62 adaptation_field_control: u8,
63 continuity_counter: u8,
64 ) -> Self {
65 #[cfg(feature = "log")]
66 {
67 trace!("pid: [{}]", pid);
68 trace!("adaptation_field_control: [{}]", adaptation_field_control);
69 trace!("continuity_counter: [{}]", continuity_counter);
70 }
71
72 TSHeader {
73 tei,
74 pusi,
75 transport_priority,
76 pid,
77 tsc: match tsc {
78 0 => NoScrambling,
79 1 => TransportScramblingControl::Reserved,
80 2 => EvenKey,
81 3 => OddKey,
82 _ => panic!("Invalid TSC value [{}]", tsc),
83 },
84 adaptation_field_control: match adaptation_field_control {
85 0 => AdaptationFieldControl::Reserved,
86 1 => Payload,
87 2 => AdaptationField,
88 3 => AdaptationAndPayload,
89 _ => panic!(
90 "Invalid adaptation field control value [{}]",
91 adaptation_field_control
92 ),
93 },
94 continuity_counter,
95 }
96 }
97
98 pub fn from_bytes(buf: &Box<[u8]>) -> Result<TSHeader, Box<dyn Error>> {
100 let bytes: BitVec<u8, Msb0> = BitVec::from_slice(buf).to_bitvec();
101
102 if bytes[0..8].load::<u8>() != SYNC_BYTE {
104 return Err(Box::new(InvalidFirstByte { byte: buf[0] }));
105 }
106
107 #[cfg(feature = "log")]
108 trace!("header bytes: {:b}", bytes);
109
110 let header = TSHeader {
112 tei: bytes[8],
113 pusi: bytes[9],
114 transport_priority: bytes[10],
115 pid: bytes[11..24].to_bitvec().load_be(),
116 tsc: match bytes[24..26].to_bitvec().load_be() {
117 0 => NoScrambling,
118 1 => TransportScramblingControl::Reserved,
119 2 => EvenKey,
120 3 => OddKey,
121 default => panic!("Invalid TSC value [{}]", default),
122 },
123 adaptation_field_control: match bytes[26..28].to_bitvec().load_be::<u8>() {
124 0 => AdaptationFieldControl::Reserved,
125 1 => Payload,
126 2 => AdaptationField,
127 3 => AdaptationAndPayload,
128 default => panic!(
129 "Invalid adaptation field control value [{}]",
130 default
131 ),
132 },
133 continuity_counter: bytes[28..32].load_be(),
134 };
135
136 #[cfg(feature = "log")]
137 trace!("Header for TSPacket: {}", header);
138
139 Ok(header)
140 }
141
142 pub fn tei(&self) -> bool {
144 self.tei
145 }
146
147 pub fn pusi(&self) -> bool {
149 self.pusi
150 }
151
152 pub fn transport_priority(&self) -> bool {
154 self.transport_priority
155 }
156
157 pub fn pid(&self) -> u16 {
159 self.pid
160 }
161
162 pub fn tsc(&self) -> TransportScramblingControl {
164 self.tsc
165 }
166
167 pub fn adaptation_field_control(&self) -> AdaptationFieldControl {
169 self.adaptation_field_control
170 }
171
172 pub fn has_adaptation_field(&self) -> bool {
174 match self.adaptation_field_control {
175 AdaptationField | AdaptationAndPayload => true,
176 _ => false
177 }
178 }
179
180 pub fn has_payload(&self) -> bool {
182 match self.adaptation_field_control {
183 Payload | AdaptationAndPayload => true,
184 _ => false
185 }
186 }
187
188 pub fn continuity_counter(&self) -> u8 {
190 self.continuity_counter
191 }
192
193
194}
195
196impl Display for TSHeader {
197 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
198 let msg = format!("\n\
199 TEI: {}\n\
200 PUSI: {}\n\
201 Transport Priority: {}\n\
202 PID: {}\n\
203 Transport Scrambling Control: {:?}\n\
204 Adaptation Field Control: {:?}\n\
205 Continuity Counter: {}",
206 self.tei,
207 self.pusi,
208 self.transport_priority,
209 self.pid,
210 self.tsc,
211 self.adaptation_field_control,
212 self.continuity_counter,
213 );
214 write!(f, "{}", msg)
215 }
216}
217
218#[cfg(test)]
219mod tests {
220 use super::*;
221 use test_case::test_case;
222
223 #[test]
224 fn from_bytes() {
225 let buf: Box<[u8]> = Box::new([0x47, 0x01, 0x00, 0x1A]);
226 let header = TSHeader::from_bytes(&buf).unwrap();
227 assert_eq!(header.tei(), false, "Transport Error Indicator is incorrect");
228 assert_eq!(header.pusi(), false, "Payload Unit Start Indicator is incorrect");
229 assert_eq!(header.transport_priority(), false, "Transport Priority is incorrect");
230 assert_eq!(header.pid(), 256, "Transport Priority is incorrect");
231 assert_eq!(header.adaptation_field_control(), Payload, "Transport Priority is incorrect");
232 assert_eq!(header.continuity_counter(), 10, "Transport Priority is incorrect");
233 }
234
235 #[test]
236 fn from_bytes2() {
237 let buf: Box<[u8]> = Box::new([0x47, 0xE1, 0x00, 0x3B]);
238 let header = TSHeader::from_bytes(&buf).unwrap();
239 assert_eq!(header.tei(), true, "Transport Error Indicator is incorrect");
240 assert_eq!(header.pusi(), true, "Payload Unit Start Indicator is incorrect");
241 assert_eq!(header.transport_priority(), true, "Transport Priority is incorrect");
242 assert_eq!(header.pid(), 256, "Transport Priority is incorrect");
243 assert_eq!(header.adaptation_field_control(), AdaptationAndPayload, "Transport Priority is incorrect");
244 assert_eq!(header.continuity_counter(), 11, "Transport Priority is incorrect");
245 }
246}