Skip to main content

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 mod annexb;
9pub mod avcc;
10pub mod nal;
11pub mod push;
12pub mod rbsp;
13
14/// Contextual data that needs to be tracked between evaluations of different portions of H264
15/// syntax.
16#[derive(Default, Debug)]
17pub struct Context {
18    seq_param_sets: ParamSetMap<nal::sps::SeqParameterSet>,
19    pic_param_sets: ParamSetMap<nal::pps::PicParameterSet>,
20    subset_seq_param_sets: ParamSetMap<nal::subset_sps::SubsetSps>,
21}
22impl Context {
23    #[inline]
24    pub fn new() -> Self {
25        Default::default()
26    }
27    #[inline]
28    pub fn sps_by_id(&self, id: nal::sps::SeqParamSetId) -> Option<&nal::sps::SeqParameterSet> {
29        self.seq_param_sets.get(usize::from(id.id()))
30    }
31    #[inline]
32    pub fn sps(&self) -> impl Iterator<Item = &nal::sps::SeqParameterSet> {
33        self.seq_param_sets.iter()
34    }
35    #[inline]
36    pub fn put_seq_param_set(&mut self, sps: nal::sps::SeqParameterSet) {
37        let i = usize::from(sps.seq_parameter_set_id.id());
38        self.seq_param_sets.put(i, sps);
39    }
40    #[inline]
41    pub fn pps_by_id(&self, id: nal::pps::PicParamSetId) -> Option<&nal::pps::PicParameterSet> {
42        self.pic_param_sets.get(usize::from(id.id()))
43    }
44    #[inline]
45    pub fn pps(&self) -> impl Iterator<Item = &nal::pps::PicParameterSet> {
46        self.pic_param_sets.iter()
47    }
48    #[inline]
49    pub fn put_pic_param_set(&mut self, pps: nal::pps::PicParameterSet) {
50        let i = usize::from(pps.pic_parameter_set_id.id());
51        self.pic_param_sets.put(i, pps);
52    }
53    #[inline]
54    pub fn subset_sps_by_id(
55        &self,
56        id: nal::sps::SeqParamSetId,
57    ) -> Option<&nal::subset_sps::SubsetSps> {
58        self.subset_seq_param_sets.get(usize::from(id.id()))
59    }
60    #[inline]
61    pub fn subset_sps(&self) -> impl Iterator<Item = &nal::subset_sps::SubsetSps> {
62        self.subset_seq_param_sets.iter()
63    }
64    /// Stores a subset SPS and also registers its base SPS in the regular SPS map
65    /// so that PPS and slice header parsing can find it via `sps_by_id()`.
66    #[inline]
67    pub fn put_subset_seq_param_set(&mut self, subset: nal::subset_sps::SubsetSps) {
68        let i = usize::from(subset.sps.seq_parameter_set_id.id());
69        self.seq_param_sets.put(i, subset.sps.clone());
70        self.subset_seq_param_sets.put(i, subset);
71    }
72}
73
74/// A map for very small indexes; SPS/PPS IDs must be in `[0, 32)`, and typically only 0 is used.
75struct ParamSetMap<T>(Vec<Option<T>>);
76impl<T> Default for ParamSetMap<T> {
77    fn default() -> Self {
78        Self(Default::default())
79    }
80}
81impl<T> ParamSetMap<T> {
82    fn get(&self, index: usize) -> Option<&T> {
83        self.0.get(index).map(Option::as_ref).flatten()
84    }
85    fn put(&mut self, index: usize, t: T) {
86        if self.0.len() <= index {
87            self.0.resize_with(index + 1, || None);
88        }
89        self.0[index] = Some(t);
90    }
91    fn iter(&self) -> impl Iterator<Item = &T> {
92        self.0.iter().filter_map(Option::as_ref)
93    }
94}
95impl<T: Debug> Debug for ParamSetMap<T> {
96    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97        f.debug_map()
98            .entries(
99                self.0
100                    .iter()
101                    .enumerate()
102                    .filter_map(|(i, p)| p.as_ref().map(|p| (i, p))),
103            )
104            .finish()
105    }
106}
107
108#[cfg(test)]
109mod tests {
110    #[test]
111    fn map() {
112        let mut s = super::ParamSetMap::default();
113        assert!(s.iter().copied().collect::<Vec<_>>().is_empty());
114        s.put(0, 0);
115        assert_eq!(s.iter().copied().collect::<Vec<_>>(), &[0]);
116        s.put(2, 2);
117        assert_eq!(s.iter().copied().collect::<Vec<_>>(), &[0, 2]);
118        s.put(1, 1);
119        assert_eq!(s.iter().copied().collect::<Vec<_>>(), &[0, 1, 2]);
120    }
121}