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> {
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 unsafe {
160 let instance = &*(ptr as *mut T::Instance);
161 let imp = instance.imp();
162
163 gst::panic_to_error!(imp, ptr::null_mut(), {
164 match imp.update_caps(&from_glib_borrow(caps)) {
165 Ok(caps) => caps.into_glib_ptr(),
166 Err(err) => {
167 err.log_with_imp(imp);
168 ptr::null_mut()
169 }
170 }
171 })
172 }
173}
174
175unsafe extern "C" fn video_aggregator_aggregate_frames<T: VideoAggregatorImpl>(
176 ptr: *mut ffi::GstVideoAggregator,
177 outbuf: *mut *mut gst::ffi::GstBuffer,
178) -> gst::ffi::GstFlowReturn {
179 unsafe {
180 let instance = &*(ptr as *mut T::Instance);
181 let imp = instance.imp();
182
183 gst::panic_to_error!(imp, gst::FlowReturn::Error, {
184 let instance = imp.obj();
185 let instance = instance.unsafe_cast_ref::<VideoAggregator>();
186 let token = AggregateFramesToken(instance);
187
188 imp.aggregate_frames(
189 &token,
190 gst::BufferRef::from_mut_ptr(
191 outbuf as *mut gst::ffi::GstBuffer,
193 ),
194 )
195 .into()
196 })
197 .into_glib()
198 }
199}
200
201unsafe extern "C" fn video_aggregator_create_output_buffer<T: VideoAggregatorImpl>(
202 ptr: *mut ffi::GstVideoAggregator,
203 outbuf: *mut *mut gst::ffi::GstBuffer,
204) -> gst::ffi::GstFlowReturn {
205 unsafe {
206 let instance = &*(ptr as *mut T::Instance);
207 let imp = instance.imp();
208
209 gst::panic_to_error!(imp, gst::FlowReturn::Error, {
210 match imp.create_output_buffer() {
211 Ok(buffer) => {
212 *outbuf = buffer.map(|b| b.into_glib_ptr()).unwrap_or(ptr::null_mut());
213 Ok(gst::FlowSuccess::Ok)
214 }
215 Err(err) => {
216 *outbuf = ptr::null_mut();
217 Err(err)
218 }
219 }
220 .into()
221 })
222 .into_glib()
223 }
224}
225
226unsafe extern "C" fn video_aggregator_find_best_format<T: VideoAggregatorImpl>(
227 ptr: *mut ffi::GstVideoAggregator,
228 downstream_caps: *mut gst::ffi::GstCaps,
229 best_info: *mut ffi::GstVideoInfo,
230 at_least_one_alpha: *mut glib::ffi::gboolean,
231) {
232 unsafe {
233 let instance = &*(ptr as *mut T::Instance);
234 let imp = instance.imp();
235
236 gst::panic_to_error!(imp, (), {
237 match imp.find_best_format(&from_glib_borrow(downstream_caps)) {
238 None => (),
239 Some((info, alpha)) => {
240 *best_info = *info.to_glib_none().0;
241 *at_least_one_alpha = alpha.into_glib();
242 }
243 }
244 })
245 }
246}