#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct StreamId(pub u8);
const PROGRAM_STREAM_MAP: u8 = 0xBC;
const PADDING_STREAM: u8 = 0xBE;
const PRIVATE_STREAM_2: u8 = 0xBF;
const ECM_STREAM: u8 = 0xF0;
const EMM_STREAM: u8 = 0xF1;
const DSMCC_STREAM: u8 = 0xF2;
const H222_1_TYPE_E: u8 = 0xF8;
const EXTENDED_STREAM_ID: u8 = 0xFD;
const PROGRAM_STREAM_DIRECTORY: u8 = 0xFF;
pub const STREAM_ID_EXTENSION_AVS3_VIDEO: u8 = 0x41;
pub const STREAM_ID_EXTENSION_AVS3_AUDIO: u8 = 0b100_1111;
impl StreamId {
pub const PROGRAM_STREAM_MAP: StreamId = StreamId(PROGRAM_STREAM_MAP);
pub const PADDING_STREAM: StreamId = StreamId(PADDING_STREAM);
pub const PRIVATE_STREAM_2: StreamId = StreamId(PRIVATE_STREAM_2);
pub const EXTENDED_STREAM_ID: StreamId = StreamId(EXTENDED_STREAM_ID);
#[must_use]
pub const fn has_optional_header(self) -> bool {
!matches!(
self.0,
PROGRAM_STREAM_MAP
| PADDING_STREAM
| PRIVATE_STREAM_2
| ECM_STREAM
| EMM_STREAM
| DSMCC_STREAM
| H222_1_TYPE_E
| PROGRAM_STREAM_DIRECTORY
)
}
#[must_use]
pub const fn is_audio(self) -> bool {
self.0 & 0xE0 == 0xC0
}
#[must_use]
pub const fn is_video(self) -> bool {
self.0 & 0xF0 == 0xE0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn classification() {
assert!(StreamId(0xC0).is_audio());
assert!(StreamId(0xE0).is_video());
assert!(StreamId(0xE0).has_optional_header());
assert!(StreamId(0xBD).has_optional_header()); assert!(!StreamId::PADDING_STREAM.has_optional_header());
assert!(!StreamId::PROGRAM_STREAM_MAP.has_optional_header());
assert!(!StreamId(0xFF).has_optional_header());
assert!(StreamId::EXTENDED_STREAM_ID.has_optional_header());
assert_eq!(StreamId::EXTENDED_STREAM_ID, StreamId(0xFD));
assert_eq!(STREAM_ID_EXTENSION_AVS3_VIDEO, 0x41);
assert_eq!(STREAM_ID_EXTENSION_AVS3_AUDIO, 0x4F);
}
}