1 | use ffi::{GstGLFilter, GstGLFilterClass, GstGLMemory}; |
2 | use glib::translate::*; |
3 | use gst::{ |
4 | ffi::GstBuffer, result_from_gboolean, Buffer, Caps, LoggableError, PadDirection, CAT_RUST, |
5 | }; |
6 | |
7 | use super::prelude::*; |
8 | use crate::{ffi, prelude::*, GLFilter, GLMemory}; |
9 | |
10 | #[derive (Copy, Clone, Debug, PartialEq, Eq)] |
11 | pub enum GLFilterMode { |
12 | Buffer, |
13 | Texture, |
14 | } |
15 | |
16 | pub trait GLFilterImpl: GLFilterImplExt + GLBaseFilterImpl { |
17 | const MODE: GLFilterMode; |
18 | // rustdoc-stripper-ignore-next |
19 | /// Calls [`add_rgba_pad_templates`](ffi::gst_gl_filter_add_rgba_pad_templates) |
20 | /// in [`GLFilter::class_init`] if [`true`]. |
21 | const ADD_RGBA_PAD_TEMPLATES: bool = true; |
22 | |
23 | fn set_caps(&self, incaps: &Caps, outcaps: &Caps) -> Result<(), LoggableError> { |
24 | GLFilterImplExt::parent_set_caps(self, incaps, outcaps) |
25 | } |
26 | |
27 | fn filter(&self, input: &Buffer, output: &Buffer) -> Result<(), LoggableError> { |
28 | self.parent_filter(input, output) |
29 | } |
30 | |
31 | fn filter_texture(&self, input: &GLMemory, output: &GLMemory) -> Result<(), LoggableError> { |
32 | self.parent_filter_texture(input, output) |
33 | } |
34 | |
35 | fn init_fbo(&self) -> Result<(), LoggableError> { |
36 | self.parent_init_fbo() |
37 | } |
38 | |
39 | fn transform_internal_caps( |
40 | &self, |
41 | direction: PadDirection, |
42 | caps: &Caps, |
43 | filter_caps: Option<&Caps>, |
44 | ) -> Option<Caps> { |
45 | self.parent_transform_internal_caps(direction, caps, filter_caps) |
46 | } |
47 | } |
48 | |
49 | mod sealed { |
50 | pub trait Sealed {} |
51 | impl<T: super::GLFilterImplExt> Sealed for T {} |
52 | } |
53 | |
54 | pub trait GLFilterImplExt: sealed::Sealed + ObjectSubclass { |
55 | fn parent_set_caps(&self, incaps: &Caps, outcaps: &Caps) -> Result<(), LoggableError> { |
56 | unsafe { |
57 | let data = Self::type_data(); |
58 | let parent_class = data.as_ref().parent_class() as *mut GstGLFilterClass; |
59 | |
60 | (*parent_class) |
61 | .set_caps |
62 | .map(|f| { |
63 | result_from_gboolean!( |
64 | f( |
65 | self.obj().unsafe_cast_ref::<GLFilter>().to_glib_none().0, |
66 | incaps.to_glib_none().0, |
67 | outcaps.to_glib_none().0, |
68 | ), |
69 | CAT_RUST, |
70 | "Parent function `set_caps` failed" |
71 | ) |
72 | }) |
73 | .unwrap_or(Ok(())) |
74 | } |
75 | } |
76 | |
77 | fn parent_filter(&self, input: &Buffer, output: &Buffer) -> Result<(), LoggableError> { |
78 | unsafe { |
79 | let data = Self::type_data(); |
80 | let parent_class = data.as_ref().parent_class() as *mut GstGLFilterClass; |
81 | |
82 | (*parent_class) |
83 | .filter |
84 | .map(|f| { |
85 | result_from_gboolean!( |
86 | f( |
87 | self.obj().unsafe_cast_ref::<GLFilter>().to_glib_none().0, |
88 | input.to_glib_none().0, |
89 | output.to_glib_none().0, |
90 | ), |
91 | CAT_RUST, |
92 | "Parent function `filter` failed" |
93 | ) |
94 | }) |
95 | .unwrap_or(Ok(())) |
96 | } |
97 | } |
98 | |
99 | fn parent_filter_texture( |
100 | &self, |
101 | input: &GLMemory, |
102 | output: &GLMemory, |
103 | ) -> Result<(), LoggableError> { |
104 | unsafe { |
105 | let data = Self::type_data(); |
106 | let parent_class = data.as_ref().parent_class() as *mut GstGLFilterClass; |
107 | |
108 | (*parent_class) |
109 | .filter_texture |
110 | .map(|f| { |
111 | result_from_gboolean!( |
112 | f( |
113 | self.obj().unsafe_cast_ref::<GLFilter>().to_glib_none().0, |
114 | input.to_glib_none().0, |
115 | output.to_glib_none().0, |
116 | ), |
117 | CAT_RUST, |
118 | "Parent function `filter_texture` failed" |
119 | ) |
120 | }) |
121 | .unwrap_or(Ok(())) |
122 | } |
123 | } |
124 | |
125 | fn parent_init_fbo(&self) -> Result<(), LoggableError> { |
126 | unsafe { |
127 | let data = Self::type_data(); |
128 | let parent_class = data.as_ref().parent_class() as *mut GstGLFilterClass; |
129 | |
130 | (*parent_class) |
131 | .init_fbo |
132 | .map(|f| { |
133 | result_from_gboolean!( |
134 | f(self.obj().unsafe_cast_ref::<GLFilter>().to_glib_none().0), |
135 | CAT_RUST, |
136 | "Parent function `init_fbo` failed" |
137 | ) |
138 | }) |
139 | .unwrap_or(Ok(())) |
140 | } |
141 | } |
142 | fn parent_transform_internal_caps( |
143 | &self, |
144 | direction: PadDirection, |
145 | caps: &Caps, |
146 | filter_caps: Option<&Caps>, |
147 | ) -> Option<Caps> { |
148 | unsafe { |
149 | let data = Self::type_data(); |
150 | let parent_class = data.as_ref().parent_class() as *mut GstGLFilterClass; |
151 | |
152 | let f = (*parent_class) |
153 | .transform_internal_caps |
154 | .expect("Missing parent function `transform_internal_caps`" ); |
155 | |
156 | from_glib_full(f( |
157 | self.obj().unsafe_cast_ref::<GLFilter>().to_glib_none().0, |
158 | direction.into_glib(), |
159 | caps.to_glib_none().0, |
160 | filter_caps.to_glib_none().0, |
161 | )) |
162 | } |
163 | } |
164 | } |
165 | |
166 | impl<T: GLFilterImpl> GLFilterImplExt for T {} |
167 | |
168 | unsafe impl<T: GLFilterImpl> IsSubclassable<T> for GLFilter { |
169 | fn class_init(klass: &mut glib::Class<Self>) { |
170 | Self::parent_class_init::<T>(class:klass); |
171 | let klass: &mut GstGLFilterClass = klass.as_mut(); |
172 | klass.set_caps = Some(set_caps::<T>); |
173 | klass.init_fbo = Some(init_fbo::<T>); |
174 | klass.transform_internal_caps = Some(transform_internal_caps::<T>); |
175 | |
176 | match <T as GLFilterImpl>::MODE { |
177 | GLFilterMode::Buffer => { |
178 | klass.filter = Some(filter::<T>); |
179 | klass.filter_texture = None; |
180 | } |
181 | GLFilterMode::Texture => { |
182 | klass.filter = None; |
183 | klass.filter_texture = Some(filter_texture::<T>); |
184 | } |
185 | } |
186 | |
187 | if <T as GLFilterImpl>::ADD_RGBA_PAD_TEMPLATES { |
188 | unsafe { ffi::gst_gl_filter_add_rgba_pad_templates(klass) } |
189 | } |
190 | } |
191 | } |
192 | |
193 | unsafe extern "C" fn filter<T: GLFilterImpl>( |
194 | ptr: *mut GstGLFilter, |
195 | input: *mut GstBuffer, |
196 | output: *mut GstBuffer, |
197 | ) -> glib::ffi::gboolean { |
198 | let instance: &::Instance = &*(ptr as *mut T::Instance); |
199 | let imp: &T = instance.imp(); |
200 | |
201 | gstbool::panic_to_error!(imp, false, { |
202 | match imp.filter(&from_glib_borrow(input), &from_glib_borrow(output)) { |
203 | Ok(()) => true, |
204 | Err(err) => { |
205 | err.log_with_imp(imp); |
206 | false |
207 | } |
208 | } |
209 | }) |
210 | .into_glib() |
211 | } |
212 | |
213 | unsafe extern "C" fn filter_texture<T: GLFilterImpl>( |
214 | ptr: *mut GstGLFilter, |
215 | input: *mut GstGLMemory, |
216 | output: *mut GstGLMemory, |
217 | ) -> glib::ffi::gboolean { |
218 | let instance: &::Instance = &*(ptr as *mut T::Instance); |
219 | let imp: &T = instance.imp(); |
220 | |
221 | gstbool::panic_to_error!(imp, false, { |
222 | match imp.filter_texture(&from_glib_borrow(input), &from_glib_borrow(output)) { |
223 | Ok(()) => true, |
224 | Err(err) => { |
225 | err.log_with_imp(imp); |
226 | false |
227 | } |
228 | } |
229 | }) |
230 | .into_glib() |
231 | } |
232 | |
233 | unsafe extern "C" fn init_fbo<T: GLFilterImpl>(ptr: *mut GstGLFilter) -> glib::ffi::gboolean { |
234 | let instance: &::Instance = &*(ptr as *mut T::Instance); |
235 | let imp: &T = instance.imp(); |
236 | |
237 | gstbool::panic_to_error!(imp, false, { |
238 | match imp.init_fbo() { |
239 | Ok(()) => true, |
240 | Err(err) => { |
241 | err.log_with_imp(imp); |
242 | false |
243 | } |
244 | } |
245 | }) |
246 | .into_glib() |
247 | } |
248 | |
249 | unsafe extern "C" fn set_caps<T: GLFilterImpl>( |
250 | ptr: *mut GstGLFilter, |
251 | incaps: *mut gst::ffi::GstCaps, |
252 | outcaps: *mut gst::ffi::GstCaps, |
253 | ) -> glib::ffi::gboolean { |
254 | let instance: &::Instance = &*(ptr as *mut T::Instance); |
255 | let imp: &T = instance.imp(); |
256 | |
257 | gstbool::panic_to_error!(imp, false, { |
258 | match GLFilterImpl::set_caps(imp, &from_glib_borrow(incaps), &from_glib_borrow(outcaps)) { |
259 | Ok(()) => true, |
260 | Err(err) => { |
261 | err.log_with_imp(imp); |
262 | false |
263 | } |
264 | } |
265 | }) |
266 | .into_glib() |
267 | } |
268 | |
269 | unsafe extern "C" fn transform_internal_caps<T: GLFilterImpl>( |
270 | ptr: *mut GstGLFilter, |
271 | direction: gst::ffi::GstPadDirection, |
272 | caps: *mut gst::ffi::GstCaps, |
273 | filter_caps: *mut gst::ffi::GstCaps, |
274 | ) -> *mut gst::ffi::GstCaps { |
275 | let instance: &::Instance = &*(ptr as *mut T::Instance); |
276 | let imp: &T = instance.imp(); |
277 | |
278 | gst::panic_to_error!(imp, None, { |
279 | let filter_caps: Borrowed<Option<Caps>> = from_glib_borrow(filter_caps); |
280 | |
281 | imp.transform_internal_caps( |
282 | from_glib(direction), |
283 | &from_glib_borrow(caps), |
284 | filter_caps.as_ref().as_ref(), |
285 | ) |
286 | }) |
287 | .map(|caps| caps.into_glib_ptr()) |
288 | .unwrap_or(default:std::ptr::null_mut()) |
289 | } |
290 | |