mpeg2ts_reader/descriptor/
avcvideo.rs

1//! Provides some metadata from the SPS/PPS within this AVC stream, and also some flags to indicate
2//! usage of certain AVC stream features.
3
4use super::DescriptorError;
5use crate::descriptor::descriptor_len;
6use std::fmt;
7
8/// Descriptor holding copies of properties from the AVC metadata such as AVC 'profile' and 'level'.
9pub struct AvcVideoDescriptor<'buf> {
10    buf: &'buf [u8],
11}
12impl<'buf> AvcVideoDescriptor<'buf> {
13    /// The descriptor tag value which identifies the descriptor as a `AvcVideoDescriptor`.
14    pub const TAG: u8 = 40;
15    /// Construct a `AvcVideoDescriptor` instance that will parse the data from the given
16    /// slice.
17    pub fn new(tag: u8, buf: &'buf [u8]) -> Result<AvcVideoDescriptor<'buf>, DescriptorError> {
18        assert_eq!(tag, Self::TAG);
19        descriptor_len(buf, tag, 4)?;
20        Ok(AvcVideoDescriptor { buf })
21    }
22
23    /// The AVC _profile_ used in this stream will be equal to, or lower than, this value
24    pub fn profile_idc(&self) -> u8 {
25        self.buf[0]
26    }
27    /// Value of the same flag from this AVC stream's _Sequence Parameter Set_
28    pub fn constraint_set0_flag(&self) -> bool {
29        self.buf[1] & 0b1000_0000 != 0
30    }
31    /// Value of the same flag from this AVC stream's _Sequence Parameter Set_
32    pub fn constraint_set1_flag(&self) -> bool {
33        self.buf[1] & 0b0100_0000 != 0
34    }
35    /// Value of the same flag from this AVC stream's _Sequence Parameter Set_
36    pub fn constraint_set2_flag(&self) -> bool {
37        self.buf[1] & 0b0010_0000 != 0
38    }
39    /// Value of the same flag from this AVC stream's _Sequence Parameter Set_
40    pub fn constraint_set3_flag(&self) -> bool {
41        self.buf[1] & 0b0001_0000 != 0
42    }
43    /// Value of the same flag from this AVC stream's _Sequence Parameter Set_
44    pub fn constraint_set4_flag(&self) -> bool {
45        self.buf[1] & 0b0000_1000 != 0
46    }
47    /// Value of the same flag from this AVC stream's _Sequence Parameter Set_
48    pub fn constraint_set5_flag(&self) -> bool {
49        self.buf[1] & 0b0000_0100 != 0
50    }
51    /// Value of the same flags from this AVC stream's _Sequence Parameter Set_
52    pub fn avc_compatible_flags(&self) -> u8 {
53        self.buf[1] & 0b0000_0011
54    }
55    /// The AVC _level_ used in this stream will be equal to, or lower than, this value
56    pub fn level_idc(&self) -> u8 {
57        self.buf[2]
58    }
59    /// Stream may include AVC still pictures
60    pub fn avc_still_present(&self) -> bool {
61        self.buf[3] & 0b1000_0000 != 0
62    }
63    /// Stream may contain AVC 24-hour pictures
64    pub fn avc_24_hour_picture_flag(&self) -> bool {
65        self.buf[3] & 0b0100_0000 != 0
66    }
67    /// If false, _frame packing arrangement_ or _stereo video information_ SEI message should be
68    /// present
69    pub fn frame_packing_sei_not_present_flag(&self) -> bool {
70        self.buf[3] & 0b0010_0000 != 0
71    }
72}
73
74impl fmt::Debug for AvcVideoDescriptor<'_> {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
76        f.debug_struct("AvcVideoDescriptor")
77            .field("profile_idc", &self.profile_idc())
78            .field("constraint_set0_flag", &self.constraint_set0_flag())
79            .field("constraint_set1_flag", &self.constraint_set1_flag())
80            .field("constraint_set2_flag", &self.constraint_set2_flag())
81            .field("constraint_set3_flag", &self.constraint_set3_flag())
82            .field("constraint_set4_flag", &self.constraint_set4_flag())
83            .field("constraint_set5_flag", &self.constraint_set5_flag())
84            .field("avc_compatible_flags", &self.avc_compatible_flags())
85            .field("level_idc", &self.level_idc())
86            .field("avc_still_present", &self.avc_still_present())
87            .field("avc_24_hour_picture_flag", &self.avc_24_hour_picture_flag())
88            .field(
89                "frame_packing_sei_not_present_flag",
90                &self.frame_packing_sei_not_present_flag(),
91            )
92            .finish()
93    }
94}
95
96#[cfg(test)]
97mod test {
98    use super::super::{CoreDescriptors, Descriptor};
99    use assert_matches::assert_matches;
100    use hex_literal::*;
101
102    #[test]
103    fn descriptor() {
104        let data = hex!("280442c01e3f");
105        let desc = CoreDescriptors::from_bytes(&data[..]).unwrap();
106        assert_matches!(desc, CoreDescriptors::AvcVideo(avc_video) => {
107            assert_eq!(avc_video.level_idc(), 30);
108            assert_eq!(avc_video.constraint_set0_flag(), true);
109            assert_eq!(avc_video.constraint_set1_flag(), true);
110            assert_eq!(avc_video.constraint_set3_flag(), false);
111            assert_eq!(avc_video.constraint_set4_flag(), false);
112            assert_eq!(avc_video.constraint_set5_flag(), false);
113            assert_eq!(avc_video.avc_compatible_flags(), 0);
114            assert_eq!(avc_video.profile_idc(), 66);
115            assert_eq!(avc_video.avc_still_present(), false);
116            assert_eq!(avc_video.avc_24_hour_picture_flag(), false);
117            assert_eq!(avc_video.frame_packing_sei_not_present_flag(), true);
118        })
119    }
120
121    #[test]
122    fn debug() {
123        let data = hex!("280442c01e3f");
124        let desc = CoreDescriptors::from_bytes(&data[..]).unwrap();
125        assert_matches!(desc, CoreDescriptors::AvcVideo(avc_video) => {
126            assert!(!format!("{:?}", avc_video).is_empty());
127        });
128    }
129}