mod av1;
mod enc_misc;
mod h264;
mod hevc;
mod mpeg2;
mod vp8;
mod vp9;
pub use av1::*;
pub use enc_misc::*;
pub use h264::*;
pub use hevc::*;
pub use mpeg2::*;
pub use vp8::*;
pub use vp9::*;
use std::rc::Rc;
use log::error;
use crate::bindings;
use crate::va_check;
use crate::Context;
use crate::VaError;
pub struct Buffer {
context: Rc<Context>,
id: bindings::VABufferID,
}
impl Buffer {
pub(crate) fn new(context: Rc<Context>, mut type_: BufferType) -> Result<Self, VaError> {
let mut buffer_id = 0;
let nb_elements = match type_ {
BufferType::SliceParameter(SliceParameter::H264(ref mut params)) => {
params.inner_mut().len()
}
BufferType::SliceParameter(SliceParameter::AV1(ref mut params)) => {
params.inner_mut().len()
}
_ => 1,
};
let (ptr, size) = match type_ {
BufferType::PictureParameter(ref mut picture_param) => match picture_param {
PictureParameter::MPEG2(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
PictureParameter::VP8(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
PictureParameter::VP9(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
PictureParameter::H264(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
PictureParameter::HEVC(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
PictureParameter::HEVCRext(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
PictureParameter::HEVCScc(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
PictureParameter::AV1(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
},
BufferType::SliceParameter(ref mut slice_param) => match slice_param {
SliceParameter::MPEG2(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
SliceParameter::VP8(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
SliceParameter::VP9(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
SliceParameter::H264(ref mut wrapper) => (
wrapper.inner_mut().as_mut_ptr() as *mut std::ffi::c_void,
std::mem::size_of::<bindings::VASliceParameterBufferH264>(),
),
SliceParameter::HEVC(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
SliceParameter::HEVCRext(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
SliceParameter::AV1(ref mut wrapper) => (
wrapper.inner_mut().as_mut_ptr() as *mut std::ffi::c_void,
std::mem::size_of::<bindings::VASliceParameterBufferAV1>(),
),
},
BufferType::IQMatrix(ref mut iq_matrix) => match iq_matrix {
IQMatrix::MPEG2(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
IQMatrix::VP8(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
IQMatrix::H264(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
IQMatrix::HEVC(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
},
BufferType::Probability(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
BufferType::SliceData(ref mut data) => {
(data.as_mut_ptr() as *mut std::ffi::c_void, data.len())
}
BufferType::EncSequenceParameter(ref mut seq_param) => match seq_param {
EncSequenceParameter::H264(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncSequenceParameter::HEVC(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncSequenceParameter::VP8(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncSequenceParameter::VP9(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncSequenceParameter::AV1(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
},
BufferType::EncPictureParameter(ref mut picture_param) => match picture_param {
EncPictureParameter::H264(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncPictureParameter::HEVC(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncPictureParameter::VP8(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncPictureParameter::VP9(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncPictureParameter::AV1(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
},
BufferType::EncSliceParameter(ref mut slice_param) => match slice_param {
EncSliceParameter::H264(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncSliceParameter::HEVC(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncSliceParameter::AV1(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
},
BufferType::EncMacroblockParameterBuffer(ref mut mb_param) => match mb_param {
EncMacroblockParameterBuffer::H264(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
},
BufferType::EncCodedBuffer(size) => (std::ptr::null_mut(), size),
BufferType::EncMiscParameter(ref mut enc_misc_param) => match enc_misc_param {
EncMiscParameter::FrameRate(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncMiscParameter::RateControl(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncMiscParameter::MaxSliceSize(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncMiscParameter::MaxFrameSize(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncMiscParameter::SkipFrame(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncMiscParameter::HRD(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncMiscParameter::QualityLevel(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncMiscParameter::Quantization(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
},
};
va_check(unsafe {
bindings::vaCreateBuffer(
context.display().handle(),
context.id(),
type_.inner(),
size as u32,
nb_elements as u32,
ptr,
&mut buffer_id,
)
})?;
Ok(Self {
context,
id: buffer_id,
})
}
pub fn as_id_vec(buffers: &[Self]) -> Vec<bindings::VABufferID> {
buffers.iter().map(|buffer| buffer.id).collect()
}
}
impl Drop for Buffer {
fn drop(&mut self) {
let status = va_check(unsafe {
bindings::vaDestroyBuffer(self.context.display().handle(), self.id)
});
if status.is_err() {
error!("vaDestroyBuffer failed: {}", status.unwrap_err());
}
}
}
pub enum BufferType {
PictureParameter(PictureParameter),
SliceParameter(SliceParameter),
IQMatrix(IQMatrix),
Probability(vp8::ProbabilityDataBufferVP8),
SliceData(Vec<u8>),
EncSequenceParameter(EncSequenceParameter),
EncPictureParameter(EncPictureParameter),
EncSliceParameter(EncSliceParameter),
EncMacroblockParameterBuffer(EncMacroblockParameterBuffer),
EncCodedBuffer(usize),
EncMiscParameter(EncMiscParameter),
}
impl BufferType {
pub(crate) fn inner(&self) -> bindings::VABufferType::Type {
match self {
BufferType::PictureParameter(_) => bindings::VABufferType::VAPictureParameterBufferType,
BufferType::SliceParameter(_) => bindings::VABufferType::VASliceParameterBufferType,
BufferType::IQMatrix(_) => bindings::VABufferType::VAIQMatrixBufferType,
BufferType::Probability(_) => bindings::VABufferType::VAProbabilityBufferType,
BufferType::SliceData { .. } => bindings::VABufferType::VASliceDataBufferType,
BufferType::EncSequenceParameter(_) => {
bindings::VABufferType::VAEncSequenceParameterBufferType
}
BufferType::EncPictureParameter(_) => {
bindings::VABufferType::VAEncPictureParameterBufferType
}
BufferType::EncSliceParameter(_) => {
bindings::VABufferType::VAEncSliceParameterBufferType
}
BufferType::EncMacroblockParameterBuffer(_) => {
bindings::VABufferType::VAEncMacroblockMapBufferType
}
BufferType::EncCodedBuffer(_) => bindings::VABufferType::VAEncCodedBufferType,
BufferType::EncMiscParameter(_) => bindings::VABufferType::VAEncMiscParameterBufferType,
}
}
}
pub enum PictureParameter {
MPEG2(mpeg2::PictureParameterBufferMPEG2),
VP8(vp8::PictureParameterBufferVP8),
VP9(vp9::PictureParameterBufferVP9),
H264(h264::PictureParameterBufferH264),
HEVC(hevc::PictureParameterBufferHEVC),
HEVCRext(hevc::PictureParameterBufferHEVCRext),
HEVCScc(hevc::PictureParameterBufferHEVCScc),
AV1(av1::PictureParameterBufferAV1),
}
pub enum SliceParameter {
MPEG2(mpeg2::SliceParameterBufferMPEG2),
VP8(vp8::SliceParameterBufferVP8),
VP9(vp9::SliceParameterBufferVP9),
H264(h264::SliceParameterBufferH264),
HEVC(hevc::SliceParameterBufferHEVC),
HEVCRext(hevc::SliceParameterBufferHEVCRext),
AV1(av1::SliceParameterBufferAV1),
}
pub enum IQMatrix {
MPEG2(mpeg2::IQMatrixBufferMPEG2),
VP8(vp8::IQMatrixBufferVP8),
H264(h264::IQMatrixBufferH264),
HEVC(hevc::IQMatrixBufferHEVC),
}
pub enum EncSequenceParameter {
H264(h264::EncSequenceParameterBufferH264),
HEVC(hevc::EncSequenceParameterBufferHEVC),
VP8(vp8::EncSequenceParameterBufferVP8),
VP9(vp9::EncSequenceParameterBufferVP9),
AV1(av1::EncSequenceParameterBufferAV1),
}
pub enum EncPictureParameter {
H264(h264::EncPictureParameterBufferH264),
HEVC(hevc::EncPictureParameterBufferHEVC),
VP8(vp8::EncPictureParameterBufferVP8),
VP9(vp9::EncPictureParameterBufferVP9),
AV1(av1::EncPictureParameterBufferAV1),
}
pub enum EncSliceParameter {
H264(h264::EncSliceParameterBufferH264),
HEVC(hevc::EncSliceParameterBufferHEVC),
AV1(av1::EncTileGroupBufferAV1),
}
pub enum EncMacroblockParameterBuffer {
H264(h264::EncMacroblockParameterBufferH264),
}
pub struct EncCodedBuffer(Buffer);
impl EncCodedBuffer {
pub(crate) fn new(context: Rc<Context>, size: usize) -> Result<Self, VaError> {
Ok(Self(Buffer::new(
context,
BufferType::EncCodedBuffer(size),
)?))
}
pub fn id(&self) -> bindings::VABufferID {
self.0.id
}
}
pub struct MappedCodedSegment<'s> {
pub bit_offset: u32,
pub status: u32,
pub buf: &'s [u8],
}
pub struct MappedCodedBuffer<'p> {
segments: Vec<MappedCodedSegment<'p>>,
buffer: &'p EncCodedBuffer,
}
impl<'p> MappedCodedBuffer<'p> {
pub fn new(buffer: &'p EncCodedBuffer) -> Result<Self, VaError> {
let mut addr = std::ptr::null_mut();
let mut segments = Vec::new();
va_check(unsafe {
bindings::vaMapBuffer(buffer.0.context.display().handle(), buffer.id(), &mut addr)
})?;
while !addr.is_null() {
let segment: &bindings::VACodedBufferSegment =
unsafe { &*(addr as *const bindings::VACodedBufferSegment) };
let size = segment.size;
let buf = segment.buf;
let buf = unsafe { std::slice::from_raw_parts(buf as *mut u8, size as usize) };
segments.push(MappedCodedSegment {
bit_offset: segment.bit_offset,
status: segment.status,
buf,
});
addr = segment.next;
}
Ok(Self { segments, buffer })
}
pub fn iter(&self) -> impl Iterator<Item = &MappedCodedSegment<'p>> {
self.segments.iter()
}
pub fn segments(&self) -> &Vec<MappedCodedSegment<'p>> {
&self.segments
}
}
impl<'p> Drop for MappedCodedBuffer<'p> {
fn drop(&mut self) {
let status = va_check(unsafe {
bindings::vaUnmapBuffer(self.buffer.0.context.display().handle(), self.buffer.id())
});
if status.is_err() {
error!("vaUnmapBuffer failed: {}", status.unwrap_err());
}
}
}
pub enum EncMiscParameter {
FrameRate(EncMiscParameterFrameRate),
RateControl(EncMiscParameterRateControl),
MaxSliceSize(EncMiscParameterMaxSliceSize),
MaxFrameSize(EncMiscParameterBufferMaxFrameSize),
SkipFrame(EncMiscParameterSkipFrame),
HRD(EncMiscParameterHRD),
QualityLevel(EncMiscParameterBufferQualityLevel),
Quantization(EncMiscParameterQuantization),
}