1use std::borrow::Cow;
2
3use crate::common::{FileFilter, Rational32, 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) -> crate::input::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) -> crate::input::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: crate::common::AviUtl2Info) -> crate::common::AnyResult<Self>;
381
382 fn plugin_info(&self) -> crate::input::InputPluginTable;
384
385 fn open(&self, file: std::path::PathBuf) -> crate::common::AnyResult<Self::InputHandle>;
387 fn close(&self, handle: Self::InputHandle) -> crate::common::AnyResult<()>;
389
390 fn get_track_count(
392 &self,
393 handle: &mut Self::InputHandle,
394 ) -> crate::common::AnyResult<(u32, u32)> {
395 let info = self.get_input_info(handle, 0, 0)?;
396 let video_tracks = info.video.as_ref().map_or(0, |_| 1);
397 let audio_tracks = info.audio.as_ref().map_or(0, |_| 1);
398 Ok((video_tracks, audio_tracks))
399 }
400
401 fn get_input_info(
403 &self,
404 handle: &mut Self::InputHandle,
405 video_track: u32,
406 audio_track: u32,
407 ) -> crate::common::AnyResult<crate::input::InputInfo>;
408
409 fn read_video(
418 &self,
419 handle: &Self::InputHandle,
420 frame: u32,
421 returner: &mut crate::input::ImageReturner,
422 ) -> crate::common::AnyResult<()> {
423 let _ = (handle, frame, returner);
424 Result::<(), anyhow::Error>::Err(anyhow::anyhow!(
425 "read_video is not implemented for this plugin"
426 ))
427 }
428
429 fn read_video_mut(
438 &self,
439 handle: &mut Self::InputHandle,
440 frame: u32,
441 returner: &mut crate::input::ImageReturner,
442 ) -> crate::common::AnyResult<()> {
443 self.read_video(handle, frame, returner)
444 }
445
446 fn can_set_video_track(
452 &self,
453 handle: &mut Self::InputHandle,
454 track: u32,
455 ) -> crate::common::AnyResult<u32> {
456 let _ = handle;
457 Ok(track)
458 }
459
460 fn time_to_frame(
464 &self,
465 handle: &mut Self::InputHandle,
466 track: u32,
467 time: f64,
468 ) -> crate::common::AnyResult<u32> {
469 const RESOLUTION: i32 = 1000; let info = self.get_input_info(handle, track, 0)?;
471 if let Some(video_info) = &info.video {
472 Ok(
473 (video_info.fps * Rational32::new((time * RESOLUTION as f64) as i32, RESOLUTION))
474 .to_integer() as u32,
475 )
476 } else {
477 Err(anyhow::anyhow!("No video information available"))
478 }
479 }
480
481 fn read_audio(
490 &self,
491 handle: &Self::InputHandle,
492 start: i32,
493 length: i32,
494 returner: &mut crate::input::AudioReturner,
495 ) -> crate::common::AnyResult<()> {
496 let _ = (handle, start, length, returner);
497 Result::<(), anyhow::Error>::Err(anyhow::anyhow!(
498 "read_audio is not implemented for this plugin"
499 ))
500 }
501
502 fn read_audio_mut(
511 &self,
512 handle: &mut Self::InputHandle,
513 start: i32,
514 length: i32,
515 returner: &mut crate::input::AudioReturner,
516 ) -> crate::common::AnyResult<()> {
517 self.read_audio(handle, start, length, returner)
518 }
519
520 fn can_set_audio_track(
526 &self,
527 handle: &mut Self::InputHandle,
528 track: u32,
529 ) -> crate::common::AnyResult<u32> {
530 let _ = handle;
531 Ok(track)
532 }
533
534 fn config(&self, hwnd: crate::common::Win32WindowHandle) -> crate::common::AnyResult<()> {
536 let _ = hwnd;
537 Ok(())
538 }
539
540 fn with_instance<R>(f: impl FnOnce(&Self) -> R) -> R
546 where
547 Self: crate::input::__bridge::InputSingleton,
548 {
549 <Self as crate::input::__bridge::InputSingleton>::with_instance(f)
550 }
551
552 fn with_instance_mut<R>(f: impl FnOnce(&mut Self) -> R) -> R
558 where
559 Self: crate::input::__bridge::InputSingleton,
560 {
561 <Self as crate::input::__bridge::InputSingleton>::with_instance_mut(f)
562 }
563}