Skip to content

Commit 1f2cef4

Browse files
authored
Faster H264Reader (webrtc-rs#506)
* perf: speedup H264Parser * refactor: split code for buffer management
1 parent 182406d commit 1f2cef4

File tree

1 file changed

+80
-40
lines changed
  • media/src/io/h264_reader

1 file changed

+80
-40
lines changed

media/src/io/h264_reader/mod.rs

Lines changed: 80 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ mod h264_reader_test;
44
use std::fmt;
55
use std::io::Read;
66

7-
use bytes::{BufMut, Bytes, BytesMut};
7+
use bytes::{BufMut, BytesMut};
88

99
use crate::error::{Error, Result};
1010

@@ -132,62 +132,105 @@ impl NAL {
132132
const NAL_PREFIX_3BYTES: [u8; 3] = [0, 0, 1];
133133
const NAL_PREFIX_4BYTES: [u8; 4] = [0, 0, 0, 1];
134134

135+
/// Wrapper class around reading buffer
136+
struct ReadBuffer {
137+
buffer: Box<[u8]>,
138+
read_end: usize,
139+
filled_end: usize,
140+
}
141+
142+
impl 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+
135173
/// H264Reader reads data from stream and constructs h264 nal units
136174
pub struct H264Reader<R: Read> {
137175
reader: R,
138-
nal_buffer: BytesMut,
139-
count_of_consecutive_zero_bytes: usize,
176+
// reading buffers
177+
buffer: ReadBuffer,
178+
// for reading
140179
nal_prefix_parsed: bool,
141-
read_buffer: Vec<u8>,
142-
temp_buf: Vec<u8>,
180+
count_of_consecutive_zero_bytes: usize,
181+
nal_buffer: BytesMut,
143182
}
144183

145184
impl<R: Read> H264Reader<R> {
146185
/// new creates new `H264Reader` with `capacity` sized read buffer.
147186
pub fn new(reader: R, capacity: usize) -> H264Reader<R> {
148187
H264Reader {
149188
reader,
150-
nal_buffer: BytesMut::new(),
151-
count_of_consecutive_zero_bytes: 0,
152189
nal_prefix_parsed: false,
153-
read_buffer: vec![],
154-
temp_buf: vec![0u8; capacity],
190+
buffer: ReadBuffer::new(capacity),
191+
count_of_consecutive_zero_bytes: 0,
192+
nal_buffer: BytesMut::new(),
155193
}
156194
}
157195

158-
fn read(&mut self, num_to_read: usize) -> Result<Bytes> {
159-
let buf = &mut self.temp_buf;
160-
while self.read_buffer.len() < num_to_read {
161-
let n = match self.reader.read(buf) {
162-
Ok(n) => {
163-
if n == 0 {
164-
break;
165-
}
166-
n
167-
}
168-
Err(e) => return Err(Error::Io(e.into())),
169-
};
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)?;
170212

171-
self.read_buffer.extend_from_slice(&buf[0..n]);
213+
if self.buffer.in_buffer() == 0 {
214+
return Ok((result, result_filled));
215+
}
172216
}
217+
}
173218

174-
let num_should_read = if num_to_read <= self.read_buffer.len() {
175-
num_to_read
176-
} else {
177-
self.read_buffer.len()
178-
};
219+
fn read1(&mut self) -> Result<Option<u8>> {
220+
if self.buffer.in_buffer() == 0 {
221+
self.buffer.fill_buffer(&mut self.reader)?;
179222

180-
Ok(Bytes::from(
181-
self.read_buffer
182-
.drain(..num_should_read)
183-
.collect::<Vec<u8>>(),
184-
))
223+
if self.buffer.in_buffer() == 0 {
224+
return Ok(None);
225+
}
226+
}
227+
228+
Ok(Some(self.buffer.consume(1)[0]))
185229
}
186230

187231
fn bit_stream_starts_with_h264prefix(&mut self) -> Result<usize> {
188-
let prefix_buffer = self.read(4)?;
232+
let (prefix_buffer, n) = self.read4()?;
189233

190-
let n = prefix_buffer.len();
191234
if n == 0 {
192235
return Err(Error::ErrIoEOF);
193236
}
@@ -229,13 +272,10 @@ impl<R: Read> H264Reader<R> {
229272
}
230273

231274
loop {
232-
let buffer = self.read(1)?;
233-
let n = buffer.len();
275+
let Some(read_byte) = self.read1()? else {
276+
break
277+
};
234278

235-
if n != 1 {
236-
break;
237-
}
238-
let read_byte = buffer[0];
239279
let nal_found = self.process_byte(read_byte);
240280
if nal_found {
241281
let nal_unit_type = NalUnitType::from(self.nal_buffer[0] & 0x1F);

0 commit comments

Comments
 (0)