X-Git-Url: https://git.nihav.org/?p=nihav-player.git;a=blobdiff_plain;f=nihed-cros-libva%2Fsrc%2Fbuffer.rs;fp=nihed-cros-libva%2Fsrc%2Fbuffer.rs;h=41d59340b4ca95774ef4e6df747fadd32509bb51;hp=0000000000000000000000000000000000000000;hb=683627242f69bed0b818d976d4b03d651e529697;hpb=549511e9deafd9ec08b3c80489e7e85c5f5f0b3b diff --git a/nihed-cros-libva/src/buffer.rs b/nihed-cros-libva/src/buffer.rs new file mode 100644 index 0000000..41d5934 --- /dev/null +++ b/nihed-cros-libva/src/buffer.rs @@ -0,0 +1,203 @@ +// Copyright 2022 The ChromiumOS Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +//! Wrappers and helpers around `VABuffer`s. + +mod h264; +mod mpeg2; +mod vp8; +mod vp9; + +pub use h264::*; +pub use mpeg2::*; +pub use vp8::*; +pub use vp9::*; + +use std::rc::Rc; + +use anyhow::Result; +use log::error; + +use crate::bindings; +use crate::status::Status; +use crate::Context; + +/// Wrapper type representing a buffer created with `vaCreateBuffer`. +pub struct Buffer { + context: Rc, + id: bindings::VABufferID, +} + +impl Buffer { + /// Creates a new buffer by wrapping a `vaCreateBuffer` call. This is just a helper for + /// [`Context::create_buffer`]. + pub(crate) fn new(context: Rc, mut type_: BufferType) -> Result { + let mut buffer_id = 0; + + 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()), + ), + }, + + 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 _ 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()), + ), + }, + + 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()) + } + }; + + // Safe because `self` represents a valid `VAContext`. `ptr` and `size` are also ensured to + // be correct, as `ptr` is just a cast to `*c_void` from a Rust struct, and `size` is + // computed from `std::mem::size_of_val`. + Status(unsafe { + bindings::vaCreateBuffer( + context.display().handle(), + context.id(), + type_.inner(), + size as u32, + 1, + ptr, + &mut buffer_id, + ) + }) + .check()?; + + Ok(Self { + context, + id: buffer_id, + }) + } + + /// Convenience function to return a `VABufferID` vector from a slice of `Buffer`s in order to + /// easily interface with the C API where a buffer array might be needed. + pub fn as_id_vec(buffers: &[Self]) -> Vec { + buffers.iter().map(|buffer| buffer.id).collect() + } +} + +impl Drop for Buffer { + fn drop(&mut self) { + // Safe because `self` represents a valid buffer, created with + // vaCreateBuffers. + let status = + Status(unsafe { bindings::vaDestroyBuffer(self.context.display().handle(), self.id) }) + .check(); + if status.is_err() { + error!("vaDestroyBuffer failed: {}", status.unwrap_err()); + } + } +} + +/// Abstraction over `VABufferType`s. +pub enum BufferType { + /// Abstraction over `VAPictureParameterBufferType`. Needed for MPEG2, VP8, VP9, H264. + PictureParameter(PictureParameter), + /// Abstraction over `VASliceParameterBufferType`. Needed for MPEG2, VP8, VP9, H264. + SliceParameter(SliceParameter), + /// Abstraction over `VAIQMatrixBufferType`. Needed for VP8, H264. + IQMatrix(IQMatrix), + /// Abstraction over `VAProbabilityDataBufferType`. Needed for VP8. + Probability(vp8::ProbabilityDataBufferVP8), + /// Abstraction over `VASliceDataBufferType`. Needed for VP9, H264. + SliceData(Vec), +} + +impl BufferType { + /// Returns the inner FFI buffer type. + 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, + } + } +} + +/// Abstraction over the `PictureParameterBuffer` types we support. +pub enum PictureParameter { + /// Wrapper over VAPictureParameterBufferMPEG2. + MPEG2(mpeg2::PictureParameterBufferMPEG2), + /// Wrapper over VAPictureParameterBufferVP8. + VP8(vp8::PictureParameterBufferVP8), + /// Wrapper over VAPictureParameterBufferVP9. + VP9(vp9::PictureParameterBufferVP9), + /// Wrapper over VAPictureParameterBufferH264. + H264(h264::PictureParameterBufferH264), +} + +/// Abstraction over the `SliceParameterBuffer` types we support +pub enum SliceParameter { + /// Wrapper over VASliceParameterBufferMPEG2 + MPEG2(mpeg2::SliceParameterBufferMPEG2), + /// Wrapper over VASliceParameterBufferVP8 + VP8(vp8::SliceParameterBufferVP8), + /// Wrapper over VASliceParameterBufferVP9 + VP9(vp9::SliceParameterBufferVP9), + /// Wrapper over VASliceParameterBufferH264 + H264(h264::SliceParameterBufferH264), +} + +/// Abstraction over the `IQMatrixBuffer` types we support. +pub enum IQMatrix { + /// Abstraction over `VAIQMatrixBufferMPEG2` + MPEG2(mpeg2::IQMatrixBufferMPEG2), + /// Abstraction over `VAIQMatrixBufferVP8` + VP8(vp8::IQMatrixBufferVP8), + /// Abstraction over `VAIQMatrixBufferH264` + H264(h264::IQMatrixBufferH264), +}