webrtc_media/io/h264_reader/
mod.rs1#[cfg(test)]
2mod h264_reader_test;
3
4use std::fmt;
5use std::io::Read;
6
7use bytes::{BufMut, BytesMut};
8
9use crate::error::{Error, Result};
10
11#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
14pub enum NalUnitType {
15 #[default]
17 Unspecified = 0,
18 CodedSliceNonIdr = 1,
20 CodedSliceDataPartitionA = 2,
22 CodedSliceDataPartitionB = 3,
24 CodedSliceDataPartitionC = 4,
26 CodedSliceIdr = 5,
28 SEI = 6,
30 SPS = 7,
32 PPS = 8,
34 AUD = 9,
36 EndOfSequence = 10,
38 EndOfStream = 11,
40 Filler = 12,
42 SpsExt = 13,
44 CodedSliceAux = 19,
46 Reserved,
48 }
52
53impl fmt::Display for NalUnitType {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 let s = match *self {
56 NalUnitType::Unspecified => "Unspecified",
57 NalUnitType::CodedSliceNonIdr => "CodedSliceNonIdr",
58 NalUnitType::CodedSliceDataPartitionA => "CodedSliceDataPartitionA",
59 NalUnitType::CodedSliceDataPartitionB => "CodedSliceDataPartitionB",
60 NalUnitType::CodedSliceDataPartitionC => "CodedSliceDataPartitionC",
61 NalUnitType::CodedSliceIdr => "CodedSliceIdr",
62 NalUnitType::SEI => "SEI",
63 NalUnitType::SPS => "SPS",
64 NalUnitType::PPS => "PPS",
65 NalUnitType::AUD => "AUD",
66 NalUnitType::EndOfSequence => "EndOfSequence",
67 NalUnitType::EndOfStream => "EndOfStream",
68 NalUnitType::Filler => "Filler",
69 NalUnitType::SpsExt => "SpsExt",
70 NalUnitType::CodedSliceAux => "NalUnitTypeCodedSliceAux",
71 _ => "Reserved",
72 };
73 write!(f, "{}({})", s, *self as u8)
74 }
75}
76
77impl From<u8> for NalUnitType {
78 fn from(v: u8) -> Self {
79 match v {
80 0 => NalUnitType::Unspecified,
81 1 => NalUnitType::CodedSliceNonIdr,
82 2 => NalUnitType::CodedSliceDataPartitionA,
83 3 => NalUnitType::CodedSliceDataPartitionB,
84 4 => NalUnitType::CodedSliceDataPartitionC,
85 5 => NalUnitType::CodedSliceIdr,
86 6 => NalUnitType::SEI,
87 7 => NalUnitType::SPS,
88 8 => NalUnitType::PPS,
89 9 => NalUnitType::AUD,
90 10 => NalUnitType::EndOfSequence,
91 11 => NalUnitType::EndOfStream,
92 12 => NalUnitType::Filler,
93 13 => NalUnitType::SpsExt,
94 19 => NalUnitType::CodedSliceAux,
95 _ => NalUnitType::Reserved,
96 }
97 }
98}
99
100pub struct NAL {
102 pub picture_order_count: u32,
103
104 pub forbidden_zero_bit: bool,
106 pub ref_idc: u8,
107 pub unit_type: NalUnitType,
108
109 pub data: BytesMut,
111}
112
113impl NAL {
114 fn new(data: BytesMut) -> Self {
115 NAL {
116 picture_order_count: 0,
117 forbidden_zero_bit: false,
118 ref_idc: 0,
119 unit_type: NalUnitType::Unspecified,
120 data,
121 }
122 }
123
124 fn parse_header(&mut self) {
125 let first_byte = self.data[0];
126 self.forbidden_zero_bit = ((first_byte & 0x80) >> 7) == 1; self.ref_idc = (first_byte & 0x60) >> 5; self.unit_type = NalUnitType::from(first_byte & 0x1F); }
130}
131
132const NAL_PREFIX_3BYTES: [u8; 3] = [0, 0, 1];
133const NAL_PREFIX_4BYTES: [u8; 4] = [0, 0, 0, 1];
134
135struct ReadBuffer {
137 buffer: Box<[u8]>,
138 read_end: usize,
139 filled_end: usize,
140}
141
142impl ReadBuffer {
143 fn new(capacity: usize) -> ReadBuffer {
144 Self {
145 buffer: vec![0u8; capacity].into_boxed_slice(),
146 read_end: 0,
147 filled_end: 0,
148 }
149 }
150
151 #[inline]
152 fn in_buffer(&self) -> usize {
153 self.filled_end - self.read_end
154 }
155
156 fn consume(&mut self, consume: usize) -> &[u8] {
157 debug_assert!(self.read_end + consume <= self.filled_end);
158 let result = &self.buffer[self.read_end..][..consume];
159 self.read_end += consume;
160 result
161 }
162
163 pub(crate) fn fill_buffer(&mut self, reader: &mut impl Read) -> Result<()> {
164 debug_assert_eq!(self.read_end, self.filled_end);
165
166 self.read_end = 0;
167 self.filled_end = reader.read(&mut self.buffer)?;
168
169 Ok(())
170 }
171}
172
173pub struct H264Reader<R: Read> {
175 reader: R,
176 buffer: ReadBuffer,
178 nal_prefix_parsed: bool,
180 count_of_consecutive_zero_bytes: usize,
181 nal_buffer: BytesMut,
182}
183
184impl<R: Read> H264Reader<R> {
185 pub fn new(reader: R, capacity: usize) -> H264Reader<R> {
187 H264Reader {
188 reader,
189 nal_prefix_parsed: false,
190 buffer: ReadBuffer::new(capacity),
191 count_of_consecutive_zero_bytes: 0,
192 nal_buffer: BytesMut::new(),
193 }
194 }
195
196 fn read4(&mut self) -> Result<([u8; 4], usize)> {
197 let mut result = [0u8; 4];
198 let mut result_filled = 0;
199 loop {
200 let in_buffer = self.buffer.in_buffer();
201
202 if in_buffer + result_filled >= 4 {
203 let consume = 4 - result_filled;
204 result[result_filled..].copy_from_slice(self.buffer.consume(consume));
205 return Ok((result, 4));
206 }
207
208 result[result_filled..][..in_buffer].copy_from_slice(self.buffer.consume(in_buffer));
209 result_filled += in_buffer;
210
211 self.buffer.fill_buffer(&mut self.reader)?;
212
213 if self.buffer.in_buffer() == 0 {
214 return Ok((result, result_filled));
215 }
216 }
217 }
218
219 fn read1(&mut self) -> Result<Option<u8>> {
220 if self.buffer.in_buffer() == 0 {
221 self.buffer.fill_buffer(&mut self.reader)?;
222
223 if self.buffer.in_buffer() == 0 {
224 return Ok(None);
225 }
226 }
227
228 Ok(Some(self.buffer.consume(1)[0]))
229 }
230
231 fn bit_stream_starts_with_h264prefix(&mut self) -> Result<usize> {
232 let (prefix_buffer, n) = self.read4()?;
233
234 if n == 0 {
235 return Err(Error::ErrIoEOF);
236 }
237
238 if n < 3 {
239 return Err(Error::ErrDataIsNotH264Stream);
240 }
241
242 let nal_prefix3bytes_found = NAL_PREFIX_3BYTES[..] == prefix_buffer[..3];
243 if n == 3 {
244 if nal_prefix3bytes_found {
245 return Err(Error::ErrIoEOF);
246 }
247 return Err(Error::ErrDataIsNotH264Stream);
248 }
249
250 if nal_prefix3bytes_found {
252 self.nal_buffer.put_u8(prefix_buffer[3]);
253 return Ok(3);
254 }
255
256 let nal_prefix4bytes_found = NAL_PREFIX_4BYTES[..] == prefix_buffer;
257 if nal_prefix4bytes_found {
258 Ok(4)
259 } else {
260 Err(Error::ErrDataIsNotH264Stream)
261 }
262 }
263
264 pub fn next_nal(&mut self) -> Result<NAL> {
268 if !self.nal_prefix_parsed {
269 self.bit_stream_starts_with_h264prefix()?;
270
271 self.nal_prefix_parsed = true;
272 }
273
274 loop {
275 let Some(read_byte) = self.read1()? else {
276 break;
277 };
278
279 let nal_found = self.process_byte(read_byte);
280 if nal_found {
281 let nal_unit_type = NalUnitType::from(self.nal_buffer[0] & 0x1F);
282 if nal_unit_type == NalUnitType::SEI {
283 self.nal_buffer.clear();
284 continue;
285 } else {
286 break;
287 }
288 }
289
290 self.nal_buffer.put_u8(read_byte);
291 }
292
293 if self.nal_buffer.is_empty() {
294 return Err(Error::ErrIoEOF);
295 }
296
297 let mut nal = NAL::new(self.nal_buffer.split());
298 nal.parse_header();
299
300 Ok(nal)
301 }
302
303 fn process_byte(&mut self, read_byte: u8) -> bool {
304 let mut nal_found = false;
305
306 match read_byte {
307 0 => {
308 self.count_of_consecutive_zero_bytes += 1;
309 }
310 1 => {
311 if self.count_of_consecutive_zero_bytes >= 2 {
312 let count_of_consecutive_zero_bytes_in_prefix =
313 if self.count_of_consecutive_zero_bytes > 2 {
314 3
315 } else {
316 2
317 };
318 let nal_unit_length =
319 self.nal_buffer.len() - count_of_consecutive_zero_bytes_in_prefix;
320 if nal_unit_length > 0 {
321 let _ = self.nal_buffer.split_off(nal_unit_length);
322 nal_found = true;
323 }
324 }
325 self.count_of_consecutive_zero_bytes = 0;
326 }
327 _ => {
328 self.count_of_consecutive_zero_bytes = 0;
329 }
330 }
331
332 nal_found
333 }
334}