257 lines
7.0 KiB
Rust
257 lines
7.0 KiB
Rust
//! VapourSynth frame formats.
|
|
|
|
use std::ffi::CStr;
|
|
use std::fmt::{self, Display};
|
|
use std::marker::PhantomData;
|
|
use std::ops::Deref;
|
|
use vapoursynth_sys as ffi;
|
|
|
|
/// Contains information about a video format.
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub struct Format<'core> {
|
|
handle: &'core ffi::VSFormat,
|
|
}
|
|
|
|
/// Preset VapourSynth formats.
|
|
///
|
|
/// The presets suffixed with H and S have floating point sample type. The H and S suffixes stand
|
|
/// for half precision and single precision, respectively.
|
|
///
|
|
/// The compat formats are the only packed formats in VapourSynth. Everything else is planar. They
|
|
/// exist for compatibility with Avisynth plugins. They are not to be implemented in native
|
|
/// VapourSynth plugins.
|
|
#[cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))]
|
|
#[repr(i32)]
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
|
pub enum PresetFormat {
|
|
Gray8 = 1000010,
|
|
Gray16 = 1000011,
|
|
GrayH = 1000012,
|
|
GrayS = 1000013,
|
|
YUV420P8 = 3000010,
|
|
YUV422P8 = 3000011,
|
|
YUV444P8 = 3000012,
|
|
YUV410P8 = 3000013,
|
|
YUV411P8 = 3000014,
|
|
YUV440P8 = 3000015,
|
|
YUV420P9 = 3000016,
|
|
YUV422P9 = 3000017,
|
|
YUV444P9 = 3000018,
|
|
YUV420P10 = 3000019,
|
|
YUV422P10 = 3000020,
|
|
YUV444P10 = 3000021,
|
|
YUV420P16 = 3000022,
|
|
YUV422P16 = 3000023,
|
|
YUV444P16 = 3000024,
|
|
YUV444PH = 3000025,
|
|
YUV444PS = 3000026,
|
|
YUV420P12 = 3000027,
|
|
YUV422P12 = 3000028,
|
|
YUV444P12 = 3000029,
|
|
YUV420P14 = 3000030,
|
|
YUV422P14 = 3000031,
|
|
YUV444P14 = 3000032,
|
|
RGB24 = 2000010,
|
|
RGB27 = 2000011,
|
|
RGB30 = 2000012,
|
|
RGB48 = 2000013,
|
|
RGBH = 2000014,
|
|
RGBS = 2000015,
|
|
CompatBGR32 = 9000010,
|
|
CompatYUY2 = 9000011,
|
|
}
|
|
|
|
/// Format color families.
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
|
pub enum ColorFamily {
|
|
Gray,
|
|
RGB,
|
|
YUV,
|
|
YCoCg,
|
|
Compat,
|
|
}
|
|
|
|
/// Format sample types.
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
|
pub enum SampleType {
|
|
Integer,
|
|
Float,
|
|
}
|
|
|
|
/// A unique format identifier.
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
|
pub struct FormatID(pub(crate) i32);
|
|
|
|
impl<'core> PartialEq for Format<'core> {
|
|
#[inline]
|
|
fn eq(&self, other: &Format<'core>) -> bool {
|
|
self.id() == other.id()
|
|
}
|
|
}
|
|
|
|
impl<'core> Eq for Format<'core> {}
|
|
|
|
#[doc(hidden)]
|
|
impl<'core> Deref for Format<'core> {
|
|
type Target = ffi::VSFormat;
|
|
|
|
// Technically this should return `&'core`.
|
|
#[inline]
|
|
fn deref(&self) -> &Self::Target {
|
|
self.handle
|
|
}
|
|
}
|
|
|
|
impl<'core> Format<'core> {
|
|
/// Wraps a raw pointer in a `Format`.
|
|
///
|
|
/// # Safety
|
|
/// The caller must ensure `ptr` and the lifetime is valid.
|
|
#[inline]
|
|
pub(crate) unsafe fn from_ptr(ptr: *const ffi::VSFormat) -> Self {
|
|
Self { handle: &*ptr }
|
|
}
|
|
|
|
/// Gets the unique identifier of this format.
|
|
#[inline]
|
|
pub fn id(self) -> FormatID {
|
|
FormatID(self.handle.id)
|
|
}
|
|
|
|
/// Gets the printable name of this format.
|
|
#[inline]
|
|
pub fn name(self) -> &'core str {
|
|
unsafe { CStr::from_ptr(&self.handle.name as _).to_str().unwrap() }
|
|
}
|
|
|
|
/// Gets the number of planes of this format.
|
|
#[inline]
|
|
pub fn plane_count(self) -> usize {
|
|
let plane_count = self.handle.numPlanes;
|
|
debug_assert!(plane_count >= 0);
|
|
plane_count as usize
|
|
}
|
|
|
|
/// Gets the color family of this format.
|
|
#[inline]
|
|
pub fn color_family(self) -> ColorFamily {
|
|
match self.handle.colorFamily {
|
|
x if x == ffi::VSColorFamily::cmGray as i32 => ColorFamily::Gray,
|
|
x if x == ffi::VSColorFamily::cmRGB as i32 => ColorFamily::RGB,
|
|
x if x == ffi::VSColorFamily::cmYUV as i32 => ColorFamily::YUV,
|
|
x if x == ffi::VSColorFamily::cmYCoCg as i32 => ColorFamily::YCoCg,
|
|
x if x == ffi::VSColorFamily::cmCompat as i32 => ColorFamily::Compat,
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
/// Gets the sample type of this format.
|
|
#[inline]
|
|
pub fn sample_type(self) -> SampleType {
|
|
match self.handle.sampleType {
|
|
x if x == ffi::VSSampleType::stInteger as i32 => SampleType::Integer,
|
|
x if x == ffi::VSSampleType::stFloat as i32 => SampleType::Float,
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
/// Gets the number of significant bits per sample.
|
|
#[inline]
|
|
pub fn bits_per_sample(self) -> u8 {
|
|
let rv = self.handle.bitsPerSample;
|
|
debug_assert!(rv >= 0 && rv <= i32::from(u8::max_value()));
|
|
rv as u8
|
|
}
|
|
|
|
/// Gets the number of bytes needed for a sample. This is always a power of 2 and the smallest
|
|
/// possible that can fit the number of bits used per sample.
|
|
#[inline]
|
|
pub fn bytes_per_sample(self) -> u8 {
|
|
let rv = self.handle.bytesPerSample;
|
|
debug_assert!(rv >= 0 && rv <= i32::from(u8::max_value()));
|
|
rv as u8
|
|
}
|
|
|
|
/// log2 subsampling factor, applied to second and third plane.
|
|
#[inline]
|
|
pub fn sub_sampling_w(self) -> u8 {
|
|
let rv = self.handle.subSamplingW;
|
|
debug_assert!(rv >= 0 && rv <= i32::from(u8::max_value()));
|
|
rv as u8
|
|
}
|
|
|
|
/// log2 subsampling factor, applied to second and third plane.
|
|
#[inline]
|
|
pub fn sub_sampling_h(self) -> u8 {
|
|
let rv = self.handle.subSamplingH;
|
|
debug_assert!(rv >= 0 && rv <= i32::from(u8::max_value()));
|
|
rv as u8
|
|
}
|
|
}
|
|
|
|
impl From<PresetFormat> for FormatID {
|
|
fn from(x: PresetFormat) -> Self {
|
|
FormatID(x as i32)
|
|
}
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
impl From<ColorFamily> for ffi::VSColorFamily {
|
|
#[inline]
|
|
fn from(x: ColorFamily) -> Self {
|
|
match x {
|
|
ColorFamily::Gray => ffi::VSColorFamily::cmGray,
|
|
ColorFamily::RGB => ffi::VSColorFamily::cmRGB,
|
|
ColorFamily::YUV => ffi::VSColorFamily::cmYUV,
|
|
ColorFamily::YCoCg => ffi::VSColorFamily::cmYCoCg,
|
|
ColorFamily::Compat => ffi::VSColorFamily::cmCompat,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
impl From<SampleType> for ffi::VSSampleType {
|
|
#[inline]
|
|
fn from(x: SampleType) -> Self {
|
|
match x {
|
|
SampleType::Integer => ffi::VSSampleType::stInteger,
|
|
SampleType::Float => ffi::VSSampleType::stFloat,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Display for ColorFamily {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
|
write!(
|
|
f,
|
|
"{}",
|
|
match *self {
|
|
ColorFamily::Gray => "Gray",
|
|
ColorFamily::RGB => "RGB",
|
|
ColorFamily::YUV => "YUV",
|
|
ColorFamily::YCoCg => "YCoCg",
|
|
ColorFamily::Compat => "Compat",
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|
|
impl Display for SampleType {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
|
write!(
|
|
f,
|
|
"{}",
|
|
match *self {
|
|
SampleType::Integer => "Integer",
|
|
SampleType::Float => "Float",
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|
|
impl From<i32> for FormatID {
|
|
fn from(x: i32) -> Self {
|
|
FormatID(x)
|
|
}
|
|
}
|