1#![forbid(unsafe_code)]
35#![deny(rust_2018_idioms, future_incompatible, missing_docs)]
36
37pub mod packet;
38#[macro_use]
39pub mod demultiplex;
40pub mod descriptor;
41pub mod mpegts_crc;
42pub mod pes;
43pub mod psi;
44
45use std::fmt;
46use std::fmt::Formatter;
47pub use smptera_format_identifiers_rust as smptera;
50
51#[derive(PartialEq, Eq, Hash, Clone, Copy)]
56pub struct StreamType(pub u8);
57
58impl StreamType {
59 pub const ISO_11172_VIDEO: StreamType = StreamType(0x01);
62 pub const H262: StreamType = StreamType(0x02);
64 pub const ISO_11172_AUDIO: StreamType = StreamType(0x03);
66 pub const ISO_138183_AUDIO: StreamType = StreamType(0x04);
68 pub const H222_0_PRIVATE_SECTIONS: StreamType = StreamType(0x05);
70 pub const H222_0_PES_PRIVATE_DATA: StreamType = StreamType(0x06);
72 pub const MHEG: StreamType = StreamType(0x07);
74 pub const H222_0_DSM_CC: StreamType = StreamType(0x08);
76 pub const H2221: StreamType = StreamType(0x09);
78 pub const ISO_13818_6_MULTIPROTOCOL_ENCAPSULATION: StreamType = StreamType(0x0A);
80 pub const DSMCC_UN_MESSAGES: StreamType = StreamType(0x0B);
82 pub const DSMCC_STREAM_DESCRIPTORS: StreamType = StreamType(0x0C);
84 pub const DSMCC_SECTIONS: StreamType = StreamType(0x0D);
86 pub const H222_0_AUXILIARY: StreamType = StreamType(0x0E);
88 pub const ADTS: StreamType = StreamType(0x0F);
90 pub const ISO_14496_2_VISUAL: StreamType = StreamType(0x10);
92 pub const LATM: StreamType = StreamType(0x11);
94 pub const FLEX_MUX_PES: StreamType = StreamType(0x12);
96 pub const FLEX_MUX_ISO_14496_SECTIONS: StreamType = StreamType(0x13);
98 pub const SYNCHRONIZED_DOWNLOAD_PROTOCOL: StreamType = StreamType(0x14);
100 pub const METADATA_IN_PES: StreamType = StreamType(0x15);
102 pub const METADATA_IN_METADATA_SECTIONS: StreamType = StreamType(0x16);
104 pub const DSMCC_DATA_CAROUSEL_METADATA: StreamType = StreamType(0x17);
106 pub const DSMCC_OBJECT_CAROUSEL_METADATA: StreamType = StreamType(0x18);
108 pub const SYNCHRONIZED_DOWNLOAD_PROTOCOL_METADATA: StreamType = StreamType(0x19);
110 pub const IPMP: StreamType = StreamType(0x1a);
112 pub const H264: StreamType = StreamType(0x1b);
114 pub const AUDIO_WITHOUT_TRANSPORT_SYNTAX: StreamType = StreamType(0x1c);
116 pub const ISO_14496_17_TEXT: StreamType = StreamType(0x1d);
118 pub const H265: StreamType = StreamType(0x24);
121 pub const CHINESE_VIDEO_STANDARD: StreamType = StreamType(0x42);
124 pub const ATSC_DOLBY_DIGITAL_AUDIO: StreamType = StreamType(0x81);
128 pub const ATSC_DSMCC_NETWORK_RESOURCES_TABLE: StreamType = StreamType(0x95);
131 pub const ATSC_DSMCC_SYNCHRONOUS_DATA: StreamType = StreamType(0xc2);
134 pub fn is_pes(self) -> bool {
139 matches!(
140 self,
141 StreamType::ISO_11172_VIDEO
142 | StreamType::H262
143 | StreamType::ISO_11172_AUDIO
144 | StreamType::ISO_138183_AUDIO
145 | StreamType::H222_0_PES_PRIVATE_DATA
146 | StreamType::MHEG
147 | StreamType::H222_0_DSM_CC
148 | StreamType::H2221
149 | StreamType::ISO_13818_6_MULTIPROTOCOL_ENCAPSULATION
150 | StreamType::DSMCC_UN_MESSAGES
151 | StreamType::DSMCC_STREAM_DESCRIPTORS
152 | StreamType::DSMCC_SECTIONS
153 | StreamType::H222_0_AUXILIARY
154 | StreamType::ADTS
155 | StreamType::ISO_14496_2_VISUAL
156 | StreamType::LATM
157 | StreamType::FLEX_MUX_PES
158 | StreamType::FLEX_MUX_ISO_14496_SECTIONS
159 | StreamType::SYNCHRONIZED_DOWNLOAD_PROTOCOL
160 | StreamType::METADATA_IN_PES
161 | StreamType::METADATA_IN_METADATA_SECTIONS
162 | StreamType::DSMCC_DATA_CAROUSEL_METADATA
163 | StreamType::DSMCC_OBJECT_CAROUSEL_METADATA
164 | StreamType::SYNCHRONIZED_DOWNLOAD_PROTOCOL_METADATA
165 | StreamType::IPMP
166 | StreamType::H264
167 | StreamType::AUDIO_WITHOUT_TRANSPORT_SYNTAX
168 | StreamType::ISO_14496_17_TEXT
169 | StreamType::H265
170 | StreamType::CHINESE_VIDEO_STANDARD
171 | StreamType::ATSC_DOLBY_DIGITAL_AUDIO
172 | StreamType::ATSC_DSMCC_NETWORK_RESOURCES_TABLE
173 | StreamType::ATSC_DSMCC_SYNCHRONOUS_DATA
174 )
175 }
176}
177impl fmt::Debug for StreamType {
178 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
179 match *self {
180 StreamType::ISO_11172_VIDEO => f.write_str("ISO_11172_VIDEO"),
181 StreamType::H262 => f.write_str("H262"),
182 StreamType::ISO_11172_AUDIO => f.write_str("ISO_11172_AUDIO"),
183 StreamType::ISO_138183_AUDIO => f.write_str("ISO_138183_AUDIO"),
184 StreamType::H222_0_PRIVATE_SECTIONS => f.write_str("H222_0_PRIVATE_SECTIONS"),
185 StreamType::H222_0_PES_PRIVATE_DATA => f.write_str("H222_0_PES_PRIVATE_DATA"),
186 StreamType::MHEG => f.write_str("MHEG"),
187 StreamType::H222_0_DSM_CC => f.write_str("H222_0_DSM_CC"),
188 StreamType::H2221 => f.write_str("H2221"),
189 StreamType::ISO_13818_6_MULTIPROTOCOL_ENCAPSULATION => {
190 f.write_str("ISO_13818_6_MULTIPROTOCOL_ENCAPSULATION")
191 }
192 StreamType::DSMCC_UN_MESSAGES => f.write_str("DSMCC_UN_MESSAGES"),
193 StreamType::DSMCC_STREAM_DESCRIPTORS => f.write_str("DSMCC_STREAM_DESCRIPTORS"),
194 StreamType::DSMCC_SECTIONS => f.write_str("DSMCC_SECTIONS"),
195 StreamType::H222_0_AUXILIARY => f.write_str("H222_0_AUXILIARY"),
196 StreamType::ADTS => f.write_str("ADTS"),
197 StreamType::ISO_14496_2_VISUAL => f.write_str("ISO_14496_2_VISUAL"),
198 StreamType::LATM => f.write_str("LATM"),
199 StreamType::FLEX_MUX_PES => f.write_str("FLEX_MUX_PES"),
200 StreamType::FLEX_MUX_ISO_14496_SECTIONS => f.write_str("FLEX_MUX_ISO_14496_SECTIONS"),
201 StreamType::SYNCHRONIZED_DOWNLOAD_PROTOCOL => {
202 f.write_str("SYNCHRONIZED_DOWNLOAD_PROTOCOL")
203 }
204 StreamType::METADATA_IN_PES => f.write_str("METADATA_IN_PES"),
205 StreamType::METADATA_IN_METADATA_SECTIONS => {
206 f.write_str("METADATA_IN_METADATA_SECTIONS")
207 }
208 StreamType::DSMCC_DATA_CAROUSEL_METADATA => f.write_str("DSMCC_DATA_CAROUSEL_METADATA"),
209 StreamType::DSMCC_OBJECT_CAROUSEL_METADATA => {
210 f.write_str("DSMCC_OBJECT_CAROUSEL_METADATA")
211 }
212 StreamType::SYNCHRONIZED_DOWNLOAD_PROTOCOL_METADATA => {
213 f.write_str("SYNCHRONIZED_DOWNLOAD_PROTOCOL_METADATA")
214 }
215 StreamType::IPMP => f.write_str("IPMP"),
216 StreamType::H264 => f.write_str("H264"),
217 StreamType::AUDIO_WITHOUT_TRANSPORT_SYNTAX => {
218 f.write_str("AUDIO_WITHOUT_TRANSPORT_SYNTAX")
219 }
220 StreamType::ISO_14496_17_TEXT => f.write_str("ISO_14496_17_TEXT"),
221 StreamType::H265 => f.write_str("H265"),
222 StreamType::CHINESE_VIDEO_STANDARD => f.write_str("CHINESE_VIDEO_STANDARD"),
223 StreamType::ATSC_DOLBY_DIGITAL_AUDIO => f.write_str("ATSC_DOLBY_DIGITAL_AUDIO"),
224 StreamType::ATSC_DSMCC_NETWORK_RESOURCES_TABLE => {
225 f.write_str("ATSC_DSMCC_NETWORK_RESOURCES_TABLE")
226 }
227 StreamType::ATSC_DSMCC_SYNCHRONOUS_DATA => f.write_str("ATSC_DSMCC_SYNCHRONOUS_DATA"),
228 _ => {
229 if self.0 >= 0x80 {
230 f.write_fmt(format_args!("PRIVATE({})", self.0))
231 } else {
232 f.write_fmt(format_args!("RESERVED({})", self.0))
233 }
234 }
235 }
236 }
237}
238
239impl From<StreamType> for u8 {
240 fn from(val: StreamType) -> Self {
241 val.0
242 }
243}
244impl From<u8> for StreamType {
245 fn from(val: u8) -> Self {
246 StreamType(val)
247 }
248}
249
250pub const STUFFING_PID: packet::Pid = packet::Pid::new(0x1fff);
252
253#[cfg(test)]
254mod test {
255 use super::StreamType;
256
257 fn is_reserved(st: &StreamType) -> bool {
258 match st.0 {
259 0x00 | 0x1e..=0x23 | 0x25..=0x41 | 0x43..=0x7f => true,
260 _ => false,
261 }
262 }
263
264 fn is_private(st: &StreamType) -> bool {
265 match st.0 {
266 0x80 | 0x82..=0x94 | 0x96..=0xc1 | 0xc3..=0xff => true,
268 _ => false,
269 }
270 }
271
272 #[test]
273 fn pes() {
274 for st in 0..=255 {
275 let ty = StreamType(st);
276 if ty == StreamType::H222_0_PRIVATE_SECTIONS || is_reserved(&ty) || is_private(&ty) {
277 assert!(!ty.is_pes(), "{:?}", ty);
278 } else {
279 assert!(ty.is_pes(), "{:?}", ty);
280 }
281 assert_eq!(ty, StreamType::from(u8::from(ty)));
282 let _ = format!("{:?}", ty);
283 }
284 }
285}