1use std::borrow::Cow;
2
3use crate::common::{AnyResult, AviUtl2Info, FileFilter, Rational32, Win32WindowHandle, Yc48, f16};
4use zerocopy::IntoBytes;
5
6#[derive(Debug, Clone)]
8pub struct InputPluginTable {
9 pub name: String,
11 pub information: String,
14
15 pub input_type: InputType,
17 pub concurrent: bool,
27 pub file_filters: Vec<FileFilter>,
29
30 pub can_config: bool,
32}
33
34#[derive(Debug, Clone)]
36pub struct VideoInputInfo {
37 pub fps: Rational32,
39
40 pub num_frames: u32,
43
44 pub manual_frame_index: bool,
49
50 pub width: u32,
52 pub height: u32,
54
55 pub format: InputPixelFormat,
57}
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
61pub enum InputPixelFormat {
62 Bgr,
74 Bgra,
86 Yuy2,
89 Pa64,
92 Yc48,
98 Hf64,
101}
102
103#[derive(Debug, Clone)]
105pub struct AudioInputInfo {
106 pub sample_rate: u32,
108 pub num_samples: u32,
110 pub channels: u16,
112
113 pub format: AudioFormat,
115}
116
117#[derive(Debug, Clone)]
119pub enum AudioFormat {
120 Pcm16,
122 IeeeFloat32,
124}
125
126#[derive(Debug, Clone)]
128pub struct InputInfo {
129 pub video: Option<VideoInputInfo>,
131 pub audio: Option<AudioInputInfo>,
133}
134
135#[derive(Debug, Clone)]
137pub enum InputType {
138 Video,
140 Audio,
142 Both,
144}
145
146impl InputType {
147 pub(crate) fn to_bits(&self) -> i32 {
148 match self {
149 InputType::Video => 1,
150 InputType::Audio => 2,
151 InputType::Both => 3,
152 }
153 }
154}
155
156#[derive(Debug, Clone)]
158pub struct ImageBuffer(pub Vec<u8>);
159
160impl std::ops::Deref for ImageBuffer {
161 type Target = [u8];
162 fn deref(&self) -> &Self::Target {
163 &self.0
164 }
165}
166
167pub trait IntoImage {
169 fn into_image(self) -> ImageBuffer;
170}
171
172impl<T: AsImage> IntoImage for T {
173 fn into_image(self) -> ImageBuffer {
174 ImageBuffer(self.as_image().into_owned())
175 }
176}
177
178pub trait AsImage {
180 fn as_image(&'_ self) -> Cow<'_, [u8]>;
181}
182
183impl AsImage for ImageBuffer {
184 fn as_image(&'_ self) -> Cow<'_, [u8]> {
185 Cow::Borrowed(&self.0)
186 }
187}
188
189impl AsImage for Vec<u8> {
190 fn as_image(&'_ self) -> Cow<'_, [u8]> {
191 Cow::Borrowed(self)
192 }
193}
194
195impl AsImage for &[u8] {
196 fn as_image(&'_ self) -> Cow<'_, [u8]> {
197 Cow::Borrowed(self)
198 }
199}
200
201impl AsImage for Cow<'_, [u8]> {
202 fn as_image(&'_ self) -> Cow<'_, [u8]> {
203 match self {
204 Cow::Borrowed(b) => Cow::Borrowed(b),
205 Cow::Owned(b) => Cow::Borrowed(b),
206 }
207 }
208}
209
210duplicate::duplicate! {
211 [
212 Name Trait method;
213 [ImageReturner] [AsImage] [as_image];
214 [AudioReturner] [AsAudio] [as_audio];
215 ]
216 pub struct Name {
218 ptr: *mut u8,
219 pub(crate) written: usize,
220 }
221
222 impl Name {
223 pub(crate) unsafe fn new(ptr: *mut u8) -> Self {
227 Self { ptr, written: 0 }
228 }
229
230 pub fn write(&mut self, data: &impl Trait) {
231 let image = data.method();
232 unsafe {
233 std::ptr::copy_nonoverlapping(image.as_ptr(), self.ptr.add(self.written), image.len());
234 }
235 self.written += image.len();
236 }
237 }
238}
239
240#[duplicate::duplicate_item(
241 T;
242 [Vec<u16>];
243 [Vec<i16>];
244 [Vec<f16>];
245 [Vec<Yc48>];
246)]
247impl AsImage for T {
248 fn as_image(&'_ self) -> Cow<'_, [u8]> {
249 Cow::Borrowed(self.as_bytes())
250 }
251}
252
253#[cfg(feature = "image")]
254impl AsImage for image::RgbImage {
255 fn as_image(&'_ self) -> Cow<'_, [u8]> {
256 let mut data = self.as_raw().to_owned();
257 crate::utils::bgr_to_rgb_bytes(&mut data);
258 crate::utils::flip_vertical(&mut data, self.width() as usize * 3, self.height() as usize);
259 Cow::Owned(data)
260 }
261}
262
263#[cfg(feature = "image")]
264impl AsImage for image::RgbaImage {
265 fn as_image(&'_ self) -> Cow<'_, [u8]> {
266 let mut data = self.as_raw().to_owned();
267 crate::utils::bgra_to_rgba_bytes(&mut data);
268 crate::utils::flip_vertical(&mut data, self.width() as usize * 4, self.height() as usize);
269 Cow::Owned(data)
270 }
271}
272
273#[cfg(feature = "image")]
274impl AsImage for image::ImageBuffer<image::Rgb<u16>, Vec<u16>> {
275 fn as_image(&'_ self) -> Cow<'_, [u8]> {
276 let data = self.as_raw();
277 Cow::Owned(data.as_bytes().to_vec())
278 }
279}
280
281#[cfg(feature = "image")]
282impl AsImage for image::ImageBuffer<image::Rgba<u16>, Vec<u16>> {
283 fn as_image(&'_ self) -> Cow<'_, [u8]> {
284 let data = self.as_raw();
285 Cow::Owned(data.as_bytes().to_vec())
286 }
287}
288
289macro_rules! as_image_impl_for_tuple {
290 ($type:ty, $($name:ident),+) => {
291 impl AsImage for Vec<$type> {
292 fn as_image(&'_ self) -> Cow<'_, [u8]> {
293 let mut img_data = Vec::with_capacity(self.len() * std::mem::size_of::<$type>());
294 for ($($name,)+) in self {
295 $(img_data.extend_from_slice(&$name.to_le_bytes());)+
296 }
297 Cow::Owned(img_data)
298 }
299 }
300 };
301}
302
303as_image_impl_for_tuple!((u8, u8, u8), r, g, b);
304as_image_impl_for_tuple!((u8, u8, u8, u8), r, g, b, a);
305as_image_impl_for_tuple!((u16, u16, u16, u16), r, g, b, a);
306as_image_impl_for_tuple!((f16, f16, f16, f16), r, g, b, a);
307as_image_impl_for_tuple!((i16, i16, i16), y, cb, cr);
308
309#[derive(Debug, Clone)]
311pub struct AudioBuffer(pub Vec<u8>);
312
313impl std::ops::Deref for AudioBuffer {
314 type Target = [u8];
315 fn deref(&self) -> &Self::Target {
316 &self.0
317 }
318}
319
320pub trait IntoAudio {
322 fn into_audio(self) -> AudioBuffer;
323}
324
325impl<T: AsAudio> IntoAudio for T {
326 fn into_audio(self) -> AudioBuffer {
327 AudioBuffer(self.as_audio().into_owned())
328 }
329}
330
331pub trait AsAudio {
333 fn as_audio(&'_ self) -> Cow<'_, [u8]>;
334}
335
336impl AsAudio for AudioBuffer {
337 fn as_audio(&'_ self) -> Cow<'_, [u8]> {
338 Cow::Borrowed(&self.0)
339 }
340}
341impl AsAudio for Vec<u8> {
342 fn as_audio(&'_ self) -> Cow<'_, [u8]> {
343 Cow::Borrowed(self)
344 }
345}
346#[duplicate::duplicate_item(
347 T;
348 [Vec<u16>];
349 [Vec<f32>];
350)]
351impl AsAudio for T {
352 fn as_audio(&'_ self) -> Cow<'_, [u8]> {
353 Cow::Borrowed(self.as_bytes())
354 }
355}
356
357macro_rules! into_audio_impl_for_tuple {
358 ($type:ty, $($name:ident),+) => {
359 impl AsAudio for Vec<$type> {
360 fn as_audio(&'_ self) -> Cow<'_, [u8]> {
361 let mut audio_data = Vec::with_capacity(self.len() * std::mem::size_of::<$type>());
362 for ($($name,)+) in self {
363 $(audio_data.extend_from_slice(&$name.to_le_bytes());)+
364 }
365 Cow::Owned(audio_data)
366 }
367 }
368 };
369}
370into_audio_impl_for_tuple!((u16, u16), l, r);
371into_audio_impl_for_tuple!((f32, f32), l, r);
372
373pub trait InputPlugin: Send + Sync + Sized {
376 type InputHandle: std::any::Any + Send + Sync;
378
379 fn new(info: AviUtl2Info) -> AnyResult<Self>;
381
382 fn plugin_info(&self) -> InputPluginTable;
384
385 fn open(&self, file: std::path::PathBuf) -> AnyResult<Self::InputHandle>;
387 fn close(&self, handle: Self::InputHandle) -> AnyResult<()>;
389
390 fn get_track_count(&self, handle: &mut Self::InputHandle) -> AnyResult<(u32, u32)> {
392 let info = self.get_input_info(handle, 0, 0)?;
393 let video_tracks = info.video.as_ref().map_or(0, |_| 1);
394 let audio_tracks = info.audio.as_ref().map_or(0, |_| 1);
395 Ok((video_tracks, audio_tracks))
396 }
397
398 fn get_input_info(
400 &self,
401 handle: &mut Self::InputHandle,
402 video_track: u32,
403 audio_track: u32,
404 ) -> AnyResult<InputInfo>;
405
406 fn read_video(
415 &self,
416 handle: &Self::InputHandle,
417 frame: u32,
418 returner: &mut ImageReturner,
419 ) -> AnyResult<()> {
420 let _ = (handle, frame, returner);
421 Result::<(), anyhow::Error>::Err(anyhow::anyhow!(
422 "read_video is not implemented for this plugin"
423 ))
424 }
425
426 fn read_video_mut(
435 &self,
436 handle: &mut Self::InputHandle,
437 frame: u32,
438 returner: &mut ImageReturner,
439 ) -> AnyResult<()> {
440 self.read_video(handle, frame, returner)
441 }
442
443 fn can_set_video_track(&self, _handle: &mut Self::InputHandle, track: u32) -> AnyResult<u32> {
449 Ok(track)
450 }
451
452 fn time_to_frame(
456 &self,
457 handle: &mut Self::InputHandle,
458 track: u32,
459 time: f64,
460 ) -> AnyResult<u32> {
461 const RESOLUTION: i32 = 1000; let info = self.get_input_info(handle, track, 0)?;
463 if let Some(video_info) = &info.video {
464 Ok(
465 (video_info.fps * Rational32::new((time * RESOLUTION as f64) as i32, RESOLUTION))
466 .to_integer() as u32,
467 )
468 } else {
469 Err(anyhow::anyhow!("No video information available"))
470 }
471 }
472
473 fn read_audio(
482 &self,
483 handle: &Self::InputHandle,
484 start: i32,
485 length: i32,
486 returner: &mut AudioReturner,
487 ) -> AnyResult<()> {
488 let _ = (handle, start, length, returner);
489 Result::<(), anyhow::Error>::Err(anyhow::anyhow!(
490 "read_audio is not implemented for this plugin"
491 ))
492 }
493
494 fn read_audio_mut(
503 &self,
504 handle: &mut Self::InputHandle,
505 start: i32,
506 length: i32,
507 returner: &mut AudioReturner,
508 ) -> AnyResult<()> {
509 self.read_audio(handle, start, length, returner)
510 }
511
512 fn can_set_audio_track(&self, _handle: &mut Self::InputHandle, track: u32) -> AnyResult<u32> {
518 Ok(track)
519 }
520
521 fn config(&self, _hwnd: Win32WindowHandle) -> AnyResult<()> {
523 Ok(())
524 }
525
526 fn with_instance<R>(f: impl FnOnce(&Self) -> R) -> R
532 where
533 Self: crate::input::__bridge::InputSingleton,
534 {
535 <Self as crate::input::__bridge::InputSingleton>::with_instance(f)
536 }
537
538 fn with_instance_mut<R>(f: impl FnOnce(&mut Self) -> R) -> R
544 where
545 Self: crate::input::__bridge::InputSingleton,
546 {
547 <Self as crate::input::__bridge::InputSingleton>::with_instance_mut(f)
548 }
549}