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