gstreamer_base/subclass/
base_parse.rs
1use std::mem;
4
5use glib::translate::*;
6use gst::subclass::prelude::*;
7
8use crate::{ffi, prelude::*, BaseParse, BaseParseFrame};
9
10pub trait BaseParseImpl: ElementImpl + ObjectSubclass<Type: IsA<BaseParse>> {
11 fn start(&self) -> Result<(), gst::ErrorMessage> {
15 self.parent_start()
16 }
17
18 fn stop(&self) -> Result<(), gst::ErrorMessage> {
22 self.parent_stop()
23 }
24
25 fn set_sink_caps(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
28 self.parent_set_sink_caps(caps)
29 }
30
31 fn handle_frame(
45 &self,
46 frame: BaseParseFrame,
47 ) -> Result<(gst::FlowSuccess, u32), gst::FlowError> {
48 self.parent_handle_frame(frame)
49 }
50
51 fn convert(
54 &self,
55 src_val: impl gst::format::FormattedValue,
56 dest_format: gst::Format,
57 ) -> Option<gst::GenericFormattedValue> {
58 self.parent_convert(src_val, dest_format)
59 }
60}
61
62pub trait BaseParseImplExt: BaseParseImpl {
63 fn parent_start(&self) -> Result<(), gst::ErrorMessage> {
64 unsafe {
65 let data = Self::type_data();
66 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseParseClass;
67 (*parent_class)
68 .start
69 .map(|f| {
70 if from_glib(f(self
71 .obj()
72 .unsafe_cast_ref::<BaseParse>()
73 .to_glib_none()
74 .0))
75 {
76 Ok(())
77 } else {
78 Err(gst::error_msg!(
79 gst::CoreError::StateChange,
80 ["Parent function `start` failed"]
81 ))
82 }
83 })
84 .unwrap_or(Ok(()))
85 }
86 }
87
88 fn parent_stop(&self) -> Result<(), gst::ErrorMessage> {
89 unsafe {
90 let data = Self::type_data();
91 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseParseClass;
92 (*parent_class)
93 .stop
94 .map(|f| {
95 if from_glib(f(self
96 .obj()
97 .unsafe_cast_ref::<BaseParse>()
98 .to_glib_none()
99 .0))
100 {
101 Ok(())
102 } else {
103 Err(gst::error_msg!(
104 gst::CoreError::StateChange,
105 ["Parent function `stop` failed"]
106 ))
107 }
108 })
109 .unwrap_or(Ok(()))
110 }
111 }
112
113 fn parent_set_sink_caps(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
114 unsafe {
115 let data = Self::type_data();
116 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseParseClass;
117 (*parent_class)
118 .set_sink_caps
119 .map(|f| {
120 gst::result_from_gboolean!(
121 f(
122 self.obj().unsafe_cast_ref::<BaseParse>().to_glib_none().0,
123 caps.to_glib_none().0,
124 ),
125 gst::CAT_RUST,
126 "Parent function `set_sink_caps` failed",
127 )
128 })
129 .unwrap_or(Ok(()))
130 }
131 }
132
133 fn parent_handle_frame(
134 &self,
135 frame: BaseParseFrame,
136 ) -> Result<(gst::FlowSuccess, u32), gst::FlowError> {
137 unsafe {
138 let data = Self::type_data();
139 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseParseClass;
140 let mut skipsize = 0;
141 (*parent_class)
142 .handle_frame
143 .map(|f| {
144 let res = try_from_glib(f(
145 self.obj().unsafe_cast_ref::<BaseParse>().to_glib_none().0,
146 frame.to_glib_none().0,
147 &mut skipsize,
148 ));
149 (res.unwrap(), skipsize as u32)
150 })
151 .ok_or(gst::FlowError::Error)
152 }
153 }
154
155 fn parent_convert(
156 &self,
157 src_val: impl gst::format::FormattedValue,
158 dest_format: gst::Format,
159 ) -> Option<gst::GenericFormattedValue> {
160 unsafe {
161 let data = Self::type_data();
162 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseParseClass;
163 let res = (*parent_class).convert.map(|f| {
164 let mut dest_val = mem::MaybeUninit::uninit();
165
166 let res = from_glib(f(
167 self.obj().unsafe_cast_ref::<BaseParse>().to_glib_none().0,
168 src_val.format().into_glib(),
169 src_val.into_raw_value(),
170 dest_format.into_glib(),
171 dest_val.as_mut_ptr(),
172 ));
173 (res, dest_val)
174 });
175
176 match res {
177 Some((true, dest_val)) => Some(gst::GenericFormattedValue::new(
178 dest_format,
179 dest_val.assume_init(),
180 )),
181 _ => None,
182 }
183 }
184 }
185}
186
187impl<T: BaseParseImpl> BaseParseImplExt for T {}
188
189unsafe impl<T: BaseParseImpl> IsSubclassable<T> for BaseParse {
190 fn class_init(klass: &mut glib::Class<Self>) {
191 Self::parent_class_init::<T>(klass);
192 let klass = klass.as_mut();
193 klass.start = Some(base_parse_start::<T>);
194 klass.stop = Some(base_parse_stop::<T>);
195 klass.set_sink_caps = Some(base_parse_set_sink_caps::<T>);
196 klass.handle_frame = Some(base_parse_handle_frame::<T>);
197 klass.convert = Some(base_parse_convert::<T>);
198 }
199}
200
201unsafe extern "C" fn base_parse_start<T: BaseParseImpl>(
202 ptr: *mut ffi::GstBaseParse,
203) -> glib::ffi::gboolean {
204 let instance = &*(ptr as *mut T::Instance);
205 let imp = instance.imp();
206
207 gst::panic_to_error!(imp, false, {
208 match imp.start() {
209 Ok(()) => true,
210 Err(err) => {
211 imp.post_error_message(err);
212 false
213 }
214 }
215 })
216 .into_glib()
217}
218
219unsafe extern "C" fn base_parse_stop<T: BaseParseImpl>(
220 ptr: *mut ffi::GstBaseParse,
221) -> glib::ffi::gboolean {
222 let instance = &*(ptr as *mut T::Instance);
223 let imp = instance.imp();
224
225 gst::panic_to_error!(imp, false, {
226 match imp.stop() {
227 Ok(()) => true,
228 Err(err) => {
229 imp.post_error_message(err);
230 false
231 }
232 }
233 })
234 .into_glib()
235}
236
237unsafe extern "C" fn base_parse_set_sink_caps<T: BaseParseImpl>(
238 ptr: *mut ffi::GstBaseParse,
239 caps: *mut gst::ffi::GstCaps,
240) -> glib::ffi::gboolean {
241 let instance = &*(ptr as *mut T::Instance);
242 let imp = instance.imp();
243 let caps: Borrowed<gst::Caps> = from_glib_borrow(caps);
244
245 gst::panic_to_error!(imp, false, {
246 match imp.set_sink_caps(&caps) {
247 Ok(()) => true,
248 Err(err) => {
249 err.log_with_imp(imp);
250 false
251 }
252 }
253 })
254 .into_glib()
255}
256
257unsafe extern "C" fn base_parse_handle_frame<T: BaseParseImpl>(
258 ptr: *mut ffi::GstBaseParse,
259 frame: *mut ffi::GstBaseParseFrame,
260 skipsize: *mut i32,
261) -> gst::ffi::GstFlowReturn {
262 let instance = &*(ptr as *mut T::Instance);
263 let imp = instance.imp();
264 let instance = imp.obj();
265 let instance = instance.unsafe_cast_ref::<BaseParse>();
266 let wrap_frame = BaseParseFrame::new(frame, instance);
267
268 let res = gst::panic_to_error!(imp, Err(gst::FlowError::Error), {
269 imp.handle_frame(wrap_frame)
270 });
271
272 match res {
273 Ok((flow, skip)) => {
274 *skipsize = i32::try_from(skip).expect("skip is higher than i32::MAX");
275 gst::FlowReturn::from_ok(flow)
276 }
277 Err(flow) => gst::FlowReturn::from_error(flow),
278 }
279 .into_glib()
280}
281
282unsafe extern "C" fn base_parse_convert<T: BaseParseImpl>(
283 ptr: *mut ffi::GstBaseParse,
284 source_format: gst::ffi::GstFormat,
285 source_value: i64,
286 dest_format: gst::ffi::GstFormat,
287 dest_value: *mut i64,
288) -> glib::ffi::gboolean {
289 let instance = &*(ptr as *mut T::Instance);
290 let imp = instance.imp();
291 let source = gst::GenericFormattedValue::new(from_glib(source_format), source_value);
292
293 let res = gst::panic_to_error!(imp, None, { imp.convert(source, from_glib(dest_format)) });
294
295 match res {
296 Some(dest) => {
297 *dest_value = dest.into_raw_value();
298 true
299 }
300 _ => false,
301 }
302 .into_glib()
303}