xref: /aosp_15_r20/external/crosvm/media/ffmpeg/src/avutil.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use crate::avcodec::AvError;
6*bb4ee6a4SAndroid Build Coastguard Worker use crate::avcodec::AvPixelFormat;
7*bb4ee6a4SAndroid Build Coastguard Worker use crate::ffi;
8*bb4ee6a4SAndroid Build Coastguard Worker 
9*bb4ee6a4SAndroid Build Coastguard Worker pub const AV_NOPTS_VALUE: u64 = 0x8000000000000000;
10*bb4ee6a4SAndroid Build Coastguard Worker const MAX_FFMPEG_PLANES: usize = 4;
11*bb4ee6a4SAndroid Build Coastguard Worker 
12*bb4ee6a4SAndroid Build Coastguard Worker /// Get the maximum data alignment that may be required by FFmpeg.
13*bb4ee6a4SAndroid Build Coastguard Worker /// This could change depending on FFmpeg's build configuration (AVX etc.).
max_buffer_alignment() -> usize14*bb4ee6a4SAndroid Build Coastguard Worker pub fn max_buffer_alignment() -> usize {
15*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY:
16*bb4ee6a4SAndroid Build Coastguard Worker     // Safe because this function has no side effects and just returns an integer.
17*bb4ee6a4SAndroid Build Coastguard Worker     unsafe { ffi::av_cpu_max_align() }
18*bb4ee6a4SAndroid Build Coastguard Worker }
19*bb4ee6a4SAndroid Build Coastguard Worker 
20*bb4ee6a4SAndroid Build Coastguard Worker // See AvPixelFormat::line_size.
av_image_line_size( format: AvPixelFormat, width: u32, plane: usize, ) -> Result<usize, AvError>21*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) fn av_image_line_size(
22*bb4ee6a4SAndroid Build Coastguard Worker     format: AvPixelFormat,
23*bb4ee6a4SAndroid Build Coastguard Worker     width: u32,
24*bb4ee6a4SAndroid Build Coastguard Worker     plane: usize,
25*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<usize, AvError> {
26*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY:
27*bb4ee6a4SAndroid Build Coastguard Worker     // Safe because format is a valid format and this function is pure computation.
28*bb4ee6a4SAndroid Build Coastguard Worker     match unsafe { ffi::av_image_get_linesize(format.pix_fmt(), width as _, plane as _) } {
29*bb4ee6a4SAndroid Build Coastguard Worker         i if i >= 0 => Ok(i as _),
30*bb4ee6a4SAndroid Build Coastguard Worker         err => Err(AvError(err)),
31*bb4ee6a4SAndroid Build Coastguard Worker     }
32*bb4ee6a4SAndroid Build Coastguard Worker }
33*bb4ee6a4SAndroid Build Coastguard Worker 
34*bb4ee6a4SAndroid Build Coastguard Worker // See AvPixelFormat::plane_sizes.
av_image_plane_sizes<I: IntoIterator<Item = u32>>( format: AvPixelFormat, linesizes: I, height: u32, ) -> Result<Vec<usize>, AvError>35*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) fn av_image_plane_sizes<I: IntoIterator<Item = u32>>(
36*bb4ee6a4SAndroid Build Coastguard Worker     format: AvPixelFormat,
37*bb4ee6a4SAndroid Build Coastguard Worker     linesizes: I,
38*bb4ee6a4SAndroid Build Coastguard Worker     height: u32,
39*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Vec<usize>, AvError> {
40*bb4ee6a4SAndroid Build Coastguard Worker     let mut linesizes_buf = [0; MAX_FFMPEG_PLANES];
41*bb4ee6a4SAndroid Build Coastguard Worker     let mut planes = 0;
42*bb4ee6a4SAndroid Build Coastguard Worker     for (i, linesize) in linesizes.into_iter().take(MAX_FFMPEG_PLANES).enumerate() {
43*bb4ee6a4SAndroid Build Coastguard Worker         linesizes_buf[i] = linesize as _;
44*bb4ee6a4SAndroid Build Coastguard Worker         planes += 1;
45*bb4ee6a4SAndroid Build Coastguard Worker     }
46*bb4ee6a4SAndroid Build Coastguard Worker     let mut plane_sizes_buf = [0; MAX_FFMPEG_PLANES];
47*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY:
48*bb4ee6a4SAndroid Build Coastguard Worker     // Safe because plane_sizes_buf and linesizes_buf have the size specified by the API, format is
49*bb4ee6a4SAndroid Build Coastguard Worker     // valid, and this function doesn't have any side effects other than writing to plane_sizes_buf.
50*bb4ee6a4SAndroid Build Coastguard Worker     AvError::result(unsafe {
51*bb4ee6a4SAndroid Build Coastguard Worker         ffi::av_image_fill_plane_sizes(
52*bb4ee6a4SAndroid Build Coastguard Worker             plane_sizes_buf.as_mut_ptr(),
53*bb4ee6a4SAndroid Build Coastguard Worker             format.pix_fmt(),
54*bb4ee6a4SAndroid Build Coastguard Worker             height as _,
55*bb4ee6a4SAndroid Build Coastguard Worker             linesizes_buf.as_ptr(),
56*bb4ee6a4SAndroid Build Coastguard Worker         )
57*bb4ee6a4SAndroid Build Coastguard Worker     })?;
58*bb4ee6a4SAndroid Build Coastguard Worker     Ok(plane_sizes_buf
59*bb4ee6a4SAndroid Build Coastguard Worker         .into_iter()
60*bb4ee6a4SAndroid Build Coastguard Worker         .map(|x| x as _)
61*bb4ee6a4SAndroid Build Coastguard Worker         .take(planes)
62*bb4ee6a4SAndroid Build Coastguard Worker         .collect())
63*bb4ee6a4SAndroid Build Coastguard Worker }
64