// Copyright (C) 2020 François Laignel // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use gst_sys; use gst_video_sys; use glib::translate::*; use glib::subclass::prelude::*; use gst; use gst::subclass::prelude::*; use gst_base::subclass::prelude::*; use VideoSink; use VideoSinkClass; pub trait VideoSinkImpl: VideoSinkImplExt + BaseSinkImpl + ElementImpl + Send + Sync + 'static { fn show_frame( &self, element: &VideoSink, buffer: &gst::Buffer, ) -> Result { self.parent_show_frame(element, buffer) } } pub trait VideoSinkImplExt { fn parent_show_frame( &self, element: &VideoSink, buffer: &gst::Buffer, ) -> Result; } impl VideoSinkImplExt for T { fn parent_show_frame( &self, element: &VideoSink, buffer: &gst::Buffer, ) -> Result { unsafe { let data = self.get_type_data(); let parent_class = data.as_ref().get_parent_class() as *mut gst_video_sys::GstVideoSinkClass; (*parent_class) .show_frame .map(|f| { gst::FlowReturn::from_glib(f(element.to_glib_none().0, buffer.to_glib_none().0)) }) .unwrap_or(gst::FlowReturn::Error) .into_result() } } } unsafe impl IsSubclassable for VideoSinkClass where ::Instance: PanicPoison, { fn override_vfuncs(&mut self) { >::override_vfuncs(self); unsafe { let klass = &mut *(self as *mut Self as *mut gst_video_sys::GstVideoSinkClass); klass.show_frame = Some(video_sink_show_frame::); } } } unsafe extern "C" fn video_sink_show_frame( ptr: *mut gst_video_sys::GstVideoSink, buffer: *mut gst_sys::GstBuffer, ) -> gst_sys::GstFlowReturn where T: VideoSinkImpl, T::Instance: PanicPoison, { let instance = &*(ptr as *mut T::Instance); let imp = instance.get_impl(); let wrap: Borrowed = from_glib_borrow(ptr); let buffer = from_glib_borrow(buffer); gst_panic_to_error!(&wrap, &instance.panicked(), gst::FlowReturn::Error, { imp.show_frame(&wrap, &buffer).into() }) .to_glib() }