1use std::borrow::Cow;
11use std::io::Cursor;
12use std::io::Seek;
13use std::io::Write;
14use std::marker::PhantomData;
15use std::os::fd::OwnedFd;
16
17use byteorder::ReadBytesExt;
18use byteorder::LE;
19use bytes::Buf;
20use thiserror::Error;
21
22use crate::codec::h264::parser::Nalu as H264Nalu;
23use crate::codec::h265::parser::Nalu as H265Nalu;
24use crate::decoder::stateless::DecodeError;
25use crate::decoder::stateless::PoolLayer;
26use crate::decoder::stateless::StatelessVideoDecoder;
27use crate::decoder::BlockingMode;
28use crate::decoder::DecodedHandle;
29use crate::decoder::DecoderEvent;
30use crate::decoder::FramePool;
31use crate::decoder::StreamInfo;
32use crate::DecodedFormat;
33use crate::Fourcc;
34use crate::FrameLayout;
35use crate::PlaneLayout;
36use crate::Resolution;
37
38pub struct IvfIterator<'a> {
40 cursor: Cursor<&'a [u8]>,
41}
42
43impl<'a> IvfIterator<'a> {
44 pub fn new(data: &'a [u8]) -> Self {
45 let mut cursor = Cursor::new(data);
46
47 cursor.seek(std::io::SeekFrom::Start(32)).unwrap();
49
50 Self { cursor }
51 }
52}
53
54impl<'a> Iterator for IvfIterator<'a> {
55 type Item = &'a [u8];
56
57 fn next(&mut self) -> Option<Self::Item> {
58 if self.cursor.remaining() < 12 {
60 return None;
61 }
62
63 let len = self.cursor.read_u32::<LE>().ok()? as usize;
64 let _ = self.cursor.read_u64::<LE>().ok()?;
66
67 if self.cursor.remaining() < len {
68 return None;
69 }
70
71 let start = self.cursor.position() as usize;
72 let _ = self.cursor.seek(std::io::SeekFrom::Current(len as i64));
73 let end = self.cursor.position() as usize;
74
75 Some(&self.cursor.get_ref()[start..end])
76 }
77}
78
79pub struct IvfFileHeader {
81 pub magic: [u8; 4],
82 pub version: u16,
83 pub header_size: u16,
84 pub codec: [u8; 4],
85 pub width: u16,
86 pub height: u16,
87 pub framerate: u32,
88 pub timescale: u32,
89 pub frame_count: u32,
90 pub unused: u32,
91}
92
93impl Default for IvfFileHeader {
94 fn default() -> Self {
95 Self {
96 magic: Self::MAGIC,
97 version: 0,
98 header_size: 32,
99 codec: Self::CODEC_VP9,
100 width: 320,
101 height: 240,
102 framerate: 1,
103 timescale: 1000,
104 frame_count: 1,
105 unused: Default::default(),
106 }
107 }
108}
109
110impl IvfFileHeader {
111 pub const MAGIC: [u8; 4] = *b"DKIF";
112 pub const CODEC_VP8: [u8; 4] = *b"VP80";
113 pub const CODEC_VP9: [u8; 4] = *b"VP90";
114 pub const CODEC_AV1: [u8; 4] = *b"AV01";
115
116 pub fn new(codec: [u8; 4], width: u16, height: u16, framerate: u32, frame_count: u32) -> Self {
117 let default = Self::default();
118
119 Self {
120 codec,
121 width,
122 height,
123 framerate: framerate * default.timescale,
124 frame_count,
125 ..default
126 }
127 }
128}
129
130impl IvfFileHeader {
131 pub fn writo_into(&self, writer: &mut impl std::io::Write) -> std::io::Result<()> {
133 writer.write_all(&self.magic)?;
134 writer.write_all(&self.version.to_le_bytes())?;
135 writer.write_all(&self.header_size.to_le_bytes())?;
136 writer.write_all(&self.codec)?;
137 writer.write_all(&self.width.to_le_bytes())?;
138 writer.write_all(&self.height.to_le_bytes())?;
139 writer.write_all(&self.framerate.to_le_bytes())?;
140 writer.write_all(&self.timescale.to_le_bytes())?;
141 writer.write_all(&self.frame_count.to_le_bytes())?;
142 writer.write_all(&self.unused.to_le_bytes())?;
143
144 Ok(())
145 }
146}
147
148pub struct IvfFrameHeader {
150 pub frame_size: u32,
151 pub timestamp: u64,
152}
153
154impl IvfFrameHeader {
155 pub fn writo_into(&self, writer: &mut impl std::io::Write) -> std::io::Result<()> {
157 writer.write_all(&self.frame_size.to_le_bytes())?;
158 writer.write_all(&self.timestamp.to_le_bytes())?;
159 Ok(())
160 }
161}
162
163pub struct NalIterator<'a, Nalu>(Cursor<&'a [u8]>, PhantomData<Nalu>);
165
166impl<'a, Nalu> NalIterator<'a, Nalu> {
167 pub fn new(stream: &'a [u8]) -> Self {
168 Self(Cursor::new(stream), PhantomData)
169 }
170}
171
172impl<'a> Iterator for NalIterator<'a, H264Nalu<'a>> {
173 type Item = Cow<'a, [u8]>;
174
175 fn next(&mut self) -> Option<Self::Item> {
176 H264Nalu::next(&mut self.0).map(|n| n.data).ok()
177 }
178}
179
180impl<'a> Iterator for NalIterator<'a, H265Nalu<'a>> {
181 type Item = Cow<'a, [u8]>;
182
183 fn next(&mut self) -> Option<Self::Item> {
184 H265Nalu::next(&mut self.0).map(|n| n.data).ok()
185 }
186}
187
188#[derive(Error, Debug)]
189pub enum BitWriterError {
190 #[error("invalid bit count")]
191 InvalidBitCount,
192 #[error(transparent)]
193 Io(#[from] std::io::Error),
194}
195
196pub type BitWriterResult<T> = std::result::Result<T, BitWriterError>;
197
198pub struct BitWriter<W: Write> {
199 out: W,
200 nth_bit: u8,
201 curr_byte: u8,
202}
203
204impl<W: Write> BitWriter<W> {
205 pub fn new(writer: W) -> Self {
206 Self {
207 out: writer,
208 curr_byte: 0,
209 nth_bit: 0,
210 }
211 }
212
213 pub fn write_f<T: Into<u32>>(&mut self, bits: usize, value: T) -> BitWriterResult<usize> {
215 let value = value.into();
216
217 if bits > 32 {
218 return Err(BitWriterError::InvalidBitCount);
219 }
220
221 let mut written = 0;
222 for bit in (0..bits).rev() {
223 let bit = (1 << bit) as u32;
224
225 self.write_bit((value & bit) == bit)?;
226 written += 1;
227 }
228
229 Ok(written)
230 }
231
232 pub fn write_bit(&mut self, bit: bool) -> BitWriterResult<()> {
234 self.curr_byte |= (bit as u8) << (7u8 - self.nth_bit);
235 self.nth_bit += 1;
236
237 if self.nth_bit == 8 {
238 self.out.write_all(&[self.curr_byte])?;
239 self.nth_bit = 0;
240 self.curr_byte = 0;
241 }
242
243 Ok(())
244 }
245
246 pub fn flush(&mut self) -> BitWriterResult<()> {
248 if self.nth_bit != 0 {
249 self.out.write_all(&[self.curr_byte])?;
250 self.nth_bit = 0;
251 self.curr_byte = 0;
252 }
253
254 self.out.flush()?;
255 Ok(())
256 }
257
258 pub fn has_data_pending(&self) -> bool {
260 self.nth_bit != 0
261 }
262
263 pub(crate) fn inner(&self) -> &W {
264 &self.out
265 }
266
267 pub(crate) fn inner_mut(&mut self) -> &mut W {
268 &mut self.out
269 }
270}
271
272impl<W: Write> Drop for BitWriter<W> {
273 fn drop(&mut self) {
274 if let Err(e) = self.flush() {
275 log::error!("Unable to flush bits {e:?}");
276 }
277 }
278}
279
280#[allow(clippy::type_complexity)]
282pub fn simple_playback_loop<D, R, I, H, FP>(
283 decoder: &mut D,
284 stream_iter: I,
285 on_new_frame: &mut dyn FnMut(H),
286 allocate_new_frames: &mut dyn FnMut(&StreamInfo, usize) -> anyhow::Result<Vec<H::Descriptor>>,
287 output_format: DecodedFormat,
288 blocking_mode: BlockingMode,
289) -> anyhow::Result<()>
290where
291 H: DecodedHandle,
292 FP: FramePool<Descriptor = H::Descriptor> + ?Sized,
293 D: StatelessVideoDecoder<Handle = H, FramePool = FP> + ?Sized,
294 R: AsRef<[u8]>,
295 I: Iterator<Item = R>,
296{
297 let mut check_events = |decoder: &mut D| -> anyhow::Result<()> {
300 while let Some(event) = decoder.next_event() {
301 match event {
302 DecoderEvent::FrameReady(frame) => {
303 on_new_frame(frame);
304 }
305 DecoderEvent::FormatChanged(mut format_setter) => {
306 format_setter.try_format(output_format).unwrap();
307 let stream_info = format_setter.stream_info().clone();
308 let min_num_frames = stream_info.min_num_frames;
309 let pools = format_setter.frame_pool(PoolLayer::All);
312 let nb_pools = pools.len();
313 for pool in pools {
314 let pool_num_frames = pool.num_managed_frames();
316 if pool_num_frames < (min_num_frames / nb_pools) {
317 let frames = allocate_new_frames(
318 &stream_info,
319 min_num_frames - pool_num_frames,
320 )?;
321 pool.add_frames(frames).unwrap();
322 }
323 }
324 }
325 }
326 }
327
328 Ok(())
329 };
330
331 for (frame_num, packet) in stream_iter.enumerate() {
332 let mut bitstream = packet.as_ref();
333 loop {
334 match decoder.decode(frame_num as u64, bitstream) {
335 Ok(bytes_decoded) => {
336 bitstream = &bitstream[bytes_decoded..];
337
338 if blocking_mode == BlockingMode::Blocking {
339 check_events(decoder)?;
340 }
341
342 if bitstream.is_empty() {
343 break;
346 }
347 }
348 Err(DecodeError::CheckEvents) | Err(DecodeError::NotEnoughOutputBuffers(_)) => {
349 check_events(decoder)?
350 }
351 Err(e) => anyhow::bail!(e),
352 }
353 }
354 }
355
356 decoder.flush()?;
357 check_events(decoder)
358}
359
360pub fn simple_playback_loop_owned_frames(
362 _: &StreamInfo,
363 nb_frames: usize,
364) -> anyhow::Result<Vec<()>> {
365 Ok(vec![(); nb_frames])
366}
367
368pub fn simple_playback_loop_userptr_frames(
370 stream_info: &StreamInfo,
371 nb_frames: usize,
372) -> anyhow::Result<Vec<UserPtrFrame>> {
373 let alloc_function = match stream_info.format {
374 DecodedFormat::I420 | DecodedFormat::NV12 => &UserPtrFrame::new_nv12,
375 _ => anyhow::bail!(
376 "{:?} format is unsupported with user memory",
377 stream_info.format
378 ),
379 };
380
381 Ok((0..nb_frames)
382 .map(|_| alloc_function(stream_info.coded_resolution))
383 .collect::<Vec<_>>())
384}
385
386#[derive(Debug)]
388pub struct UserPtrFrame {
389 pub buffers: Vec<*mut u8>,
390 pub mem_layout: std::alloc::Layout,
391 pub layout: FrameLayout,
392}
393
394impl UserPtrFrame {
395 pub fn new_nv12(size: Resolution) -> Self {
397 macro_rules! align {
399 ($n:expr, $r:expr) => {
400 ($n + ($r - 1)) & !($r - 1)
401 };
402 }
403
404 let width = align!(size.width, 16) as usize;
406 let height = align!(size.height, 4) as usize;
407 let stride = align!(width, 64);
408 let uv_start = height * stride;
409 let uv_size = (height / 2) * stride;
410
411 Self::alloc(
412 FrameLayout {
413 format: (Fourcc::from(b"NV12"), 0),
414 size: Resolution::from((width as u32, height as u32)),
415 planes: vec![
416 PlaneLayout {
417 buffer_index: 0,
418 offset: 0,
419 stride,
420 },
421 PlaneLayout {
422 buffer_index: 0,
423 offset: uv_start,
424 stride,
425 },
426 ],
427 },
428 uv_start.max(uv_size),
429 )
430 }
431
432 pub fn alloc(layout: FrameLayout, buffer_size: usize) -> Self {
433 let buffer_count = layout
434 .planes
435 .iter()
436 .map(|plane| plane.buffer_index)
437 .collect::<std::collections::HashSet<usize>>()
438 .len();
439
440 let mem_layout =
442 unsafe { std::alloc::Layout::from_size_align_unchecked(buffer_size, 4096) };
443
444 let buffers = (0..buffer_count)
445 .map(|_| {
446 unsafe { std::alloc::alloc(mem_layout) }
448 })
449 .collect();
450
451 Self {
452 buffers,
453 mem_layout,
454 layout,
455 }
456 }
457}
458
459#[derive(Debug)]
460pub struct DmabufFrame {
461 pub fds: Vec<OwnedFd>,
462 pub layout: FrameLayout,
463}
464
465impl Drop for UserPtrFrame {
466 fn drop(&mut self) {
467 for buffer in std::mem::take(&mut self.buffers).into_iter() {
468 unsafe { std::alloc::dealloc(buffer, self.mem_layout) }
470 }
471 }
472}
473
474#[cfg(test)]
475mod tests {
476 use super::*;
477
478 #[test]
479 fn test_ivf_file_header() {
480 let mut hdr = IvfFileHeader {
481 version: 0,
482 codec: IvfFileHeader::CODEC_VP9,
483 width: 256,
484 height: 256,
485 framerate: 30_000,
486 timescale: 1_000,
487 frame_count: 1,
488
489 ..Default::default()
490 };
491
492 let mut buf = Vec::new();
493 hdr.writo_into(&mut buf).unwrap();
494
495 const EXPECTED: [u8; 32] = [
496 0x44, 0x4b, 0x49, 0x46, 0x00, 0x00, 0x20, 0x00, 0x56, 0x50, 0x39, 0x30, 0x00, 0x01,
497 0x00, 0x01, 0x30, 0x75, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
498 0x00, 0x00, 0x00, 0x00,
499 ];
500
501 assert_eq!(&buf, &EXPECTED);
502
503 hdr.width = 1920;
504 hdr.height = 800;
505 hdr.framerate = 24;
506 hdr.timescale = 1;
507 hdr.frame_count = 100;
508
509 buf.clear();
510 hdr.writo_into(&mut buf).unwrap();
511
512 const EXPECTED2: [u8; 32] = [
513 0x44, 0x4b, 0x49, 0x46, 0x00, 0x00, 0x20, 0x00, 0x56, 0x50, 0x39, 0x30, 0x80, 0x07,
514 0x20, 0x03, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
515 0x00, 0x00, 0x00, 0x00,
516 ];
517
518 assert_eq!(&buf, &EXPECTED2);
519 }
520
521 #[test]
522 fn test_ivf_frame_header() {
523 let mut hdr = IvfFrameHeader {
524 frame_size: 199249,
525 timestamp: 0,
526 };
527
528 let mut buf = Vec::new();
529 hdr.writo_into(&mut buf).unwrap();
530
531 const EXPECTED: [u8; 12] = [
532 0x51, 0x0a, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533 ];
534
535 assert_eq!(&buf, &EXPECTED);
536
537 hdr.timestamp = 1;
538 hdr.frame_size = 52;
539
540 buf.clear();
541 hdr.writo_into(&mut buf).unwrap();
542
543 const EXPECTED2: [u8; 12] = [
544 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 ];
546
547 assert_eq!(&buf, &EXPECTED2);
548 }
549
550 #[test]
551 fn test_bitwriter_f1() {
552 let mut buf = Vec::<u8>::new();
553 {
554 let mut writer = BitWriter::new(&mut buf);
555 writer.write_f(1, true).unwrap();
556 writer.write_f(1, false).unwrap();
557 writer.write_f(1, false).unwrap();
558 writer.write_f(1, false).unwrap();
559 writer.write_f(1, true).unwrap();
560 writer.write_f(1, true).unwrap();
561 writer.write_f(1, true).unwrap();
562 writer.write_f(1, true).unwrap();
563 }
564 assert_eq!(buf, vec![0b10001111u8]);
565 }
566
567 #[test]
568 fn test_bitwriter_f3() {
569 let mut buf = Vec::<u8>::new();
570 {
571 let mut writer = BitWriter::new(&mut buf);
572 writer.write_f(3, 0b100u8).unwrap();
573 writer.write_f(3, 0b101u8).unwrap();
574 writer.write_f(3, 0b011u8).unwrap();
575 }
576 assert_eq!(buf, vec![0b10010101u8, 0b10000000u8]);
577 }
578
579 #[test]
580 fn test_bitwriter_f4() {
581 let mut buf = Vec::<u8>::new();
582 {
583 let mut writer = BitWriter::new(&mut buf);
584 writer.write_f(4, 0b1000u8).unwrap();
585 writer.write_f(4, 0b1011u8).unwrap();
586 }
587 assert_eq!(buf, vec![0b10001011u8]);
588 }
589}