h264_reader/
lib.rs

1//! Parser for H264 bitstream syntax.  Not a video decoder.
2
3#![forbid(unsafe_code)]
4#![deny(rust_2018_idioms)]
5
6use std::fmt::Debug;
7
8pub use bitstream_io;
9
10pub mod annexb;
11pub mod avcc;
12pub mod nal;
13pub mod push;
14pub mod rbsp;
15
16/// Contextual data that needs to be tracked between evaluations of different portions of H264
17/// syntax.
18#[derive(Default, Debug)]
19pub struct Context {
20    seq_param_sets: ParamSetMap<nal::sps::SeqParameterSet>,
21    pic_param_sets: ParamSetMap<nal::pps::PicParameterSet>,
22}
23impl Context {
24    #[inline]
25    pub fn new() -> Self {
26        Default::default()
27    }
28    #[inline]
29    pub fn sps_by_id(&self, id: nal::sps::SeqParamSetId) -> Option<&nal::sps::SeqParameterSet> {
30        self.seq_param_sets.get(usize::from(id.id()))
31    }
32    #[inline]
33    pub fn sps(&self) -> impl Iterator<Item = &nal::sps::SeqParameterSet> {
34        self.seq_param_sets.iter()
35    }
36    #[inline]
37    pub fn put_seq_param_set(&mut self, sps: nal::sps::SeqParameterSet) {
38        let i = usize::from(sps.seq_parameter_set_id.id());
39        self.seq_param_sets.put(i, sps);
40    }
41    #[inline]
42    pub fn pps_by_id(&self, id: nal::pps::PicParamSetId) -> Option<&nal::pps::PicParameterSet> {
43        self.pic_param_sets.get(usize::from(id.id()))
44    }
45    #[inline]
46    pub fn pps(&self) -> impl Iterator<Item = &nal::pps::PicParameterSet> {
47        self.pic_param_sets.iter()
48    }
49    #[inline]
50    pub fn put_pic_param_set(&mut self, pps: nal::pps::PicParameterSet) {
51        let i = usize::from(pps.pic_parameter_set_id.id());
52        self.pic_param_sets.put(i, pps);
53    }
54}
55
56/// A map for very small indexes; SPS/PPS IDs must be in `[0, 32)`, and typically only 0 is used.
57struct ParamSetMap<T>(Vec<Option<T>>);
58impl<T> Default for ParamSetMap<T> {
59    fn default() -> Self {
60        Self(Default::default())
61    }
62}
63impl<T> ParamSetMap<T> {
64    fn get(&self, index: usize) -> Option<&T> {
65        self.0.get(index).map(Option::as_ref).flatten()
66    }
67    fn put(&mut self, index: usize, t: T) {
68        if self.0.len() <= index {
69            self.0.resize_with(index + 1, || None);
70        }
71        self.0[index] = Some(t);
72    }
73    fn iter(&self) -> impl Iterator<Item = &T> {
74        self.0.iter().filter_map(Option::as_ref)
75    }
76}
77impl<T: Debug> Debug for ParamSetMap<T> {
78    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79        f.debug_map()
80            .entries(
81                self.0
82                    .iter()
83                    .enumerate()
84                    .filter_map(|(i, p)| p.as_ref().map(|p| (i, p))),
85            )
86            .finish()
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    #[test]
93    fn map() {
94        let mut s = super::ParamSetMap::default();
95        assert!(s.iter().copied().collect::<Vec<_>>().is_empty());
96        s.put(0, 0);
97        assert_eq!(s.iter().copied().collect::<Vec<_>>(), &[0]);
98        s.put(2, 2);
99        assert_eq!(s.iter().copied().collect::<Vec<_>>(), &[0, 2]);
100        s.put(1, 1);
101        assert_eq!(s.iter().copied().collect::<Vec<_>>(), &[0, 1, 2]);
102    }
103}