libav-ng 0.1.6

New high level Rust bindings for libav
Documentation
use libav_sys_ng::{
    self, av_frame_alloc, av_frame_free, av_frame_get_buffer, av_get_bits_per_pixel,
    av_pix_fmt_desc_get, AVFrame,
};

pub struct Frame {
    _frame: *mut libav_sys_ng::AVFrame,
    is_frame_allocated: bool,
}

impl Frame {
    pub fn empty() -> Option<Self> {
        let _frame = unsafe { av_frame_alloc() };

        if _frame.is_null() {
            return None;
        }

        Some(Self {
            _frame,
            is_frame_allocated: false,
        })
    }

    pub fn from_size_and_pixfmt(width: i32, height: i32, pixfmt: i32) -> Option<Self> {
        unsafe {
            let mut _frame = av_frame_alloc();

            if _frame.is_null() {
                None
            } else {
                (*_frame).width = width;
                (*_frame).height = height;
                (*_frame).format = pixfmt;

                let mut this = Frame {
                    _frame,
                    is_frame_allocated: false,
                };

                this.allocate_buffer();

                Some(this)
            }
        }
    }

    pub fn data_plane(&self, plane_nr: usize) -> Result<&[u8], &str> {
        if plane_nr >= 8 {
            return Err("Out of bounds.");
        }
        
        let size = self.frame_size()?;
        
        unsafe {
            Ok(core::slice::from_raw_parts(
                (*self._frame).data[plane_nr],
                size,
            ))
        }
    }

    pub fn frame_size(&self) -> Result<usize, &str> {
        let data = unsafe { av_pix_fmt_desc_get((*self._frame).format) };
        let depth = if data.is_null() {
            Err("Failed to get pixel format info")
        } else {
            Ok(unsafe { av_get_bits_per_pixel(data) } as usize)
        };

        if depth.is_err() {
            return Err(depth.err().unwrap());
        }

        let size = (unsafe { *self._frame }).width as usize
            * (unsafe { *self._frame }).height as usize
            * depth.ok().unwrap()
            / 8;

        Ok(size)
    }

    pub fn data_plane_mut(&mut self, plane_nr: usize) -> Result<&mut [u8], &str> {
        if plane_nr >= 8 {
            return Err("Out of bounds.");
        }
        
        let size = self.frame_size()?;
        
        unsafe {
            Ok(core::slice::from_raw_parts_mut(
                (*self._frame).data[plane_nr],
                size,
            ))
        }
    }

    fn allocate_buffer(&mut self) {
        if self.is_frame_allocated {
            return;
        }

        unsafe {
            av_frame_get_buffer(self._frame, 0);
        }

        self.is_frame_allocated = true;
    }

    pub fn format(&self) -> i32 {
        unsafe { (*self._frame).format }
    }

    pub fn linesize(&self) -> [i32; 8] {
        unsafe { (*self._frame).linesize }
    }

    pub unsafe fn raw(&self) -> &AVFrame {
        &*self._frame.cast()
    }

    pub unsafe fn raw_mut(&mut self) -> &mut AVFrame {
        &mut *self._frame
    }
}

impl Drop for Frame {
    fn drop(&mut self) {
        unsafe {
            av_frame_free(&mut self._frame);
        }
    }
}