gstreamer_video/subclass/
video_aggregator.rs1use std::{mem, ptr};
4
5use glib::translate::*;
6use gst_base::{prelude::*, subclass::prelude::*};
7
8use crate::{ffi, VideoAggregator};
9
10pub struct AggregateFramesToken<'a>(pub(crate) &'a VideoAggregator);
11
12pub trait VideoAggregatorImpl: AggregatorImpl + ObjectSubclass<Type: IsA<VideoAggregator>> {
13 fn update_caps(&self, caps: &gst::Caps) -> Result<gst::Caps, gst::LoggableError> {
14 self.parent_update_caps(caps)
15 }
16
17 fn aggregate_frames(
18 &self,
19 token: &AggregateFramesToken,
20 outbuf: &mut gst::BufferRef,
21 ) -> Result<gst::FlowSuccess, gst::FlowError> {
22 self.parent_aggregate_frames(token, outbuf)
23 }
24
25 fn create_output_buffer(&self) -> Result<Option<gst::Buffer>, gst::FlowError> {
26 self.parent_create_output_buffer()
27 }
28
29 fn find_best_format(&self, downstream_caps: &gst::Caps) -> Option<(crate::VideoInfo, bool)> {
30 self.parent_find_best_format(downstream_caps)
31 }
32}
33
34pub trait VideoAggregatorImplExt: VideoAggregatorImpl {
35 fn parent_update_caps(&self, caps: &gst::Caps) -> Result<gst::Caps, gst::LoggableError> {
36 unsafe {
37 let data = Self::type_data();
38 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoAggregatorClass;
39 let f = (*parent_class)
40 .update_caps
41 .expect("Missing parent function `update_caps`");
42
43 Option::<_>::from_glib_full(f(
44 self.obj()
45 .unsafe_cast_ref::<VideoAggregator>()
46 .to_glib_none()
47 .0,
48 caps.as_mut_ptr(),
49 ))
50 .ok_or_else(|| {
51 gst::loggable_error!(gst::CAT_RUST, "Parent function `update_caps` failed")
52 })
53 }
54 }
55
56 fn parent_aggregate_frames(
57 &self,
58 token: &AggregateFramesToken,
59 outbuf: &mut gst::BufferRef,
60 ) -> Result<gst::FlowSuccess, gst::FlowError> {
61 assert_eq!(
62 self.obj().as_ptr() as *mut ffi::GstVideoAggregator,
63 token.0.as_ptr()
64 );
65
66 unsafe {
67 let data = Self::type_data();
68 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoAggregatorClass;
69 let f = (*parent_class)
70 .aggregate_frames
71 .expect("Missing parent function `aggregate_frames`");
72
73 try_from_glib(f(
74 self.obj()
75 .unsafe_cast_ref::<VideoAggregator>()
76 .to_glib_none()
77 .0,
78 outbuf.as_mut_ptr() as *mut *mut gst::ffi::GstBuffer,
80 ))
81 }
82 }
83
84 fn parent_create_output_buffer(&self) -> Result<Option<gst::Buffer>, gst::FlowError> {
85 unsafe {
86 let data = Self::type_data();
87 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoAggregatorClass;
88 let f = (*parent_class)
89 .create_output_buffer
90 .expect("Missing parent function `create_output_buffer`");
91
92 let mut buffer = ptr::null_mut();
93 try_from_glib(f(
94 self.obj()
95 .unsafe_cast_ref::<VideoAggregator>()
96 .to_glib_none()
97 .0,
98 &mut buffer,
99 ))
100 .map(|_: gst::FlowSuccess| from_glib_full(buffer))
101 }
102 }
103
104 fn parent_find_best_format(
105 &self,
106 downstream_caps: &gst::Caps,
107 ) -> Option<(crate::VideoInfo, bool)> {
108 unsafe {
109 let data = Self::type_data();
110 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoAggregatorClass;
111 (*parent_class).find_best_format.and_then(|f| {
112 let mut info = mem::MaybeUninit::uninit();
113 ffi::gst_video_info_init(info.as_mut_ptr());
114 let mut info = info.assume_init();
115
116 let mut at_least_one_alpha = glib::ffi::GFALSE;
117
118 f(
119 self.obj()
120 .unsafe_cast_ref::<VideoAggregator>()
121 .to_glib_none()
122 .0,
123 downstream_caps.as_mut_ptr(),
124 &mut info,
125 &mut at_least_one_alpha,
126 );
127
128 if info.finfo.is_null() {
129 None
130 } else {
131 Some((
132 from_glib_none(&info as *const ffi::GstVideoInfo),
133 from_glib(at_least_one_alpha),
134 ))
135 }
136 })
137 }
138 }
139}
140
141impl<T: VideoAggregatorImpl> VideoAggregatorImplExt for T {}
142
143unsafe impl<T: VideoAggregatorImpl> IsSubclassable<T> for VideoAggregator {
144 fn class_init(klass: &mut glib::Class<Self>) {
145 Self::parent_class_init::<T>(klass);
146
147 let klass = klass.as_mut();
148 klass.update_caps = Some(video_aggregator_update_caps::<T>);
149 klass.aggregate_frames = Some(video_aggregator_aggregate_frames::<T>);
150 klass.create_output_buffer = Some(video_aggregator_create_output_buffer::<T>);
151 klass.find_best_format = Some(video_aggregator_find_best_format::<T>);
152 }
153}
154
155unsafe extern "C" fn video_aggregator_update_caps<T: VideoAggregatorImpl>(
156 ptr: *mut ffi::GstVideoAggregator,
157 caps: *mut gst::ffi::GstCaps,
158) -> *mut gst::ffi::GstCaps {
159 let instance = &*(ptr as *mut T::Instance);
160 let imp = instance.imp();
161
162 gst::panic_to_error!(imp, ptr::null_mut(), {
163 match imp.update_caps(&from_glib_borrow(caps)) {
164 Ok(caps) => caps.into_glib_ptr(),
165 Err(err) => {
166 err.log_with_imp(imp);
167 ptr::null_mut()
168 }
169 }
170 })
171}
172
173unsafe extern "C" fn video_aggregator_aggregate_frames<T: VideoAggregatorImpl>(
174 ptr: *mut ffi::GstVideoAggregator,
175 outbuf: *mut *mut gst::ffi::GstBuffer,
176) -> gst::ffi::GstFlowReturn {
177 let instance = &*(ptr as *mut T::Instance);
178 let imp = instance.imp();
179
180 gst::panic_to_error!(imp, gst::FlowReturn::Error, {
181 let instance = imp.obj();
182 let instance = instance.unsafe_cast_ref::<VideoAggregator>();
183 let token = AggregateFramesToken(instance);
184
185 imp.aggregate_frames(
186 &token,
187 gst::BufferRef::from_mut_ptr(
188 outbuf as *mut gst::ffi::GstBuffer,
190 ),
191 )
192 .into()
193 })
194 .into_glib()
195}
196
197unsafe extern "C" fn video_aggregator_create_output_buffer<T: VideoAggregatorImpl>(
198 ptr: *mut ffi::GstVideoAggregator,
199 outbuf: *mut *mut gst::ffi::GstBuffer,
200) -> gst::ffi::GstFlowReturn {
201 let instance = &*(ptr as *mut T::Instance);
202 let imp = instance.imp();
203
204 gst::panic_to_error!(imp, gst::FlowReturn::Error, {
205 match imp.create_output_buffer() {
206 Ok(buffer) => {
207 *outbuf = buffer.map(|b| b.into_glib_ptr()).unwrap_or(ptr::null_mut());
208 Ok(gst::FlowSuccess::Ok)
209 }
210 Err(err) => {
211 *outbuf = ptr::null_mut();
212 Err(err)
213 }
214 }
215 .into()
216 })
217 .into_glib()
218}
219
220unsafe extern "C" fn video_aggregator_find_best_format<T: VideoAggregatorImpl>(
221 ptr: *mut ffi::GstVideoAggregator,
222 downstream_caps: *mut gst::ffi::GstCaps,
223 best_info: *mut ffi::GstVideoInfo,
224 at_least_one_alpha: *mut glib::ffi::gboolean,
225) {
226 let instance = &*(ptr as *mut T::Instance);
227 let imp = instance.imp();
228
229 gst::panic_to_error!(imp, (), {
230 match imp.find_best_format(&from_glib_borrow(downstream_caps)) {
231 None => (),
232 Some((info, alpha)) => {
233 *best_info = *info.to_glib_none().0;
234 *at_least_one_alpha = alpha.into_glib();
235 }
236 }
237 })
238}