rusvid_video_encoder 0.2.1

h264 mp4 encoder for rusvid
Documentation
use ffmpeg_sys_next::{
    av_frame_alloc, av_frame_free, av_image_fill_arrays, av_image_get_buffer_size, AVFrame,
    AVPixelFormat,
};

use super::WrapperType;
use crate::error::VideoEncoderError;
use crate::status::FfmpegSysStatus;

pub struct Frame(*mut AVFrame);

impl Frame {
    pub fn new(pix_fmt: AVPixelFormat) -> Result<Self, VideoEncoderError> {
        unsafe {
            let frame = av_frame_alloc();
            if frame.is_null() {
                return Err(VideoEncoderError::FfmpegSysError {
                    message: "Could not allocate the video frame.",
                    error_code: FfmpegSysStatus::Unknown,
                });
            }

            (*frame).format = pix_fmt as i32;

            Ok(Frame(frame))
        }
    }

    pub fn set_resolution(&mut self, resolution: (u32, u32)) {
        unsafe {
            (*self.0).width = resolution.0 as i32;
            (*self.0).height = resolution.1 as i32;
        }
    }

    pub fn set_pts(&mut self, value: i64) {
        unsafe { (*self.0).pts = value }
    }

    pub fn get_pts(&self) -> i64 {
        unsafe { (*self.0).pts }
    }

    pub fn add_pts(&mut self, value: i64) {
        self.set_pts(self.get_pts() + value);
    }

    pub fn get_raw_buffer(
        &self,
        pix_fmt: AVPixelFormat,
        target: (u32, u32),
    ) -> Result<Vec<u8>, VideoEncoderError> {
        let nframe_bytes =
            unsafe { av_image_get_buffer_size(pix_fmt, target.0 as i32, target.1 as i32, 16) };

        let status = FfmpegSysStatus::from_ffmpeg_sys_error(nframe_bytes);
        if status.is_error() {
            return Err(VideoEncoderError::FfmpegSysError {
                message: "Error in `av_image_get_buffer_size`",
                error_code: status,
            });
        }

        Ok(vec![0; nframe_bytes as usize])
    }

    pub fn fill_array(
        &mut self,
        frame_buf: &Vec<u8>,
        pix_fmt: AVPixelFormat,
        resolution: (u32, u32),
    ) -> Result<(), VideoEncoderError> {
        let err = unsafe {
            av_image_fill_arrays(
                (*self.0).data.as_mut_ptr(),
                (*self.0).linesize.as_mut_ptr(),
                frame_buf.as_ptr(),
                pix_fmt,
                resolution.0 as i32,
                resolution.1 as i32,
                1,
            )
        };

        let status = FfmpegSysStatus::from_ffmpeg_sys_error(err);
        if status.is_error() {
            let err = VideoEncoderError::FfmpegSysError {
                message: "error in `av_image_fill_arrays`",
                error_code: status,
            };
            println!("{err:?}");
        }

        Ok(())
    }
}

impl WrapperType for Frame {
    type OUT = AVFrame;

    fn get_inner(&self) -> *const Self::OUT {
        self.0
    }

    fn get_inner_mut(&mut self) -> *mut Self::OUT {
        self.0
    }
}

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