phaneron_plugin_utils/
yadif.rs1use std::collections::VecDeque;
20
21use phaneron_plugin::{traits::ProcessShader, types::NodeContext, types::VideoFrame, ShaderParams};
22
23#[derive(PartialEq, Eq)]
24pub enum YadifMode {
25 Field,
26 FrameNospatial,
27 FieldNospatial,
28}
29
30pub struct YadifConfig {
31 pub mode: YadifMode,
32 pub tff: bool,
33}
34
35pub struct Yadif {
36 config: YadifConfig,
37 send_field: bool,
38 skip_spatial: bool,
39 yadif_cl: YadifCl,
40 input: VecDeque<VideoFrame>,
41}
42
43impl Yadif {
44 pub fn new(context: &NodeContext, width: usize, height: usize, config: YadifConfig) -> Self {
45 let send_field =
46 config.mode == YadifMode::Field || config.mode == YadifMode::FieldNospatial;
47 let skip_spatial =
48 config.mode == YadifMode::FrameNospatial || config.mode == YadifMode::FieldNospatial;
49 let yadif_cl = YadifCl::new(context, width, height);
50 Self {
51 config,
52 send_field,
53 skip_spatial,
54 yadif_cl,
55 input: VecDeque::with_capacity(4), }
57 }
58
59 pub fn run(&mut self, source: &VideoFrame) -> Vec<VideoFrame> {
60 self.input.push_front(source.clone());
61 if self.input.len() < 3 {
62 return vec![];
63 }
64
65 if self.input.len() > 3 {
66 self.input.pop_back();
67 }
68
69 let mut outputs: Vec<VideoFrame> = vec![];
70
71 let output = self.run_yadif(false);
72 outputs.push(output);
73
74 if self.send_field {
75 let output = self.run_yadif(true);
76 outputs.push(output);
77 }
78
79 outputs
80 }
81
82 fn run_yadif(&mut self, is_second: bool) -> VideoFrame {
83 self.yadif_cl.run(
84 self.input.iter().collect::<Vec<&VideoFrame>>().as_slice(),
85 u32::from(self.config.tff) ^ u32::from(!is_second),
86 u32::from(self.config.tff),
87 u32::from(self.skip_spatial),
88 )
89 }
90}
91
92pub struct YadifCl {
93 width: usize,
94 height: usize,
95 shader: Box<dyn ProcessShader>,
96}
97
98impl YadifCl {
99 fn new(context: &NodeContext, width: usize, height: usize) -> Self {
100 let kernel = include_str!("shaders/yadif.cl");
101 let shader = context.create_process_shader(kernel.into(), "yadif".into());
102
103 Self {
104 width,
105 height,
106 shader: Box::new(shader),
107 }
108 }
109
110 fn run(&self, inputs: &[&VideoFrame], parity: u32, tff: u32, skip_spatial: u32) -> VideoFrame {
111 let mut params = ShaderParams::default();
112 params.set_param_video_frame_input(inputs[0].clone());
113 params.set_param_video_frame_input(inputs[1].clone());
114 params.set_param_video_frame_input(inputs[2].clone());
115 params.set_param_u32_input(parity);
116 params.set_param_u32_input(tff);
117 params.set_param_u32_input(skip_spatial);
118 params.set_param_video_frame_output(self.width, self.height);
119
120 let outputs = self.shader.run(params, &[self.width, self.height]);
121
122 outputs[0].clone()
123 }
124}