Skip to main content

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    /// Byte offset of extension fields (chroma_format, bit_depth, SPS ext) if present.
26    extension_offset: Option<usize>,
27}
28impl<'buf> TryFrom<&'buf [u8]> for AvcDecoderConfigurationRecord<'buf> {
29    type Error = AvccError;
30
31    fn try_from(data: &'buf [u8]) -> Result<Self, Self::Error> {
32        let avcc = AvcDecoderConfigurationRecord {
33            data,
34            extension_offset: None,
35        };
36        // we must confirm we have enough bytes for all fixed fields before we do anything else,
37        avcc.ck(Self::MIN_CONF_SIZE)?;
38        if avcc.configuration_version() != 1 {
39            // The spec requires that decoders ignore streams where the version number is not 1,
40            // indicating there was an incompatible change in the configuration format,
41            return Err(AvccError::UnsupportedConfigurationVersion(
42                avcc.configuration_version(),
43            ));
44        }
45        // Do a whole load of work to ensure that the buffer is large enough for all the optional
46        // fields actually indicated to be present, so that we don't have to put these checks into
47        // the accessor functions of individual fields,
48        let mut len = avcc.seq_param_sets_end()?;
49
50        avcc.ck(len + 1)?;
51        let mut num_pps = data[len];
52        len += 1;
53        while num_pps > 0 {
54            avcc.ck(len + 2)?;
55            let pps_len = (u16::from(data[len]) << 8 | u16::from(data[len + 1])) as usize;
56            len += 2;
57            avcc.ck(len + pps_len)?;
58            len += pps_len;
59            num_pps -= 1;
60        }
61
62        // Per ISO/IEC 14496-15, profiles with chroma info have extension fields after the PPS
63        // array: chroma_format, bit_depth_luma_minus8, bit_depth_chroma_minus8, and an optional
64        // array of SPS extension NAL units.
65        let extension_offset = if avcc.avc_profile_indication().has_chroma_info()
66            && data.len() > len
67        {
68            let ext_start = len;
69            avcc.ck(len + 4)?;
70            len += 3; // chroma_format, bit_depth_luma_minus8, bit_depth_chroma_minus8
71            let num_sps_ext = data[len] as usize;
72            len += 1;
73            for _ in 0..num_sps_ext {
74                avcc.ck(len + 2)?;
75                let sps_ext_len = (u16::from(data[len]) << 8 | u16::from(data[len + 1])) as usize;
76                len += 2;
77                avcc.ck(len + sps_ext_len)?;
78                len += sps_ext_len;
79            }
80            Some(ext_start)
81        } else {
82            None
83        };
84
85        Ok(AvcDecoderConfigurationRecord {
86            data,
87            extension_offset,
88        })
89    }
90}
91impl<'buf> AvcDecoderConfigurationRecord<'buf> {
92    const MIN_CONF_SIZE: usize = 6;
93
94    fn seq_param_sets_end(&self) -> Result<usize, AvccError> {
95        let mut num_sps = self.num_of_sequence_parameter_sets();
96        let mut len = Self::MIN_CONF_SIZE;
97        while num_sps > 0 {
98            self.ck(len + 2)?;
99            let sps_len = (u16::from(self.data[len]) << 8 | u16::from(self.data[len + 1])) as usize;
100            len += 2;
101            self.ck(len + sps_len)?;
102            len += sps_len;
103            num_sps -= 1;
104        }
105        Ok(len)
106    }
107    fn ck(&self, len: usize) -> Result<(), AvccError> {
108        if self.data.len() < len {
109            Err(AvccError::NotEnoughData {
110                expected: len,
111                actual: self.data.len(),
112            })
113        } else {
114            Ok(())
115        }
116    }
117    pub fn configuration_version(&self) -> u8 {
118        self.data[0]
119    }
120    pub fn num_of_sequence_parameter_sets(&self) -> usize {
121        (self.data[5] & 0b0001_1111) as usize
122    }
123    pub fn avc_profile_indication(&self) -> ProfileIdc {
124        self.data[1].into()
125    }
126    pub fn profile_compatibility(&self) -> ConstraintFlags {
127        self.data[2].into()
128    }
129    pub fn avc_level_indication(&self) -> Level {
130        Level::from_constraint_flags_and_level_idc(self.profile_compatibility(), self.data[3])
131    }
132    /// Number of bytes used to specify the length of each NAL unit
133    /// 0 => 1 byte, 1 => 2 bytes, 2 => 3 bytes, 3 => 4 bytes
134    pub fn length_size_minus_one(&self) -> u8 {
135        self.data[4] & 0b0000_0011
136    }
137    pub fn sequence_parameter_sets(
138        &self,
139    ) -> impl Iterator<Item = Result<&'buf [u8], ParamSetError>> {
140        let num = self.num_of_sequence_parameter_sets();
141        let data = &self.data[Self::MIN_CONF_SIZE..];
142        ParamSetIter::new(data, UnitType::SeqParameterSet).take(num)
143    }
144    /// Returns the chroma format (0-3) from the extension fields, if present.
145    pub fn chroma_format(&self) -> Option<u8> {
146        self.extension_offset
147            .map(|off| self.data[off] & 0b0000_0011)
148    }
149    /// Returns bit_depth_luma_minus8 (0-7) from the extension fields, if present.
150    pub fn bit_depth_luma_minus8(&self) -> Option<u8> {
151        self.extension_offset
152            .map(|off| self.data[off + 1] & 0b0000_0111)
153    }
154    /// Returns bit_depth_chroma_minus8 (0-7) from the extension fields, if present.
155    pub fn bit_depth_chroma_minus8(&self) -> Option<u8> {
156        self.extension_offset
157            .map(|off| self.data[off + 2] & 0b0000_0111)
158    }
159    pub fn sequence_parameter_set_extensions(
160        &self,
161    ) -> impl Iterator<Item = Result<&'buf [u8], ParamSetError>> + 'buf {
162        let (data, num) = if let Some(off) = self.extension_offset {
163            let num = self.data[off + 3] as usize;
164            (&self.data[off + 4..], num)
165        } else {
166            (&self.data[..0], 0)
167        };
168        ParamSetIter::new(data, UnitType::SeqParameterSetExtension).take(num)
169    }
170    pub fn picture_parameter_sets(
171        &self,
172    ) -> impl Iterator<Item = Result<&'buf [u8], ParamSetError>> + 'buf {
173        let offset = self.seq_param_sets_end().unwrap();
174        let num = self.data[offset];
175        let data = &self.data[offset + 1..];
176        ParamSetIter::new(data, UnitType::PicParameterSet).take(num as usize)
177    }
178
179    /// Creates an H264 parser context, using the settings encoded into
180    /// this `AvcDecoderConfigurationRecord`.
181    ///
182    /// In particular, the _sequence parameter set_ and _picture parameter set_ values of this
183    /// configuration record will be inserted into the resulting context.
184    pub fn create_context(&self) -> Result<Context, AvccError> {
185        let mut ctx = Context::new();
186        for sps in self.sequence_parameter_sets() {
187            let sps = sps.map_err(AvccError::ParamSet)?;
188            let sps = RefNal::new(&sps[..], &[], true);
189            let sps = crate::nal::sps::SeqParameterSet::from_bits(sps.rbsp_bits())
190                .map_err(AvccError::Sps)?;
191            ctx.put_seq_param_set(sps);
192        }
193        for pps in self.picture_parameter_sets() {
194            let pps = pps.map_err(AvccError::ParamSet)?;
195            let pps = RefNal::new(&pps[..], &[], true);
196            let pps = crate::nal::pps::PicParameterSet::from_bits(&ctx, pps.rbsp_bits())
197                .map_err(AvccError::Pps)?;
198            ctx.put_pic_param_set(pps);
199        }
200        Ok(ctx)
201    }
202}
203
204#[derive(Debug)]
205pub enum ParamSetError {
206    NalHeader(NalHeaderError),
207    IncorrectNalType {
208        expected: UnitType,
209        actual: UnitType,
210    },
211    /// A _sequence parameter set_ found within the AVC decoder config was not consistent with the
212    /// settings of the decoder config itself
213    IncompatibleSps(SeqParameterSet),
214}
215
216struct ParamSetIter<'buf>(&'buf [u8], UnitType);
217
218impl<'buf> ParamSetIter<'buf> {
219    pub fn new(buf: &'buf [u8], unit_type: UnitType) -> ParamSetIter<'buf> {
220        ParamSetIter(buf, unit_type)
221    }
222}
223impl<'buf> Iterator for ParamSetIter<'buf> {
224    type Item = Result<&'buf [u8], ParamSetError>;
225
226    fn next(&mut self) -> Option<Self::Item> {
227        if self.0.is_empty() {
228            None
229        } else {
230            let len = u16::from(self.0[0]) << 8 | u16::from(self.0[1]);
231            let data = &self.0[2..];
232            let res = match NalHeader::new(data[0]) {
233                Ok(nal_header) => {
234                    if nal_header.nal_unit_type() == self.1 {
235                        let (data, remainder) = data.split_at(len as usize);
236                        self.0 = remainder;
237                        Ok(data)
238                    } else {
239                        Err(ParamSetError::IncorrectNalType {
240                            expected: self.1,
241                            actual: nal_header.nal_unit_type(),
242                        })
243                    }
244                }
245                Err(err) => Err(ParamSetError::NalHeader(err)),
246            };
247            Some(res)
248        }
249    }
250}
251
252#[cfg(test)]
253mod test {
254    use super::*;
255    use crate::nal::pps::PicParamSetId;
256    use crate::nal::sps::SeqParamSetId;
257    use hex_literal::*;
258
259    #[test]
260    fn it_works() {
261        let avcc_data = hex!("0142c01e ffe10020 6742c01e b91061ff 78088000 00030080 00001971 3006d600 daf7bdc0 7c2211a8 01000468 de3c80");
262        let avcc = AvcDecoderConfigurationRecord::try_from(&avcc_data[..]).unwrap();
263        assert_eq!(1, avcc.configuration_version());
264        assert_eq!(1, avcc.num_of_sequence_parameter_sets());
265        assert_eq!(ProfileIdc::from(66), avcc.avc_profile_indication());
266        let flags = avcc.profile_compatibility();
267        assert!(flags.flag0());
268        assert!(flags.flag1());
269        assert!(!flags.flag2());
270        assert!(!flags.flag3());
271        assert!(!flags.flag4());
272        assert!(!flags.flag5());
273        // Baseline profile has no extension fields
274        assert_eq!(avcc.chroma_format(), None);
275        assert_eq!(avcc.bit_depth_luma_minus8(), None);
276        assert_eq!(avcc.bit_depth_chroma_minus8(), None);
277        assert_eq!(avcc.sequence_parameter_set_extensions().count(), 0);
278        let ctx = avcc.create_context().unwrap();
279        let sps = ctx
280            .sps_by_id(SeqParamSetId::from_u32(0).unwrap())
281            .expect("missing sps");
282        assert_eq!(avcc.avc_level_indication(), sps.level());
283        assert_eq!(avcc.avc_profile_indication(), sps.profile_idc);
284        assert_eq!(
285            SeqParamSetId::from_u32(0).unwrap(),
286            sps.seq_parameter_set_id
287        );
288        let _pps = ctx
289            .pps_by_id(PicParamSetId::from_u32(0).unwrap())
290            .expect("missing pps");
291    }
292    #[test]
293    fn high_profile_extension_fields() {
294        // Hand-crafted avcC with High profile (100) and extension fields:
295        //   chroma_format=1 (4:2:0), bit_depth_luma_minus8=0, bit_depth_chroma_minus8=0,
296        //   0 SPS extension NAL units.
297        // Base: version=1, profile=100(High), compat=0x00, level=31
298        //   lengthSizeMinusOne=3 (0xff = reserved|3)
299        //   1 SPS (0xe1 = reserved|1)
300        let sps_nalu = hex!("6764001e acd940a0 2ff96100 00030001 00000300 3c9c5802 d0000bb8 00004e20 6e200000 10000003 00010000 03000321");
301        let pps_nalu = hex!("68eb e3cb 22c0");
302        let mut avcc_data: Vec<u8> = Vec::new();
303        // Fixed header
304        avcc_data.extend_from_slice(&[0x01, 0x64, 0x00, 0x1e, 0xff]);
305        // 1 SPS
306        avcc_data.push(0xe1);
307        avcc_data.extend_from_slice(&(sps_nalu.len() as u16).to_be_bytes());
308        avcc_data.extend_from_slice(&sps_nalu);
309        // 1 PPS
310        avcc_data.push(0x01);
311        avcc_data.extend_from_slice(&(pps_nalu.len() as u16).to_be_bytes());
312        avcc_data.extend_from_slice(&pps_nalu);
313        // Extension fields: chroma_format=1, bit_depth_luma=0, bit_depth_chroma=0, 0 SPS ext
314        avcc_data.extend_from_slice(&[0xfd, 0xf8, 0xf8, 0x00]);
315
316        let avcc = AvcDecoderConfigurationRecord::try_from(&avcc_data[..]).unwrap();
317        assert_eq!(avcc.avc_profile_indication(), ProfileIdc::from(100));
318        assert_eq!(avcc.chroma_format(), Some(1));
319        assert_eq!(avcc.bit_depth_luma_minus8(), Some(0));
320        assert_eq!(avcc.bit_depth_chroma_minus8(), Some(0));
321        assert_eq!(avcc.sequence_parameter_set_extensions().count(), 0);
322    }
323    #[test]
324    fn high_profile_without_extension() {
325        // High profile avcC that omits the optional extension fields.
326        let sps_nalu = hex!("6764001e acd940a0 2ff96100 00030001 00000300 3c9c5802 d0000bb8 00004e20 6e200000 10000003 00010000 03000321");
327        let pps_nalu = hex!("68eb e3cb 22c0");
328        let mut avcc_data: Vec<u8> = Vec::new();
329        avcc_data.extend_from_slice(&[0x01, 0x64, 0x00, 0x1e, 0xff]);
330        avcc_data.push(0xe1);
331        avcc_data.extend_from_slice(&(sps_nalu.len() as u16).to_be_bytes());
332        avcc_data.extend_from_slice(&sps_nalu);
333        avcc_data.push(0x01);
334        avcc_data.extend_from_slice(&(pps_nalu.len() as u16).to_be_bytes());
335        avcc_data.extend_from_slice(&pps_nalu);
336        // No extension fields appended
337
338        let avcc = AvcDecoderConfigurationRecord::try_from(&avcc_data[..]).unwrap();
339        assert_eq!(avcc.avc_profile_indication(), ProfileIdc::from(100));
340        assert_eq!(avcc.chroma_format(), None);
341        assert_eq!(avcc.bit_depth_luma_minus8(), None);
342        assert_eq!(avcc.bit_depth_chroma_minus8(), None);
343    }
344    #[test]
345    fn sps_with_emulation_protection() {
346        // From a Hikvision 2CD2032-I.
347        let avcc_data = hex!(
348            "014d401e ffe10017 674d401e 9a660a0f
349                              ff350101 01400000 fa000003 01f40101
350                              000468ee 3c80"
351        );
352        let avcc = AvcDecoderConfigurationRecord::try_from(&avcc_data[..]).unwrap();
353        let _sps_data = avcc.sequence_parameter_sets().next().unwrap().unwrap();
354        let ctx = avcc.create_context().unwrap();
355        let _sps = ctx
356            .sps_by_id(SeqParamSetId::from_u32(0).unwrap())
357            .expect("missing sps");
358    }
359}