use crate::{avutil::AVPixelFormat, ffi, shared::*};
use std::{ptr, slice};
const AV_NUM_DATA_POINTERS: usize = ffi::AV_NUM_DATA_POINTERS as usize;
pub struct AVImage {
data: [*mut u8; AV_NUM_DATA_POINTERS],
linesizes: [i32; AV_NUM_DATA_POINTERS],
linear: *mut u8,
linear_length: usize,
linear_capacity: usize,
}
impl AVImage {
pub fn new(pix_fmt: AVPixelFormat, width: i32, height: i32, align: i32) -> Option<Self> {
let num_of_bytes = Self::get_buffer_size(pix_fmt, width, height, align)?;
let mut data = [ptr::null_mut(); AV_NUM_DATA_POINTERS];
let mut linesizes = [0; AV_NUM_DATA_POINTERS];
let mut linear = vec![0u8; num_of_bytes as usize];
match unsafe {
ffi::av_image_fill_arrays(
data.as_mut_ptr(),
linesizes.as_mut_ptr(),
linear.as_mut_ptr(),
pix_fmt,
width,
height,
align,
)
}
.upgrade()
{
Ok(_) => {}
Err(AVERROR_ENOMEM) => panic!(),
Err(_) => return None,
}
let linear_length = linear.len();
let linear_capacity = linear.capacity();
let linear = Vec::leak(linear).as_mut_ptr();
Some(Self {
data,
linesizes,
linear,
linear_length,
linear_capacity,
})
}
pub fn get_buffer_size(fmt: AVPixelFormat, width: i32, height: i32, align: i32) -> Option<i32> {
unsafe { ffi::av_image_get_buffer_size(fmt, width, height, align) }
.upgrade()
.ok()
}
pub fn data(&self) -> &[*mut u8; AV_NUM_DATA_POINTERS] {
&self.data
}
pub fn linesizes(&self) -> &[i32; AV_NUM_DATA_POINTERS] {
&self.linesizes
}
pub fn as_slice(&self) -> &[u8] {
unsafe { slice::from_raw_parts(self.linear, self.linear_length) }
}
}
impl Drop for AVImage {
fn drop(&mut self) {
let _ =
unsafe { Vec::from_raw_parts(self.linear, self.linear_length, self.linear_capacity) };
}
}
pub use ffi::av_image_fill_arrays;