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