#[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::Context;
use crate::VaError;
use crate::bindings;
use crate::va_check;
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(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
PictureParameter::VP8(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
PictureParameter::VP9(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
PictureParameter::H264(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
PictureParameter::HEVC(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
PictureParameter::HEVCRext(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
PictureParameter::HEVCScc(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(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
PictureParameter::JPEGBaseline(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
PictureParameter::EncJPEG(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(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
SliceParameter::VP8(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
SliceParameter::VP9(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
SliceParameter::H264(wrapper) => (
wrapper.inner_mut().as_mut_ptr() as *mut std::ffi::c_void,
std::mem::size_of::<bindings::VASliceParameterBufferH264>(),
),
SliceParameter::HEVC(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
SliceParameter::HEVCRext(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(wrapper) => (
wrapper.inner_mut().as_mut_ptr() as *mut std::ffi::c_void,
std::mem::size_of::<bindings::VASliceParameterBufferAV1>(),
),
SliceParameter::JPEGBaseline(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
SliceParameter::EncJpeg(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(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
IQMatrix::VP8(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
IQMatrix::H264(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
IQMatrix::HEVC(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
IQMatrix::JPEGBaseline(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(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(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncSequenceParameter::HEVC(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncSequenceParameter::VP8(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncSequenceParameter::VP9(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(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(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncPictureParameter::HEVC(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncPictureParameter::VP8(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncPictureParameter::VP9(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(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(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncSliceParameter::HEVC(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(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(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(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncMiscParameter::RateControl(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncMiscParameter::MaxSliceSize(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncMiscParameter::MaxFrameSize(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncMiscParameter::SkipFrame(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncMiscParameter::HRD(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncMiscParameter::QualityLevel(wrapper) => (
wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void,
std::mem::size_of_val(wrapper.inner_mut()),
),
EncMiscParameter::Quantization(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(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 {
crate::va::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()
}
}
pub enum BorrowedBufferType<'a> {
SliceData(&'a [u8]),
EncPackedHeaderData(&'a [u8]),
ProtectedSliceDataBuffer(&'a [u8]),
}
impl<'a> BorrowedBufferType<'a> {
pub(crate) fn inner(&self) -> bindings::VABufferType::Type {
match self {
BorrowedBufferType::SliceData(_) => bindings::VABufferType::VASliceDataBufferType,
BorrowedBufferType::EncPackedHeaderData(_) => {
bindings::VABufferType::VAEncPackedHeaderDataBufferType
}
BorrowedBufferType::ProtectedSliceDataBuffer(_) => {
bindings::VABufferType::VAProtectedSliceDataBufferType
}
}
}
}
impl Buffer {
pub(crate) fn new_borrowed(
context: Rc<Context>,
type_: BorrowedBufferType,
) -> Result<Self, VaError> {
let mut buffer_id = 0;
let nb_elements = 1;
let (ptr, size) = match type_ {
BorrowedBufferType::SliceData(data) => {
(data.as_ptr() as *mut std::ffi::c_void, data.len())
}
BorrowedBufferType::EncPackedHeaderData(data) => {
(data.as_ptr() as *mut std::ffi::c_void, data.len())
}
BorrowedBufferType::ProtectedSliceDataBuffer(data) => {
(data.as_ptr() as *mut std::ffi::c_void, data.len())
}
};
va_check(unsafe {
crate::va::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,
})
}
}
impl Drop for Buffer {
fn drop(&mut self) {
let status = va_check(unsafe {
crate::va::vaDestroyBuffer(self.context.display().handle(), self.id)
});
if let Err(e) = status {
error!("vaDestroyBuffer failed: {}", e);
}
}
}
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 {
crate::va::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 {
crate::va::vaUnmapBuffer(self.buffer.0.context.display().handle(), self.buffer.id())
});
if let Err(e) = status {
error!("vaUnmapBuffer failed: {}", e);
}
}
}
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
}
}