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