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