use std::io::Cursor;
use std::io::Seek;
use std::marker::PhantomData;
use std::os::fd::OwnedFd;
use bytes::Buf;
use crate::codec::h264::parser::Nalu as H264Nalu;
use crate::codec::h265::parser::Nalu as H265Nalu;
use crate::decoder::stateless::DecodeError;
use crate::decoder::stateless::StatelessVideoDecoder;
use crate::decoder::BlockingMode;
use crate::decoder::DecodedHandle;
use crate::decoder::DecoderEvent;
use crate::decoder::StreamInfo;
use crate::DecodedFormat;
use crate::Fourcc;
use crate::PlaneLayout;
use crate::Resolution;
use crate::SurfaceLayout;
pub struct IvfIterator<'a> {
cursor: Cursor<&'a [u8]>,
}
impl<'a> IvfIterator<'a> {
pub fn new(data: &'a [u8]) -> Self {
let mut cursor = Cursor::new(data);
cursor.seek(std::io::SeekFrom::Start(32)).unwrap();
Self { cursor }
}
}
impl<'a> Iterator for IvfIterator<'a> {
type Item = &'a [u8];
fn next(&mut self) -> Option<Self::Item> {
if self.cursor.remaining() < 6 {
return None;
}
let len = self.cursor.get_u32_le() as usize;
let _ = self.cursor.get_u64_le();
if self.cursor.remaining() < len {
return None;
}
let start = self.cursor.position() as usize;
let _ = self.cursor.seek(std::io::SeekFrom::Current(len as i64));
let end = self.cursor.position() as usize;
Some(&self.cursor.get_ref()[start..end])
}
}
pub struct NalIterator<'a, Nalu>(Cursor<&'a [u8]>, PhantomData<Nalu>);
impl<'a, Nalu> NalIterator<'a, Nalu> {
pub fn new(stream: &'a [u8]) -> Self {
Self(Cursor::new(stream), PhantomData)
}
}
impl<'a> Iterator for NalIterator<'a, H264Nalu<&[u8]>> {
type Item = &'a [u8];
fn next(&mut self) -> Option<Self::Item> {
H264Nalu::next(&mut self.0)
.map(|n| {
let start = n.sc_offset();
let end = n.offset() + n.size();
&n.data()[start..end]
})
.ok()
}
}
impl<'a> Iterator for NalIterator<'a, H265Nalu<&[u8]>> {
type Item = &'a [u8];
fn next(&mut self) -> Option<Self::Item> {
H265Nalu::next(&mut self.0)
.map(|n| {
let start = n.sc_offset();
let end = n.offset() + n.size();
&n.data()[start..end]
})
.ok()
}
}
pub fn simple_playback_loop<D, R, I, M>(
decoder: &mut D,
stream_iter: I,
on_new_frame: &mut dyn FnMut(Box<dyn DecodedHandle<Descriptor = M>>),
allocate_new_surfaces: &mut dyn FnMut(&StreamInfo, usize) -> anyhow::Result<Vec<M>>,
output_format: DecodedFormat,
blocking_mode: BlockingMode,
) -> anyhow::Result<()>
where
D: StatelessVideoDecoder<M> + ?Sized,
R: AsRef<[u8]>,
I: Iterator<Item = R>,
{
let mut check_events = |decoder: &mut D| -> anyhow::Result<()> {
while let Some(event) = decoder.next_event() {
match event {
DecoderEvent::FrameReady(frame) => {
on_new_frame(frame);
}
DecoderEvent::FormatChanged(mut format_setter) => {
format_setter.try_format(output_format).unwrap();
let min_num_surfaces = format_setter.stream_info().min_num_surfaces;
let pool_num_surfaces = format_setter.surface_pool().num_managed_surfaces();
if pool_num_surfaces < min_num_surfaces {
let surfaces = allocate_new_surfaces(
format_setter.stream_info(),
min_num_surfaces - pool_num_surfaces,
)?;
let pool = format_setter.surface_pool();
pool.add_surfaces(surfaces).unwrap();
}
}
}
}
Ok(())
};
for (frame_num, packet) in stream_iter.enumerate() {
let mut bitstream = packet.as_ref();
loop {
match decoder.decode(frame_num as u64, bitstream) {
Ok(bytes_decoded) => {
bitstream = &bitstream[bytes_decoded..];
if blocking_mode == BlockingMode::Blocking {
check_events(decoder)?;
}
if bitstream.is_empty() {
break;
}
}
Err(DecodeError::CheckEvents) | Err(DecodeError::NotEnoughOutputBuffers(_)) => {
check_events(decoder)?
}
Err(e) => anyhow::bail!(e),
}
}
}
decoder.flush()?;
check_events(decoder)
}
pub fn simple_playback_loop_owned_surfaces(
_: &StreamInfo,
nb_surfaces: usize,
) -> anyhow::Result<Vec<()>> {
Ok(vec![(); nb_surfaces])
}
pub fn simple_playback_loop_userptr_surfaces(
stream_info: &StreamInfo,
nb_surfaces: usize,
) -> anyhow::Result<Vec<UserPtrSurface>> {
let alloc_function = match stream_info.format {
DecodedFormat::I420 | DecodedFormat::NV12 => &UserPtrSurface::new_nv12,
_ => anyhow::bail!(
"{:?} format is unsupported with user memory",
stream_info.format
),
};
Ok((0..nb_surfaces)
.map(|_| alloc_function(stream_info.coded_resolution))
.collect::<Vec<_>>())
}
#[derive(Debug)]
pub struct UserPtrSurface {
pub buffers: Vec<*mut u8>,
pub mem_layout: std::alloc::Layout,
pub layout: SurfaceLayout,
}
impl UserPtrSurface {
pub fn new_nv12(size: Resolution) -> Self {
macro_rules! align {
($n:expr, $r:expr) => {
($n + ($r - 1)) & !($r - 1)
};
}
let width = align!(size.width, 16) as usize;
let height = align!(size.height, 4) as usize;
let stride = align!(width, 64);
let uv_start = height * stride;
let uv_size = (height / 2) * stride;
let buffer_size = align!(uv_start + uv_size, 4096);
let layout = unsafe { std::alloc::Layout::from_size_align_unchecked(buffer_size, 4096) };
let mem = unsafe { std::alloc::alloc(layout) };
Self {
buffers: vec![mem],
mem_layout: layout,
layout: SurfaceLayout {
format: (Fourcc::from(b"NV12"), 0),
size: Resolution::from((width as u32, height as u32)),
planes: vec![
PlaneLayout {
buffer_index: 0,
offset: 0,
stride,
},
PlaneLayout {
buffer_index: 0,
offset: uv_start,
stride,
},
],
},
}
}
}
pub struct DmabufSurface {
pub fds: Vec<OwnedFd>,
pub layout: SurfaceLayout,
}
impl Drop for UserPtrSurface {
fn drop(&mut self) {
for buffer in std::mem::take(&mut self.buffers).into_iter() {
unsafe { std::alloc::dealloc(buffer, self.mem_layout) }
}
}
}