use crate::{ Options, Image };
use std::ffi::CString;
use anyhow::Result;
use rsmpeg::avformat::AVFormatContextOutput;
use rsmpeg::ffi;
pub struct Context {
ctx: AVFormatContextOutput,
file: String,
}
impl Context {
pub fn create(file: &str) -> Result<Self> {
Ok(Self {
ctx: AVFormatContextOutput::create(
&*CString::new(file)?,
None,
)?,
file: file.to_string(),
})
}
pub fn video(
&mut self,
frames: impl Iterator<Item = impl Image>,
options: Options,
) -> Result<()> {
let codec = guess_codec(
&self.ctx,
&self.file,
ffi::AVMediaType_AVMEDIA_TYPE_VIDEO,
);
crate::video::encode(&mut self.ctx, frames, codec, options)
}
pub fn audio(
&mut self,
file: &str,
) -> Result<()> {
let codec = guess_codec(
&self.ctx,
&self.file,
ffi::AVMediaType_AVMEDIA_TYPE_AUDIO,
);
crate::audio::transcode(&mut self.ctx, file, codec)
}
}
fn guess_codec(
output_ctx: &AVFormatContextOutput,
file_name: &str,
media_type: ffi::AVMediaType,
) -> ffi::AVCodecID {
let mut file_name = file_name.to_string();
file_name.push('\0');
let file_name = file_name.as_ptr();
let oformat = output_ctx.oformat();
unsafe {
let mut oformat = (*oformat.as_ptr()).clone();
rsmpeg::ffi::av_guess_codec(
&mut oformat,
std::ptr::null(),
file_name as *const i8,
std::ptr::null(),
media_type,
)
}
}