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