rtc_media/io/ivf_reader/
mod.rs1#[cfg(test)]
7mod ivf_reader_test;
8
9use std::io::Read;
10
11use byteorder::{LittleEndian, ReadBytesExt};
12use bytes::BytesMut;
13
14use crate::io::ResetFn;
15use shared::error::{Error, Result};
16
17pub const IVF_FILE_HEADER_SIGNATURE: &[u8] = b"DKIF";
19pub const IVF_FILE_HEADER_SIZE: usize = 32;
21pub const IVF_FRAME_HEADER_SIZE: usize = 12;
23
24#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
27pub struct IVFFileHeader {
28 pub signature: [u8; 4], pub version: u16, pub header_size: u16, pub four_cc: [u8; 4], pub width: u16, pub height: u16, pub timebase_denominator: u32, pub timebase_numerator: u32, pub num_frames: u32, pub unused: u32, }
49
50#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
53pub struct IVFFrameHeader {
54 pub frame_size: u32, pub timestamp: u64, }
59
60pub struct IVFReader<R: Read> {
62 reader: R,
63 bytes_read: usize,
64}
65
66impl<R: Read> IVFReader<R> {
67 pub fn new(reader: R) -> Result<(IVFReader<R>, IVFFileHeader)> {
70 let mut r = IVFReader {
71 reader,
72 bytes_read: 0,
73 };
74
75 let header = r.parse_file_header()?;
76
77 Ok((r, header))
78 }
79
80 pub fn reset_reader(&mut self, mut reset: ResetFn<R>) {
84 self.reader = reset(self.bytes_read);
85 }
86
87 pub fn parse_next_frame(&mut self) -> Result<(BytesMut, IVFFrameHeader)> {
91 let frame_size = self.reader.read_u32::<LittleEndian>()?;
92 let timestamp = self.reader.read_u64::<LittleEndian>()?;
93 let header = IVFFrameHeader {
94 frame_size,
95 timestamp,
96 };
97
98 let mut payload = BytesMut::with_capacity(header.frame_size as usize);
99 payload.resize(header.frame_size as usize, 0);
100 self.reader.read_exact(&mut payload)?;
101
102 self.bytes_read += IVF_FRAME_HEADER_SIZE + header.frame_size as usize;
103
104 Ok((payload, header))
105 }
106
107 fn parse_file_header(&mut self) -> Result<IVFFileHeader> {
110 let mut signature = [0u8; 4];
111 let mut four_cc = [0u8; 4];
112
113 self.reader.read_exact(&mut signature)?;
114 let version = self.reader.read_u16::<LittleEndian>()?;
115 let header_size = self.reader.read_u16::<LittleEndian>()?;
116 self.reader.read_exact(&mut four_cc)?;
117 let width = self.reader.read_u16::<LittleEndian>()?;
118 let height = self.reader.read_u16::<LittleEndian>()?;
119 let timebase_denominator = self.reader.read_u32::<LittleEndian>()?;
120 let timebase_numerator = self.reader.read_u32::<LittleEndian>()?;
121 let num_frames = self.reader.read_u32::<LittleEndian>()?;
122 let unused = self.reader.read_u32::<LittleEndian>()?;
123
124 let header = IVFFileHeader {
125 signature,
126 version,
127 header_size,
128 four_cc,
129 width,
130 height,
131 timebase_denominator,
132 timebase_numerator,
133 num_frames,
134 unused,
135 };
136
137 if header.signature != IVF_FILE_HEADER_SIGNATURE {
138 return Err(Error::ErrSignatureMismatch);
139 } else if header.version != 0 {
140 return Err(Error::ErrUnknownIVFVersion);
141 }
142
143 self.bytes_read += IVF_FILE_HEADER_SIZE;
144
145 Ok(header)
146 }
147}