h264_reader/
avcc.rs

1//! Support for handling _Advanced Video Coding Configuration_ data, used in the _ISO Base Media
2//! File Format_ (AKA MP4), as the specified in _ISO/IEC 14496-15_.
3//!
4
5use crate::nal::sps::{ConstraintFlags, Level, ProfileIdc, SeqParameterSet};
6use crate::nal::{pps, sps, Nal, NalHeader, NalHeaderError, RefNal, UnitType};
7use crate::Context;
8use std::convert::TryFrom;
9
10#[derive(Debug)]
11pub enum AvccError {
12    NotEnoughData {
13        expected: usize,
14        actual: usize,
15    },
16    /// The AvcDecoderConfigurationRecord used a version number other than `1`.
17    UnsupportedConfigurationVersion(u8),
18    ParamSet(ParamSetError),
19    Sps(sps::SpsError),
20    Pps(pps::PpsError),
21}
22
23pub struct AvcDecoderConfigurationRecord<'buf> {
24    data: &'buf [u8],
25}
26impl<'buf> TryFrom<&'buf [u8]> for AvcDecoderConfigurationRecord<'buf> {
27    type Error = AvccError;
28
29    fn try_from(data: &'buf [u8]) -> Result<Self, Self::Error> {
30        let avcc = AvcDecoderConfigurationRecord { data };
31        // we must confirm we have enough bytes for all fixed fields before we do anything else,
32        avcc.ck(Self::MIN_CONF_SIZE)?;
33        if avcc.configuration_version() != 1 {
34            // The spec requires that decoders ignore streams where the version number is not 1,
35            // indicating there was an incompatible change in the configuration format,
36            return Err(AvccError::UnsupportedConfigurationVersion(
37                avcc.configuration_version(),
38            ));
39        }
40        // Do a whole load of work to ensure that the buffer is large enough for all the optional
41        // fields actually indicated to be present, so that we don't have to put these checks into
42        // the accessor functions of individual fields,
43        let mut len = avcc.seq_param_sets_end()?;
44
45        avcc.ck(len + 1)?;
46        let mut num_pps = data[len];
47        len += 1;
48        while num_pps > 0 {
49            avcc.ck(len + 2)?;
50            let pps_len = (u16::from(data[len]) << 8 | u16::from(data[len + 1])) as usize;
51            len += 2;
52            avcc.ck(len + pps_len)?;
53            len += pps_len;
54            num_pps -= 1;
55        }
56
57        Ok(avcc)
58    }
59}
60impl<'buf> AvcDecoderConfigurationRecord<'buf> {
61    const MIN_CONF_SIZE: usize = 6;
62
63    fn seq_param_sets_end(&self) -> Result<usize, AvccError> {
64        let mut num_sps = self.num_of_sequence_parameter_sets();
65        let mut len = Self::MIN_CONF_SIZE;
66        while num_sps > 0 {
67            self.ck(len + 2)?;
68            let sps_len = (u16::from(self.data[len]) << 8 | u16::from(self.data[len + 1])) as usize;
69            len += 2;
70            self.ck(len + sps_len)?;
71            len += sps_len;
72            num_sps -= 1;
73        }
74        Ok(len)
75    }
76    fn ck(&self, len: usize) -> Result<(), AvccError> {
77        if self.data.len() < len {
78            Err(AvccError::NotEnoughData {
79                expected: len,
80                actual: self.data.len(),
81            })
82        } else {
83            Ok(())
84        }
85    }
86    pub fn configuration_version(&self) -> u8 {
87        self.data[0]
88    }
89    pub fn num_of_sequence_parameter_sets(&self) -> usize {
90        (self.data[5] & 0b0001_1111) as usize
91    }
92    pub fn avc_profile_indication(&self) -> ProfileIdc {
93        self.data[1].into()
94    }
95    pub fn profile_compatibility(&self) -> ConstraintFlags {
96        self.data[2].into()
97    }
98    pub fn avc_level_indication(&self) -> Level {
99        Level::from_constraint_flags_and_level_idc(self.profile_compatibility(), self.data[3])
100    }
101    /// Number of bytes used to specify the length of each NAL unit
102    /// 0 => 1 byte, 1 => 2 bytes, 2 => 3 bytes, 3 => 4 bytes
103    pub fn length_size_minus_one(&self) -> u8 {
104        self.data[4] & 0b0000_0011
105    }
106    pub fn sequence_parameter_sets(
107        &self,
108    ) -> impl Iterator<Item = Result<&'buf [u8], ParamSetError>> {
109        let num = self.num_of_sequence_parameter_sets();
110        let data = &self.data[Self::MIN_CONF_SIZE..];
111        ParamSetIter::new(data, UnitType::SeqParameterSet).take(num)
112    }
113    pub fn picture_parameter_sets(
114        &self,
115    ) -> impl Iterator<Item = Result<&'buf [u8], ParamSetError>> + 'buf {
116        let offset = self.seq_param_sets_end().unwrap();
117        let num = self.data[offset];
118        let data = &self.data[offset + 1..];
119        ParamSetIter::new(data, UnitType::PicParameterSet).take(num as usize)
120    }
121
122    /// Creates an H264 parser context, using the settings encoded into
123    /// this `AvcDecoderConfigurationRecord`.
124    ///
125    /// In particular, the _sequence parameter set_ and _picture parameter set_ values of this
126    /// configuration record will be inserted into the resulting context.
127    pub fn create_context(&self) -> Result<Context, AvccError> {
128        let mut ctx = Context::new();
129        for sps in self.sequence_parameter_sets() {
130            let sps = sps.map_err(AvccError::ParamSet)?;
131            let sps = RefNal::new(&sps[..], &[], true);
132            let sps = crate::nal::sps::SeqParameterSet::from_bits(sps.rbsp_bits())
133                .map_err(AvccError::Sps)?;
134            ctx.put_seq_param_set(sps);
135        }
136        for pps in self.picture_parameter_sets() {
137            let pps = pps.map_err(AvccError::ParamSet)?;
138            let pps = RefNal::new(&pps[..], &[], true);
139            let pps = crate::nal::pps::PicParameterSet::from_bits(&ctx, pps.rbsp_bits())
140                .map_err(AvccError::Pps)?;
141            ctx.put_pic_param_set(pps);
142        }
143        Ok(ctx)
144    }
145}
146
147#[derive(Debug)]
148pub enum ParamSetError {
149    NalHeader(NalHeaderError),
150    IncorrectNalType {
151        expected: UnitType,
152        actual: UnitType,
153    },
154    /// A _sequence parameter set_ found within the AVC decoder config was not consistent with the
155    /// settings of the decoder config itself
156    IncompatibleSps(SeqParameterSet),
157}
158
159struct ParamSetIter<'buf>(&'buf [u8], UnitType);
160
161impl<'buf> ParamSetIter<'buf> {
162    pub fn new(buf: &'buf [u8], unit_type: UnitType) -> ParamSetIter<'buf> {
163        ParamSetIter(buf, unit_type)
164    }
165}
166impl<'buf> Iterator for ParamSetIter<'buf> {
167    type Item = Result<&'buf [u8], ParamSetError>;
168
169    fn next(&mut self) -> Option<Self::Item> {
170        if self.0.is_empty() {
171            None
172        } else {
173            let len = u16::from(self.0[0]) << 8 | u16::from(self.0[1]);
174            let data = &self.0[2..];
175            let res = match NalHeader::new(data[0]) {
176                Ok(nal_header) => {
177                    if nal_header.nal_unit_type() == self.1 {
178                        let (data, remainder) = data.split_at(len as usize);
179                        self.0 = remainder;
180                        Ok(data)
181                    } else {
182                        Err(ParamSetError::IncorrectNalType {
183                            expected: self.1,
184                            actual: nal_header.nal_unit_type(),
185                        })
186                    }
187                }
188                Err(err) => Err(ParamSetError::NalHeader(err)),
189            };
190            Some(res)
191        }
192    }
193}
194
195#[cfg(test)]
196mod test {
197    use super::*;
198    use crate::nal::pps::PicParamSetId;
199    use crate::nal::sps::SeqParamSetId;
200    use hex_literal::*;
201
202    #[test]
203    fn it_works() {
204        let avcc_data = hex!("0142c01e ffe10020 6742c01e b91061ff 78088000 00030080 00001971 3006d600 daf7bdc0 7c2211a8 01000468 de3c80");
205        let avcc = AvcDecoderConfigurationRecord::try_from(&avcc_data[..]).unwrap();
206        assert_eq!(1, avcc.configuration_version());
207        assert_eq!(1, avcc.num_of_sequence_parameter_sets());
208        assert_eq!(ProfileIdc::from(66), avcc.avc_profile_indication());
209        let flags = avcc.profile_compatibility();
210        assert!(flags.flag0());
211        assert!(flags.flag1());
212        assert!(!flags.flag2());
213        assert!(!flags.flag3());
214        assert!(!flags.flag4());
215        assert!(!flags.flag5());
216        let ctx = avcc.create_context().unwrap();
217        let sps = ctx
218            .sps_by_id(SeqParamSetId::from_u32(0).unwrap())
219            .expect("missing sps");
220        assert_eq!(avcc.avc_level_indication(), sps.level());
221        assert_eq!(avcc.avc_profile_indication(), sps.profile_idc);
222        assert_eq!(
223            SeqParamSetId::from_u32(0).unwrap(),
224            sps.seq_parameter_set_id
225        );
226        let _pps = ctx
227            .pps_by_id(PicParamSetId::from_u32(0).unwrap())
228            .expect("missing pps");
229    }
230    #[test]
231    fn sps_with_emulation_protection() {
232        // From a Hikvision 2CD2032-I.
233        let avcc_data = hex!(
234            "014d401e ffe10017 674d401e 9a660a0f
235                              ff350101 01400000 fa000003 01f40101
236                              000468ee 3c80"
237        );
238        let avcc = AvcDecoderConfigurationRecord::try_from(&avcc_data[..]).unwrap();
239        let _sps_data = avcc.sequence_parameter_sets().next().unwrap().unwrap();
240        let ctx = avcc.create_context().unwrap();
241        let _sps = ctx
242            .sps_by_id(SeqParamSetId::from_u32(0).unwrap())
243            .expect("missing sps");
244    }
245}