use crate::{
api::API,
format::{ColorFamily, FormatError, SampleType},
};
use rustsynth_sys as ffi;
impl VideoFormat {
#[must_use]
pub unsafe fn from_ptr(from: *const ffi::VSVideoFormat) -> Self {
let info = &*from;
let sample_type = if info.sampleType == ffi::VSSampleType::stInteger as i32 {
SampleType::Integer
} else {
SampleType::Float
};
let color_family = match info.colorFamily {
x if x == ffi::VSColorFamily::cfUndefined as i32 => ColorFamily::Undefined,
x if x == ffi::VSColorFamily::cfGray as i32 => ColorFamily::Gray,
x if x == ffi::VSColorFamily::cfRGB as i32 => ColorFamily::RGB,
x if x == ffi::VSColorFamily::cfYUV as i32 => ColorFamily::YUV,
_ => unreachable!(),
};
Self {
color_family,
sample_type,
bits_per_sample: info.bitsPerSample,
bytes_per_sample: info.bytesPerSample,
sub_sampling_w: info.subSamplingW,
sub_sampling_h: info.subSamplingH,
num_planes: info.numPlanes,
}
}
pub fn query(
color_family: ColorFamily,
sample_type: SampleType,
bits_per_sample: i32,
sub_sampling_w: i32,
sub_sampling_h: i32,
core: &crate::core::CoreRef,
) -> Result<Self, FormatError> {
let mut format = ffi::VSVideoFormat {
colorFamily: 0,
sampleType: 0,
bitsPerSample: 0,
bytesPerSample: 0,
subSamplingW: 0,
subSamplingH: 0,
numPlanes: 0,
};
let success = unsafe {
API::get_cached().query_video_format(
&raw mut format,
color_family as i32,
sample_type as i32,
bits_per_sample,
sub_sampling_w,
sub_sampling_h,
core.as_ptr(),
)
};
if success != 0 {
Ok(unsafe { Self::from_ptr(&raw const format) })
} else {
Err(FormatError::InvalidVideoFormat {
color_family,
sample_type,
bits_per_sample,
sub_sampling_w,
sub_sampling_h,
})
}
}
#[must_use]
pub fn query_format_id(&self, core: &crate::core::CoreRef) -> u32 {
unsafe {
API::get_cached().query_video_format_id(
self.color_family as i32,
self.sample_type as i32,
self.bits_per_sample,
self.sub_sampling_w,
self.sub_sampling_h,
core.as_ptr(),
)
}
}
#[must_use]
pub const fn as_ffi(&self) -> ffi::VSVideoFormat {
ffi::VSVideoFormat {
colorFamily: self.color_family as i32,
sampleType: self.sample_type as i32,
bitsPerSample: self.bits_per_sample,
bytesPerSample: self.bytes_per_sample,
subSamplingW: self.sub_sampling_w,
subSamplingH: self.sub_sampling_h,
numPlanes: self.num_planes,
}
}
#[must_use]
pub fn get_name(&self) -> Option<String> {
unsafe { API::get_cached().get_video_format_name(&self.as_ffi()) }
}
pub const YUV420P8: Self = Self {
color_family: ColorFamily::YUV,
sample_type: SampleType::Integer,
bits_per_sample: 8,
bytes_per_sample: 1,
sub_sampling_w: 2,
sub_sampling_h: 2,
num_planes: 3,
};
pub const YUV444P8: Self = Self {
color_family: ColorFamily::YUV,
sample_type: SampleType::Integer,
bits_per_sample: 8,
bytes_per_sample: 1,
sub_sampling_w: 1,
sub_sampling_h: 1,
num_planes: 3,
};
pub const RGB24: Self = Self {
color_family: ColorFamily::RGB,
sample_type: SampleType::Integer,
bits_per_sample: 8,
bytes_per_sample: 1,
sub_sampling_w: 0,
sub_sampling_h: 0,
num_planes: 3,
};
pub const GRAY8: Self = Self {
color_family: ColorFamily::Gray,
sample_type: SampleType::Integer,
bits_per_sample: 8,
bytes_per_sample: 1,
sub_sampling_w: 0,
sub_sampling_h: 0,
num_planes: 1,
};
}
impl VideoInfo {
#[must_use]
pub unsafe fn from_ptr(from: *const ffi::VSVideoInfo) -> Self {
let from = &*from;
Self {
format: VideoFormat::from_ptr(&raw const from.format),
fps_num: from.fpsNum,
fps_den: from.fpsDen,
width: from.width,
height: from.height,
num_frames: from.numFrames,
}
}
#[must_use]
pub const fn as_ffi(&self) -> ffi::VSVideoInfo {
ffi::VSVideoInfo {
format: self.format.as_ffi(),
fpsNum: self.fps_num,
fpsDen: self.fps_den,
width: self.width,
height: self.height,
numFrames: self.num_frames,
}
}
}
#[derive(Debug, Clone)]
pub struct VideoFormatBuilder {
color_family: ColorFamily,
sample_type: SampleType,
bits_per_sample: i32,
sub_sampling_w: i32,
sub_sampling_h: i32,
}
impl VideoFormatBuilder {
#[must_use]
pub const fn new(
color_family: ColorFamily,
sample_type: SampleType,
bits_per_sample: i32,
) -> Self {
Self {
color_family,
sample_type,
bits_per_sample,
sub_sampling_w: 0,
sub_sampling_h: 0,
}
}
#[must_use]
pub const fn sub_sampling_w(mut self, sub_sampling_w: i32) -> Self {
self.sub_sampling_w = sub_sampling_w;
self
}
#[must_use]
pub const fn sub_sampling_h(mut self, sub_sampling_h: i32) -> Self {
self.sub_sampling_h = sub_sampling_h;
self
}
#[must_use]
pub const fn sub_sampling(mut self, sub_sampling_w: i32, sub_sampling_h: i32) -> Self {
self.sub_sampling_w = sub_sampling_w;
self.sub_sampling_h = sub_sampling_h;
self
}
pub fn build(self, core: &crate::core::CoreRef) -> Result<VideoFormat, FormatError> {
VideoFormat::query(
self.color_family,
self.sample_type,
self.bits_per_sample,
self.sub_sampling_w,
self.sub_sampling_h,
core,
)
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct VideoInfo {
pub format: VideoFormat,
pub fps_num: i64,
pub fps_den: i64,
pub width: i32,
pub height: i32,
pub num_frames: i32,
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct VideoFormat {
pub color_family: ColorFamily,
pub sample_type: SampleType,
pub bits_per_sample: i32,
pub bytes_per_sample: i32,
pub sub_sampling_w: i32,
pub sub_sampling_h: i32,
pub num_planes: i32,
}