mpeg2ts_reader/descriptor/
mod.rs

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