You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

99 lines
2.8 KiB
Rust

use crate::av::as_ptr::AsMutPtr;
use crate::av::frame::Frame;
use crate::av::packet::Packet;
use crate::av::scaler::Scaler;
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_parameters_from_context, avcodec_receive_packet, avcodec_send_frame, sws_freeContext,
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()
// ));
// }
println!("{:?} / {}", frame.nb_samples(), self.frame_size());
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<Option<Packet>, 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<Self> {
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 Scaler {
fn drop(&mut self) {
unsafe { sws_freeContext(self.as_mut_ptr()) }
}
}