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}