mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-01-27 02:28:22 +00:00
media: ffmpeg: Add encoder context builder.
Similar to the decoder builder, add an encoder context builder. The encoder requires a few more parameters to be set before calling avcodec2_open, and the respective setters are provided here. As for checking for the required fields, it looks like FFmpeg will check it and error on avcodec2_open if any are missing anyway, so we'll avoid duplicating that on the binding side. BUG=b:239897269 TEST=cargo build --features ffmpeg -p ffmpeg Change-Id: I448b56ba9bae9b38ce5c2fb540e9577a2dfcd83c Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3856043 Reviewed-by: Alexandre Courbot <acourbot@chromium.org>
This commit is contained in:
parent
e539372226
commit
40ba620f0a
1 changed files with 58 additions and 4 deletions
|
@ -64,8 +64,15 @@ pub enum AvCodecOpenError {
|
|||
ContextAllocation,
|
||||
#[error("failed to open AVContext object")]
|
||||
ContextOpen,
|
||||
#[error("DecoderContextBuilder used with a non-decoder")]
|
||||
NotADecoder,
|
||||
#[error("ContextBuilder variant does not match codec type")]
|
||||
UnexpectedCodecType,
|
||||
}
|
||||
|
||||
/// Dimensions of a frame, used in AvCodecContext and AvFrame.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Dimensions {
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
}
|
||||
|
||||
impl AvCodec {
|
||||
|
@ -77,7 +84,7 @@ impl AvCodec {
|
|||
|
||||
/// Returns whether the codec is an encoder.
|
||||
pub fn is_encoder(&self) -> bool {
|
||||
// Safe because `av_codec_is_decoder` is called on a valid static `AVCodec` reference.
|
||||
// Safe because `av_codec_is_encoder` is called on a valid static `AVCodec` reference.
|
||||
(unsafe { ffi::av_codec_is_encoder(self.0) } != 0)
|
||||
}
|
||||
|
||||
|
@ -107,10 +114,22 @@ impl AvCodec {
|
|||
AvPixelFormatIterator(self.0.pix_fmts)
|
||||
}
|
||||
|
||||
/// Get a builder for a encoder [`AvCodecContext`] using this codec.
|
||||
pub fn build_encoder(&self) -> Result<EncoderContextBuilder, AvCodecOpenError> {
|
||||
if !self.is_encoder() {
|
||||
return Err(AvCodecOpenError::UnexpectedCodecType);
|
||||
}
|
||||
|
||||
Ok(EncoderContextBuilder {
|
||||
codec: self.0,
|
||||
context: self.alloc_context()?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Get a builder for a decoder [`AvCodecContext`] using this codec.
|
||||
pub fn build_decoder(&self) -> Result<DecoderContextBuilder, AvCodecOpenError> {
|
||||
if !self.is_decoder() {
|
||||
return Err(AvCodecOpenError::NotADecoder);
|
||||
return Err(AvCodecOpenError::UnexpectedCodecType);
|
||||
}
|
||||
|
||||
Ok(DecoderContextBuilder {
|
||||
|
@ -163,6 +182,41 @@ impl DecoderContextBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
/// A builder to create a [`AvCodecContext`] suitable for encoding.
|
||||
// This struct wraps an AvCodecContext directly, but the only way it can be taken out is to call
|
||||
// `build()`, which finalizes the context and prevent further modification to the callback, etc.
|
||||
pub struct EncoderContextBuilder {
|
||||
codec: *const ffi::AVCodec,
|
||||
context: AvCodecContext,
|
||||
}
|
||||
|
||||
impl EncoderContextBuilder {
|
||||
/// Set the width of input frames for this encoding context.
|
||||
pub fn set_dimensions(&mut self, dimensions: Dimensions) {
|
||||
let context = unsafe { &mut *(self.context.0) };
|
||||
context.width = dimensions.width as _;
|
||||
context.height = dimensions.height as _;
|
||||
}
|
||||
|
||||
/// Set the time base for this encoding context.
|
||||
pub fn set_time_base(&mut self, time_base: ffi::AVRational) {
|
||||
let context = unsafe { &mut *(self.context.0) };
|
||||
context.time_base = time_base;
|
||||
}
|
||||
|
||||
/// Set the input pixel format for this encoding context.
|
||||
pub fn set_pix_fmt(&mut self, fmt: AvPixelFormat) {
|
||||
let context = unsafe { &mut *(self.context.0) };
|
||||
context.pix_fmt = fmt.pix_fmt();
|
||||
}
|
||||
|
||||
/// Build a encoder AvCodecContext from the configured options.
|
||||
pub fn build(mut self) -> Result<AvCodecContext, AvCodecOpenError> {
|
||||
self.context.init(self.codec)?;
|
||||
Ok(self.context)
|
||||
}
|
||||
}
|
||||
|
||||
/// Lightweight abstraction over libavcodec's `av_codec_iterate` function that can be used to
|
||||
/// enumerate all the supported codecs.
|
||||
pub struct AvCodecIterator(*mut libc::c_void);
|
||||
|
|
Loading…
Reference in a new issue