#![allow(clippy::cast_possible_wrap)]
extern "C" {
fn vt_super_resolution_is_supported() -> bool;
fn vt_motion_blur_is_supported() -> bool;
fn vt_temporal_noise_filter_is_supported() -> bool;
fn vt_frame_rate_conversion_is_supported() -> bool;
fn vt_low_latency_super_resolution_is_supported() -> bool;
fn vt_low_latency_frame_interpolation_is_supported() -> bool;
fn vt_optical_flow_is_supported() -> bool;
fn vt_super_resolution_supported_scale_factors(out_buf: *mut u32, max: usize) -> usize;
fn vt_super_resolution_start(
frame_width: isize,
frame_height: isize,
scale_factor: isize,
use_precomputed_flow: bool,
input_is_image: bool,
out: *mut *mut core::ffi::c_void,
) -> i32;
fn vt_motion_blur_start(
frame_width: isize,
frame_height: isize,
use_precomputed_flow: bool,
out: *mut *mut core::ffi::c_void,
) -> i32;
fn vt_temporal_noise_filter_start(
frame_width: isize,
frame_height: isize,
source_pixel_format: u32,
out: *mut *mut core::ffi::c_void,
) -> i32;
fn vt_frame_rate_conversion_start(
frame_width: isize,
frame_height: isize,
use_precomputed_flow: bool,
out: *mut *mut core::ffi::c_void,
) -> i32;
fn vt_low_latency_super_resolution_start(
frame_width: isize,
frame_height: isize,
scale_factor: f32,
out: *mut *mut core::ffi::c_void,
) -> i32;
fn vt_low_latency_frame_interpolation_start(
frame_width: isize,
frame_height: isize,
number_of_interpolated_frames: isize,
out: *mut *mut core::ffi::c_void,
) -> i32;
fn vt_optical_flow_start(
frame_width: isize,
frame_height: isize,
out: *mut *mut core::ffi::c_void,
) -> i32;
fn vt_frame_processor_end(processor: *mut core::ffi::c_void);
fn vt_frame_processor_release(processor: *mut core::ffi::c_void);
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
#[allow(clippy::struct_excessive_bools)]
pub struct FrameProcessorCapabilities {
pub super_resolution: bool,
pub motion_blur: bool,
pub temporal_noise_filter: bool,
pub frame_rate_conversion: bool,
pub low_latency_super_resolution: bool,
pub low_latency_frame_interpolation: bool,
pub optical_flow: bool,
}
#[must_use]
pub fn frame_processor_capabilities() -> FrameProcessorCapabilities {
unsafe {
FrameProcessorCapabilities {
super_resolution: vt_super_resolution_is_supported(),
motion_blur: vt_motion_blur_is_supported(),
temporal_noise_filter: vt_temporal_noise_filter_is_supported(),
frame_rate_conversion: vt_frame_rate_conversion_is_supported(),
low_latency_super_resolution: vt_low_latency_super_resolution_is_supported(),
low_latency_frame_interpolation: vt_low_latency_frame_interpolation_is_supported(),
optical_flow: vt_optical_flow_is_supported(),
}
}
}
#[must_use]
pub fn super_resolution_supported_scale_factors() -> Vec<u32> {
const MAX: usize = 16;
let mut buf = vec![0u32; MAX];
let n = unsafe { vt_super_resolution_supported_scale_factors(buf.as_mut_ptr(), MAX) };
buf.truncate(n);
buf
}
pub struct FrameProcessor {
inner: *mut core::ffi::c_void,
}
unsafe impl Send for FrameProcessor {}
unsafe impl Sync for FrameProcessor {}
impl Drop for FrameProcessor {
fn drop(&mut self) {
if !self.inner.is_null() {
unsafe {
vt_frame_processor_end(self.inner);
vt_frame_processor_release(self.inner);
}
self.inner = core::ptr::null_mut();
}
}
}
impl FrameProcessor {
fn from_status(status: i32, ptr: *mut core::ffi::c_void) -> Result<Self, crate::VTError> {
if status != 0 || ptr.is_null() {
return Err(crate::VTError::SessionCreateFailed(status));
}
Ok(Self { inner: ptr })
}
pub fn start_super_resolution(
frame_width: usize,
frame_height: usize,
scale_factor: usize,
use_precomputed_flow: bool,
input_is_image: bool,
) -> Result<Self, crate::VTError> {
let mut out: *mut core::ffi::c_void = core::ptr::null_mut();
let s = unsafe {
vt_super_resolution_start(
frame_width as isize,
frame_height as isize,
scale_factor as isize,
use_precomputed_flow,
input_is_image,
&mut out,
)
};
Self::from_status(s, out)
}
pub fn start_motion_blur(
frame_width: usize,
frame_height: usize,
use_precomputed_flow: bool,
) -> Result<Self, crate::VTError> {
let mut out: *mut core::ffi::c_void = core::ptr::null_mut();
let s = unsafe {
vt_motion_blur_start(
frame_width as isize,
frame_height as isize,
use_precomputed_flow,
&mut out,
)
};
Self::from_status(s, out)
}
pub fn start_temporal_noise_filter(
frame_width: usize,
frame_height: usize,
source_pixel_format: u32,
) -> Result<Self, crate::VTError> {
let mut out: *mut core::ffi::c_void = core::ptr::null_mut();
let s = unsafe {
vt_temporal_noise_filter_start(
frame_width as isize,
frame_height as isize,
source_pixel_format,
&mut out,
)
};
Self::from_status(s, out)
}
pub fn start_frame_rate_conversion(
frame_width: usize,
frame_height: usize,
use_precomputed_flow: bool,
) -> Result<Self, crate::VTError> {
let mut out: *mut core::ffi::c_void = core::ptr::null_mut();
let s = unsafe {
vt_frame_rate_conversion_start(
frame_width as isize,
frame_height as isize,
use_precomputed_flow,
&mut out,
)
};
Self::from_status(s, out)
}
pub fn start_low_latency_super_resolution(
frame_width: usize,
frame_height: usize,
scale_factor: f32,
) -> Result<Self, crate::VTError> {
let mut out: *mut core::ffi::c_void = core::ptr::null_mut();
let s = unsafe {
vt_low_latency_super_resolution_start(
frame_width as isize,
frame_height as isize,
scale_factor,
&mut out,
)
};
Self::from_status(s, out)
}
pub fn start_low_latency_frame_interpolation(
frame_width: usize,
frame_height: usize,
number_of_interpolated_frames: usize,
) -> Result<Self, crate::VTError> {
let mut out: *mut core::ffi::c_void = core::ptr::null_mut();
let s = unsafe {
vt_low_latency_frame_interpolation_start(
frame_width as isize,
frame_height as isize,
number_of_interpolated_frames as isize,
&mut out,
)
};
Self::from_status(s, out)
}
pub fn start_optical_flow(
frame_width: usize,
frame_height: usize,
) -> Result<Self, crate::VTError> {
let mut out: *mut core::ffi::c_void = core::ptr::null_mut();
let s = unsafe {
vt_optical_flow_start(frame_width as isize, frame_height as isize, &mut out)
};
Self::from_status(s, out)
}
#[must_use]
pub const fn as_ptr(&self) -> *mut core::ffi::c_void {
self.inner
}
}