vapoursynth4_sys/
helper.rs1#![allow(clippy::cast_possible_truncation)]
10
11use std::ffi::{c_int, c_void};
12
13use crate::{
14 VSAPI, VSAudioFormat, VSAudioInfo, VSColorFamily, VSCore, VSPresetVideoFormat, VSVideoFormat,
15 VSVideoInfo,
16};
17
18#[inline]
20#[must_use]
21pub const fn is_constant_video_format(vi: &VSVideoInfo) -> bool {
22 vi.height > 0
23 && vi.width > 0
24 && vi.format.color_family as i32 != VSColorFamily::Undefined as i32
25}
26
27#[inline]
30#[must_use]
31pub const fn is_same_video_format(v1: &VSVideoFormat, v2: &VSVideoFormat) -> bool {
32 v1.color_family as i32 == v2.color_family as i32
33 && v1.sample_type as i32 == v2.sample_type as i32
34 && v1.bits_per_sample == v2.bits_per_sample
35 && v1.sub_sampling_w == v2.sub_sampling_w
36 && v1.sub_sampling_h == v2.sub_sampling_h
37}
38
39impl VSAPI {
40 #[inline]
46 pub unsafe fn is_same_video_preset_format(
47 &self,
48 preset_format: VSPresetVideoFormat,
49 v: &VSVideoFormat,
50 core: *mut VSCore,
51 ) -> bool {
52 unsafe {
53 (self.queryVideoFormatID)(
54 v.color_family,
55 v.sample_type,
56 v.bits_per_sample,
57 v.sub_sampling_w,
58 v.sub_sampling_h,
59 core,
60 ) == preset_format as u32
61 }
62 }
63}
64
65#[inline]
69#[must_use]
70pub const fn is_same_video_info(v1: &VSVideoInfo, v2: &VSVideoInfo) -> bool {
71 v1.height == v2.height && v1.width == v2.width && is_same_video_format(&v1.format, &v2.format)
72}
73
74#[inline]
77#[must_use]
78pub const fn is_same_audio_format(a1: &VSAudioFormat, a2: &VSAudioFormat) -> bool {
79 a1.bits_per_sample == a2.bits_per_sample
80 && a1.sample_type as i32 == a2.sample_type as i32
81 && a1.channel_layout == a2.channel_layout
82}
83
84#[inline]
87#[must_use]
88pub const fn is_same_audio_info(a1: &VSAudioInfo, a2: &VSAudioInfo) -> bool {
89 a1.sample_rate == a2.sample_rate && is_same_audio_format(&a1.format, &a2.format)
90}
91
92#[inline]
96pub fn muldiv_rational(num: &mut i64, den: &mut i64, mul: i64, div: i64) {
97 if *den == 0 {
99 return;
100 }
101
102 *num *= mul;
103 *den *= div;
104 let mut a = *num;
105 let mut b = *den;
106 while b != 0 {
107 let t = a;
108 a = b;
109 b = t % b;
110 }
111 if a < 0 {
112 a = -a;
113 }
114
115 *num /= a;
116 *den /= a;
117}
118
119#[inline]
121pub fn reduce_rational(num: &mut i64, den: &mut i64) {
122 muldiv_rational(num, den, 1, 1);
123}
124
125#[inline]
127pub fn add_rational(num: &mut i64, den: &mut i64, mut addnum: i64, addden: i64) {
128 if *den == 0 {
130 return;
131 }
132
133 if *den == addden {
134 *num += addnum;
135 } else {
136 let temp = addden;
137 addnum *= *den;
138 *num *= temp;
140 *den *= temp;
141
142 *num += addnum;
143
144 reduce_rational(num, den);
145 }
146}
147
148#[inline]
151#[must_use]
152pub const fn int64_to_int_s(i: i64) -> c_int {
153 if i > c_int::MAX as i64 {
154 c_int::MAX
155 } else if i < c_int::MIN as i64 {
156 c_int::MIN
157 } else {
158 i as c_int
159 }
160}
161
162#[inline]
165#[must_use]
166pub const fn double_to_float_s(d: f64) -> f32 {
167 d as f32
168}
169
170#[inline]
175pub unsafe fn bitblt(
176 dstp: *mut c_void,
177 dst_stride: isize,
178 srcp: *const c_void,
179 src_stride: isize,
180 row_size: usize,
181 height: usize,
182) {
183 if height != 0 {
184 if src_stride == dst_stride && src_stride == row_size as isize {
185 unsafe { dstp.copy_from_nonoverlapping(srcp, row_size * height) };
186 } else {
187 let mut srcp8 = srcp.cast::<u8>();
188 let mut dstp8 = dstp.cast::<u8>();
189 let mut i = 0;
190 while i < height {
191 unsafe { dstp8.copy_from_nonoverlapping(srcp8, row_size) };
192 srcp8 = srcp8.wrapping_offset(src_stride);
193 dstp8 = dstp8.wrapping_offset(dst_stride);
194 i += 1;
195 }
196 }
197 }
198}
199
200#[inline]
203#[must_use]
204pub const fn are_valid_dimensions(fi: &VSVideoFormat, width: c_int, height: c_int) -> bool {
205 width % (1 << fi.sub_sampling_w) == 0 && height % (1 << fi.sub_sampling_h) == 0
206}