use crate::av::as_ptr::AsMutPtr; use crate::av::frame::Frame; use crate::av::packet::Packet; use crate::av::stream::Stream; use crate::av::xcoder::{process_return, XCoder}; use crate::av::{encoder_from_name, verify_response}; use crate::av_err2str; use ffmpeg_sys_next::{ avcodec_free_context, avcodec_parameters_from_context, avcodec_receive_packet, avcodec_send_frame, AVCodecContext, }; pub struct Encoder(pub *mut AVCodecContext); impl Encoder { pub fn send_video_frame(&self, frame: &Frame) -> Result<(), String> { if frame.width() != self.width() || frame.height() != self.height() || frame.pixel_format() != self.pixel_format() { return Err(format!( "Frame and encoder data differ (frame: {}x{} {:?}, encoder: {}x{} {:?})", frame.width(), frame.height(), frame.pixel_format(), self.width(), self.height(), self.pixel_format() )); } self.send_frame(frame) } pub fn send_audio_frame(&self, frame: &Frame) -> Result<(), String> { // if frame.sample_format() != self.sample_format() { // return Err(format!( // "Frame and encoder data differ (frame: {:?}, encoder: {:?})", // frame.sample_format(), // self.sample_format() // )); // } self.send_frame(frame) } pub fn send_frame(&self, frame: &Frame) -> Result<(), String> { verify_response("Failed sending frame to encoder", unsafe { avcodec_send_frame(self.0, frame.as_mut_ptr()) }) .and(Ok(())) } pub fn read_packet(&self) -> Result, String> { let packet = Packet::alloc(); let resp = unsafe { avcodec_receive_packet(self.as_mut_ptr(), packet.as_mut_ptr()) }; if !process_return("Failed to read packet from encoder", resp)? { Ok(None) } else { Ok(Some(packet)) } } } impl XCoder for Encoder { fn from_name(name: &str) -> Option { encoder_from_name(name).map(|codec| Encoder(codec)) } fn as_mut_ptr(&self) -> *mut AVCodecContext { self.0 } fn configure(&self, stream: &Stream) -> Result<(), String> { let resp = unsafe { avcodec_parameters_from_context((*stream.0).codecpar, self.as_mut_ptr()) }; if resp < 0 { return Err(format!( "Failed configuring decoder from stream (code {}: {})", resp, av_err2str(resp) )); } Ok(()) } } impl Drop for Encoder { fn drop(&mut self) { unsafe { avcodec_free_context(&mut self.as_mut_ptr()) } } }