1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
//! Descriptors provide metadata about an element of a Transport Stream. //! //! For example, a descriptor may be used to specify the language of an audio track. Use of //! specific descriptors is often not mandatory (many streams do not describe the language of their //! audio). //! //! The syntax //! of specific PSI tables often allows descriptors to be attached to the table itself, or to //! entries within the table. //! //! # Extensions //! //! Descriptors are a point of extension, with a range of descriptor types defined by the core //! standard, and further descriptor types defined by standards based upon transport streams. In //! order to support this extension, while avoiding allocations (a la `dyn Trait`), //! descriptor-related types and methods within this crate have a type-parameter so that calling //! code which wants to use externally-defined descriptors can supply a type which supports them. //! //! So for example code using [`PmtSection`](..//demultiplex/struct.PmtSection.html) will need to //! specify the `Descriptor` implementation to be produced, //! //! ``` //! # use mpeg2ts_reader::psi::pmt::PmtSection; //! # use mpeg2ts_reader::descriptor::CoreDescriptors; //! # let data = [0; 4]; //! let pmt = PmtSection::from_bytes(&data).unwrap(); //! // type parameter to descriptors() is inferred from the use of CoreDescriptors below //! for d in pmt.descriptors() { //! if let Ok(CoreDescriptors::Registration(reg)) = d { //! println!("registration_descriptor {:?}", reg.format_identifier()); //! } //! } //! ``` pub mod avcvideo; pub mod iso_639_language; pub mod max_bitrate; pub mod registration; use self::avcvideo::AvcVideoDescriptor; use self::iso_639_language::Iso639LanguageDescriptor; use self::max_bitrate::MaximumBitrateDescriptor; use self::registration::RegistrationDescriptor; use std::fmt; use std::marker; /// Trait allowing users of this trait to supply their own implementation of descriptor parsing. /// /// The default implementation provided by this crate is /// [`CoreDescriptors`](enum.CoreDescriptors.html), which will only provide support for descriptor /// types directly defined by _ISO/IEC 13818-1_. To support descriptors from other standards, /// an alternative implementation of this trait may be passed as a type parameter to methods such as /// [`PmtSection::descriptors()`](..//demultiplex/struct.PmtSection.html#method.descriptors). /// /// The [`descriptor_enum!{}`](../macro.descriptor_enum.html) macro can be used to help create /// implementations of this trait. pub trait Descriptor<'buf>: Sized { /// Create an object that that can wrap and parse the type of descriptor at the start of the /// given slice. fn from_bytes(buf: &'buf [u8]) -> Result<Self, DescriptorError>; } /// Builds an enum to encapsulate all possible implementations of /// [`Descriptor`](descriptor/trait.Descriptor.html) that you want to be able to handle in your /// application. /// /// The list of variants is supplied in the macro body together with the 'tag' values of each /// option. The macro will generate an implementation of `descriptor::Descriptor` whose /// `from_bytes()` function will return the variant for the tag value found within the input /// buffer. /// /// ``` /// # use mpeg2ts_reader::*; /// use mpeg2ts_reader::descriptor::*; /// /// struct MySpecialDescriptor<'buf> { /// # buf: &'buf [u8], /// // ... /// }; /// impl<'buf> MySpecialDescriptor<'buf> { /// pub fn new(tag: u8, payload: &'buf [u8]) -> Result<Self, DescriptorError> { /// # Ok(MySpecialDescriptor { buf: payload }) /// // ... /// } /// } /// /// descriptor_enum! { /// // you could #[derive(Debug)] here if you wanted /// MyOwnDescriptors { /// /// descriptor tag values `0`, `1` and `57` to `62` inclusive are marked as reserved /// /// by _ISO/IEC 13818-1_. If any of these tag values are found, /// /// MyOwnDescriptors::from_bytes() will return MyOwnDescriptors::Reserved. /// Reserved 0|1|57..=62 => UnknownDescriptor, /// Other 2..=56|63..=254 => UnknownDescriptor, /// /// When MyOwnDescriptors::from_bytes() finds the value 255, it will return the /// /// MyOwnDescriptors::MySpecialPrivate variant, which will in turn wrap an instance /// /// of MySpecialDescriptor. /// MySpecialPrivate 255 => MySpecialDescriptor, /// } /// } /// ``` #[macro_export] macro_rules! descriptor_enum { ( $(#[$outer:meta])* $name:ident { $( $(#[$inner:ident $($args:tt)*])* $case_name:ident $($tags:pat)|* => $t:ident ),*, } ) => { $(#[$outer])* pub enum $name<'buf> { $( $(#[$inner $($args)*])* $case_name($t<'buf>), )* } impl<'buf> $crate::descriptor::Descriptor<'buf> for $name<'buf> { fn from_bytes(buf: &'buf[u8]) -> Result<Self, $crate::descriptor::DescriptorError> { if buf.len() < 2 { return Err($crate::descriptor::DescriptorError::BufferTooShort{ buflen: buf.len() }) } let tag = buf[0]; let len = buf[1] as usize; let tag_end = len + 2; if tag_end > buf.len() { return Err($crate::descriptor::DescriptorError::TagTooLongForBuffer{ taglen: len, buflen: buf.len() }) } let payload = &buf[2..tag_end]; match tag { $( $( $tags )|* => Ok($name::$case_name($t::new(tag, payload)?)), )* } } } } } /// Catch-all type for when there is no explicit handling for the given descriptor type. pub struct UnknownDescriptor<'buf> { /// the descriptor's identifying 'tag' value; different types of descriptors are assigned /// different tag values pub tag: u8, /// the descriptor's payload bytes pub payload: &'buf [u8], } impl<'buf> UnknownDescriptor<'buf> { /// Constructor, in the form required for use with the /// [`descriptor_enum!{}`](../macro.descriptor_enum.html) macro. pub fn new(tag: u8, payload: &'buf [u8]) -> Result<UnknownDescriptor<'buf>, DescriptorError> { Ok(UnknownDescriptor { tag, payload }) } } impl<'buf> fmt::Debug for UnknownDescriptor<'buf> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { f.debug_struct("UnknownDescriptor") .field("tag", &self.tag) .field("len", &self.payload.len()) .finish() } } descriptor_enum! { /// Default implementation of [`Descriptor`](trait.Descriptor.html) covering descriptor types /// from _ISO/IEC 13818-1_. /// /// **NB** coverage of the range of descriptors from the spec with descriptor-type-specific /// Rust types is currently incomplete, with those variants currently containing /// `UnknownDescriptor` needing to be changed to have type-specific implementations in some /// future release of this crate. #[derive(Debug)] CoreDescriptors { /// descriptor tag values `0`, `1` and `57` to `62` inclusive are marked as reserved by _ISO/IEC 13818-1_. Reserved 0|1|57..=62 => UnknownDescriptor, /// The `video_stream_descriptor()` syntax element from _ISO/IEC 13818-1_. VideoStream 2 => UnknownDescriptor, /// The `audio_stream_descriptor()` syntax element from _ISO/IEC 13818-1_. AudioStream 3 => UnknownDescriptor, /// The `hierarchy_descriptor()` syntax element from _ISO/IEC 13818-1_. Hierarchy 4 => UnknownDescriptor, /// The `registration_descriptor()` syntax element from _ISO/IEC 13818-1_. Registration 5 => RegistrationDescriptor, /// The `data_stream_alignment_descriptor()` syntax element from _ISO/IEC 13818-1_. DataStreamAlignment 6 => UnknownDescriptor, /// The `target_background_grid_descriptor()` syntax element from _ISO/IEC 13818-1_. TargetBackgroundGrid 7 => UnknownDescriptor, /// The `video_window_descriptor()` syntax element from _ISO/IEC 13818-1_. VideoWindow 8 => UnknownDescriptor, /// The `CA_descriptor()` syntax element from _ISO/IEC 13818-1_ ("Conditional Access"). CA 9 => UnknownDescriptor, /// The `ISO_639_language_descriptor()` syntax element from _ISO/IEC 13818-1_. ISO639Language 10 => Iso639LanguageDescriptor, /// The `system_clock_descriptor()` syntax element from _ISO/IEC 13818-1_. SystemClock 11 => UnknownDescriptor, /// The `multiplex_buffer_utilization_descriptor()` syntax element from _ISO/IEC 13818-1_. MultiplexBufferUtilization 12 => UnknownDescriptor, /// The `copyright_descriptor()` syntax element from _ISO/IEC 13818-1_. Copyright 13 => UnknownDescriptor, /// The `maximum_bitrate_descriptor()` syntax element from _ISO/IEC 13818-1_. MaximumBitrate 14 => MaximumBitrateDescriptor, /// The `private_data_indicator_descriptor()` syntax element from _ISO/IEC 13818-1_. PrivateDataIndicator 15 => UnknownDescriptor, /// The `smoothing_buffer_descriptor()` syntax element from _ISO/IEC 13818-1_. SmoothingBuffer 16 => UnknownDescriptor, /// The `STD_descriptor()` syntax element from _ISO/IEC 13818-1_. STD 17 => UnknownDescriptor, /// The `ibp_descriptor()` syntax element from _ISO/IEC 13818-1_. IBP 18 => UnknownDescriptor, /// descriptor tag values `19` to `26` inclusive are marked as reserved by _ISO IEC 13818-6_ (NB a different standard than the one supported by this crate). IsoIec13818dash6 19..=26 => UnknownDescriptor, /// The `MPEG-4_video_descriptor()` syntax element from _ISO/IEC 13818-1_. MPEG4Video 27 => UnknownDescriptor, /// The `MPEG-4_audio_descriptor()` syntax element from _ISO/IEC 13818-1_. MPEG4Audio 28 => UnknownDescriptor, /// The `IOD_descriptor()` syntax element from _ISO/IEC 13818-1_ ("Initial Object Descriptor"). IOD 29 => UnknownDescriptor, /// The `SL_descriptor()` syntax element from _ISO/IEC 13818-1_ ("Synchronization Layer"). SL 30 => UnknownDescriptor, /// The `FMC_descriptor()` syntax element from _ISO/IEC 13818-1_ ("FlexMux Channel"). FMC 31 => UnknownDescriptor, /// The `External_ES_ID_descriptor()` syntax element from _ISO/IEC 13818-1_. ExternalESID 32 => UnknownDescriptor, /// The `Muxcode_descriptor()` syntax element from _ISO/IEC 13818-1_. MuxCode 33 => UnknownDescriptor, /// The `FmxBufferSize_descriptor()` syntax element from _ISO/IEC 13818-1_ ("FlexMux buffer"). FmxBufferSize 34 => UnknownDescriptor, /// The `MultiplexBuffer_descriptor()` syntax element from _ISO/IEC 13818-1_. MultiplexBuffer 35 => UnknownDescriptor, /// The `content_labeling_descriptor()` syntax element from _ISO/IEC 13818-1_. MontentLabeling 36 => UnknownDescriptor, /// The `metadata_pointer_descriptor()` syntax element from _ISO/IEC 13818-1_. MetadataPointer 37 => UnknownDescriptor, /// The `metadata_descriptor()` syntax element from _ISO/IEC 13818-1_. Metadata 38 => UnknownDescriptor, /// The `metadata_STD_descriptor()` syntax element from _ISO/IEC 13818-1_. MetadataStd 39 => UnknownDescriptor, /// The `AVC_video_descriptor()` syntax element from _ISO/IEC 13818-1_. AvcVideo 40 => AvcVideoDescriptor, /// The `IPMP_descriptor()` syntax element defined in _ISO/IEC 13818-11_. IPMP 41 => UnknownDescriptor, /// The `AVC_timing_and_HRD_descriptor()` syntax element from _ISO/IEC 13818-1_. AvcTimingAndHrd 42 => UnknownDescriptor, /// The `MPEG-2_AAC_audio_descriptor()` syntax element from _ISO/IEC 13818-1_. Mpeg2AacAudio 43 => UnknownDescriptor, /// The `FlexMuxTiming_descriptor()` syntax element from _ISO/IEC 13818-1_. FlexMuxTiming 44 => UnknownDescriptor, /// The `MPEG-4_text_descriptor()` syntax element from _ISO/IEC 13818-1_. Mpeg4Text 45 => UnknownDescriptor, /// The `MPEG-4_audio_extension_descriptor()` syntax element from _ISO/IEC 13818-1_. Mpeg4AudioExtension 46 => UnknownDescriptor, /// The `Auxiliary_video_stream_descriptor()` syntax element from _ISO/IEC 13818-1_. AuxiliaryVideoStream 47 => UnknownDescriptor, /// The `SVC extension descriptor()` syntax element from _ISO/IEC 13818-1_. SvcExtension 48 => UnknownDescriptor, /// The `MVC extension descriptor()` syntax element from _ISO/IEC 13818-1_. MvcExtension 49 => UnknownDescriptor, /// The `J2K video descriptor()` syntax element from _ISO/IEC 13818-1_. J2kVideo 50 => UnknownDescriptor, /// The `MVC operation point descriptor()` syntax element from _ISO/IEC 13818-1_. MvcOperationPoint 51 => UnknownDescriptor, /// The `MPEG2_stereoscopic_video_format_descriptor()` syntax element from _ISO/IEC 13818-1_. Mpeg2StereoscopicVideoFormat 52 => UnknownDescriptor, /// The `Stereoscopic_program_info_descriptor()` syntax element from _ISO/IEC 13818-1_. StereoscopicProgramInfo 53 => UnknownDescriptor, /// The `Stereoscopic_video_info_descriptor()` syntax element from _ISO/IEC 13818-1_. StereoscopicVideoInfo 54 => UnknownDescriptor, /// The `Transport_profile_descriptor()` syntax element from _ISO/IEC 13818-1_. TransportProfile 55 => UnknownDescriptor, /// The `HEVC video descriptor()` syntax element from _ISO/IEC 13818-1_. HevcVideo 56 => UnknownDescriptor, /// The `Extension_descriptor()` syntax element from _ISO/IEC 13818-1_. Extension 63 => UnknownDescriptor, /// descriptor tag values `64` to `255` inclusive are marked for 'use private' use by _ISO/IEC 13818-1_. UserPrivate 64..=255 => UnknownDescriptor, } } /// Iterator over the descriptor elements in a given byte slice. pub struct DescriptorIter<'buf, Desc> where Desc: Descriptor<'buf>, { buf: &'buf [u8], phantom: marker::PhantomData<Desc>, } impl<'buf, Desc> DescriptorIter<'buf, Desc> where Desc: Descriptor<'buf>, { /// Create an iterator over all the descriptors in the given slice pub fn new(buf: &'buf [u8]) -> DescriptorIter<'buf, Desc> { DescriptorIter { buf, phantom: marker::PhantomData, } } } impl<'buf, Desc> Iterator for DescriptorIter<'buf, Desc> where Desc: Descriptor<'buf>, { type Item = Result<Desc, DescriptorError>; fn next(&mut self) -> Option<Self::Item> { if self.buf.is_empty() { return None; } if self.buf.len() < 2 { let buflen = self.buf.len(); // ensure anther call to next() will yield None, self.buf = &self.buf[0..0]; Some(Err(DescriptorError::BufferTooShort { buflen })) } else { let tag = self.buf[0]; let len = self.buf[1] as usize; let remaining_size = self.buf.len() - 2; if len > remaining_size { // ensure anther call to next() will yield None, self.buf = &self.buf[0..0]; Some(Err(DescriptorError::NotEnoughData { tag, actual: remaining_size, expected: len, })) } else { let (desc, rest) = self.buf.split_at(len + 2); self.buf = rest; Some(Descriptor::from_bytes(desc)) } } } } /// An error during parsing of a descriptor #[derive(Debug, PartialEq)] pub enum DescriptorError { /// The amount of data available in the buffer is not enough to hold the descriptor's declared /// size. NotEnoughData { /// descriptor tag value tag: u8, /// actual buffer size actual: usize, /// expected buffer size expected: usize, }, /// TODO: replace with NotEnoughData TagTooLongForBuffer { /// actual length in descriptor header taglen: usize, /// remaining bytes in buffer (which is seen to be shorter than `taglen`) buflen: usize, }, /// The buffer is too short to even hold the two bytes of generic descriptor header data BufferTooShort { /// the actual buffer length buflen: usize, }, /// There is no mapping defined of the given descriptor tag value to a `Descriptor` value. UnhandledTagValue(u8), } pub(crate) fn descriptor_len(buf: &[u8], tag: u8, len: usize) -> Result<(), DescriptorError> { if buf.len() < len { Err(DescriptorError::NotEnoughData { tag, actual: buf.len(), expected: len, }) } else { Ok(()) } } #[cfg(test)] mod test { use crate::descriptor::{descriptor_len, CoreDescriptors, DescriptorError, DescriptorIter}; use assert_matches::assert_matches; use hex_literal::*; #[test] fn core() { let data = hex!("000100"); let mut iter = DescriptorIter::<CoreDescriptors<'_>>::new(&data); let desc = iter.next().unwrap(); assert!(!format!("{:?}", desc).is_empty()); assert_matches!(desc, Ok(CoreDescriptors::Reserved(d)) => { assert_eq!(d.tag, 0); assert_eq!(d.payload, &[0]); }); } #[test] fn not_enough_data() { assert_matches!( descriptor_len(b"", 0, 1), Err(DescriptorError::NotEnoughData { tag: 0, actual: 0, expected: 1, }) ); } }