gstreamer_video/subclass/
video_aggregator_pad.rs1use std::{mem, ptr};
4
5use glib::translate::*;
6use gst_base::{prelude::*, subclass::prelude::*};
7
8use crate::{ffi, subclass::AggregateFramesToken, VideoAggregator, VideoAggregatorPad};
9
10pub trait VideoAggregatorPadImpl: VideoAggregatorPadImplExt + AggregatorPadImpl {
11 fn update_conversion_info(&self) {
12 self.parent_update_conversion_info()
13 }
14
15 fn prepare_frame(
16 &self,
17 aggregator: &crate::VideoAggregator,
18 token: &AggregateFramesToken,
19 buffer: &gst::Buffer,
20 ) -> Option<crate::VideoFrame<crate::video_frame::Readable>> {
21 self.parent_prepare_frame(aggregator, token, buffer)
22 }
23
24 fn clean_frame(
25 &self,
26 aggregator: &crate::VideoAggregator,
27 token: &AggregateFramesToken,
28 frame: Option<crate::VideoFrame<crate::video_frame::Readable>>,
29 ) {
30 self.parent_clean_frame(aggregator, token, frame)
31 }
32}
33
34mod sealed {
35 pub trait Sealed {}
36 impl<T: super::VideoAggregatorPadImplExt> Sealed for T {}
37}
38
39pub trait VideoAggregatorPadImplExt: ObjectSubclass + sealed::Sealed {
40 fn parent_update_conversion_info(&self) {
41 unsafe {
42 let data = Self::type_data();
43 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoAggregatorPadClass;
44 if let Some(f) = (*parent_class).update_conversion_info {
45 f(self
46 .obj()
47 .unsafe_cast_ref::<VideoAggregatorPad>()
48 .to_glib_none()
49 .0);
50 }
51 }
52 }
53
54 fn parent_prepare_frame(
55 &self,
56 aggregator: &crate::VideoAggregator,
57 token: &AggregateFramesToken,
58 buffer: &gst::Buffer,
59 ) -> Option<crate::VideoFrame<crate::video_frame::Readable>> {
60 assert_eq!(aggregator.as_ptr(), token.0.as_ptr());
61
62 unsafe {
63 let data = Self::type_data();
64 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoAggregatorPadClass;
65 if let Some(f) = (*parent_class).prepare_frame {
66 let mut prepared_frame = mem::MaybeUninit::zeroed();
67
68 f(
69 self.obj()
70 .unsafe_cast_ref::<VideoAggregatorPad>()
71 .to_glib_none()
72 .0,
73 aggregator.to_glib_none().0,
74 buffer.as_mut_ptr(),
75 prepared_frame.as_mut_ptr(),
76 );
77
78 let prepared_frame = prepared_frame.assume_init();
79 if prepared_frame.buffer.is_null() {
80 None
81 } else {
82 Some(crate::VideoFrame::from_glib_full(prepared_frame))
83 }
84 } else {
85 None
86 }
87 }
88 }
89
90 fn parent_clean_frame(
91 &self,
92 aggregator: &crate::VideoAggregator,
93 token: &AggregateFramesToken,
94 frame: Option<crate::VideoFrame<crate::video_frame::Readable>>,
95 ) {
96 assert_eq!(aggregator.as_ptr(), token.0.as_ptr());
97
98 unsafe {
99 let data = Self::type_data();
100 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoAggregatorPadClass;
101 if let Some(f) = (*parent_class).clean_frame {
102 let mut prepared_frame = if let Some(frame) = frame {
103 frame.into_raw()
104 } else {
105 mem::zeroed()
106 };
107
108 f(
109 self.obj()
110 .unsafe_cast_ref::<VideoAggregatorPad>()
111 .to_glib_none()
112 .0,
113 aggregator.to_glib_none().0,
114 &mut prepared_frame,
115 );
116 }
117 }
118 }
119}
120
121impl<T: VideoAggregatorPadImpl> VideoAggregatorPadImplExt for T {}
122
123unsafe impl<T: VideoAggregatorPadImpl> IsSubclassable<T> for VideoAggregatorPad {
124 fn class_init(klass: &mut glib::Class<Self>) {
125 Self::parent_class_init::<T>(klass);
126
127 let klass = klass.as_mut();
128 klass.update_conversion_info = Some(video_aggregator_pad_update_conversion_info::<T>);
129 klass.prepare_frame = Some(video_aggregator_pad_prepare_frame::<T>);
130 klass.clean_frame = Some(video_aggregator_pad_clean_frame::<T>);
131 }
132}
133
134unsafe extern "C" fn video_aggregator_pad_update_conversion_info<T: VideoAggregatorPadImpl>(
135 ptr: *mut ffi::GstVideoAggregatorPad,
136) {
137 let instance = &*(ptr as *mut T::Instance);
138 let imp = instance.imp();
139
140 imp.update_conversion_info();
141}
142
143unsafe extern "C" fn video_aggregator_pad_prepare_frame<T: VideoAggregatorPadImpl>(
144 ptr: *mut ffi::GstVideoAggregatorPad,
145 aggregator: *mut ffi::GstVideoAggregator,
146 buffer: *mut gst::ffi::GstBuffer,
147 prepared_frame: *mut ffi::GstVideoFrame,
148) -> glib::ffi::gboolean {
149 let instance = &*(ptr as *mut T::Instance);
150 let imp = instance.imp();
151 let aggregator: Borrowed<VideoAggregator> = from_glib_borrow(aggregator);
152
153 let token = AggregateFramesToken(&aggregator);
154
155 match imp.prepare_frame(&aggregator, &token, &from_glib_borrow(buffer)) {
156 Some(frame) => {
157 *prepared_frame = frame.into_raw();
158 }
159 None => {
160 ptr::write(prepared_frame, mem::zeroed());
161 }
162 }
163
164 glib::ffi::GTRUE
165}
166
167unsafe extern "C" fn video_aggregator_pad_clean_frame<T: VideoAggregatorPadImpl>(
168 ptr: *mut ffi::GstVideoAggregatorPad,
169 aggregator: *mut ffi::GstVideoAggregator,
170 prepared_frame: *mut ffi::GstVideoFrame,
171) {
172 let instance = &*(ptr as *mut T::Instance);
173 let imp = instance.imp();
174 let aggregator: Borrowed<VideoAggregator> = from_glib_borrow(aggregator);
175
176 let token = AggregateFramesToken(&aggregator);
177
178 let frame = if (*prepared_frame).buffer.is_null() {
179 None
180 } else {
181 let frame = crate::VideoFrame::from_glib_full(*prepared_frame);
182 ptr::write(prepared_frame, mem::zeroed());
183 Some(frame)
184 };
185
186 imp.clean_frame(&aggregator, &token, frame);
187}