#![forbid(unsafe_code)]
#![deny(rust_2018_idioms, future_incompatible, missing_docs)]
pub mod packet;
#[macro_use]
pub mod demultiplex;
pub mod descriptor;
pub mod mpegts_crc;
pub mod pes;
pub mod psi;
use std::fmt;
use std::fmt::Formatter;
pub use smptera_format_identifiers_rust as smptera;
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
pub struct StreamType(pub u8);
impl StreamType {
pub const ISO_11172_VIDEO: StreamType = StreamType(0x01);
pub const H262: StreamType = StreamType(0x02);
pub const ISO_11172_AUDIO: StreamType = StreamType(0x03);
pub const ISO_138183_AUDIO: StreamType = StreamType(0x04);
pub const H222_0_PRIVATE_SECTIONS: StreamType = StreamType(0x05);
pub const H222_0_PES_PRIVATE_DATA: StreamType = StreamType(0x06);
pub const MHEG: StreamType = StreamType(0x07);
pub const H222_0_DSM_CC: StreamType = StreamType(0x08);
pub const H2221: StreamType = StreamType(0x09);
pub const ISO_13818_6_MULTIPROTOCOL_ENCAPSULATION: StreamType = StreamType(0x0A);
pub const DSMCC_UN_MESSAGES: StreamType = StreamType(0x0B);
pub const DSMCC_STREAM_DESCRIPTORS: StreamType = StreamType(0x0C);
pub const DSMCC_SECTIONS: StreamType = StreamType(0x0D);
pub const H222_0_AUXILIARY: StreamType = StreamType(0x0E);
pub const ADTS: StreamType = StreamType(0x0F);
pub const ISO_14496_2_VISUAL: StreamType = StreamType(0x10);
pub const LATM: StreamType = StreamType(0x11);
pub const FLEX_MUX_PES: StreamType = StreamType(0x12);
pub const FLEX_MUX_ISO_14496_SECTIONS: StreamType = StreamType(0x13);
pub const SYNCHRONIZED_DOWNLOAD_PROTOCOL: StreamType = StreamType(0x14);
pub const METADATA_IN_PES: StreamType = StreamType(0x15);
pub const METADATA_IN_METADATA_SECTIONS: StreamType = StreamType(0x16);
pub const DSMCC_DATA_CAROUSEL_METADATA: StreamType = StreamType(0x17);
pub const DSMCC_OBJECT_CAROUSEL_METADATA: StreamType = StreamType(0x18);
pub const SYNCHRONIZED_DOWNLOAD_PROTOCOL_METADATA: StreamType = StreamType(0x19);
pub const IPMP: StreamType = StreamType(0x1a);
pub const H264: StreamType = StreamType(0x1b);
pub const AUDIO_WITHOUT_TRANSPORT_SYNTAX: StreamType = StreamType(0x1c);
pub const ISO_14496_17_TEXT: StreamType = StreamType(0x1d);
pub const H265: StreamType = StreamType(0x24);
pub const CHINESE_VIDEO_STANDARD: StreamType = StreamType(0x42);
pub const ATSC_DOLBY_DIGITAL_AUDIO: StreamType = StreamType(0x81);
pub const ATSC_DSMCC_NETWORK_RESOURCES_TABLE: StreamType = StreamType(0x95);
pub const ATSC_DSMCC_SYNCHRONOUS_DATA: StreamType = StreamType(0xc2);
pub fn is_pes(self) -> bool {
matches!(
self,
StreamType::ISO_11172_VIDEO
| StreamType::H262
| StreamType::ISO_11172_AUDIO
| StreamType::ISO_138183_AUDIO
| StreamType::H222_0_PES_PRIVATE_DATA
| StreamType::MHEG
| StreamType::H222_0_DSM_CC
| StreamType::H2221
| StreamType::ISO_13818_6_MULTIPROTOCOL_ENCAPSULATION
| StreamType::DSMCC_UN_MESSAGES
| StreamType::DSMCC_STREAM_DESCRIPTORS
| StreamType::DSMCC_SECTIONS
| StreamType::H222_0_AUXILIARY
| StreamType::ADTS
| StreamType::ISO_14496_2_VISUAL
| StreamType::LATM
| StreamType::FLEX_MUX_PES
| StreamType::FLEX_MUX_ISO_14496_SECTIONS
| StreamType::SYNCHRONIZED_DOWNLOAD_PROTOCOL
| StreamType::METADATA_IN_PES
| StreamType::METADATA_IN_METADATA_SECTIONS
| StreamType::DSMCC_DATA_CAROUSEL_METADATA
| StreamType::DSMCC_OBJECT_CAROUSEL_METADATA
| StreamType::SYNCHRONIZED_DOWNLOAD_PROTOCOL_METADATA
| StreamType::IPMP
| StreamType::H264
| StreamType::AUDIO_WITHOUT_TRANSPORT_SYNTAX
| StreamType::ISO_14496_17_TEXT
| StreamType::H265
| StreamType::CHINESE_VIDEO_STANDARD
| StreamType::ATSC_DOLBY_DIGITAL_AUDIO
| StreamType::ATSC_DSMCC_NETWORK_RESOURCES_TABLE
| StreamType::ATSC_DSMCC_SYNCHRONOUS_DATA
)
}
}
impl fmt::Debug for StreamType {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match *self {
StreamType::ISO_11172_VIDEO => f.write_str("ISO_11172_VIDEO"),
StreamType::H262 => f.write_str("H262"),
StreamType::ISO_11172_AUDIO => f.write_str("ISO_11172_AUDIO"),
StreamType::ISO_138183_AUDIO => f.write_str("ISO_138183_AUDIO"),
StreamType::H222_0_PRIVATE_SECTIONS => f.write_str("H222_0_PRIVATE_SECTIONS"),
StreamType::H222_0_PES_PRIVATE_DATA => f.write_str("H222_0_PES_PRIVATE_DATA"),
StreamType::MHEG => f.write_str("MHEG"),
StreamType::H222_0_DSM_CC => f.write_str("H222_0_DSM_CC"),
StreamType::H2221 => f.write_str("H2221"),
StreamType::ISO_13818_6_MULTIPROTOCOL_ENCAPSULATION => {
f.write_str("ISO_13818_6_MULTIPROTOCOL_ENCAPSULATION")
}
StreamType::DSMCC_UN_MESSAGES => f.write_str("DSMCC_UN_MESSAGES"),
StreamType::DSMCC_STREAM_DESCRIPTORS => f.write_str("DSMCC_STREAM_DESCRIPTORS"),
StreamType::DSMCC_SECTIONS => f.write_str("DSMCC_SECTIONS"),
StreamType::H222_0_AUXILIARY => f.write_str("H222_0_AUXILIARY"),
StreamType::ADTS => f.write_str("ADTS"),
StreamType::ISO_14496_2_VISUAL => f.write_str("ISO_14496_2_VISUAL"),
StreamType::LATM => f.write_str("LATM"),
StreamType::FLEX_MUX_PES => f.write_str("FLEX_MUX_PES"),
StreamType::FLEX_MUX_ISO_14496_SECTIONS => f.write_str("FLEX_MUX_ISO_14496_SECTIONS"),
StreamType::SYNCHRONIZED_DOWNLOAD_PROTOCOL => {
f.write_str("SYNCHRONIZED_DOWNLOAD_PROTOCOL")
}
StreamType::METADATA_IN_PES => f.write_str("METADATA_IN_PES"),
StreamType::METADATA_IN_METADATA_SECTIONS => {
f.write_str("METADATA_IN_METADATA_SECTIONS")
}
StreamType::DSMCC_DATA_CAROUSEL_METADATA => f.write_str("DSMCC_DATA_CAROUSEL_METADATA"),
StreamType::DSMCC_OBJECT_CAROUSEL_METADATA => {
f.write_str("DSMCC_OBJECT_CAROUSEL_METADATA")
}
StreamType::SYNCHRONIZED_DOWNLOAD_PROTOCOL_METADATA => {
f.write_str("SYNCHRONIZED_DOWNLOAD_PROTOCOL_METADATA")
}
StreamType::IPMP => f.write_str("IPMP"),
StreamType::H264 => f.write_str("H264"),
StreamType::AUDIO_WITHOUT_TRANSPORT_SYNTAX => {
f.write_str("AUDIO_WITHOUT_TRANSPORT_SYNTAX")
}
StreamType::ISO_14496_17_TEXT => f.write_str("ISO_14496_17_TEXT"),
StreamType::H265 => f.write_str("H265"),
StreamType::CHINESE_VIDEO_STANDARD => f.write_str("CHINESE_VIDEO_STANDARD"),
StreamType::ATSC_DOLBY_DIGITAL_AUDIO => f.write_str("ATSC_DOLBY_DIGITAL_AUDIO"),
StreamType::ATSC_DSMCC_NETWORK_RESOURCES_TABLE => {
f.write_str("ATSC_DSMCC_NETWORK_RESOURCES_TABLE")
}
StreamType::ATSC_DSMCC_SYNCHRONOUS_DATA => f.write_str("ATSC_DSMCC_SYNCHRONOUS_DATA"),
_ => {
if self.0 >= 0x80 {
f.write_fmt(format_args!("PRIVATE({})", self.0))
} else {
f.write_fmt(format_args!("RESERVED({})", self.0))
}
}
}
}
}
impl From<StreamType> for u8 {
fn from(val: StreamType) -> Self {
val.0
}
}
impl From<u8> for StreamType {
fn from(val: u8) -> Self {
StreamType(val)
}
}
pub const STUFFING_PID: packet::Pid = packet::Pid::new(0x1fff);
#[cfg(test)]
mod test {
use super::StreamType;
fn is_reserved(st: &StreamType) -> bool {
match st.0 {
0x00 | 0x1e..=0x23 | 0x25..=0x41 | 0x43..=0x7f => true,
_ => false,
}
}
fn is_private(st: &StreamType) -> bool {
match st.0 {
0x80 | 0x82..=0x94 | 0x96..=0xc1 | 0xc3..=0xff => true,
_ => false,
}
}
#[test]
fn pes() {
for st in 0..=255 {
let ty = StreamType(st);
if ty == StreamType::H222_0_PRIVATE_SECTIONS || is_reserved(&ty) || is_private(&ty) {
assert!(!ty.is_pes(), "{:?}", ty);
} else {
assert!(ty.is_pes(), "{:?}", ty);
}
assert_eq!(ty, StreamType::from(u8::from(ty)));
let _ = format!("{:?}", ty);
}
}
}