extern crate ffmpeg_next as ffmpeg;
use crate::error::Error;
use crate::ffi_hwaccel;
type Result<T> = std::result::Result<T, Error>;
pub(crate) struct HardwareAccelerationContext {
pixel_format: ffmpeg::util::format::Pixel,
_hardware_device_context: ffi_hwaccel::HardwareDeviceContext,
}
impl HardwareAccelerationContext {
pub(crate) fn new(
decoder: &mut ffmpeg::codec::Context,
device_type: HardwareAccelerationDeviceType,
) -> Result<Self> {
let codec = ffmpeg::codec::decoder::find(decoder.id()).ok_or(Error::UninitializedCodec)?;
let pixel_format =
ffi_hwaccel::codec_find_corresponding_hwaccel_pixfmt(&codec, device_type)
.ok_or(Error::UnsupportedCodecHardwareAccelerationDeviceType)?;
ffi_hwaccel::codec_context_hwaccel_set_get_format(decoder, pixel_format);
let hardware_device_context = ffi_hwaccel::HardwareDeviceContext::new(device_type)?;
ffi_hwaccel::codec_context_hwaccel_set_hw_device_ctx(decoder, &hardware_device_context);
Ok(HardwareAccelerationContext {
pixel_format,
_hardware_device_context: hardware_device_context,
})
}
pub(crate) fn format(&self) -> ffmpeg::util::format::Pixel {
self.pixel_format
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum HardwareAccelerationDeviceType {
Vdpau,
Cuda,
VaApi,
Dxva2,
Qsv,
VideoToolbox,
D3D11Va,
Drm,
OpenCl,
MediaCodec,
D3D12Va,
}
impl HardwareAccelerationDeviceType {
pub fn is_available(self) -> bool {
Self::list_available().contains(&self)
}
pub fn list_available() -> Vec<HardwareAccelerationDeviceType> {
ffi_hwaccel::hwdevice_list_available_device_types()
}
}
impl HardwareAccelerationDeviceType {
pub fn from(value: ffmpeg::ffi::AVHWDeviceType) -> Option<HardwareAccelerationDeviceType> {
match value {
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_VDPAU => Some(Self::Vdpau),
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_CUDA => Some(Self::Cuda),
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_VAAPI => Some(Self::VaApi),
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_DXVA2 => Some(Self::Dxva2),
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_QSV => Some(Self::Qsv),
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_VIDEOTOOLBOX => Some(Self::VideoToolbox),
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_D3D11VA => Some(Self::D3D11Va),
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_DRM => Some(Self::Drm),
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_OPENCL => Some(Self::OpenCl),
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_MEDIACODEC => Some(Self::MediaCodec),
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_NONE => None,
#[allow(unreachable_patterns)]
_ => None,
}
}
}
impl From<HardwareAccelerationDeviceType> for ffmpeg::ffi::AVHWDeviceType {
fn from(value: HardwareAccelerationDeviceType) -> Self {
match value {
HardwareAccelerationDeviceType::Vdpau => {
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_VDPAU
}
HardwareAccelerationDeviceType::Cuda => {
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_CUDA
}
HardwareAccelerationDeviceType::VaApi => {
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_VAAPI
}
HardwareAccelerationDeviceType::Dxva2 => {
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_DXVA2
}
HardwareAccelerationDeviceType::Qsv => {
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_QSV
}
HardwareAccelerationDeviceType::VideoToolbox => {
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_VIDEOTOOLBOX
}
HardwareAccelerationDeviceType::D3D11Va => {
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_D3D11VA
}
HardwareAccelerationDeviceType::Drm => {
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_DRM
}
HardwareAccelerationDeviceType::OpenCl => {
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_OPENCL
}
HardwareAccelerationDeviceType::MediaCodec => {
ffmpeg::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_MEDIACODEC
}
HardwareAccelerationDeviceType::D3D12Va => {
unimplemented!()
}
}
}
}