1*1b4853f5SAndroid Build Coastguard Worker // Copyright 2022-2024 The ChromiumOS Authors 2*1b4853f5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*1b4853f5SAndroid Build Coastguard Worker // found in the LICENSE file. 4*1b4853f5SAndroid Build Coastguard Worker 5*1b4853f5SAndroid Build Coastguard Worker //! This module implements a lightweight and safe decoder interface over `libavcodec`. It is 6*1b4853f5SAndroid Build Coastguard Worker //! designed to concentrate all calls to unsafe methods in one place, while providing the same 7*1b4853f5SAndroid Build Coastguard Worker //! low-level access as the libavcodec functions do. 8*1b4853f5SAndroid Build Coastguard Worker 9*1b4853f5SAndroid Build Coastguard Worker use std::ffi::CStr; 10*1b4853f5SAndroid Build Coastguard Worker use std::fmt::Debug; 11*1b4853f5SAndroid Build Coastguard Worker use std::fmt::Display; 12*1b4853f5SAndroid Build Coastguard Worker use std::marker::PhantomData; 13*1b4853f5SAndroid Build Coastguard Worker use std::mem::ManuallyDrop; 14*1b4853f5SAndroid Build Coastguard Worker use std::ops::Deref; 15*1b4853f5SAndroid Build Coastguard Worker 16*1b4853f5SAndroid Build Coastguard Worker use libc::c_char; 17*1b4853f5SAndroid Build Coastguard Worker use libc::c_int; 18*1b4853f5SAndroid Build Coastguard Worker use libc::c_void; 19*1b4853f5SAndroid Build Coastguard Worker use thiserror::Error as ThisError; 20*1b4853f5SAndroid Build Coastguard Worker 21*1b4853f5SAndroid Build Coastguard Worker use super::*; 22*1b4853f5SAndroid Build Coastguard Worker use crate::ffmpeg::ffi::AVPictureType; 23*1b4853f5SAndroid Build Coastguard Worker 24*1b4853f5SAndroid Build Coastguard Worker /// An error returned by a low-level libavcodec function. 25*1b4853f5SAndroid Build Coastguard Worker #[derive(Debug, ThisError)] 26*1b4853f5SAndroid Build Coastguard Worker pub struct AvError(pub libc::c_int); 27*1b4853f5SAndroid Build Coastguard Worker 28*1b4853f5SAndroid Build Coastguard Worker impl AvError { result(ret: c_int) -> Result<(), Self>29*1b4853f5SAndroid Build Coastguard Worker pub fn result(ret: c_int) -> Result<(), Self> { 30*1b4853f5SAndroid Build Coastguard Worker if ret >= 0 { 31*1b4853f5SAndroid Build Coastguard Worker Ok(()) 32*1b4853f5SAndroid Build Coastguard Worker } else { 33*1b4853f5SAndroid Build Coastguard Worker Err(AvError(ret)) 34*1b4853f5SAndroid Build Coastguard Worker } 35*1b4853f5SAndroid Build Coastguard Worker } 36*1b4853f5SAndroid Build Coastguard Worker } 37*1b4853f5SAndroid Build Coastguard Worker 38*1b4853f5SAndroid Build Coastguard Worker impl Display for AvError { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result39*1b4853f5SAndroid Build Coastguard Worker fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 40*1b4853f5SAndroid Build Coastguard Worker let mut buffer = [0u8; 255]; 41*1b4853f5SAndroid Build Coastguard Worker let ret = 42*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 43*1b4853f5SAndroid Build Coastguard Worker // Safe because we are passing valid bounds for the buffer. 44*1b4853f5SAndroid Build Coastguard Worker unsafe { ffi::av_strerror(self.0, buffer.as_mut_ptr() as *mut c_char, buffer.len()) }; 45*1b4853f5SAndroid Build Coastguard Worker match ret { 46*1b4853f5SAndroid Build Coastguard Worker ret if ret >= 0 => { 47*1b4853f5SAndroid Build Coastguard Worker let end_of_string = buffer.iter().position(|i| *i == 0).unwrap_or(buffer.len()); 48*1b4853f5SAndroid Build Coastguard Worker let error_string = std::string::String::from_utf8_lossy(&buffer[..end_of_string]); 49*1b4853f5SAndroid Build Coastguard Worker f.write_str(&error_string) 50*1b4853f5SAndroid Build Coastguard Worker } 51*1b4853f5SAndroid Build Coastguard Worker _ => f.write_fmt(format_args!("Unknown avcodec error {}", self.0)), 52*1b4853f5SAndroid Build Coastguard Worker } 53*1b4853f5SAndroid Build Coastguard Worker } 54*1b4853f5SAndroid Build Coastguard Worker } 55*1b4853f5SAndroid Build Coastguard Worker 56*1b4853f5SAndroid Build Coastguard Worker /// Lightweight abstraction over libavcodec's `AVCodec` struct, allowing the query the capabilities 57*1b4853f5SAndroid Build Coastguard Worker /// of supported codecs and opening a session to work with them. 58*1b4853f5SAndroid Build Coastguard Worker /// 59*1b4853f5SAndroid Build Coastguard Worker /// `AVCodec` instances in libavcodec are all static, hence we can safely use a static reference 60*1b4853f5SAndroid Build Coastguard Worker /// lifetime here. 61*1b4853f5SAndroid Build Coastguard Worker #[derive(Copy, Clone)] 62*1b4853f5SAndroid Build Coastguard Worker pub struct AvCodec(&'static ffi::AVCodec); 63*1b4853f5SAndroid Build Coastguard Worker 64*1b4853f5SAndroid Build Coastguard Worker /// SAFETY: `AVCodec` is static and thus safe to share. 65*1b4853f5SAndroid Build Coastguard Worker unsafe impl Send for AvCodec {} 66*1b4853f5SAndroid Build Coastguard Worker 67*1b4853f5SAndroid Build Coastguard Worker #[derive(Debug, ThisError)] 68*1b4853f5SAndroid Build Coastguard Worker pub enum AvCodecOpenError { 69*1b4853f5SAndroid Build Coastguard Worker #[error("failed to allocate AVContext object")] 70*1b4853f5SAndroid Build Coastguard Worker ContextAllocation, 71*1b4853f5SAndroid Build Coastguard Worker #[error("failed to open AVContext object")] 72*1b4853f5SAndroid Build Coastguard Worker ContextOpen, 73*1b4853f5SAndroid Build Coastguard Worker #[error("ContextBuilder variant does not match codec type")] 74*1b4853f5SAndroid Build Coastguard Worker UnexpectedCodecType, 75*1b4853f5SAndroid Build Coastguard Worker } 76*1b4853f5SAndroid Build Coastguard Worker 77*1b4853f5SAndroid Build Coastguard Worker /// Dimensions of a frame, used in AvCodecContext and AvFrame. 78*1b4853f5SAndroid Build Coastguard Worker #[derive(Copy, Clone, Debug, PartialEq, Eq)] 79*1b4853f5SAndroid Build Coastguard Worker pub struct Dimensions { 80*1b4853f5SAndroid Build Coastguard Worker pub width: u32, 81*1b4853f5SAndroid Build Coastguard Worker pub height: u32, 82*1b4853f5SAndroid Build Coastguard Worker } 83*1b4853f5SAndroid Build Coastguard Worker 84*1b4853f5SAndroid Build Coastguard Worker impl AvCodec { 85*1b4853f5SAndroid Build Coastguard Worker /// Returns whether the codec is a decoder. is_decoder(&self) -> bool86*1b4853f5SAndroid Build Coastguard Worker pub fn is_decoder(&self) -> bool { 87*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 88*1b4853f5SAndroid Build Coastguard Worker // Safe because `av_codec_is_decoder` is called on a valid static `AVCodec` reference. 89*1b4853f5SAndroid Build Coastguard Worker (unsafe { ffi::av_codec_is_decoder(self.0) } != 0) 90*1b4853f5SAndroid Build Coastguard Worker } 91*1b4853f5SAndroid Build Coastguard Worker 92*1b4853f5SAndroid Build Coastguard Worker /// Returns whether the codec is an encoder. is_encoder(&self) -> bool93*1b4853f5SAndroid Build Coastguard Worker pub fn is_encoder(&self) -> bool { 94*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 95*1b4853f5SAndroid Build Coastguard Worker // Safe because `av_codec_is_encoder` is called on a valid static `AVCodec` reference. 96*1b4853f5SAndroid Build Coastguard Worker (unsafe { ffi::av_codec_is_encoder(self.0) } != 0) 97*1b4853f5SAndroid Build Coastguard Worker } 98*1b4853f5SAndroid Build Coastguard Worker 99*1b4853f5SAndroid Build Coastguard Worker /// Returns the name of the codec. name(&self) -> &'static str100*1b4853f5SAndroid Build Coastguard Worker pub fn name(&self) -> &'static str { 101*1b4853f5SAndroid Build Coastguard Worker const INVALID_CODEC_STR: &str = "invalid codec"; 102*1b4853f5SAndroid Build Coastguard Worker 103*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 104*1b4853f5SAndroid Build Coastguard Worker // Safe because `CStr::from_ptr` is called on a valid zero-terminated C string. 105*1b4853f5SAndroid Build Coastguard Worker unsafe { CStr::from_ptr(self.0.name).to_str() }.unwrap_or(INVALID_CODEC_STR) 106*1b4853f5SAndroid Build Coastguard Worker } 107*1b4853f5SAndroid Build Coastguard Worker 108*1b4853f5SAndroid Build Coastguard Worker /// Returns the capabilities of the codec, as a mask of AV_CODEC_CAP_* bits. capabilities(&self) -> u32109*1b4853f5SAndroid Build Coastguard Worker pub fn capabilities(&self) -> u32 { 110*1b4853f5SAndroid Build Coastguard Worker self.0.capabilities as u32 111*1b4853f5SAndroid Build Coastguard Worker } 112*1b4853f5SAndroid Build Coastguard Worker 113*1b4853f5SAndroid Build Coastguard Worker /// Returns an iterator over the profiles supported by this codec. profile_iter(&self) -> AvProfileIterator114*1b4853f5SAndroid Build Coastguard Worker pub fn profile_iter(&self) -> AvProfileIterator { 115*1b4853f5SAndroid Build Coastguard Worker AvProfileIterator(self.0.profiles) 116*1b4853f5SAndroid Build Coastguard Worker } 117*1b4853f5SAndroid Build Coastguard Worker 118*1b4853f5SAndroid Build Coastguard Worker /// Returns an iterator over the pixel formats supported by this codec. 119*1b4853f5SAndroid Build Coastguard Worker /// 120*1b4853f5SAndroid Build Coastguard Worker /// For a decoder, the returned array will likely be empty. This means that ffmpeg's native 121*1b4853f5SAndroid Build Coastguard Worker /// pixel format (YUV420) will be used. pixel_format_iter(&self) -> AvPixelFormatIterator122*1b4853f5SAndroid Build Coastguard Worker pub fn pixel_format_iter(&self) -> AvPixelFormatIterator { 123*1b4853f5SAndroid Build Coastguard Worker AvPixelFormatIterator(self.0.pix_fmts) 124*1b4853f5SAndroid Build Coastguard Worker } 125*1b4853f5SAndroid Build Coastguard Worker 126*1b4853f5SAndroid Build Coastguard Worker /// Get a builder for a encoder [`AvCodecContext`] using this codec. build_encoder(&self) -> Result<EncoderContextBuilder, AvCodecOpenError>127*1b4853f5SAndroid Build Coastguard Worker pub fn build_encoder(&self) -> Result<EncoderContextBuilder, AvCodecOpenError> { 128*1b4853f5SAndroid Build Coastguard Worker if !self.is_encoder() { 129*1b4853f5SAndroid Build Coastguard Worker return Err(AvCodecOpenError::UnexpectedCodecType); 130*1b4853f5SAndroid Build Coastguard Worker } 131*1b4853f5SAndroid Build Coastguard Worker 132*1b4853f5SAndroid Build Coastguard Worker Ok(EncoderContextBuilder { 133*1b4853f5SAndroid Build Coastguard Worker codec: self.0, 134*1b4853f5SAndroid Build Coastguard Worker context: self.alloc_context()?, 135*1b4853f5SAndroid Build Coastguard Worker }) 136*1b4853f5SAndroid Build Coastguard Worker } 137*1b4853f5SAndroid Build Coastguard Worker 138*1b4853f5SAndroid Build Coastguard Worker /// Get a builder for a decoder [`AvCodecContext`] using this codec. build_decoder(&self) -> Result<DecoderContextBuilder, AvCodecOpenError>139*1b4853f5SAndroid Build Coastguard Worker pub fn build_decoder(&self) -> Result<DecoderContextBuilder, AvCodecOpenError> { 140*1b4853f5SAndroid Build Coastguard Worker if !self.is_decoder() { 141*1b4853f5SAndroid Build Coastguard Worker return Err(AvCodecOpenError::UnexpectedCodecType); 142*1b4853f5SAndroid Build Coastguard Worker } 143*1b4853f5SAndroid Build Coastguard Worker 144*1b4853f5SAndroid Build Coastguard Worker Ok(DecoderContextBuilder { 145*1b4853f5SAndroid Build Coastguard Worker codec: self.0, 146*1b4853f5SAndroid Build Coastguard Worker context: self.alloc_context()?, 147*1b4853f5SAndroid Build Coastguard Worker }) 148*1b4853f5SAndroid Build Coastguard Worker } 149*1b4853f5SAndroid Build Coastguard Worker 150*1b4853f5SAndroid Build Coastguard Worker /// Internal helper for `build_decoder` to allocate an [`AvCodecContext`]. This needs to be 151*1b4853f5SAndroid Build Coastguard Worker /// paired with a later call to [`AvCodecContext::init`]. alloc_context(&self) -> Result<AvCodecContext, AvCodecOpenError>152*1b4853f5SAndroid Build Coastguard Worker fn alloc_context(&self) -> Result<AvCodecContext, AvCodecOpenError> { 153*1b4853f5SAndroid Build Coastguard Worker // TODO(b:315859322): add safety doc string 154*1b4853f5SAndroid Build Coastguard Worker #[allow(clippy::undocumented_unsafe_blocks)] 155*1b4853f5SAndroid Build Coastguard Worker let context = unsafe { ffi::avcodec_alloc_context3(self.0).as_mut() } 156*1b4853f5SAndroid Build Coastguard Worker .ok_or(AvCodecOpenError::ContextAllocation)?; 157*1b4853f5SAndroid Build Coastguard Worker 158*1b4853f5SAndroid Build Coastguard Worker Ok(AvCodecContext(context)) 159*1b4853f5SAndroid Build Coastguard Worker } 160*1b4853f5SAndroid Build Coastguard Worker } 161*1b4853f5SAndroid Build Coastguard Worker 162*1b4853f5SAndroid Build Coastguard Worker /// A builder to create a [`AvCodecContext`] suitable for decoding. 163*1b4853f5SAndroid Build Coastguard Worker // This struct wraps an AvCodecContext directly, but the only way it can be taken out is to call 164*1b4853f5SAndroid Build Coastguard Worker // `build()`, which finalizes the context and prevent further modification to the callback, etc. 165*1b4853f5SAndroid Build Coastguard Worker pub struct DecoderContextBuilder { 166*1b4853f5SAndroid Build Coastguard Worker codec: *const ffi::AVCodec, 167*1b4853f5SAndroid Build Coastguard Worker context: AvCodecContext, 168*1b4853f5SAndroid Build Coastguard Worker } 169*1b4853f5SAndroid Build Coastguard Worker 170*1b4853f5SAndroid Build Coastguard Worker impl DecoderContextBuilder { 171*1b4853f5SAndroid Build Coastguard Worker /// Set a custom callback that provides output buffers. 172*1b4853f5SAndroid Build Coastguard Worker /// 173*1b4853f5SAndroid Build Coastguard Worker /// `get_buffer2` is a function that decides which buffer is used to render a frame (see 174*1b4853f5SAndroid Build Coastguard Worker /// libavcodec's documentation for `get_buffer2` for more details). If provided, this function 175*1b4853f5SAndroid Build Coastguard Worker /// must be thread-safe. 176*1b4853f5SAndroid Build Coastguard Worker /// `opaque` is a pointer that will be passed as first argument to `get_buffer2` when it is 177*1b4853f5SAndroid Build Coastguard Worker /// called. set_get_buffer_2( &mut self, get_buffer2: unsafe extern "C" fn(*mut ffi::AVCodecContext, *mut ffi::AVFrame, i32) -> i32, opaque: *mut libc::c_void, )178*1b4853f5SAndroid Build Coastguard Worker pub fn set_get_buffer_2( 179*1b4853f5SAndroid Build Coastguard Worker &mut self, 180*1b4853f5SAndroid Build Coastguard Worker get_buffer2: unsafe extern "C" fn(*mut ffi::AVCodecContext, *mut ffi::AVFrame, i32) -> i32, 181*1b4853f5SAndroid Build Coastguard Worker opaque: *mut libc::c_void, 182*1b4853f5SAndroid Build Coastguard Worker ) { 183*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 184*1b4853f5SAndroid Build Coastguard Worker // Safe because self.context.0 is a pointer to a live AVCodecContext allocation. 185*1b4853f5SAndroid Build Coastguard Worker let context = unsafe { &mut *(self.context.0) }; 186*1b4853f5SAndroid Build Coastguard Worker context.get_buffer2 = Some(get_buffer2); 187*1b4853f5SAndroid Build Coastguard Worker context.opaque = opaque; 188*1b4853f5SAndroid Build Coastguard Worker } 189*1b4853f5SAndroid Build Coastguard Worker 190*1b4853f5SAndroid Build Coastguard Worker /// Set the initial format for the context. 191*1b4853f5SAndroid Build Coastguard Worker /// 192*1b4853f5SAndroid Build Coastguard Worker /// This ensures the context has a valid resolution and pixel format right after its creation. set_initial_format(&self, coded_format: (u32, u32), pix_fmt: AvPixelFormat)193*1b4853f5SAndroid Build Coastguard Worker pub fn set_initial_format(&self, coded_format: (u32, u32), pix_fmt: AvPixelFormat) { 194*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 195*1b4853f5SAndroid Build Coastguard Worker // Safe because self.context.0 is a pointer to a live AVCodecContext allocation. 196*1b4853f5SAndroid Build Coastguard Worker let context = unsafe { &mut *(self.context.0) }; 197*1b4853f5SAndroid Build Coastguard Worker context.width = coded_format.0 as i32; 198*1b4853f5SAndroid Build Coastguard Worker context.height = coded_format.1 as i32; 199*1b4853f5SAndroid Build Coastguard Worker context.coded_width = coded_format.0 as i32; 200*1b4853f5SAndroid Build Coastguard Worker context.coded_height = coded_format.1 as i32; 201*1b4853f5SAndroid Build Coastguard Worker context.pix_fmt = pix_fmt.0; 202*1b4853f5SAndroid Build Coastguard Worker } 203*1b4853f5SAndroid Build Coastguard Worker 204*1b4853f5SAndroid Build Coastguard Worker /// Build a decoder AvCodecContext from the configured options. build(mut self) -> Result<AvCodecContext, AvCodecOpenError>205*1b4853f5SAndroid Build Coastguard Worker pub fn build(mut self) -> Result<AvCodecContext, AvCodecOpenError> { 206*1b4853f5SAndroid Build Coastguard Worker self.context.init(self.codec)?; 207*1b4853f5SAndroid Build Coastguard Worker Ok(self.context) 208*1b4853f5SAndroid Build Coastguard Worker } 209*1b4853f5SAndroid Build Coastguard Worker } 210*1b4853f5SAndroid Build Coastguard Worker 211*1b4853f5SAndroid Build Coastguard Worker /// A builder to create a [`AvCodecContext`] suitable for encoding. 212*1b4853f5SAndroid Build Coastguard Worker // This struct wraps an AvCodecContext directly, but the only way it can be taken out is to call 213*1b4853f5SAndroid Build Coastguard Worker // `build()`, which finalizes the context and prevent further modification to the callback, etc. 214*1b4853f5SAndroid Build Coastguard Worker pub struct EncoderContextBuilder { 215*1b4853f5SAndroid Build Coastguard Worker codec: *const ffi::AVCodec, 216*1b4853f5SAndroid Build Coastguard Worker context: AvCodecContext, 217*1b4853f5SAndroid Build Coastguard Worker } 218*1b4853f5SAndroid Build Coastguard Worker 219*1b4853f5SAndroid Build Coastguard Worker impl EncoderContextBuilder { 220*1b4853f5SAndroid Build Coastguard Worker /// Set the width of input frames for this encoding context. set_dimensions(&mut self, dimensions: Dimensions)221*1b4853f5SAndroid Build Coastguard Worker pub fn set_dimensions(&mut self, dimensions: Dimensions) { 222*1b4853f5SAndroid Build Coastguard Worker // TODO(b:315859322): add safety doc string 223*1b4853f5SAndroid Build Coastguard Worker #[allow(clippy::undocumented_unsafe_blocks)] 224*1b4853f5SAndroid Build Coastguard Worker let context = unsafe { &mut *(self.context.0) }; 225*1b4853f5SAndroid Build Coastguard Worker context.width = dimensions.width as _; 226*1b4853f5SAndroid Build Coastguard Worker context.height = dimensions.height as _; 227*1b4853f5SAndroid Build Coastguard Worker } 228*1b4853f5SAndroid Build Coastguard Worker 229*1b4853f5SAndroid Build Coastguard Worker /// Set the time base for this encoding context. set_time_base(&mut self, time_base: ffi::AVRational)230*1b4853f5SAndroid Build Coastguard Worker pub fn set_time_base(&mut self, time_base: ffi::AVRational) { 231*1b4853f5SAndroid Build Coastguard Worker // TODO(b:315859322): add safety doc string 232*1b4853f5SAndroid Build Coastguard Worker #[allow(clippy::undocumented_unsafe_blocks)] 233*1b4853f5SAndroid Build Coastguard Worker let context = unsafe { &mut *(self.context.0) }; 234*1b4853f5SAndroid Build Coastguard Worker context.time_base = time_base; 235*1b4853f5SAndroid Build Coastguard Worker } 236*1b4853f5SAndroid Build Coastguard Worker 237*1b4853f5SAndroid Build Coastguard Worker /// Set the input pixel format for this encoding context. set_pix_fmt(&mut self, fmt: AvPixelFormat)238*1b4853f5SAndroid Build Coastguard Worker pub fn set_pix_fmt(&mut self, fmt: AvPixelFormat) { 239*1b4853f5SAndroid Build Coastguard Worker // TODO(b:315859322): add safety doc string 240*1b4853f5SAndroid Build Coastguard Worker #[allow(clippy::undocumented_unsafe_blocks)] 241*1b4853f5SAndroid Build Coastguard Worker let context = unsafe { &mut *(self.context.0) }; 242*1b4853f5SAndroid Build Coastguard Worker context.pix_fmt = fmt.pix_fmt(); 243*1b4853f5SAndroid Build Coastguard Worker } 244*1b4853f5SAndroid Build Coastguard Worker 245*1b4853f5SAndroid Build Coastguard Worker /// Build a encoder AvCodecContext from the configured options. build(mut self) -> Result<AvCodecContext, AvCodecOpenError>246*1b4853f5SAndroid Build Coastguard Worker pub fn build(mut self) -> Result<AvCodecContext, AvCodecOpenError> { 247*1b4853f5SAndroid Build Coastguard Worker self.context.init(self.codec)?; 248*1b4853f5SAndroid Build Coastguard Worker Ok(self.context) 249*1b4853f5SAndroid Build Coastguard Worker } 250*1b4853f5SAndroid Build Coastguard Worker } 251*1b4853f5SAndroid Build Coastguard Worker 252*1b4853f5SAndroid Build Coastguard Worker impl Default for AvCodecIterator { default() -> Self253*1b4853f5SAndroid Build Coastguard Worker fn default() -> Self { 254*1b4853f5SAndroid Build Coastguard Worker Self::new() 255*1b4853f5SAndroid Build Coastguard Worker } 256*1b4853f5SAndroid Build Coastguard Worker } 257*1b4853f5SAndroid Build Coastguard Worker 258*1b4853f5SAndroid Build Coastguard Worker /// Lightweight abstraction over libavcodec's `av_codec_iterate` function that can be used to 259*1b4853f5SAndroid Build Coastguard Worker /// enumerate all the supported codecs. 260*1b4853f5SAndroid Build Coastguard Worker pub struct AvCodecIterator(*mut libc::c_void); 261*1b4853f5SAndroid Build Coastguard Worker 262*1b4853f5SAndroid Build Coastguard Worker impl AvCodecIterator { new() -> Self263*1b4853f5SAndroid Build Coastguard Worker pub fn new() -> Self { 264*1b4853f5SAndroid Build Coastguard Worker Self(std::ptr::null_mut()) 265*1b4853f5SAndroid Build Coastguard Worker } 266*1b4853f5SAndroid Build Coastguard Worker } 267*1b4853f5SAndroid Build Coastguard Worker 268*1b4853f5SAndroid Build Coastguard Worker impl Iterator for AvCodecIterator { 269*1b4853f5SAndroid Build Coastguard Worker type Item = AvCodec; 270*1b4853f5SAndroid Build Coastguard Worker next(&mut self) -> Option<Self::Item>271*1b4853f5SAndroid Build Coastguard Worker fn next(&mut self) -> Option<Self::Item> { 272*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 273*1b4853f5SAndroid Build Coastguard Worker // Safe because our pointer was initialized to `NULL` and we only use it with 274*1b4853f5SAndroid Build Coastguard Worker // `av_codec_iterate`, which will update it to a valid value. 275*1b4853f5SAndroid Build Coastguard Worker unsafe { ffi::av_codec_iterate(&mut self.0 as *mut *mut libc::c_void).as_ref() } 276*1b4853f5SAndroid Build Coastguard Worker .map(AvCodec) 277*1b4853f5SAndroid Build Coastguard Worker } 278*1b4853f5SAndroid Build Coastguard Worker } 279*1b4853f5SAndroid Build Coastguard Worker 280*1b4853f5SAndroid Build Coastguard Worker /// Simple wrapper over `AVProfile` that provides helpful methods. 281*1b4853f5SAndroid Build Coastguard Worker pub struct AvProfile(&'static ffi::AVProfile); 282*1b4853f5SAndroid Build Coastguard Worker 283*1b4853f5SAndroid Build Coastguard Worker impl AvProfile { 284*1b4853f5SAndroid Build Coastguard Worker /// Return the profile id, which can be matched against FF_PROFILE_*. profile(&self) -> u32285*1b4853f5SAndroid Build Coastguard Worker pub fn profile(&self) -> u32 { 286*1b4853f5SAndroid Build Coastguard Worker self.0.profile as u32 287*1b4853f5SAndroid Build Coastguard Worker } 288*1b4853f5SAndroid Build Coastguard Worker 289*1b4853f5SAndroid Build Coastguard Worker /// Return the name of this profile. name(&self) -> &'static str290*1b4853f5SAndroid Build Coastguard Worker pub fn name(&self) -> &'static str { 291*1b4853f5SAndroid Build Coastguard Worker const INVALID_PROFILE_STR: &str = "invalid profile"; 292*1b4853f5SAndroid Build Coastguard Worker 293*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 294*1b4853f5SAndroid Build Coastguard Worker // Safe because `CStr::from_ptr` is called on a valid zero-terminated C string. 295*1b4853f5SAndroid Build Coastguard Worker unsafe { CStr::from_ptr(self.0.name).to_str() }.unwrap_or(INVALID_PROFILE_STR) 296*1b4853f5SAndroid Build Coastguard Worker } 297*1b4853f5SAndroid Build Coastguard Worker } 298*1b4853f5SAndroid Build Coastguard Worker 299*1b4853f5SAndroid Build Coastguard Worker impl Display for AvProfile { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result300*1b4853f5SAndroid Build Coastguard Worker fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 301*1b4853f5SAndroid Build Coastguard Worker f.write_str(self.name()) 302*1b4853f5SAndroid Build Coastguard Worker } 303*1b4853f5SAndroid Build Coastguard Worker } 304*1b4853f5SAndroid Build Coastguard Worker 305*1b4853f5SAndroid Build Coastguard Worker impl Debug for AvProfile { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result306*1b4853f5SAndroid Build Coastguard Worker fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 307*1b4853f5SAndroid Build Coastguard Worker Display::fmt(self, f) 308*1b4853f5SAndroid Build Coastguard Worker } 309*1b4853f5SAndroid Build Coastguard Worker } 310*1b4853f5SAndroid Build Coastguard Worker 311*1b4853f5SAndroid Build Coastguard Worker /// Lightweight abstraction over the array of supported profiles for a given codec. 312*1b4853f5SAndroid Build Coastguard Worker pub struct AvProfileIterator(*const ffi::AVProfile); 313*1b4853f5SAndroid Build Coastguard Worker 314*1b4853f5SAndroid Build Coastguard Worker impl Iterator for AvProfileIterator { 315*1b4853f5SAndroid Build Coastguard Worker type Item = AvProfile; 316*1b4853f5SAndroid Build Coastguard Worker next(&mut self) -> Option<Self::Item>317*1b4853f5SAndroid Build Coastguard Worker fn next(&mut self) -> Option<Self::Item> { 318*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 319*1b4853f5SAndroid Build Coastguard Worker // Safe because the contract of `new` stipulates we have received a valid `AVCodec` 320*1b4853f5SAndroid Build Coastguard Worker // reference, thus the `profiles` pointer must either be NULL or point to a valid array 321*1b4853f5SAndroid Build Coastguard Worker // or `VAProfile`s. 322*1b4853f5SAndroid Build Coastguard Worker match unsafe { self.0.as_ref() } { 323*1b4853f5SAndroid Build Coastguard Worker None => None, 324*1b4853f5SAndroid Build Coastguard Worker Some(profile) => { 325*1b4853f5SAndroid Build Coastguard Worker match profile.profile { 326*1b4853f5SAndroid Build Coastguard Worker ffi::FF_PROFILE_UNKNOWN => None, 327*1b4853f5SAndroid Build Coastguard Worker _ => { 328*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 329*1b4853f5SAndroid Build Coastguard Worker // Safe because we have been initialized to a static, valid profiles array 330*1b4853f5SAndroid Build Coastguard Worker // which is terminated by FF_PROFILE_UNKNOWN. 331*1b4853f5SAndroid Build Coastguard Worker self.0 = unsafe { self.0.offset(1) }; 332*1b4853f5SAndroid Build Coastguard Worker Some(AvProfile(profile)) 333*1b4853f5SAndroid Build Coastguard Worker } 334*1b4853f5SAndroid Build Coastguard Worker } 335*1b4853f5SAndroid Build Coastguard Worker } 336*1b4853f5SAndroid Build Coastguard Worker } 337*1b4853f5SAndroid Build Coastguard Worker } 338*1b4853f5SAndroid Build Coastguard Worker } 339*1b4853f5SAndroid Build Coastguard Worker 340*1b4853f5SAndroid Build Coastguard Worker #[derive(Clone, Copy)] 341*1b4853f5SAndroid Build Coastguard Worker /// Simple wrapper over `AVPixelFormat` that provides helpful methods. 342*1b4853f5SAndroid Build Coastguard Worker pub struct AvPixelFormat(pub ffi::AVPixelFormat); 343*1b4853f5SAndroid Build Coastguard Worker 344*1b4853f5SAndroid Build Coastguard Worker pub const AV_PIXEL_FORMAT_YUV420P: AvPixelFormat = 345*1b4853f5SAndroid Build Coastguard Worker AvPixelFormat(ffi::AVPixelFormat_AV_PIX_FMT_YUV420P); 346*1b4853f5SAndroid Build Coastguard Worker pub const AV_PIXEL_FORMAT_NV12: AvPixelFormat = AvPixelFormat(ffi::AVPixelFormat_AV_PIX_FMT_NV12); 347*1b4853f5SAndroid Build Coastguard Worker 348*1b4853f5SAndroid Build Coastguard Worker impl From<AvPixelFormat> for ffi::AVPixelFormat { from(val: AvPixelFormat) -> Self349*1b4853f5SAndroid Build Coastguard Worker fn from(val: AvPixelFormat) -> Self { 350*1b4853f5SAndroid Build Coastguard Worker val.0 351*1b4853f5SAndroid Build Coastguard Worker } 352*1b4853f5SAndroid Build Coastguard Worker } 353*1b4853f5SAndroid Build Coastguard Worker 354*1b4853f5SAndroid Build Coastguard Worker impl AvPixelFormat { 355*1b4853f5SAndroid Build Coastguard Worker /// Return the name of this pixel format. name(&self) -> &'static str356*1b4853f5SAndroid Build Coastguard Worker pub fn name(&self) -> &'static str { 357*1b4853f5SAndroid Build Coastguard Worker const INVALID_FORMAT_STR: &str = "invalid pixel format"; 358*1b4853f5SAndroid Build Coastguard Worker 359*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 360*1b4853f5SAndroid Build Coastguard Worker // Safe because `av_get_pix_fmt_name` returns either NULL or a valid C string. 361*1b4853f5SAndroid Build Coastguard Worker let pix_fmt_name = unsafe { ffi::av_get_pix_fmt_name(self.0) }; 362*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 363*1b4853f5SAndroid Build Coastguard Worker // Safe because `pix_fmt_name` is a valid pointer to a C string. 364*1b4853f5SAndroid Build Coastguard Worker match unsafe { 365*1b4853f5SAndroid Build Coastguard Worker pix_fmt_name 366*1b4853f5SAndroid Build Coastguard Worker .as_ref() 367*1b4853f5SAndroid Build Coastguard Worker .and_then(|s| CStr::from_ptr(s).to_str().ok()) 368*1b4853f5SAndroid Build Coastguard Worker } { 369*1b4853f5SAndroid Build Coastguard Worker None => INVALID_FORMAT_STR, 370*1b4853f5SAndroid Build Coastguard Worker Some(string) => string, 371*1b4853f5SAndroid Build Coastguard Worker } 372*1b4853f5SAndroid Build Coastguard Worker } 373*1b4853f5SAndroid Build Coastguard Worker 374*1b4853f5SAndroid Build Coastguard Worker /// Return the avcodec profile id, which can be matched against AV_PIX_FMT_*. 375*1b4853f5SAndroid Build Coastguard Worker /// 376*1b4853f5SAndroid Build Coastguard Worker /// Note that this is **not** the same as a fourcc. pix_fmt(&self) -> ffi::AVPixelFormat377*1b4853f5SAndroid Build Coastguard Worker pub fn pix_fmt(&self) -> ffi::AVPixelFormat { 378*1b4853f5SAndroid Build Coastguard Worker self.0 379*1b4853f5SAndroid Build Coastguard Worker } 380*1b4853f5SAndroid Build Coastguard Worker 381*1b4853f5SAndroid Build Coastguard Worker /// Return the fourcc of the pixel format, or a series of zeros if its fourcc is unknown. fourcc(&self) -> [u8; 4]382*1b4853f5SAndroid Build Coastguard Worker pub fn fourcc(&self) -> [u8; 4] { 383*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 384*1b4853f5SAndroid Build Coastguard Worker // Safe because `avcodec_pix_fmt_to_codec_tag` does not take any pointer as input and 385*1b4853f5SAndroid Build Coastguard Worker // handles any value passed as argument. 386*1b4853f5SAndroid Build Coastguard Worker unsafe { ffi::avcodec_pix_fmt_to_codec_tag(self.0) }.to_le_bytes() 387*1b4853f5SAndroid Build Coastguard Worker } 388*1b4853f5SAndroid Build Coastguard Worker 389*1b4853f5SAndroid Build Coastguard Worker /// Given the width and plane index, returns the line size (data pointer increment per row) in 390*1b4853f5SAndroid Build Coastguard Worker /// bytes. line_size(&self, width: u32, plane: usize) -> usize391*1b4853f5SAndroid Build Coastguard Worker pub fn line_size(&self, width: u32, plane: usize) -> usize { 392*1b4853f5SAndroid Build Coastguard Worker // This should not fail if the format is correct. 393*1b4853f5SAndroid Build Coastguard Worker av_image_line_size(*self, width, plane).unwrap_or_default() 394*1b4853f5SAndroid Build Coastguard Worker } 395*1b4853f5SAndroid Build Coastguard Worker 396*1b4853f5SAndroid Build Coastguard Worker /// Given an iterator of line sizes and height, return the size required for each plane's buffer 397*1b4853f5SAndroid Build Coastguard Worker /// in bytes. plane_sizes<I: IntoIterator<Item = u32>>( &self, linesizes: I, height: u32, ) -> Vec<usize>398*1b4853f5SAndroid Build Coastguard Worker pub fn plane_sizes<I: IntoIterator<Item = u32>>( 399*1b4853f5SAndroid Build Coastguard Worker &self, 400*1b4853f5SAndroid Build Coastguard Worker linesizes: I, 401*1b4853f5SAndroid Build Coastguard Worker height: u32, 402*1b4853f5SAndroid Build Coastguard Worker ) -> Vec<usize> { 403*1b4853f5SAndroid Build Coastguard Worker av_image_plane_sizes(*self, linesizes, height).unwrap_or_default() 404*1b4853f5SAndroid Build Coastguard Worker } 405*1b4853f5SAndroid Build Coastguard Worker } 406*1b4853f5SAndroid Build Coastguard Worker 407*1b4853f5SAndroid Build Coastguard Worker #[derive(Debug)] 408*1b4853f5SAndroid Build Coastguard Worker pub struct FromAVPixelFormatError(()); 409*1b4853f5SAndroid Build Coastguard Worker 410*1b4853f5SAndroid Build Coastguard Worker impl TryFrom<ffi::AVPixelFormat> for AvPixelFormat { 411*1b4853f5SAndroid Build Coastguard Worker type Error = FromAVPixelFormatError; 412*1b4853f5SAndroid Build Coastguard Worker try_from(value: ffi::AVPixelFormat) -> Result<Self, Self::Error>413*1b4853f5SAndroid Build Coastguard Worker fn try_from(value: ffi::AVPixelFormat) -> Result<Self, Self::Error> { 414*1b4853f5SAndroid Build Coastguard Worker if value > ffi::AVPixelFormat_AV_PIX_FMT_NONE && value < ffi::AVPixelFormat_AV_PIX_FMT_NB { 415*1b4853f5SAndroid Build Coastguard Worker Ok(AvPixelFormat(value)) 416*1b4853f5SAndroid Build Coastguard Worker } else { 417*1b4853f5SAndroid Build Coastguard Worker Err(FromAVPixelFormatError(())) 418*1b4853f5SAndroid Build Coastguard Worker } 419*1b4853f5SAndroid Build Coastguard Worker } 420*1b4853f5SAndroid Build Coastguard Worker } 421*1b4853f5SAndroid Build Coastguard Worker 422*1b4853f5SAndroid Build Coastguard Worker impl Display for AvPixelFormat { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result423*1b4853f5SAndroid Build Coastguard Worker fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 424*1b4853f5SAndroid Build Coastguard Worker f.write_str(self.name()) 425*1b4853f5SAndroid Build Coastguard Worker } 426*1b4853f5SAndroid Build Coastguard Worker } 427*1b4853f5SAndroid Build Coastguard Worker 428*1b4853f5SAndroid Build Coastguard Worker impl Debug for AvPixelFormat { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result429*1b4853f5SAndroid Build Coastguard Worker fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 430*1b4853f5SAndroid Build Coastguard Worker let fourcc = self.fourcc(); 431*1b4853f5SAndroid Build Coastguard Worker f.write_fmt(format_args!( 432*1b4853f5SAndroid Build Coastguard Worker "{}{}{}{}", 433*1b4853f5SAndroid Build Coastguard Worker fourcc[0] as char, fourcc[1] as char, fourcc[2] as char, fourcc[3] as char 434*1b4853f5SAndroid Build Coastguard Worker )) 435*1b4853f5SAndroid Build Coastguard Worker } 436*1b4853f5SAndroid Build Coastguard Worker } 437*1b4853f5SAndroid Build Coastguard Worker 438*1b4853f5SAndroid Build Coastguard Worker /// Lightweight abstraction over the array of supported pixel formats for a given codec. 439*1b4853f5SAndroid Build Coastguard Worker pub struct AvPixelFormatIterator(*const ffi::AVPixelFormat); 440*1b4853f5SAndroid Build Coastguard Worker 441*1b4853f5SAndroid Build Coastguard Worker impl Iterator for AvPixelFormatIterator { 442*1b4853f5SAndroid Build Coastguard Worker type Item = AvPixelFormat; 443*1b4853f5SAndroid Build Coastguard Worker next(&mut self) -> Option<Self::Item>444*1b4853f5SAndroid Build Coastguard Worker fn next(&mut self) -> Option<Self::Item> { 445*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 446*1b4853f5SAndroid Build Coastguard Worker // Safe because the contract of `AvCodec::new` and `AvCodec::pixel_format_iter` guarantees 447*1b4853f5SAndroid Build Coastguard Worker // that we have been built from a valid `AVCodec` reference, which `pix_fmts` pointer 448*1b4853f5SAndroid Build Coastguard Worker // must either be NULL or point to a valid array or `VAPixelFormat`s. 449*1b4853f5SAndroid Build Coastguard Worker match unsafe { self.0.as_ref() } { 450*1b4853f5SAndroid Build Coastguard Worker None => None, 451*1b4853f5SAndroid Build Coastguard Worker Some(&pixfmt) => { 452*1b4853f5SAndroid Build Coastguard Worker match pixfmt { 453*1b4853f5SAndroid Build Coastguard Worker // Array of pixel formats is terminated by AV_PIX_FMT_NONE. 454*1b4853f5SAndroid Build Coastguard Worker ffi::AVPixelFormat_AV_PIX_FMT_NONE => None, 455*1b4853f5SAndroid Build Coastguard Worker _ => { 456*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 457*1b4853f5SAndroid Build Coastguard Worker // Safe because we have been initialized to a static, valid profiles array 458*1b4853f5SAndroid Build Coastguard Worker // which is terminated by AV_PIX_FMT_NONE. 459*1b4853f5SAndroid Build Coastguard Worker self.0 = unsafe { self.0.offset(1) }; 460*1b4853f5SAndroid Build Coastguard Worker Some(AvPixelFormat(pixfmt)) 461*1b4853f5SAndroid Build Coastguard Worker } 462*1b4853f5SAndroid Build Coastguard Worker } 463*1b4853f5SAndroid Build Coastguard Worker } 464*1b4853f5SAndroid Build Coastguard Worker } 465*1b4853f5SAndroid Build Coastguard Worker } 466*1b4853f5SAndroid Build Coastguard Worker } 467*1b4853f5SAndroid Build Coastguard Worker 468*1b4853f5SAndroid Build Coastguard Worker /// A codec context from which decoding can be performed. 469*1b4853f5SAndroid Build Coastguard Worker pub struct AvCodecContext(*mut ffi::AVCodecContext); 470*1b4853f5SAndroid Build Coastguard Worker 471*1b4853f5SAndroid Build Coastguard Worker impl Drop for AvCodecContext { drop(&mut self)472*1b4853f5SAndroid Build Coastguard Worker fn drop(&mut self) { 473*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 474*1b4853f5SAndroid Build Coastguard Worker // Safe because our context member is properly allocated and owned by us. 475*1b4853f5SAndroid Build Coastguard Worker // Note: `avcodec_open2` might not have been called in case we're wrapped by a 476*1b4853f5SAndroid Build Coastguard Worker // `DecoderContextBuilder` but avcodec_free_context works on both opened and closed 477*1b4853f5SAndroid Build Coastguard Worker // contexts. 478*1b4853f5SAndroid Build Coastguard Worker unsafe { ffi::avcodec_free_context(&mut self.0) }; 479*1b4853f5SAndroid Build Coastguard Worker } 480*1b4853f5SAndroid Build Coastguard Worker } 481*1b4853f5SAndroid Build Coastguard Worker 482*1b4853f5SAndroid Build Coastguard Worker impl AsRef<ffi::AVCodecContext> for AvCodecContext { as_ref(&self) -> &ffi::AVCodecContext483*1b4853f5SAndroid Build Coastguard Worker fn as_ref(&self) -> &ffi::AVCodecContext { 484*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 485*1b4853f5SAndroid Build Coastguard Worker // Safe because our context member is properly initialized and fully owned by us. 486*1b4853f5SAndroid Build Coastguard Worker unsafe { &*self.0 } 487*1b4853f5SAndroid Build Coastguard Worker } 488*1b4853f5SAndroid Build Coastguard Worker } 489*1b4853f5SAndroid Build Coastguard Worker 490*1b4853f5SAndroid Build Coastguard Worker pub enum TryReceiveResult { 491*1b4853f5SAndroid Build Coastguard Worker Received, 492*1b4853f5SAndroid Build Coastguard Worker TryAgain, 493*1b4853f5SAndroid Build Coastguard Worker FlushCompleted, 494*1b4853f5SAndroid Build Coastguard Worker } 495*1b4853f5SAndroid Build Coastguard Worker 496*1b4853f5SAndroid Build Coastguard Worker impl AvCodecContext { 497*1b4853f5SAndroid Build Coastguard Worker /// Internal helper for [`DecoderContextBuilder`] to initialize the context. init(&mut self, codec: *const ffi::AVCodec) -> Result<(), AvCodecOpenError>498*1b4853f5SAndroid Build Coastguard Worker fn init(&mut self, codec: *const ffi::AVCodec) -> Result<(), AvCodecOpenError> { 499*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 500*1b4853f5SAndroid Build Coastguard Worker // Safe because `codec` is a valid static AVCodec reference, and `self.0` is a valid 501*1b4853f5SAndroid Build Coastguard Worker // AVCodecContext allocation. 502*1b4853f5SAndroid Build Coastguard Worker if unsafe { ffi::avcodec_open2(self.0, codec, std::ptr::null_mut()) } < 0 { 503*1b4853f5SAndroid Build Coastguard Worker return Err(AvCodecOpenError::ContextOpen); 504*1b4853f5SAndroid Build Coastguard Worker } 505*1b4853f5SAndroid Build Coastguard Worker 506*1b4853f5SAndroid Build Coastguard Worker Ok(()) 507*1b4853f5SAndroid Build Coastguard Worker } 508*1b4853f5SAndroid Build Coastguard Worker 509*1b4853f5SAndroid Build Coastguard Worker /// Send a packet to be decoded by the codec. 510*1b4853f5SAndroid Build Coastguard Worker /// 511*1b4853f5SAndroid Build Coastguard Worker /// Returns `true` if the packet has been accepted and will be decoded, `false` if the codec can 512*1b4853f5SAndroid Build Coastguard Worker /// not accept frames at the moment - in this case `try_receive_frame` must be called before 513*1b4853f5SAndroid Build Coastguard Worker /// the packet can be submitted again. 514*1b4853f5SAndroid Build Coastguard Worker /// 515*1b4853f5SAndroid Build Coastguard Worker /// Error codes are the same as those returned by `avcodec_send_packet` with the exception of 516*1b4853f5SAndroid Build Coastguard Worker /// EAGAIN which is converted into `Ok(false)` as it is not actually an error. try_send_packet(&mut self, packet: &AvPacket) -> Result<bool, AvError>517*1b4853f5SAndroid Build Coastguard Worker pub fn try_send_packet(&mut self, packet: &AvPacket) -> Result<bool, AvError> { 518*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 519*1b4853f5SAndroid Build Coastguard Worker // Safe because the context is valid through the life of this object, and `packet`'s 520*1b4853f5SAndroid Build Coastguard Worker // lifetime properties ensures its memory area is readable. 521*1b4853f5SAndroid Build Coastguard Worker match unsafe { ffi::avcodec_send_packet(self.0, &packet.packet) } { 522*1b4853f5SAndroid Build Coastguard Worker AVERROR_EAGAIN => Ok(false), 523*1b4853f5SAndroid Build Coastguard Worker ret if ret >= 0 => Ok(true), 524*1b4853f5SAndroid Build Coastguard Worker err => Err(AvError(err)), 525*1b4853f5SAndroid Build Coastguard Worker } 526*1b4853f5SAndroid Build Coastguard Worker } 527*1b4853f5SAndroid Build Coastguard Worker 528*1b4853f5SAndroid Build Coastguard Worker /// Attempt to write a decoded frame in `frame` if the codec has enough data to do so. 529*1b4853f5SAndroid Build Coastguard Worker /// 530*1b4853f5SAndroid Build Coastguard Worker /// Returns `Received` if `frame` has been filled with the next decoded frame, `TryAgain` if 531*1b4853f5SAndroid Build Coastguard Worker /// no frame could be returned at that time (in which case `try_send_packet` should be called to 532*1b4853f5SAndroid Build Coastguard Worker /// submit more input to decode), or `FlushCompleted` to signal that a previous flush triggered 533*1b4853f5SAndroid Build Coastguard Worker /// by calling the `flush` method has completed. 534*1b4853f5SAndroid Build Coastguard Worker /// 535*1b4853f5SAndroid Build Coastguard Worker /// Error codes are the same as those returned by `avcodec_receive_frame` with the exception of 536*1b4853f5SAndroid Build Coastguard Worker /// EAGAIN and EOF which are handled as `TryAgain` and `FlushCompleted` respectively. try_receive_frame(&mut self, frame: &mut AvFrame) -> Result<TryReceiveResult, AvError>537*1b4853f5SAndroid Build Coastguard Worker pub fn try_receive_frame(&mut self, frame: &mut AvFrame) -> Result<TryReceiveResult, AvError> { 538*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 539*1b4853f5SAndroid Build Coastguard Worker // Safe because the context is valid through the life of this object, and `avframe` is 540*1b4853f5SAndroid Build Coastguard Worker // guaranteed to contain a properly initialized frame. 541*1b4853f5SAndroid Build Coastguard Worker match unsafe { ffi::avcodec_receive_frame(self.0, frame.0) } { 542*1b4853f5SAndroid Build Coastguard Worker AVERROR_EAGAIN => Ok(TryReceiveResult::TryAgain), 543*1b4853f5SAndroid Build Coastguard Worker AVERROR_EOF => Ok(TryReceiveResult::FlushCompleted), 544*1b4853f5SAndroid Build Coastguard Worker ret if ret >= 0 => Ok(TryReceiveResult::Received), 545*1b4853f5SAndroid Build Coastguard Worker err => Err(AvError(err)), 546*1b4853f5SAndroid Build Coastguard Worker } 547*1b4853f5SAndroid Build Coastguard Worker } 548*1b4853f5SAndroid Build Coastguard Worker 549*1b4853f5SAndroid Build Coastguard Worker /// Send a frame to be encoded by the codec. 550*1b4853f5SAndroid Build Coastguard Worker /// 551*1b4853f5SAndroid Build Coastguard Worker /// Returns `true` if the frame has been accepted and will be encoded, `false` if the codec can 552*1b4853f5SAndroid Build Coastguard Worker /// not accept input at the moment - in this case `try_receive_frame` must be called before 553*1b4853f5SAndroid Build Coastguard Worker /// the frame can be submitted again. 554*1b4853f5SAndroid Build Coastguard Worker /// 555*1b4853f5SAndroid Build Coastguard Worker /// Error codes are the same as those returned by `avcodec_send_frame` with the exception of 556*1b4853f5SAndroid Build Coastguard Worker /// EAGAIN which is converted into `Ok(false)` as it is not actually an error. try_send_frame(&mut self, frame: &AvFrame) -> Result<bool, AvError>557*1b4853f5SAndroid Build Coastguard Worker pub fn try_send_frame(&mut self, frame: &AvFrame) -> Result<bool, AvError> { 558*1b4853f5SAndroid Build Coastguard Worker // TODO(b:315859322): add safety doc string 559*1b4853f5SAndroid Build Coastguard Worker #[allow(clippy::undocumented_unsafe_blocks)] 560*1b4853f5SAndroid Build Coastguard Worker match unsafe { ffi::avcodec_send_frame(self.0, frame.0 as *const _) } { 561*1b4853f5SAndroid Build Coastguard Worker AVERROR_EAGAIN => Ok(false), 562*1b4853f5SAndroid Build Coastguard Worker ret if ret >= 0 => Ok(true), 563*1b4853f5SAndroid Build Coastguard Worker err => Err(AvError(err)), 564*1b4853f5SAndroid Build Coastguard Worker } 565*1b4853f5SAndroid Build Coastguard Worker } 566*1b4853f5SAndroid Build Coastguard Worker 567*1b4853f5SAndroid Build Coastguard Worker /// Attempt to write an encoded frame in `packet` if the codec has enough data to do so. 568*1b4853f5SAndroid Build Coastguard Worker /// 569*1b4853f5SAndroid Build Coastguard Worker /// Returns `Received` if `packet` has been filled with encoded data, `TryAgain` if 570*1b4853f5SAndroid Build Coastguard Worker /// no packet could be returned at that time (in which case `try_send_frame` should be called to 571*1b4853f5SAndroid Build Coastguard Worker /// submit more input to decode), or `FlushCompleted` to signal that a previous flush triggered 572*1b4853f5SAndroid Build Coastguard Worker /// by calling the `flush` method has completed. 573*1b4853f5SAndroid Build Coastguard Worker /// 574*1b4853f5SAndroid Build Coastguard Worker /// Error codes are the same as those returned by `avcodec_receive_packet` with the exception of 575*1b4853f5SAndroid Build Coastguard Worker /// EAGAIN and EOF which are handled as `TryAgain` and `FlushCompleted` respectively. try_receive_packet( &mut self, packet: &mut AvPacket, ) -> Result<TryReceiveResult, AvError>576*1b4853f5SAndroid Build Coastguard Worker pub fn try_receive_packet( 577*1b4853f5SAndroid Build Coastguard Worker &mut self, 578*1b4853f5SAndroid Build Coastguard Worker packet: &mut AvPacket, 579*1b4853f5SAndroid Build Coastguard Worker ) -> Result<TryReceiveResult, AvError> { 580*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 581*1b4853f5SAndroid Build Coastguard Worker // Safe because the context is valid through the life of this object, and `avframe` is 582*1b4853f5SAndroid Build Coastguard Worker // guaranteed to contain a properly initialized frame. 583*1b4853f5SAndroid Build Coastguard Worker match unsafe { ffi::avcodec_receive_packet(self.0, &mut packet.packet) } { 584*1b4853f5SAndroid Build Coastguard Worker AVERROR_EAGAIN => Ok(TryReceiveResult::TryAgain), 585*1b4853f5SAndroid Build Coastguard Worker AVERROR_EOF => Ok(TryReceiveResult::FlushCompleted), 586*1b4853f5SAndroid Build Coastguard Worker ret if ret >= 0 => Ok(TryReceiveResult::Received), 587*1b4853f5SAndroid Build Coastguard Worker err => Err(AvError(err)), 588*1b4853f5SAndroid Build Coastguard Worker } 589*1b4853f5SAndroid Build Coastguard Worker } 590*1b4853f5SAndroid Build Coastguard Worker 591*1b4853f5SAndroid Build Coastguard Worker /// Reset the internal codec state/flush internal buffers. 592*1b4853f5SAndroid Build Coastguard Worker /// Should be called e.g. when seeking or switching to a different stream. reset(&mut self)593*1b4853f5SAndroid Build Coastguard Worker pub fn reset(&mut self) { 594*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 595*1b4853f5SAndroid Build Coastguard Worker // Safe because the context is valid through the life of this object. 596*1b4853f5SAndroid Build Coastguard Worker unsafe { ffi::avcodec_flush_buffers(self.0) } 597*1b4853f5SAndroid Build Coastguard Worker } 598*1b4853f5SAndroid Build Coastguard Worker 599*1b4853f5SAndroid Build Coastguard Worker /// Ask the context to start flushing, i.e. to process all pending input packets and produce 600*1b4853f5SAndroid Build Coastguard Worker /// frames for them. 601*1b4853f5SAndroid Build Coastguard Worker /// 602*1b4853f5SAndroid Build Coastguard Worker /// The flush process is complete when `try_receive_frame` returns `FlushCompleted`, flush_decoder(&mut self) -> Result<(), AvError>603*1b4853f5SAndroid Build Coastguard Worker pub fn flush_decoder(&mut self) -> Result<(), AvError> { 604*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 605*1b4853f5SAndroid Build Coastguard Worker // Safe because the context is valid through the life of this object. 606*1b4853f5SAndroid Build Coastguard Worker AvError::result(unsafe { ffi::avcodec_send_packet(self.0, std::ptr::null()) }) 607*1b4853f5SAndroid Build Coastguard Worker } 608*1b4853f5SAndroid Build Coastguard Worker 609*1b4853f5SAndroid Build Coastguard Worker /// Ask the context to start flushing, i.e. to process all pending input frames and produce 610*1b4853f5SAndroid Build Coastguard Worker /// packets for them. 611*1b4853f5SAndroid Build Coastguard Worker /// 612*1b4853f5SAndroid Build Coastguard Worker /// The flush process is complete when `try_receive_packet` returns `FlushCompleted`, flush_encoder(&mut self) -> Result<(), AvError>613*1b4853f5SAndroid Build Coastguard Worker pub fn flush_encoder(&mut self) -> Result<(), AvError> { 614*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 615*1b4853f5SAndroid Build Coastguard Worker // Safe because the context is valid through the life of this object. 616*1b4853f5SAndroid Build Coastguard Worker AvError::result(unsafe { ffi::avcodec_send_frame(self.0, std::ptr::null()) }) 617*1b4853f5SAndroid Build Coastguard Worker } 618*1b4853f5SAndroid Build Coastguard Worker 619*1b4853f5SAndroid Build Coastguard Worker /// Set the time base for this context. set_time_base(&mut self, time_base: AVRational)620*1b4853f5SAndroid Build Coastguard Worker pub fn set_time_base(&mut self, time_base: AVRational) { 621*1b4853f5SAndroid Build Coastguard Worker // TODO(b:315859322): add safety doc string 622*1b4853f5SAndroid Build Coastguard Worker #[allow(clippy::undocumented_unsafe_blocks)] 623*1b4853f5SAndroid Build Coastguard Worker let context = unsafe { &mut *(self.0) }; 624*1b4853f5SAndroid Build Coastguard Worker context.time_base = time_base; 625*1b4853f5SAndroid Build Coastguard Worker } 626*1b4853f5SAndroid Build Coastguard Worker 627*1b4853f5SAndroid Build Coastguard Worker /// Set the bit rate for this context. set_bit_rate(&mut self, bit_rate: u64)628*1b4853f5SAndroid Build Coastguard Worker pub fn set_bit_rate(&mut self, bit_rate: u64) { 629*1b4853f5SAndroid Build Coastguard Worker // TODO(b:315859322): add safety doc string 630*1b4853f5SAndroid Build Coastguard Worker #[allow(clippy::undocumented_unsafe_blocks)] 631*1b4853f5SAndroid Build Coastguard Worker let context = unsafe { &mut *(self.0) }; 632*1b4853f5SAndroid Build Coastguard Worker context.bit_rate = bit_rate as _; 633*1b4853f5SAndroid Build Coastguard Worker } 634*1b4853f5SAndroid Build Coastguard Worker 635*1b4853f5SAndroid Build Coastguard Worker /// Set the max bit rate (rc_max_rate) for this context. set_max_bit_rate(&mut self, bit_rate: u64)636*1b4853f5SAndroid Build Coastguard Worker pub fn set_max_bit_rate(&mut self, bit_rate: u64) { 637*1b4853f5SAndroid Build Coastguard Worker // TODO(b:315859322): add safety doc string 638*1b4853f5SAndroid Build Coastguard Worker #[allow(clippy::undocumented_unsafe_blocks)] 639*1b4853f5SAndroid Build Coastguard Worker let context = unsafe { &mut *(self.0) }; 640*1b4853f5SAndroid Build Coastguard Worker context.rc_max_rate = bit_rate as _; 641*1b4853f5SAndroid Build Coastguard Worker } 642*1b4853f5SAndroid Build Coastguard Worker } 643*1b4853f5SAndroid Build Coastguard Worker 644*1b4853f5SAndroid Build Coastguard Worker /// Trait for types that can be used as data provider for a `AVBuffer`. 645*1b4853f5SAndroid Build Coastguard Worker /// 646*1b4853f5SAndroid Build Coastguard Worker /// `AVBuffer` is an owned buffer type, so all the type needs to do is being able to provide a 647*1b4853f5SAndroid Build Coastguard Worker /// stable pointer to its own data as well as its length. Implementors need to be sendable across 648*1b4853f5SAndroid Build Coastguard Worker /// threads because avcodec is allowed to use threads in its codec implementations. 649*1b4853f5SAndroid Build Coastguard Worker pub trait AvBufferSource: Send { as_ptr(&self) -> *const u8650*1b4853f5SAndroid Build Coastguard Worker fn as_ptr(&self) -> *const u8; as_mut_ptr(&mut self) -> *mut u8651*1b4853f5SAndroid Build Coastguard Worker fn as_mut_ptr(&mut self) -> *mut u8; 652*1b4853f5SAndroid Build Coastguard Worker len(&self) -> usize653*1b4853f5SAndroid Build Coastguard Worker fn len(&self) -> usize; 654*1b4853f5SAndroid Build Coastguard Worker is_empty(&self) -> bool655*1b4853f5SAndroid Build Coastguard Worker fn is_empty(&self) -> bool { 656*1b4853f5SAndroid Build Coastguard Worker self.len() == 0 657*1b4853f5SAndroid Build Coastguard Worker } 658*1b4853f5SAndroid Build Coastguard Worker } 659*1b4853f5SAndroid Build Coastguard Worker 660*1b4853f5SAndroid Build Coastguard Worker impl AvBufferSource for Vec<u8> { as_ptr(&self) -> *const u8661*1b4853f5SAndroid Build Coastguard Worker fn as_ptr(&self) -> *const u8 { 662*1b4853f5SAndroid Build Coastguard Worker self.as_ptr() 663*1b4853f5SAndroid Build Coastguard Worker } 664*1b4853f5SAndroid Build Coastguard Worker as_mut_ptr(&mut self) -> *mut u8665*1b4853f5SAndroid Build Coastguard Worker fn as_mut_ptr(&mut self) -> *mut u8 { 666*1b4853f5SAndroid Build Coastguard Worker self.as_mut_ptr() 667*1b4853f5SAndroid Build Coastguard Worker } 668*1b4853f5SAndroid Build Coastguard Worker len(&self) -> usize669*1b4853f5SAndroid Build Coastguard Worker fn len(&self) -> usize { 670*1b4853f5SAndroid Build Coastguard Worker self.len() 671*1b4853f5SAndroid Build Coastguard Worker } 672*1b4853f5SAndroid Build Coastguard Worker } 673*1b4853f5SAndroid Build Coastguard Worker 674*1b4853f5SAndroid Build Coastguard Worker /// Wrapper around `AVBuffer` and `AVBufferRef`. 675*1b4853f5SAndroid Build Coastguard Worker /// 676*1b4853f5SAndroid Build Coastguard Worker /// libavcodec can manage its own memory for input and output data. Doing so implies a transparent 677*1b4853f5SAndroid Build Coastguard Worker /// copy of user-provided data (packets or frames) from and to this memory, which is wasteful. 678*1b4853f5SAndroid Build Coastguard Worker /// 679*1b4853f5SAndroid Build Coastguard Worker /// This copy can be avoided by explicitly providing our own buffers to libavcodec using 680*1b4853f5SAndroid Build Coastguard Worker /// `AVBufferRef`. Doing so means that the lifetime of these buffers becomes managed by avcodec. 681*1b4853f5SAndroid Build Coastguard Worker /// This struct helps make this process safe by taking full ownership of an `AvBufferSource` and 682*1b4853f5SAndroid Build Coastguard Worker /// dropping it when libavcodec is done with it. 683*1b4853f5SAndroid Build Coastguard Worker pub struct AvBuffer(*mut ffi::AVBufferRef); 684*1b4853f5SAndroid Build Coastguard Worker 685*1b4853f5SAndroid Build Coastguard Worker impl AvBuffer { 686*1b4853f5SAndroid Build Coastguard Worker /// Create a new `AvBuffer` from an `AvBufferSource`. 687*1b4853f5SAndroid Build Coastguard Worker /// 688*1b4853f5SAndroid Build Coastguard Worker /// Ownership of `source` is transferred to libavcodec, which will drop it when the number of 689*1b4853f5SAndroid Build Coastguard Worker /// references to this buffer reaches zero. 690*1b4853f5SAndroid Build Coastguard Worker /// 691*1b4853f5SAndroid Build Coastguard Worker /// Returns `None` if the buffer could not be created due to an error in libavcodec. new<D: AvBufferSource + 'static>(source: D) -> Option<Self>692*1b4853f5SAndroid Build Coastguard Worker pub fn new<D: AvBufferSource + 'static>(source: D) -> Option<Self> { 693*1b4853f5SAndroid Build Coastguard Worker // Move storage to the heap so we find it at the same place in `avbuffer_free` 694*1b4853f5SAndroid Build Coastguard Worker let mut storage = Box::new(source); 695*1b4853f5SAndroid Build Coastguard Worker 696*1b4853f5SAndroid Build Coastguard Worker extern "C" fn avbuffer_free<D>(opaque: *mut c_void, _data: *mut u8) { 697*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 698*1b4853f5SAndroid Build Coastguard Worker // Safe because `opaque` has been created from `Box::into_raw`. `storage` will be 699*1b4853f5SAndroid Build Coastguard Worker // dropped immediately which will release any resources held by the storage. 700*1b4853f5SAndroid Build Coastguard Worker let _ = unsafe { Box::from_raw(opaque as *mut D) }; 701*1b4853f5SAndroid Build Coastguard Worker } 702*1b4853f5SAndroid Build Coastguard Worker 703*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 704*1b4853f5SAndroid Build Coastguard Worker // Safe because storage points to valid data throughout the lifetime of AVBuffer and we are 705*1b4853f5SAndroid Build Coastguard Worker // checking the return value against NULL, which signals an error. 706*1b4853f5SAndroid Build Coastguard Worker Some(Self(unsafe { 707*1b4853f5SAndroid Build Coastguard Worker ffi::av_buffer_create( 708*1b4853f5SAndroid Build Coastguard Worker storage.as_mut_ptr(), 709*1b4853f5SAndroid Build Coastguard Worker storage.len(), 710*1b4853f5SAndroid Build Coastguard Worker Some(avbuffer_free::<D>), 711*1b4853f5SAndroid Build Coastguard Worker Box::into_raw(storage) as *mut c_void, 712*1b4853f5SAndroid Build Coastguard Worker 0, 713*1b4853f5SAndroid Build Coastguard Worker ) 714*1b4853f5SAndroid Build Coastguard Worker .as_mut()? 715*1b4853f5SAndroid Build Coastguard Worker })) 716*1b4853f5SAndroid Build Coastguard Worker } 717*1b4853f5SAndroid Build Coastguard Worker 718*1b4853f5SAndroid Build Coastguard Worker /// Return a slice to the data contained in this buffer. as_mut_slice(&mut self) -> &mut [u8]719*1b4853f5SAndroid Build Coastguard Worker pub fn as_mut_slice(&mut self) -> &mut [u8] { 720*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 721*1b4853f5SAndroid Build Coastguard Worker // Safe because the data has been initialized from valid storage in the constructor. 722*1b4853f5SAndroid Build Coastguard Worker unsafe { std::slice::from_raw_parts_mut((*self.0).data, (*self.0).size) } 723*1b4853f5SAndroid Build Coastguard Worker } 724*1b4853f5SAndroid Build Coastguard Worker 725*1b4853f5SAndroid Build Coastguard Worker /// Consumes the `AVBuffer`, returning a `AVBufferRef` that can be used in `AVFrame`, `AVPacket` 726*1b4853f5SAndroid Build Coastguard Worker /// and others. 727*1b4853f5SAndroid Build Coastguard Worker /// 728*1b4853f5SAndroid Build Coastguard Worker /// After calling, the caller is responsible for unref-ing the returned AVBufferRef, either 729*1b4853f5SAndroid Build Coastguard Worker /// directly or through one of the automatic management facilities in `AVFrame`, `AVPacket` or 730*1b4853f5SAndroid Build Coastguard Worker /// others. into_raw(self) -> *mut ffi::AVBufferRef731*1b4853f5SAndroid Build Coastguard Worker pub fn into_raw(self) -> *mut ffi::AVBufferRef { 732*1b4853f5SAndroid Build Coastguard Worker ManuallyDrop::new(self).0 733*1b4853f5SAndroid Build Coastguard Worker } 734*1b4853f5SAndroid Build Coastguard Worker } 735*1b4853f5SAndroid Build Coastguard Worker 736*1b4853f5SAndroid Build Coastguard Worker impl Drop for AvBuffer { drop(&mut self)737*1b4853f5SAndroid Build Coastguard Worker fn drop(&mut self) { 738*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 739*1b4853f5SAndroid Build Coastguard Worker // Safe because `self.0` is a valid pointer to an AVBufferRef. 740*1b4853f5SAndroid Build Coastguard Worker unsafe { ffi::av_buffer_unref(&mut self.0) }; 741*1b4853f5SAndroid Build Coastguard Worker } 742*1b4853f5SAndroid Build Coastguard Worker } 743*1b4853f5SAndroid Build Coastguard Worker 744*1b4853f5SAndroid Build Coastguard Worker /// An encoded input packet that can be submitted to `AvCodecContext::try_send_packet`. 745*1b4853f5SAndroid Build Coastguard Worker pub struct AvPacket<'a> { 746*1b4853f5SAndroid Build Coastguard Worker packet: ffi::AVPacket, 747*1b4853f5SAndroid Build Coastguard Worker _buffer_data: PhantomData<&'a ()>, 748*1b4853f5SAndroid Build Coastguard Worker } 749*1b4853f5SAndroid Build Coastguard Worker 750*1b4853f5SAndroid Build Coastguard Worker impl<'a> Drop for AvPacket<'a> { drop(&mut self)751*1b4853f5SAndroid Build Coastguard Worker fn drop(&mut self) { 752*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 753*1b4853f5SAndroid Build Coastguard Worker // Safe because `self.packet` is a valid `AVPacket` instance. 754*1b4853f5SAndroid Build Coastguard Worker unsafe { 755*1b4853f5SAndroid Build Coastguard Worker ffi::av_packet_unref(&mut self.packet); 756*1b4853f5SAndroid Build Coastguard Worker } 757*1b4853f5SAndroid Build Coastguard Worker } 758*1b4853f5SAndroid Build Coastguard Worker } 759*1b4853f5SAndroid Build Coastguard Worker 760*1b4853f5SAndroid Build Coastguard Worker impl<'a> AsRef<ffi::AVPacket> for AvPacket<'a> { as_ref(&self) -> &ffi::AVPacket761*1b4853f5SAndroid Build Coastguard Worker fn as_ref(&self) -> &ffi::AVPacket { 762*1b4853f5SAndroid Build Coastguard Worker &self.packet 763*1b4853f5SAndroid Build Coastguard Worker } 764*1b4853f5SAndroid Build Coastguard Worker } 765*1b4853f5SAndroid Build Coastguard Worker 766*1b4853f5SAndroid Build Coastguard Worker impl<'a> AvPacket<'a> { 767*1b4853f5SAndroid Build Coastguard Worker /// Create an empty AvPacket without buffers. 768*1b4853f5SAndroid Build Coastguard Worker /// 769*1b4853f5SAndroid Build Coastguard Worker /// This packet should be only used with an encoder; in which case the encoder will 770*1b4853f5SAndroid Build Coastguard Worker /// automatically allocate a buffer of appropriate size and store it inside this `AvPacket`. empty() -> Self771*1b4853f5SAndroid Build Coastguard Worker pub fn empty() -> Self { 772*1b4853f5SAndroid Build Coastguard Worker Self { 773*1b4853f5SAndroid Build Coastguard Worker packet: ffi::AVPacket { 774*1b4853f5SAndroid Build Coastguard Worker pts: AV_NOPTS_VALUE as i64, 775*1b4853f5SAndroid Build Coastguard Worker dts: AV_NOPTS_VALUE as i64, 776*1b4853f5SAndroid Build Coastguard Worker pos: -1, 777*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 778*1b4853f5SAndroid Build Coastguard Worker // Safe because all the other elements of this struct can be zeroed. 779*1b4853f5SAndroid Build Coastguard Worker ..unsafe { std::mem::zeroed() } 780*1b4853f5SAndroid Build Coastguard Worker }, 781*1b4853f5SAndroid Build Coastguard Worker _buffer_data: PhantomData, 782*1b4853f5SAndroid Build Coastguard Worker } 783*1b4853f5SAndroid Build Coastguard Worker } 784*1b4853f5SAndroid Build Coastguard Worker 785*1b4853f5SAndroid Build Coastguard Worker /// Create a new AvPacket that borrows the `input_data`. 786*1b4853f5SAndroid Build Coastguard Worker /// 787*1b4853f5SAndroid Build Coastguard Worker /// The returned `AvPacket` will hold a reference to `input_data`, meaning that libavcodec might 788*1b4853f5SAndroid Build Coastguard Worker /// perform a copy from/to it. new<T: AvBufferSource>(pts: i64, input_data: &'a mut T) -> Self789*1b4853f5SAndroid Build Coastguard Worker pub fn new<T: AvBufferSource>(pts: i64, input_data: &'a mut T) -> Self { 790*1b4853f5SAndroid Build Coastguard Worker Self { 791*1b4853f5SAndroid Build Coastguard Worker packet: ffi::AVPacket { 792*1b4853f5SAndroid Build Coastguard Worker buf: std::ptr::null_mut(), 793*1b4853f5SAndroid Build Coastguard Worker pts, 794*1b4853f5SAndroid Build Coastguard Worker dts: AV_NOPTS_VALUE as i64, 795*1b4853f5SAndroid Build Coastguard Worker data: input_data.as_mut_ptr(), 796*1b4853f5SAndroid Build Coastguard Worker size: input_data.len() as c_int, 797*1b4853f5SAndroid Build Coastguard Worker side_data: std::ptr::null_mut(), 798*1b4853f5SAndroid Build Coastguard Worker pos: -1, 799*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 800*1b4853f5SAndroid Build Coastguard Worker // Safe because all the other elements of this struct can be zeroed. 801*1b4853f5SAndroid Build Coastguard Worker ..unsafe { std::mem::zeroed() } 802*1b4853f5SAndroid Build Coastguard Worker }, 803*1b4853f5SAndroid Build Coastguard Worker _buffer_data: PhantomData, 804*1b4853f5SAndroid Build Coastguard Worker } 805*1b4853f5SAndroid Build Coastguard Worker } 806*1b4853f5SAndroid Build Coastguard Worker 807*1b4853f5SAndroid Build Coastguard Worker /// Create a new AvPacket that owns the `av_buffer`. 808*1b4853f5SAndroid Build Coastguard Worker /// 809*1b4853f5SAndroid Build Coastguard Worker /// The returned `AvPacket` will have a `'static` lifetime and will keep `input_data` alive for 810*1b4853f5SAndroid Build Coastguard Worker /// as long as libavcodec needs it. new_owned(pts: i64, mut av_buffer: AvBuffer) -> Self811*1b4853f5SAndroid Build Coastguard Worker pub fn new_owned(pts: i64, mut av_buffer: AvBuffer) -> Self { 812*1b4853f5SAndroid Build Coastguard Worker let data_slice = av_buffer.as_mut_slice(); 813*1b4853f5SAndroid Build Coastguard Worker let data = data_slice.as_mut_ptr(); 814*1b4853f5SAndroid Build Coastguard Worker let size = data_slice.len() as i32; 815*1b4853f5SAndroid Build Coastguard Worker 816*1b4853f5SAndroid Build Coastguard Worker Self { 817*1b4853f5SAndroid Build Coastguard Worker packet: ffi::AVPacket { 818*1b4853f5SAndroid Build Coastguard Worker buf: av_buffer.into_raw(), 819*1b4853f5SAndroid Build Coastguard Worker pts, 820*1b4853f5SAndroid Build Coastguard Worker dts: AV_NOPTS_VALUE as i64, 821*1b4853f5SAndroid Build Coastguard Worker data, 822*1b4853f5SAndroid Build Coastguard Worker size, 823*1b4853f5SAndroid Build Coastguard Worker side_data: std::ptr::null_mut(), 824*1b4853f5SAndroid Build Coastguard Worker pos: -1, 825*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 826*1b4853f5SAndroid Build Coastguard Worker // Safe because all the other elements of this struct can be zeroed. 827*1b4853f5SAndroid Build Coastguard Worker ..unsafe { std::mem::zeroed() } 828*1b4853f5SAndroid Build Coastguard Worker }, 829*1b4853f5SAndroid Build Coastguard Worker _buffer_data: PhantomData, 830*1b4853f5SAndroid Build Coastguard Worker } 831*1b4853f5SAndroid Build Coastguard Worker } 832*1b4853f5SAndroid Build Coastguard Worker } 833*1b4853f5SAndroid Build Coastguard Worker 834*1b4853f5SAndroid Build Coastguard Worker /// An owned AVFrame, i.e. one decoded frame from libavcodec that can be converted into a 835*1b4853f5SAndroid Build Coastguard Worker /// destination buffer. 836*1b4853f5SAndroid Build Coastguard Worker pub struct AvFrame(*mut ffi::AVFrame); 837*1b4853f5SAndroid Build Coastguard Worker 838*1b4853f5SAndroid Build Coastguard Worker /// A builder for AVFrame that allows specifying buffers and image metadata. 839*1b4853f5SAndroid Build Coastguard Worker pub struct AvFrameBuilder(AvFrame); 840*1b4853f5SAndroid Build Coastguard Worker 841*1b4853f5SAndroid Build Coastguard Worker /// A descriptor describing a subslice of `buffers` in [`AvFrameBuilder::build_owned`] that 842*1b4853f5SAndroid Build Coastguard Worker /// represents a plane's image data. 843*1b4853f5SAndroid Build Coastguard Worker #[derive(Debug, Clone)] 844*1b4853f5SAndroid Build Coastguard Worker pub struct PlaneDescriptor { 845*1b4853f5SAndroid Build Coastguard Worker /// The index within `buffers`. 846*1b4853f5SAndroid Build Coastguard Worker pub buffer_index: usize, 847*1b4853f5SAndroid Build Coastguard Worker /// The offset from the start of `buffers[buffer_index]`. 848*1b4853f5SAndroid Build Coastguard Worker pub offset: usize, 849*1b4853f5SAndroid Build Coastguard Worker /// The increment of data pointer in bytes per row of the plane. 850*1b4853f5SAndroid Build Coastguard Worker pub stride: usize, 851*1b4853f5SAndroid Build Coastguard Worker } 852*1b4853f5SAndroid Build Coastguard Worker 853*1b4853f5SAndroid Build Coastguard Worker #[derive(Debug, ThisError)] 854*1b4853f5SAndroid Build Coastguard Worker pub enum AvFrameError { 855*1b4853f5SAndroid Build Coastguard Worker #[error("failed to allocate AVFrame object")] 856*1b4853f5SAndroid Build Coastguard Worker FrameAllocationFailed, 857*1b4853f5SAndroid Build Coastguard Worker #[error("dimension is negative or too large")] 858*1b4853f5SAndroid Build Coastguard Worker DimensionOverflow, 859*1b4853f5SAndroid Build Coastguard Worker #[error("a row does not fit in the specified stride")] 860*1b4853f5SAndroid Build Coastguard Worker InvalidStride, 861*1b4853f5SAndroid Build Coastguard Worker #[error("buffer index out of range")] 862*1b4853f5SAndroid Build Coastguard Worker BufferOutOfRange, 863*1b4853f5SAndroid Build Coastguard Worker #[error("specified dimensions overflow the buffer size")] 864*1b4853f5SAndroid Build Coastguard Worker BufferTooSmall, 865*1b4853f5SAndroid Build Coastguard Worker #[error("plane reference to buffer alias each other")] 866*1b4853f5SAndroid Build Coastguard Worker BufferAlias, 867*1b4853f5SAndroid Build Coastguard Worker #[error("error while calling libavcodec")] 868*1b4853f5SAndroid Build Coastguard Worker AvError(#[from] AvError), 869*1b4853f5SAndroid Build Coastguard Worker } 870*1b4853f5SAndroid Build Coastguard Worker 871*1b4853f5SAndroid Build Coastguard Worker impl AvFrame { 872*1b4853f5SAndroid Build Coastguard Worker /// Create a new AvFrame. The frame's parameters and backing memory will be assigned when it is 873*1b4853f5SAndroid Build Coastguard Worker /// decoded into. new() -> Result<Self, AvFrameError>874*1b4853f5SAndroid Build Coastguard Worker pub fn new() -> Result<Self, AvFrameError> { 875*1b4853f5SAndroid Build Coastguard Worker Ok(Self( 876*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 877*1b4853f5SAndroid Build Coastguard Worker // Safe because `av_frame_alloc` does not take any input. 878*1b4853f5SAndroid Build Coastguard Worker unsafe { ffi::av_frame_alloc().as_mut() }.ok_or(AvFrameError::FrameAllocationFailed)?, 879*1b4853f5SAndroid Build Coastguard Worker )) 880*1b4853f5SAndroid Build Coastguard Worker } 881*1b4853f5SAndroid Build Coastguard Worker 882*1b4853f5SAndroid Build Coastguard Worker /// Create a new AvFrame builder that allows setting the frame's parameters and backing memory 883*1b4853f5SAndroid Build Coastguard Worker /// through its methods. builder() -> Result<AvFrameBuilder, AvFrameError>884*1b4853f5SAndroid Build Coastguard Worker pub fn builder() -> Result<AvFrameBuilder, AvFrameError> { 885*1b4853f5SAndroid Build Coastguard Worker AvFrame::new().map(AvFrameBuilder) 886*1b4853f5SAndroid Build Coastguard Worker } 887*1b4853f5SAndroid Build Coastguard Worker 888*1b4853f5SAndroid Build Coastguard Worker /// Return the frame's width and height. dimensions(&self) -> Dimensions889*1b4853f5SAndroid Build Coastguard Worker pub fn dimensions(&self) -> Dimensions { 890*1b4853f5SAndroid Build Coastguard Worker Dimensions { 891*1b4853f5SAndroid Build Coastguard Worker width: self.as_ref().width as _, 892*1b4853f5SAndroid Build Coastguard Worker height: self.as_ref().height as _, 893*1b4853f5SAndroid Build Coastguard Worker } 894*1b4853f5SAndroid Build Coastguard Worker } 895*1b4853f5SAndroid Build Coastguard Worker 896*1b4853f5SAndroid Build Coastguard Worker /// Return the frame's pixel format. format(&self) -> AvPixelFormat897*1b4853f5SAndroid Build Coastguard Worker pub fn format(&self) -> AvPixelFormat { 898*1b4853f5SAndroid Build Coastguard Worker AvPixelFormat(self.as_ref().format) 899*1b4853f5SAndroid Build Coastguard Worker } 900*1b4853f5SAndroid Build Coastguard Worker 901*1b4853f5SAndroid Build Coastguard Worker /// Set the picture type (I-frame, P-frame etc.) on this frame. set_pict_type(&mut self, ty: AVPictureType)902*1b4853f5SAndroid Build Coastguard Worker pub fn set_pict_type(&mut self, ty: AVPictureType) { 903*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 904*1b4853f5SAndroid Build Coastguard Worker // Safe because self.0 is a valid AVFrame reference. 905*1b4853f5SAndroid Build Coastguard Worker unsafe { 906*1b4853f5SAndroid Build Coastguard Worker (*self.0).pict_type = ty; 907*1b4853f5SAndroid Build Coastguard Worker } 908*1b4853f5SAndroid Build Coastguard Worker } 909*1b4853f5SAndroid Build Coastguard Worker 910*1b4853f5SAndroid Build Coastguard Worker /// Set the presentation timestamp (PTS) of this frame. set_pts(&mut self, ts: i64)911*1b4853f5SAndroid Build Coastguard Worker pub fn set_pts(&mut self, ts: i64) { 912*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 913*1b4853f5SAndroid Build Coastguard Worker // Safe because self.0 is a valid AVFrame reference. 914*1b4853f5SAndroid Build Coastguard Worker unsafe { 915*1b4853f5SAndroid Build Coastguard Worker (*self.0).pts = ts; 916*1b4853f5SAndroid Build Coastguard Worker } 917*1b4853f5SAndroid Build Coastguard Worker } 918*1b4853f5SAndroid Build Coastguard Worker 919*1b4853f5SAndroid Build Coastguard Worker /// Query if this AvFrame is writable, i.e. it is refcounted and the refcounts are 1. is_writable(&self) -> bool920*1b4853f5SAndroid Build Coastguard Worker pub fn is_writable(&self) -> bool { 921*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 922*1b4853f5SAndroid Build Coastguard Worker // Safe because self.0 is a valid AVFrame reference. 923*1b4853f5SAndroid Build Coastguard Worker unsafe { ffi::av_frame_is_writable(self.0) != 0 } 924*1b4853f5SAndroid Build Coastguard Worker } 925*1b4853f5SAndroid Build Coastguard Worker 926*1b4853f5SAndroid Build Coastguard Worker /// If the frame is not writable already (see [`is_writable`]), make a copy of its buffer to 927*1b4853f5SAndroid Build Coastguard Worker /// make it writable. 928*1b4853f5SAndroid Build Coastguard Worker /// 929*1b4853f5SAndroid Build Coastguard Worker /// [`is_writable`]: AvFrame::is_writable make_writable(&mut self) -> Result<(), AvFrameError>930*1b4853f5SAndroid Build Coastguard Worker pub fn make_writable(&mut self) -> Result<(), AvFrameError> { 931*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 932*1b4853f5SAndroid Build Coastguard Worker // Safe because self.0 is a valid AVFrame reference. 933*1b4853f5SAndroid Build Coastguard Worker AvError::result(unsafe { ffi::av_frame_make_writable(self.0) }).map_err(Into::into) 934*1b4853f5SAndroid Build Coastguard Worker } 935*1b4853f5SAndroid Build Coastguard Worker } 936*1b4853f5SAndroid Build Coastguard Worker 937*1b4853f5SAndroid Build Coastguard Worker impl AvFrameBuilder { 938*1b4853f5SAndroid Build Coastguard Worker /// Set the frame's width and height. 939*1b4853f5SAndroid Build Coastguard Worker /// 940*1b4853f5SAndroid Build Coastguard Worker /// The dimensions must not be greater than `i32::MAX`. set_dimensions(&mut self, dimensions: Dimensions) -> Result<(), AvFrameError>941*1b4853f5SAndroid Build Coastguard Worker pub fn set_dimensions(&mut self, dimensions: Dimensions) -> Result<(), AvFrameError> { 942*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 943*1b4853f5SAndroid Build Coastguard Worker // Safe because self.0 is a valid AVFrame instance and width and height are in range. 944*1b4853f5SAndroid Build Coastguard Worker unsafe { 945*1b4853f5SAndroid Build Coastguard Worker (*self.0 .0).width = dimensions 946*1b4853f5SAndroid Build Coastguard Worker .width 947*1b4853f5SAndroid Build Coastguard Worker .try_into() 948*1b4853f5SAndroid Build Coastguard Worker .map_err(|_| AvFrameError::DimensionOverflow)?; 949*1b4853f5SAndroid Build Coastguard Worker (*self.0 .0).height = dimensions 950*1b4853f5SAndroid Build Coastguard Worker .height 951*1b4853f5SAndroid Build Coastguard Worker .try_into() 952*1b4853f5SAndroid Build Coastguard Worker .map_err(|_| AvFrameError::DimensionOverflow)?; 953*1b4853f5SAndroid Build Coastguard Worker } 954*1b4853f5SAndroid Build Coastguard Worker Ok(()) 955*1b4853f5SAndroid Build Coastguard Worker } 956*1b4853f5SAndroid Build Coastguard Worker 957*1b4853f5SAndroid Build Coastguard Worker /// Set the frame's format. set_format(&mut self, format: AvPixelFormat) -> Result<(), AvFrameError>958*1b4853f5SAndroid Build Coastguard Worker pub fn set_format(&mut self, format: AvPixelFormat) -> Result<(), AvFrameError> { 959*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 960*1b4853f5SAndroid Build Coastguard Worker // Safe because self.0 is a valid AVFrame instance and format is a valid pixel format. 961*1b4853f5SAndroid Build Coastguard Worker unsafe { 962*1b4853f5SAndroid Build Coastguard Worker (*self.0 .0).format = format.pix_fmt(); 963*1b4853f5SAndroid Build Coastguard Worker } 964*1b4853f5SAndroid Build Coastguard Worker Ok(()) 965*1b4853f5SAndroid Build Coastguard Worker } 966*1b4853f5SAndroid Build Coastguard Worker 967*1b4853f5SAndroid Build Coastguard Worker /// Build an AvFrame from iterators of [`AvBuffer`]s and subslice of buffers describing the 968*1b4853f5SAndroid Build Coastguard Worker /// planes. 969*1b4853f5SAndroid Build Coastguard Worker /// 970*1b4853f5SAndroid Build Coastguard Worker /// The frame will own the `buffers`. 971*1b4853f5SAndroid Build Coastguard Worker /// 972*1b4853f5SAndroid Build Coastguard Worker /// This function checks that: 973*1b4853f5SAndroid Build Coastguard Worker /// - Each plane fits inside the bounds of the associated buffer. 974*1b4853f5SAndroid Build Coastguard Worker /// - Different planes do not overlap each other's buffer slice. In this check, all planes are 975*1b4853f5SAndroid Build Coastguard Worker /// assumed to be potentially mutable, regardless of whether the AvFrame is actually used for 976*1b4853f5SAndroid Build Coastguard Worker /// read or write access. Aliasing reference to the same buffer will be rejected, since it can 977*1b4853f5SAndroid Build Coastguard Worker /// potentially allow routines to overwrite each 978*1b4853f5SAndroid Build Coastguard Worker // other's result. 979*1b4853f5SAndroid Build Coastguard Worker /// An exception to this is when the same buffer is passed multiple times in `buffers`. In 980*1b4853f5SAndroid Build Coastguard Worker /// this case, each buffer is treated as a different buffer. Since clones have to be made to 981*1b4853f5SAndroid Build Coastguard Worker /// be passed multiple times in `buffers`, the frame will not be considered [writable]. Hence 982*1b4853f5SAndroid Build Coastguard Worker /// aliasing is safe in this case, but the caller is required to explicit opt-in to this 983*1b4853f5SAndroid Build Coastguard Worker /// read-only handling by passing clones of the buffer into `buffers` and have a different 984*1b4853f5SAndroid Build Coastguard Worker /// buffer index for each plane combination that could overlap in their range. 985*1b4853f5SAndroid Build Coastguard Worker /// 986*1b4853f5SAndroid Build Coastguard Worker /// [writable]: AvFrame::is_writable build_owned< BI: IntoIterator<Item = AvBuffer>, PI: IntoIterator<Item = PlaneDescriptor>, >( self, buffers: BI, planes: PI, ) -> Result<AvFrame, AvFrameError>987*1b4853f5SAndroid Build Coastguard Worker pub fn build_owned< 988*1b4853f5SAndroid Build Coastguard Worker BI: IntoIterator<Item = AvBuffer>, 989*1b4853f5SAndroid Build Coastguard Worker PI: IntoIterator<Item = PlaneDescriptor>, 990*1b4853f5SAndroid Build Coastguard Worker >( 991*1b4853f5SAndroid Build Coastguard Worker self, 992*1b4853f5SAndroid Build Coastguard Worker buffers: BI, 993*1b4853f5SAndroid Build Coastguard Worker planes: PI, 994*1b4853f5SAndroid Build Coastguard Worker ) -> Result<AvFrame, AvFrameError> { 995*1b4853f5SAndroid Build Coastguard Worker let mut buffers: Vec<_> = buffers.into_iter().collect(); 996*1b4853f5SAndroid Build Coastguard Worker let planes: Vec<_> = planes.into_iter().collect(); 997*1b4853f5SAndroid Build Coastguard Worker let format = self.0.format(); 998*1b4853f5SAndroid Build Coastguard Worker let plane_sizes = format.plane_sizes( 999*1b4853f5SAndroid Build Coastguard Worker planes.iter().map(|x| x.stride as u32), 1000*1b4853f5SAndroid Build Coastguard Worker self.0.dimensions().height, 1001*1b4853f5SAndroid Build Coastguard Worker ); 1002*1b4853f5SAndroid Build Coastguard Worker let mut ranges = vec![]; 1003*1b4853f5SAndroid Build Coastguard Worker 1004*1b4853f5SAndroid Build Coastguard Worker for ( 1005*1b4853f5SAndroid Build Coastguard Worker plane, 1006*1b4853f5SAndroid Build Coastguard Worker PlaneDescriptor { 1007*1b4853f5SAndroid Build Coastguard Worker buffer_index, 1008*1b4853f5SAndroid Build Coastguard Worker offset, 1009*1b4853f5SAndroid Build Coastguard Worker stride, 1010*1b4853f5SAndroid Build Coastguard Worker }, 1011*1b4853f5SAndroid Build Coastguard Worker ) in planes.into_iter().enumerate() 1012*1b4853f5SAndroid Build Coastguard Worker { 1013*1b4853f5SAndroid Build Coastguard Worker if buffer_index > buffers.len() { 1014*1b4853f5SAndroid Build Coastguard Worker return Err(AvFrameError::BufferOutOfRange); 1015*1b4853f5SAndroid Build Coastguard Worker } 1016*1b4853f5SAndroid Build Coastguard Worker let end = offset + plane_sizes[plane]; 1017*1b4853f5SAndroid Build Coastguard Worker if end > buffers[buffer_index].as_mut_slice().len() { 1018*1b4853f5SAndroid Build Coastguard Worker return Err(AvFrameError::BufferTooSmall); 1019*1b4853f5SAndroid Build Coastguard Worker } 1020*1b4853f5SAndroid Build Coastguard Worker if stride < format.line_size(self.0.dimensions().width, plane) { 1021*1b4853f5SAndroid Build Coastguard Worker return Err(AvFrameError::InvalidStride); 1022*1b4853f5SAndroid Build Coastguard Worker } 1023*1b4853f5SAndroid Build Coastguard Worker // TODO(b:315859322): add safety doc string 1024*1b4853f5SAndroid Build Coastguard Worker #[allow(clippy::undocumented_unsafe_blocks)] 1025*1b4853f5SAndroid Build Coastguard Worker unsafe { 1026*1b4853f5SAndroid Build Coastguard Worker (*self.0 .0).data[plane] = 1027*1b4853f5SAndroid Build Coastguard Worker buffers[buffer_index].as_mut_slice()[offset..].as_mut_ptr(); 1028*1b4853f5SAndroid Build Coastguard Worker (*self.0 .0).linesize[plane] = stride as c_int; 1029*1b4853f5SAndroid Build Coastguard Worker } 1030*1b4853f5SAndroid Build Coastguard Worker ranges.push((buffer_index, offset, end)); 1031*1b4853f5SAndroid Build Coastguard Worker } 1032*1b4853f5SAndroid Build Coastguard Worker 1033*1b4853f5SAndroid Build Coastguard Worker // Check for range overlaps. 1034*1b4853f5SAndroid Build Coastguard Worker // See function documentation for the exact rule and reasoning. 1035*1b4853f5SAndroid Build Coastguard Worker ranges.sort_unstable(); 1036*1b4853f5SAndroid Build Coastguard Worker for pair in ranges.windows(2) { 1037*1b4853f5SAndroid Build Coastguard Worker // (buffer_index, start, end) 1038*1b4853f5SAndroid Build Coastguard Worker let (b0, _s0, e0) = pair[0]; 1039*1b4853f5SAndroid Build Coastguard Worker let (b1, s1, _e1) = pair[1]; 1040*1b4853f5SAndroid Build Coastguard Worker 1041*1b4853f5SAndroid Build Coastguard Worker if b0 != b1 { 1042*1b4853f5SAndroid Build Coastguard Worker continue; 1043*1b4853f5SAndroid Build Coastguard Worker } 1044*1b4853f5SAndroid Build Coastguard Worker // Note that s0 <= s1 always holds, so we only need to check 1045*1b4853f5SAndroid Build Coastguard Worker // that the start of the second range is before the end of the first range. 1046*1b4853f5SAndroid Build Coastguard Worker if s1 < e0 { 1047*1b4853f5SAndroid Build Coastguard Worker return Err(AvFrameError::BufferAlias); 1048*1b4853f5SAndroid Build Coastguard Worker } 1049*1b4853f5SAndroid Build Coastguard Worker } 1050*1b4853f5SAndroid Build Coastguard Worker 1051*1b4853f5SAndroid Build Coastguard Worker for (i, buf) in buffers.into_iter().enumerate() { 1052*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 1053*1b4853f5SAndroid Build Coastguard Worker // Safe because self.0 is a valid AVFrame instance and buffers contains valid AvBuffers. 1054*1b4853f5SAndroid Build Coastguard Worker unsafe { 1055*1b4853f5SAndroid Build Coastguard Worker (*self.0 .0).buf[i] = buf.into_raw(); 1056*1b4853f5SAndroid Build Coastguard Worker } 1057*1b4853f5SAndroid Build Coastguard Worker } 1058*1b4853f5SAndroid Build Coastguard Worker Ok(self.0) 1059*1b4853f5SAndroid Build Coastguard Worker } 1060*1b4853f5SAndroid Build Coastguard Worker } 1061*1b4853f5SAndroid Build Coastguard Worker 1062*1b4853f5SAndroid Build Coastguard Worker impl AsRef<ffi::AVFrame> for AvFrame { as_ref(&self) -> &ffi::AVFrame1063*1b4853f5SAndroid Build Coastguard Worker fn as_ref(&self) -> &ffi::AVFrame { 1064*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 1065*1b4853f5SAndroid Build Coastguard Worker // Safe because the AVFrame has been properly initialized during construction. 1066*1b4853f5SAndroid Build Coastguard Worker unsafe { &*self.0 } 1067*1b4853f5SAndroid Build Coastguard Worker } 1068*1b4853f5SAndroid Build Coastguard Worker } 1069*1b4853f5SAndroid Build Coastguard Worker 1070*1b4853f5SAndroid Build Coastguard Worker impl Deref for AvFrame { 1071*1b4853f5SAndroid Build Coastguard Worker type Target = ffi::AVFrame; 1072*1b4853f5SAndroid Build Coastguard Worker deref(&self) -> &Self::Target1073*1b4853f5SAndroid Build Coastguard Worker fn deref(&self) -> &Self::Target { 1074*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 1075*1b4853f5SAndroid Build Coastguard Worker // Safe because the AVFrame has been properly initialized during construction. 1076*1b4853f5SAndroid Build Coastguard Worker unsafe { self.0.as_ref().unwrap() } 1077*1b4853f5SAndroid Build Coastguard Worker } 1078*1b4853f5SAndroid Build Coastguard Worker } 1079*1b4853f5SAndroid Build Coastguard Worker 1080*1b4853f5SAndroid Build Coastguard Worker impl Drop for AvFrame { drop(&mut self)1081*1b4853f5SAndroid Build Coastguard Worker fn drop(&mut self) { 1082*1b4853f5SAndroid Build Coastguard Worker // SAFETY: 1083*1b4853f5SAndroid Build Coastguard Worker // Safe because the AVFrame is valid through the life of this object and fully owned by us. 1084*1b4853f5SAndroid Build Coastguard Worker unsafe { ffi::av_frame_free(&mut self.0) }; 1085*1b4853f5SAndroid Build Coastguard Worker } 1086*1b4853f5SAndroid Build Coastguard Worker } 1087*1b4853f5SAndroid Build Coastguard Worker 1088*1b4853f5SAndroid Build Coastguard Worker #[cfg(test)] 1089*1b4853f5SAndroid Build Coastguard Worker mod tests { 1090*1b4853f5SAndroid Build Coastguard Worker use std::sync::atomic::AtomicBool; 1091*1b4853f5SAndroid Build Coastguard Worker use std::sync::atomic::Ordering; 1092*1b4853f5SAndroid Build Coastguard Worker use std::sync::Arc; 1093*1b4853f5SAndroid Build Coastguard Worker 1094*1b4853f5SAndroid Build Coastguard Worker use super::*; 1095*1b4853f5SAndroid Build Coastguard Worker 1096*1b4853f5SAndroid Build Coastguard Worker #[test] test_averror()1097*1b4853f5SAndroid Build Coastguard Worker fn test_averror() { 1098*1b4853f5SAndroid Build Coastguard Worker // Just test that the error is wrapper properly. The bindings test module already checks 1099*1b4853f5SAndroid Build Coastguard Worker // that the error bindings correspond to the right ffmpeg errors. 1100*1b4853f5SAndroid Build Coastguard Worker let averror = AvError(AVERROR_EOF); 1101*1b4853f5SAndroid Build Coastguard Worker let msg = format!("{}", averror); 1102*1b4853f5SAndroid Build Coastguard Worker assert_eq!(msg, "End of file"); 1103*1b4853f5SAndroid Build Coastguard Worker 1104*1b4853f5SAndroid Build Coastguard Worker let averror = AvError(0); 1105*1b4853f5SAndroid Build Coastguard Worker let msg = format!("{}", averror); 1106*1b4853f5SAndroid Build Coastguard Worker assert_eq!(msg, "Success"); 1107*1b4853f5SAndroid Build Coastguard Worker 1108*1b4853f5SAndroid Build Coastguard Worker let averror = AvError(10); 1109*1b4853f5SAndroid Build Coastguard Worker let msg = format!("{}", averror); 1110*1b4853f5SAndroid Build Coastguard Worker assert_eq!(msg, "Unknown avcodec error 10"); 1111*1b4853f5SAndroid Build Coastguard Worker } 1112*1b4853f5SAndroid Build Coastguard Worker 1113*1b4853f5SAndroid Build Coastguard Worker // Test that the AVPacket wrapper frees the owned AVBuffer on drop. 1114*1b4853f5SAndroid Build Coastguard Worker #[test] test_avpacket_drop()1115*1b4853f5SAndroid Build Coastguard Worker fn test_avpacket_drop() { 1116*1b4853f5SAndroid Build Coastguard Worker struct DropTestBufferSource { 1117*1b4853f5SAndroid Build Coastguard Worker dropped: Arc<AtomicBool>, 1118*1b4853f5SAndroid Build Coastguard Worker } 1119*1b4853f5SAndroid Build Coastguard Worker impl Drop for DropTestBufferSource { 1120*1b4853f5SAndroid Build Coastguard Worker fn drop(&mut self) { 1121*1b4853f5SAndroid Build Coastguard Worker self.dropped.store(true, Ordering::SeqCst); 1122*1b4853f5SAndroid Build Coastguard Worker } 1123*1b4853f5SAndroid Build Coastguard Worker } 1124*1b4853f5SAndroid Build Coastguard Worker impl AvBufferSource for DropTestBufferSource { 1125*1b4853f5SAndroid Build Coastguard Worker fn as_ptr(&self) -> *const u8 { 1126*1b4853f5SAndroid Build Coastguard Worker self as *const _ as *const u8 1127*1b4853f5SAndroid Build Coastguard Worker } 1128*1b4853f5SAndroid Build Coastguard Worker 1129*1b4853f5SAndroid Build Coastguard Worker fn as_mut_ptr(&mut self) -> *mut u8 { 1130*1b4853f5SAndroid Build Coastguard Worker self as *mut _ as *mut u8 1131*1b4853f5SAndroid Build Coastguard Worker } 1132*1b4853f5SAndroid Build Coastguard Worker 1133*1b4853f5SAndroid Build Coastguard Worker fn len(&self) -> usize { 1134*1b4853f5SAndroid Build Coastguard Worker 0 1135*1b4853f5SAndroid Build Coastguard Worker } 1136*1b4853f5SAndroid Build Coastguard Worker } 1137*1b4853f5SAndroid Build Coastguard Worker 1138*1b4853f5SAndroid Build Coastguard Worker let dropped = Arc::new(AtomicBool::new(false)); 1139*1b4853f5SAndroid Build Coastguard Worker 1140*1b4853f5SAndroid Build Coastguard Worker let pkt = AvPacket::new_owned( 1141*1b4853f5SAndroid Build Coastguard Worker 0, 1142*1b4853f5SAndroid Build Coastguard Worker AvBuffer::new(DropTestBufferSource { 1143*1b4853f5SAndroid Build Coastguard Worker dropped: dropped.clone(), 1144*1b4853f5SAndroid Build Coastguard Worker }) 1145*1b4853f5SAndroid Build Coastguard Worker .unwrap(), 1146*1b4853f5SAndroid Build Coastguard Worker ); 1147*1b4853f5SAndroid Build Coastguard Worker assert!(!dropped.load(Ordering::SeqCst)); 1148*1b4853f5SAndroid Build Coastguard Worker drop(pkt); 1149*1b4853f5SAndroid Build Coastguard Worker assert!(dropped.load(Ordering::SeqCst)); 1150*1b4853f5SAndroid Build Coastguard Worker } 1151*1b4853f5SAndroid Build Coastguard Worker } 1152