#[cfg(libva_1_14_or_higher)]
mod av1;
mod enc_jpeg;
mod enc_misc;
mod h264;
mod hevc;
mod jpeg_baseline;
mod mpeg2;
mod proc_pipeline;
mod vp8;
mod vp9;
#[cfg(libva_1_14_or_higher)]
pub use av1::*;
pub use enc_jpeg::*;
pub use enc_misc::*;
pub use h264::*;
pub use hevc::*;
pub use jpeg_baseline::*;
pub use mpeg2::*;
pub use proc_pipeline::*;
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(),
#[cfg(libva_1_14_or_higher)]
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()),
),
#[cfg(libva_1_14_or_higher)]
PictureParameter::AV1(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
PictureParameter::JPEGBaseline(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
PictureParameter::EncJPEG(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()),
),
#[cfg(libva_1_14_or_higher)]
SliceParameter::AV1(ref mut wrapper) => (
wrapper.inner_mut().as_mut_ptr() as *mut std::ffi::c_void,
std::mem::size_of::<bindings::VASliceParameterBufferAV1>(),
),
SliceParameter::JPEGBaseline(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
SliceParameter::EncJpeg(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
},
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()),
),
IQMatrix::JPEGBaseline(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
},
BufferType::HuffmanTable(ref mut huffman_table) => match huffman_table {
HuffmanTable::JPEGBaseline(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()),
),
#[cfg(libva_1_14_or_higher)]
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()),
),
#[cfg(libva_1_14_or_higher)]
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()),
),
#[cfg(libva_1_14_or_higher)]
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()),
),
},
BufferType::ProcPipelineParameter(ref mut proc_pipeline_param) => (
proc_pipeline_param.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(proc_pipeline_param.inner_mut()),
),
BufferType::QMatrix(ref mut q_matrix) => match q_matrix {
QMatrix::JPEG(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
},
BufferType::EncPackedHeaderParameter(ref mut wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
BufferType::EncPackedHeaderData(ref data) => (data.as_ptr() as *mut std::ffi::c_void, data.len()),
};
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),
HuffmanTable(HuffmanTable),
Probability(vp8::ProbabilityDataBufferVP8),
SliceData(Vec<u8>),
EncSequenceParameter(EncSequenceParameter),
EncPictureParameter(EncPictureParameter),
EncSliceParameter(EncSliceParameter),
EncMacroblockParameterBuffer(EncMacroblockParameterBuffer),
EncCodedBuffer(usize),
EncMiscParameter(EncMiscParameter),
ProcPipelineParameter(proc_pipeline::ProcPipelineParameterBuffer),
QMatrix(QMatrix),
EncPackedHeaderParameter(EncPackedHeaderParameter),
EncPackedHeaderData(Vec<u8>),
}
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::HuffmanTable(_) => bindings::VABufferType::VAHuffmanTableBufferType,
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,
BufferType::ProcPipelineParameter(_) => bindings::VABufferType::VAProcPipelineParameterBufferType,
BufferType::QMatrix(_) => bindings::VABufferType::VAQMatrixBufferType,
BufferType::EncPackedHeaderParameter(_) => bindings::VABufferType::VAEncPackedHeaderParameterBufferType,
BufferType::EncPackedHeaderData(_) => bindings::VABufferType::VAEncPackedHeaderDataBufferType,
}
}
}
pub enum PictureParameter {
MPEG2(mpeg2::PictureParameterBufferMPEG2),
VP8(vp8::PictureParameterBufferVP8),
VP9(vp9::PictureParameterBufferVP9),
H264(h264::PictureParameterBufferH264),
HEVC(hevc::PictureParameterBufferHEVC),
HEVCRext(hevc::PictureParameterBufferHEVCRext),
HEVCScc(hevc::PictureParameterBufferHEVCScc),
#[cfg(libva_1_14_or_higher)]
AV1(av1::PictureParameterBufferAV1),
JPEGBaseline(jpeg_baseline::PictureParameterBufferJPEGBaseline),
EncJPEG(enc_jpeg::EncPictureParameterBufferJPEG),
}
pub enum SliceParameter {
MPEG2(mpeg2::SliceParameterBufferMPEG2),
VP8(vp8::SliceParameterBufferVP8),
VP9(vp9::SliceParameterBufferVP9),
H264(h264::SliceParameterBufferH264),
HEVC(hevc::SliceParameterBufferHEVC),
HEVCRext(hevc::SliceParameterBufferHEVCRext),
#[cfg(libva_1_14_or_higher)]
AV1(av1::SliceParameterBufferAV1),
JPEGBaseline(jpeg_baseline::SliceParameterBufferJPEGBaseline),
EncJpeg(enc_jpeg::EncSliceParameterBufferJPEG),
}
pub enum IQMatrix {
MPEG2(mpeg2::IQMatrixBufferMPEG2),
VP8(vp8::IQMatrixBufferVP8),
H264(h264::IQMatrixBufferH264),
HEVC(hevc::IQMatrixBufferHEVC),
JPEGBaseline(jpeg_baseline::IQMatrixBufferJPEGBaseline),
}
pub enum HuffmanTable {
JPEGBaseline(jpeg_baseline::HuffmanTableBufferJPEGBaseline),
}
pub enum QMatrix {
JPEG(enc_jpeg::QMatrixBufferJPEG),
}
pub enum EncSequenceParameter {
H264(h264::EncSequenceParameterBufferH264),
HEVC(hevc::EncSequenceParameterBufferHEVC),
VP8(vp8::EncSequenceParameterBufferVP8),
VP9(vp9::EncSequenceParameterBufferVP9),
#[cfg(libva_1_14_or_higher)]
AV1(av1::EncSequenceParameterBufferAV1),
}
pub enum EncPictureParameter {
H264(h264::EncPictureParameterBufferH264),
HEVC(hevc::EncPictureParameterBufferHEVC),
VP8(vp8::EncPictureParameterBufferVP8),
VP9(vp9::EncPictureParameterBufferVP9),
#[cfg(libva_1_14_or_higher)]
AV1(av1::EncPictureParameterBufferAV1),
}
pub enum EncSliceParameter {
H264(h264::EncSliceParameterBufferH264),
HEVC(hevc::EncSliceParameterBufferHEVC),
#[cfg(libva_1_14_or_higher)]
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),
}
#[repr(u32)]
pub enum EncPackedHeaderType {
Sequence = bindings::VAEncPackedHeaderType::VAEncPackedHeaderSequence,
Picture = bindings::VAEncPackedHeaderType::VAEncPackedHeaderPicture,
Slice = bindings::VAEncPackedHeaderType::VAEncPackedHeaderSlice,
RawData = bindings::VAEncPackedHeaderType::VAEncPackedHeaderRawData,
}
pub struct EncPackedHeaderParameter(Box<bindings::VAEncPackedHeaderParameterBuffer>);
impl EncPackedHeaderParameter {
pub fn new(type_: EncPackedHeaderType, length_in_bits: u32, has_emulation: bool) -> Self {
Self(Box::new(bindings::VAEncPackedHeaderParameterBuffer {
type_: type_ as _,
bit_length: length_in_bits,
has_emulation_bytes: has_emulation as u8,
..Default::default()
}))
}
pub fn inner_mut(&mut self) -> &mut bindings::VAEncPackedHeaderParameterBuffer {
&mut self.0
}
}