h264_reader/push/
mod.rs

1//! Push parsing of encoded NALs.
2
3use crate::nal::{NalHeader, RefNal};
4
5/// [`AccumulatedNalHandler`]'s interest in receiving additional callbacks on a NAL.
6#[derive(Copy, Clone, Debug, Eq, PartialEq)]
7pub enum NalInterest {
8    /// If this NAL is incomplete, buffer it and call again later.
9    /// No effect if the NAL is complete.
10    Buffer,
11
12    /// Don't buffer any more of this NAL or make any more calls on it.
13    Ignore,
14}
15
16/// [NalAccumulator] callback which handles partially- or completely-buffered NALs.
17///
18/// The simplest handler is a closure. Implement this type manually when you
19/// your handler to own state which can be accessed via [NalAccumulator::handler],
20/// [NalAccumulator::handler_mut], or [NalAccumulator::into_handler].
21pub trait AccumulatedNalHandler {
22    fn nal(&mut self, nal: RefNal<'_>) -> NalInterest;
23}
24
25impl<F: FnMut(RefNal<'_>) -> NalInterest> AccumulatedNalHandler for F {
26    fn nal(&mut self, nal: RefNal<'_>) -> NalInterest {
27        (self)(nal)
28    }
29}
30
31/// Handles arbitrary fragments of NALs. See [NalAccumulator].
32///
33/// It's probably unnecessary to provide your own implementation of this trait
34/// except when benchmarking or testing a parser.
35pub trait NalFragmentHandler {
36    /// Pushes a fragment of a NAL.
37    ///
38    /// The caller must ensure that each element of `bufs` (if there are any)
39    /// is non-empty.
40    fn nal_fragment(&mut self, bufs: &[&[u8]], end: bool);
41}
42
43/// NAL accumulator for push parsers.
44///
45/// This is meant to be used by parsers for a specific format: Annex B, AVC, MPEG-TS, RTP, etc.
46/// Accumulates NALs in an internal buffer and delegates to an [AccumulatedNalHandler].
47///
48/// ```
49/// use h264_reader::nal::{Nal, RefNal, UnitType};
50/// use h264_reader::push::{NalAccumulator, NalFragmentHandler, NalInterest};
51/// let mut calls = Vec::new();
52/// let mut acc = NalAccumulator::new(|nal: RefNal<'_>| {
53///     let nal_unit_type = nal.header().unwrap().nal_unit_type();
54///     calls.push((nal_unit_type, nal.is_complete()));
55///     match nal_unit_type {
56///         UnitType::SeqParameterSet => NalInterest::Buffer,
57///         _ => NalInterest::Ignore,
58///     }
59/// });
60///
61/// // Push a SeqParameterSet in two calls (the latter with two byte slices).
62/// acc.nal_fragment(&[&b"\x67\x64\x00\x0A\xAC\x72\x84\x44\x26\x84\x00\x00\x03"[..]], false);
63/// acc.nal_fragment(&[&b"\x00"[..], &b"\x04\x00\x00\x03\x00\xCA\x3C\x48\x96\x11\x80"[..]], true);
64///
65/// // Push a PicParameterSet in two calls.
66/// acc.nal_fragment(&[&b"\x68"[..]], false);
67/// acc.nal_fragment(&[&b"\xE8\x43\x8F\x13\x21\x30"[..]], true);
68///
69/// assert_eq!(calls, &[
70///     (UnitType::SeqParameterSet, false),
71///     (UnitType::SeqParameterSet, true),
72///     (UnitType::PicParameterSet, false),
73///     // no second call on the PicParameterSet because the handler returned Ignore.
74/// ]);
75/// ```
76///
77/// Non-trivial handlers may need to *own* state that can be accessed outside the handler:
78///
79/// ```
80/// use h264_reader::nal::{Nal, RefNal, UnitType};
81/// use h264_reader::push::{AccumulatedNalHandler, NalAccumulator, NalFragmentHandler, NalInterest};
82/// struct MyHandler(Vec<UnitType>);
83/// impl AccumulatedNalHandler for MyHandler {
84///     fn nal(&mut self, nal: RefNal<'_>) -> NalInterest {
85///         self.0.push(nal.header().unwrap().nal_unit_type());
86///         NalInterest::Ignore
87///     }
88/// }
89/// let mut acc = NalAccumulator::new(MyHandler(Vec::new()));
90/// acc.nal_fragment(&[&b"\x67\x64\x00\x0A\xAC\x72\x84\x44\x26\x84\x00\x00\x03"[..]], false);
91/// acc.nal_fragment(&[&b"\x00"[..], &b"\x04\x00\x00\x03\x00\xCA\x3C\x48\x96\x11\x80"[..]], true);
92/// acc.nal_fragment(&[&b"\x68"[..]], false);
93/// acc.nal_fragment(&[&b"\xE8\x43\x8F\x13\x21\x30"[..]], true);
94/// assert_eq!(acc.handler().0, &[
95///     UnitType::SeqParameterSet,
96///     UnitType::PicParameterSet,
97/// ]);
98/// ```
99pub struct NalAccumulator<H: AccumulatedNalHandler> {
100    buf: Vec<u8>,
101    nal_handler: H,
102    interest: NalInterest,
103}
104impl<H: AccumulatedNalHandler> NalAccumulator<H> {
105    /// Creates a new accumulator which delegates to the given `nal_handler` on every push.
106    /// `nal_handler` always sees the NAL from the beginning.
107    pub fn new(nal_handler: H) -> Self {
108        Self {
109            buf: Vec::new(),
110            interest: NalInterest::Buffer,
111            nal_handler,
112        }
113    }
114
115    /// Gets a reference to the handler.
116    pub fn handler(&self) -> &H {
117        &self.nal_handler
118    }
119
120    /// Gets a mutable reference to the handler.
121    pub fn handler_mut(&mut self) -> &mut H {
122        &mut self.nal_handler
123    }
124
125    /// Unwraps this `NalAccumulator<h>`, returning the inner handler.
126    pub fn into_handler(self) -> H {
127        self.nal_handler
128    }
129}
130impl<H: AccumulatedNalHandler> NalFragmentHandler for NalAccumulator<H> {
131    /// Calls `nal_handler` with accumulated NAL unless any of the following are true:
132    /// *   a previous call on the same NAL returned [`NalInterest::Ignore`].
133    /// *   the NAL is totally empty.
134    /// *   `bufs` is empty and `end` is false.
135    fn nal_fragment(&mut self, bufs: &[&[u8]], end: bool) {
136        if self.interest != NalInterest::Ignore {
137            let nal = if !self.buf.is_empty() {
138                RefNal::new(&self.buf[..], bufs, end)
139            } else if bufs.is_empty() {
140                return; // no-op.
141            } else {
142                RefNal::new(bufs[0], &bufs[1..], end)
143            };
144
145            // Call the NAL handler. Avoid copying unless necessary.
146            match self.nal_handler.nal(nal) {
147                NalInterest::Buffer if !end => {
148                    let len = bufs.iter().map(|b| b.len()).sum();
149                    self.buf.reserve(len);
150                    for b in bufs {
151                        self.buf.extend_from_slice(b);
152                    }
153                }
154                NalInterest::Ignore => self.interest = NalInterest::Ignore,
155                _ => {}
156            }
157        }
158        if end {
159            self.buf.clear();
160            self.interest = NalInterest::Buffer;
161        }
162    }
163}
164impl<H: AccumulatedNalHandler + std::fmt::Debug> std::fmt::Debug for NalAccumulator<H> {
165    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
166        f.debug_struct("NalAccumulator")
167            .field("interest", &self.interest)
168            .field("buf", &self.buf)
169            .field("header", &self.buf.first().map(|&h| NalHeader::new(h)))
170            .field("nal_handler", &self.nal_handler)
171            .finish()
172    }
173}
174
175#[cfg(test)]
176mod test {
177    use crate::nal::Nal;
178    use std::io::{BufRead, Read};
179
180    use super::*;
181
182    #[test]
183    fn accumulate() {
184        // Try buffering everything.
185        let mut nals = Vec::new();
186        let handler = |nal: RefNal<'_>| {
187            if nal.is_complete() {
188                let mut buf = Vec::new();
189                nal.reader().read_to_end(&mut buf).unwrap();
190                nals.push(buf);
191            }
192            NalInterest::Buffer
193        };
194        let mut accumulator = NalAccumulator::new(handler);
195        accumulator.nal_fragment(&[], false);
196        accumulator.nal_fragment(&[], true);
197        accumulator.nal_fragment(&[&[0b0101_0001], &[1]], true);
198        accumulator.nal_fragment(&[&[0b0101_0001]], false);
199        accumulator.nal_fragment(&[], false);
200        accumulator.nal_fragment(&[&[2]], true);
201        accumulator.nal_fragment(&[&[0b0101_0001]], false);
202        accumulator.nal_fragment(&[], false);
203        accumulator.nal_fragment(&[&[3]], false);
204        accumulator.nal_fragment(&[], true);
205        assert_eq!(
206            nals,
207            &[
208                &[0b0101_0001, 1][..],
209                &[0b0101_0001, 2][..],
210                &[0b0101_0001, 3][..],
211            ]
212        );
213
214        // Try buffering nothing and see what's given on the first push.
215        nals.clear();
216        let handler = |nal: RefNal<'_>| {
217            nals.push(nal.reader().fill_buf().unwrap().to_owned());
218            NalInterest::Ignore
219        };
220        let mut accumulator = NalAccumulator::new(handler);
221        accumulator.nal_fragment(&[], false);
222        accumulator.nal_fragment(&[], true);
223        accumulator.nal_fragment(&[&[0b0101_0001, 1]], true);
224        accumulator.nal_fragment(&[&[0b0101_0001]], false);
225        accumulator.nal_fragment(&[], false);
226        accumulator.nal_fragment(&[&[2]], true);
227        accumulator.nal_fragment(&[&[0b0101_0001]], false);
228        accumulator.nal_fragment(&[], false);
229        accumulator.nal_fragment(&[&[3]], false);
230        accumulator.nal_fragment(&[], true);
231        assert_eq!(
232            nals,
233            &[
234                &[0b0101_0001, 1][..],
235                &[0b0101_0001][..],
236                &[0b0101_0001][..],
237            ]
238        );
239    }
240}