use crate::av::as_ptr::{AsMutPtr, AsPtr}; use ffmpeg_sys_next::{av_malloc, avio_alloc_context, avio_flush, AVIOContext}; use std::cmp::min; use std::os::raw::c_void; use std::vec::Vec; #[derive(Clone)] pub struct AVIO { ctx: *mut AVIOContext, inner: Box>, } impl AVIO { pub fn flush(&self) { unsafe { avio_flush(self.as_mut_ptr()); } } } #[derive(Clone)] struct AVIOInner { data: Box, read: Option Vec>, write: Option)>, seek: Option, } unsafe extern "C" fn read_packet_with_inner( ctx: *mut c_void, buffer: *mut u8, buffer_size: i32, ) -> i32 { let mut avio: Box>> = Box::from_raw(ctx.cast()); let items = avio.data.read(buffer_size); let len = min(items.len(), buffer_size as usize); buffer.copy_from(items.as_ptr().cast(), len); len as i32 } unsafe extern "C" fn write_packet_with_inner(ctx: *mut c_void, buffer: *mut u8, size: i32) -> i32 { let mut avio: Box>> = Box::from_raw(ctx.cast()); let mut byte_buffer = vec![0; size as usize]; buffer.copy_to(byte_buffer.as_mut_ptr(), size as usize); let write_fn = avio.write.unwrap(); write_fn(&mut avio.data, byte_buffer); std::mem::forget(avio); size } unsafe extern "C" fn seek_with_inner(ctx: *mut c_void, offset: i64, whence: i32) -> i64 { println!("ok"); let mut avio: Box>> = Box::from_raw(ctx.cast()); avio.data.seek(offset, whence); 0 } impl AVIO { fn new( buffer_size: usize, obj: T, read: Option Vec>, write: Option)>, seek: Option, ) -> AVIO { let mut opaque = Box::new(AVIOInner { data: Box::new(obj), read, write, seek, }); let ctx = unsafe { let buf: *mut u8 = av_malloc(buffer_size).cast(); let opaque_c: *mut AVIOInner = &mut *opaque; avio_alloc_context( buf, buffer_size as i32, if write.is_some() { 1 } else { 0 }, opaque_c.cast(), if read.is_some() { Some(read_packet_with_inner) } else { None }, if write.is_some() { Some(write_packet_with_inner) } else { None }, if seek.is_some() { Some(seek_with_inner) } else { None }, ) }; AVIO { ctx, inner: opaque } } pub fn inner(&self) -> &T { self.inner.data.as_ref() } pub fn inner_mut(&mut self) -> &mut T { self.inner.data.as_mut() } } impl AsMutPtr for AVIO { fn as_mut_ptr(&self) -> *mut AVIOContext { self.ctx } } impl AsPtr for AVIO { fn as_ptr(&self) -> *const AVIOContext { self.ctx } } impl AVIO { pub fn duplex_with_seek(item: T) -> AVIO { AVIO::new(4096, item, Some(T::read), Some(T::write), Some(T::seek)) } } impl AVIO { pub fn duplex(item: T) -> AVIO { AVIO::new(4096, item, Some(T::read), Some(T::write), None) } } impl AVIO { pub fn reader_with_seek(item: T) -> AVIO { AVIO::new(4096, item, Some(T::read), None, Some(T::seek)) } } impl AVIO { pub fn reader(item: T) -> AVIO { AVIO::new(4096, item, Some(T::read), None, None) } } impl AVIO { pub fn writer_with_seek(item: T) -> AVIO { AVIO::new(4096, item, None, Some(T::write), Some(T::seek)) } } impl AVIO { pub fn writer(item: T) -> AVIO { AVIO::new(4096, item, None, Some(T::write), None) } } pub trait AVIOSeekable { fn seek(&mut self, offset: i64, whence: i32); } pub trait AVIOWriter { fn write(&mut self, buffer: Vec); } pub trait AVIOReader { fn read(&mut self, length: i32) -> Vec; }