| 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 | |