blaze-rs 1.0.3

A Rustified OpenCL Experience
Documentation
use std::{path::Path, ptr::{addr_of_mut, NonNull}};
use ffmpeg_sys_next::*;
use ffmpeg_sys_next::AVMediaType::AVMEDIA_TYPE_VIDEO;
use crate::image::channel::Rgb;

use super::{error::{Result, Error, ErrorKind}, path_str, alloc::{new_frame, frame_to_rect}};

pub struct FfmpegInputFile {
    format_ctx: NonNull<AVFormatContext>,
    codec_ctx: NonNull<AVCodecContext>
}

impl FfmpegInputFile {
    pub fn input (path: impl AsRef<Path>) -> Result<Self> {
        let path = path_str(path).map_err(|e| Error::new(super::error::ErrorKind::InvalidData, e))?;
        let mut format_ctx = core::ptr::null_mut();

        unsafe {
            ffmpeg_tri! {
                avformat_open_input(addr_of_mut!(format_ctx), path.as_ptr(), core::ptr::null_mut(), core::ptr::null_mut());
                avformat_find_stream_info(format_ctx, core::ptr::null_mut())
            }

            av_dump_format(format_ctx, 0, path.as_ptr(), 0);
        }
        
        let mut format_ctx = NonNull::new(format_ctx).unwrap();
        let mut stream_idx = None;

        for i in unsafe { 0..format_ctx.as_mut().nb_streams } {
            unsafe {
                let stream = &**format_ctx.as_mut().streams.add(i as usize);
                if stream.codec.is_null() {
                    continue;
                }

                let codec = &*stream.codec;
                if codec.codec_type == AVMEDIA_TYPE_VIDEO {
                    stream_idx = Some(i);
                    break
                }
            }
        }

        if stream_idx.is_none() {
            return Err(Error::from_kind(ErrorKind::StreamNotFound));
        }

        let stream_idx = unsafe { stream_idx.unwrap_unchecked() };
        let codec_ctx = unsafe { &**format_ctx.as_mut().streams.add(stream_idx as usize) };
        let codec_ctx = NonNull::new(codec_ctx.codec).unwrap();

        Ok(Self { format_ctx, codec_ctx })
    }

    pub fn decoder (&self) -> Result<NonNull<AVCodec>> {
        unsafe {
            let codec = NonNull::new(avcodec_find_decoder(self.codec_ctx.as_ref().codec_id)).ok_or_else(|| Error::new(ErrorKind::Unknown, "Unknown codec"))?;
            ffmpeg_tri!(avcodec_open2(self.codec_ctx.as_ptr(), codec.as_ptr(), core::ptr::null_mut()));
            Ok(codec)
        }
    }
}

impl Drop for FfmpegInputFile {
    #[inline(always)]
    fn drop(&mut self) {
        unsafe {
            ffmpeg_tri_panic! {
                avcodec_close(self.codec_ctx.as_ptr())
            }

            avformat_close_input(addr_of_mut!(self.format_ctx).cast())
        }
    }
}

#[test]
fn test () {
    let file = FfmpegInputFile::input("tests/test2.jpg").unwrap();
    let dec = file.decoder().unwrap();

    let mut frame = new_frame();
    frame.width = 120;
    frame.height = 120;
    
    let rect = frame_to_rect::<Rgb<u8>>(&frame).unwrap();    
    todo!()
}