use crate::av::as_ptr::{AsMutPtr, AsPtr}; use crate::av::verify_response; use ffmpeg_sys_next::{ av_frame_alloc, av_frame_free, av_frame_get_buffer, AVFrame, AVPictureType, AVPixelFormat, AVSampleFormat, }; #[derive(Debug)] pub struct Frame { ptr: *mut AVFrame, owned: bool, } impl Frame { pub fn alloc() -> Frame { let frame = unsafe { av_frame_alloc() }; if frame.is_null() { panic!("Can't alloc frame"); } Frame { ptr: frame, owned: true, } } #[inline] pub fn own(&mut self) { self.owned = true } #[inline] pub fn disown(&mut self) { self.owned = false } #[inline] pub fn width(&self) -> i32 { unsafe { (*self.ptr).width } } #[inline] pub fn height(&self) -> i32 { unsafe { (*self.ptr).height } } #[inline] pub fn pict_type(&self) -> AVPictureType { unsafe { (*self.ptr).pict_type } } #[inline] pub fn set_pict_type(&self, pict_type: AVPictureType) { unsafe { (*self.ptr).pict_type = pict_type } } #[inline] pub fn set_width(&self, width: i32) { unsafe { (*self.ptr).width = width } } #[inline] pub fn set_height(&self, height: i32) { unsafe { (*self.ptr).height = height } } #[inline] pub fn set_pixel_format(&self, pixel_format: AVPixelFormat) { unsafe { (*self.ptr).format = std::mem::transmute(pixel_format) } } #[inline] pub fn pixel_format(&self) -> AVPixelFormat { unsafe { std::mem::transmute::<_, AVPixelFormat>((*self.ptr).format) } } #[inline] pub fn set_sample_format(&self, sample_format: AVSampleFormat) { unsafe { (*self.ptr).format = std::mem::transmute(sample_format) } } #[inline] pub fn sample_format(&self) -> AVSampleFormat { unsafe { std::mem::transmute::<_, AVSampleFormat>((*self.ptr).format) } } #[inline] pub fn sample_rate(&self) -> i32 { unsafe { (*self.ptr).sample_rate } } #[inline] pub fn set_sample_rate(&self, sample_rate: i32) { unsafe { (*self.ptr).sample_rate = sample_rate } } #[inline] pub fn channel_layout(&self) -> u64 { unsafe { (*self.ptr).channel_layout } } #[inline] pub fn set_channel_layout(&self, channel_layout: u64) { unsafe { (*self.ptr).channel_layout = channel_layout } } #[inline] pub fn set_nb_samples(&self, nb_samples: i32) { unsafe { (*self.ptr).nb_samples = nb_samples } } #[inline] pub fn nb_samples(&self) -> i32 { unsafe { (*self.ptr).nb_samples } } pub fn allocate_video( &mut self, pixel_format: AVPixelFormat, width: i32, height: i32, ) -> Result<(), String> { self.set_pixel_format(pixel_format); self.set_width(width); self.set_height(height); self.allocate() } pub fn allocate_audio( &self, sample_format: AVSampleFormat, channel_layout: u64, nb_samples: i32, ) -> Result<(), String> { self.set_sample_format(sample_format); self.set_channel_layout(channel_layout); self.set_nb_samples(nb_samples); self.allocate() } fn allocate(&self) -> Result<(), String> { verify_response("Failed to allocate frame", unsafe { av_frame_get_buffer(self.ptr, 32) })?; Ok(()) } #[inline] pub fn pts(&self) -> i64 { unsafe { (*self.ptr).pts } } #[inline] pub fn set_pts(&self, pts: i64) { unsafe { (*self.ptr).pts = pts } } } impl AsPtr for Frame { #[inline] fn as_ptr(&self) -> *const AVFrame { self.ptr } } impl AsMutPtr for Frame { #[inline] fn as_mut_ptr(&self) -> *mut AVFrame { self.ptr } } impl Drop for Frame { fn drop(&mut self) { if !self.owned { return; } unsafe { av_frame_free(&mut self.ptr) } } }