gst_plugin/
base_sink.rs

1// Copyright (C) 2017 Sebastian Dröge <sebastian@centricular.com>
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use std::mem;
10use std::ptr;
11
12use glib_ffi;
13use gobject_ffi;
14use gst_base_ffi;
15use gst_ffi;
16
17use glib;
18use glib::translate::*;
19use gst;
20use gst::prelude::*;
21use gst_base;
22
23use gobject_subclass::anyimpl::*;
24use gobject_subclass::object::*;
25
26use element::*;
27use object::*;
28
29pub trait BaseSinkImpl<T: BaseSinkBase>:
30    AnyImpl + ObjectImpl<T> + ElementImpl<T> + Send + Sync + 'static
31where
32    T::InstanceStructType: PanicPoison,
33{
34    fn start(&self, _element: &T) -> bool {
35        true
36    }
37
38    fn stop(&self, _element: &T) -> bool {
39        true
40    }
41
42    fn render(&self, element: &T, buffer: &gst::BufferRef) -> gst::FlowReturn;
43
44    fn prepare(&self, _element: &T, _buffer: &gst::BufferRef) -> gst::FlowReturn {
45        gst::FlowReturn::Ok
46    }
47
48    fn render_list(&self, element: &T, list: &gst::BufferListRef) -> gst::FlowReturn {
49        for buffer in list.iter() {
50            let ret = self.render(element, buffer);
51            if ret != gst::FlowReturn::Ok {
52                return ret;
53            }
54        }
55
56        gst::FlowReturn::Ok
57    }
58
59    fn prepare_list(&self, element: &T, list: &gst::BufferListRef) -> gst::FlowReturn {
60        for buffer in list.iter() {
61            let ret = self.prepare(element, buffer);
62            if ret != gst::FlowReturn::Ok {
63                return ret;
64            }
65        }
66
67        gst::FlowReturn::Ok
68    }
69
70    fn query(&self, element: &T, query: &mut gst::QueryRef) -> bool {
71        element.parent_query(query)
72    }
73
74    fn event(&self, element: &T, event: gst::Event) -> bool {
75        element.parent_event(event)
76    }
77
78    fn get_caps(&self, element: &T, filter: Option<&gst::CapsRef>) -> Option<gst::Caps> {
79        element.parent_get_caps(filter)
80    }
81
82    fn set_caps(&self, element: &T, caps: &gst::CapsRef) -> bool {
83        element.parent_set_caps(caps)
84    }
85
86    fn fixate(&self, element: &T, caps: gst::Caps) -> gst::Caps {
87        element.parent_fixate(caps)
88    }
89
90    fn unlock(&self, _element: &T) -> bool {
91        true
92    }
93
94    fn unlock_stop(&self, _element: &T) -> bool {
95        true
96    }
97}
98
99any_impl!(BaseSinkBase, BaseSinkImpl, PanicPoison);
100
101pub unsafe trait BaseSinkBase:
102    IsA<gst::Element> + IsA<gst_base::BaseSink> + ObjectType
103{
104    fn parent_query(&self, query: &mut gst::QueryRef) -> bool {
105        unsafe {
106            let klass = self.get_class();
107            let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSinkClass;
108            (*parent_klass)
109                .query
110                .map(|f| from_glib(f(self.to_glib_none().0, query.as_mut_ptr())))
111                .unwrap_or(false)
112        }
113    }
114
115    fn parent_event(&self, event: gst::Event) -> bool {
116        unsafe {
117            let klass = self.get_class();
118            let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSinkClass;
119            (*parent_klass)
120                .event
121                .map(|f| from_glib(f(self.to_glib_none().0, event.into_ptr())))
122                .unwrap_or(false)
123        }
124    }
125
126    fn parent_get_caps(&self, filter: Option<&gst::CapsRef>) -> Option<gst::Caps> {
127        unsafe {
128            let klass = self.get_class();
129            let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSinkClass;
130            let filter_ptr = if let Some(filter) = filter {
131                filter.as_mut_ptr()
132            } else {
133                ptr::null_mut()
134            };
135
136            (*parent_klass)
137                .get_caps
138                .map(|f| from_glib_full(f(self.to_glib_none().0, filter_ptr)))
139                .unwrap_or(None)
140        }
141    }
142
143    fn parent_set_caps(&self, caps: &gst::CapsRef) -> bool {
144        unsafe {
145            let klass = self.get_class();
146            let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSinkClass;
147            (*parent_klass)
148                .set_caps
149                .map(|f| from_glib(f(self.to_glib_none().0, caps.as_mut_ptr())))
150                .unwrap_or(true)
151        }
152    }
153
154    fn parent_fixate(&self, caps: gst::Caps) -> gst::Caps {
155        unsafe {
156            let klass = self.get_class();
157            let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSinkClass;
158
159            match (*parent_klass).fixate {
160                Some(fixate) => from_glib_full(fixate(self.to_glib_none().0, caps.into_ptr())),
161                None => caps,
162            }
163        }
164    }
165}
166
167pub unsafe trait BaseSinkClassExt<T: BaseSinkBase>
168where
169    T::ImplType: BaseSinkImpl<T>,
170    T::InstanceStructType: PanicPoison,
171{
172    fn override_vfuncs(&mut self, _: &ClassInitToken) {
173        unsafe {
174            let klass = &mut *(self as *const Self as *mut gst_base_ffi::GstBaseSinkClass);
175            klass.start = Some(base_sink_start::<T>);
176            klass.stop = Some(base_sink_stop::<T>);
177            klass.render = Some(base_sink_render::<T>);
178            klass.render_list = Some(base_sink_render_list::<T>);
179            klass.prepare = Some(base_sink_prepare::<T>);
180            klass.prepare_list = Some(base_sink_prepare_list::<T>);
181            klass.query = Some(base_sink_query::<T>);
182            klass.event = Some(base_sink_event::<T>);
183            klass.get_caps = Some(base_sink_get_caps::<T>);
184            klass.set_caps = Some(base_sink_set_caps::<T>);
185            klass.fixate = Some(base_sink_fixate::<T>);
186            klass.unlock = Some(base_sink_unlock::<T>);
187            klass.unlock_stop = Some(base_sink_unlock_stop::<T>);
188        }
189    }
190}
191
192glib_wrapper! {
193    pub struct BaseSink(Object<ElementInstanceStruct<BaseSink>>):
194        [gst_base::BaseSink => gst_base_ffi::GstBaseSink,
195         gst::Element => gst_ffi::GstElement,
196         gst::Object => gst_ffi::GstObject];
197
198    match fn {
199        get_type => || get_type::<BaseSink>(),
200    }
201}
202
203unsafe impl<T: IsA<gst::Element> + IsA<gst_base::BaseSink> + ObjectType> BaseSinkBase for T {}
204pub type BaseSinkClass = ClassStruct<BaseSink>;
205
206// FIXME: Boilerplate
207unsafe impl BaseSinkClassExt<BaseSink> for BaseSinkClass {}
208unsafe impl ElementClassExt<BaseSink> for BaseSinkClass {}
209unsafe impl ObjectClassExt<BaseSink> for BaseSinkClass {}
210
211unsafe impl Send for BaseSink {}
212unsafe impl Sync for BaseSink {}
213
214#[macro_export]
215macro_rules! box_base_sink_impl(
216    ($name:ident) => {
217        box_element_impl!($name);
218
219        impl<T: BaseSinkBase> BaseSinkImpl<T> for Box<$name<T>>
220        where
221            T::InstanceStructType: PanicPoison
222        {
223            fn start(&self, element: &T) -> bool {
224                let imp: &$name<T> = self.as_ref();
225                imp.start(element)
226            }
227
228            fn stop(&self, element: &T) -> bool {
229                let imp: &$name<T> = self.as_ref();
230                imp.stop(element)
231            }
232
233            fn render(&self, element: &T, buffer: &gst::BufferRef) -> gst::FlowReturn {
234                let imp: &$name<T> = self.as_ref();
235                imp.render(element, buffer)
236            }
237
238            fn prepare(&self, element: &T, buffer: &gst::BufferRef) -> gst::FlowReturn {
239                let imp: &$name<T> = self.as_ref();
240                imp.prepare(element, buffer)
241            }
242
243            fn render_list(&self, element: &T, list: &gst::BufferListRef) -> gst::FlowReturn {
244                let imp: &$name<T> = self.as_ref();
245                imp.render_list(element, list)
246            }
247
248            fn prepare_list(&self, element: &T, list: &gst::BufferListRef) -> gst::FlowReturn {
249                let imp: &$name<T> = self.as_ref();
250                imp.prepare_list(element, list)
251            }
252
253            fn query(&self, element: &T, query: &mut gst::QueryRef) -> bool {
254                let imp: &$name<T> = self.as_ref();
255                BaseSinkImpl::query(imp, element, query)
256            }
257
258            fn event(&self, element: &T, event: gst::Event) -> bool {
259                let imp: &$name<T> = self.as_ref();
260                imp.event(element, event)
261            }
262
263            fn get_caps(&self, element: &T, filter: Option<&gst::CapsRef>) -> Option<gst::Caps> {
264                let imp: &$name<T> = self.as_ref();
265                imp.get_caps(element, filter)
266            }
267
268            fn set_caps(&self, element: &T, caps: &gst::CapsRef) -> bool {
269                let imp: &$name<T> = self.as_ref();
270                imp.set_caps(element, caps)
271            }
272
273            fn fixate(&self, element: &T, caps: gst::Caps) -> gst::Caps {
274                let imp: &$name<T> = self.as_ref();
275                imp.fixate(element, caps)
276            }
277
278            fn unlock(&self, element: &T) -> bool {
279                let imp: &$name<T> = self.as_ref();
280                imp.unlock(element)
281            }
282
283            fn unlock_stop(&self, element: &T) -> bool {
284                let imp: &$name<T> = self.as_ref();
285                imp.unlock_stop(element)
286            }
287        }
288    };
289);
290
291box_base_sink_impl!(BaseSinkImpl);
292
293impl ObjectType for BaseSink {
294    const NAME: &'static str = "RsBaseSink";
295    type ParentType = gst_base::BaseSink;
296    type ImplType = Box<BaseSinkImpl<Self>>;
297    type InstanceStructType = ElementInstanceStruct<Self>;
298
299    fn class_init(token: &ClassInitToken, klass: &mut BaseSinkClass) {
300        ObjectClassExt::override_vfuncs(klass, token);
301        ElementClassExt::override_vfuncs(klass, token);
302        BaseSinkClassExt::override_vfuncs(klass, token);
303    }
304
305    object_type_fns!();
306}
307
308unsafe extern "C" fn base_sink_start<T: BaseSinkBase>(
309    ptr: *mut gst_base_ffi::GstBaseSink,
310) -> glib_ffi::gboolean
311where
312    T::ImplType: BaseSinkImpl<T>,
313    T::InstanceStructType: PanicPoison,
314{
315    floating_reference_guard!(ptr);
316    let element = &*(ptr as *mut T::InstanceStructType);
317    let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
318    let imp = element.get_impl();
319
320    panic_to_error!(&wrap, &element.panicked(), false, { imp.start(&wrap) }).to_glib()
321}
322
323unsafe extern "C" fn base_sink_stop<T: BaseSinkBase>(
324    ptr: *mut gst_base_ffi::GstBaseSink,
325) -> glib_ffi::gboolean
326where
327    T::ImplType: BaseSinkImpl<T>,
328    T::InstanceStructType: PanicPoison,
329{
330    floating_reference_guard!(ptr);
331    let element = &*(ptr as *mut T::InstanceStructType);
332    let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
333    let imp = element.get_impl();
334
335    panic_to_error!(&wrap, &element.panicked(), false, { imp.stop(&wrap) }).to_glib()
336}
337
338unsafe extern "C" fn base_sink_render<T: BaseSinkBase>(
339    ptr: *mut gst_base_ffi::GstBaseSink,
340    buffer: *mut gst_ffi::GstBuffer,
341) -> gst_ffi::GstFlowReturn
342where
343    T::ImplType: BaseSinkImpl<T>,
344    T::InstanceStructType: PanicPoison,
345{
346    floating_reference_guard!(ptr);
347    let element = &*(ptr as *mut T::InstanceStructType);
348    let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
349    let imp = element.get_impl();
350    let buffer = gst::BufferRef::from_ptr(buffer);
351
352    panic_to_error!(&wrap, &element.panicked(), gst::FlowReturn::Error, {
353        imp.render(&wrap, buffer)
354    })
355    .to_glib()
356}
357
358unsafe extern "C" fn base_sink_prepare<T: BaseSinkBase>(
359    ptr: *mut gst_base_ffi::GstBaseSink,
360    buffer: *mut gst_ffi::GstBuffer,
361) -> gst_ffi::GstFlowReturn
362where
363    T::ImplType: BaseSinkImpl<T>,
364    T::InstanceStructType: PanicPoison,
365{
366    floating_reference_guard!(ptr);
367    let element = &*(ptr as *mut T::InstanceStructType);
368    let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
369    let imp = element.get_impl();
370    let buffer = gst::BufferRef::from_ptr(buffer);
371
372    panic_to_error!(&wrap, &element.panicked(), gst::FlowReturn::Error, {
373        imp.prepare(&wrap, buffer)
374    })
375    .to_glib()
376}
377
378unsafe extern "C" fn base_sink_render_list<T: BaseSinkBase>(
379    ptr: *mut gst_base_ffi::GstBaseSink,
380    list: *mut gst_ffi::GstBufferList,
381) -> gst_ffi::GstFlowReturn
382where
383    T::ImplType: BaseSinkImpl<T>,
384    T::InstanceStructType: PanicPoison,
385{
386    floating_reference_guard!(ptr);
387    let element = &*(ptr as *mut T::InstanceStructType);
388    let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
389    let imp = element.get_impl();
390    let list = gst::BufferListRef::from_ptr(list);
391
392    panic_to_error!(&wrap, &element.panicked(), gst::FlowReturn::Error, {
393        imp.render_list(&wrap, list)
394    })
395    .to_glib()
396}
397
398unsafe extern "C" fn base_sink_prepare_list<T: BaseSinkBase>(
399    ptr: *mut gst_base_ffi::GstBaseSink,
400    list: *mut gst_ffi::GstBufferList,
401) -> gst_ffi::GstFlowReturn
402where
403    T::ImplType: BaseSinkImpl<T>,
404    T::InstanceStructType: PanicPoison,
405{
406    floating_reference_guard!(ptr);
407    let element = &*(ptr as *mut T::InstanceStructType);
408    let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
409    let imp = element.get_impl();
410    let list = gst::BufferListRef::from_ptr(list);
411
412    panic_to_error!(&wrap, &element.panicked(), gst::FlowReturn::Error, {
413        imp.prepare_list(&wrap, list)
414    })
415    .to_glib()
416}
417
418unsafe extern "C" fn base_sink_query<T: BaseSinkBase>(
419    ptr: *mut gst_base_ffi::GstBaseSink,
420    query_ptr: *mut gst_ffi::GstQuery,
421) -> glib_ffi::gboolean
422where
423    T::ImplType: BaseSinkImpl<T>,
424    T::InstanceStructType: PanicPoison,
425{
426    floating_reference_guard!(ptr);
427    let element = &*(ptr as *mut T::InstanceStructType);
428    let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
429    let imp = element.get_impl();
430    let query = gst::QueryRef::from_mut_ptr(query_ptr);
431
432    panic_to_error!(&wrap, &element.panicked(), false, {
433        BaseSinkImpl::query(imp, &wrap, query)
434    })
435    .to_glib()
436}
437
438unsafe extern "C" fn base_sink_event<T: BaseSinkBase>(
439    ptr: *mut gst_base_ffi::GstBaseSink,
440    event_ptr: *mut gst_ffi::GstEvent,
441) -> glib_ffi::gboolean
442where
443    T::ImplType: BaseSinkImpl<T>,
444    T::InstanceStructType: PanicPoison,
445{
446    floating_reference_guard!(ptr);
447    let element = &*(ptr as *mut T::InstanceStructType);
448    let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
449    let imp = element.get_impl();
450
451    panic_to_error!(&wrap, &element.panicked(), false, {
452        imp.event(&wrap, from_glib_full(event_ptr))
453    })
454    .to_glib()
455}
456
457unsafe extern "C" fn base_sink_get_caps<T: BaseSinkBase>(
458    ptr: *mut gst_base_ffi::GstBaseSink,
459    filter: *mut gst_ffi::GstCaps,
460) -> *mut gst_ffi::GstCaps
461where
462    T::ImplType: BaseSinkImpl<T>,
463    T::InstanceStructType: PanicPoison,
464{
465    floating_reference_guard!(ptr);
466    let element = &*(ptr as *mut T::InstanceStructType);
467    let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
468    let imp = element.get_impl();
469    let filter = if filter.is_null() {
470        None
471    } else {
472        Some(gst::CapsRef::from_ptr(filter))
473    };
474
475    panic_to_error!(&wrap, &element.panicked(), None, {
476        imp.get_caps(&wrap, filter)
477    })
478    .map(|caps| caps.into_ptr())
479    .unwrap_or(ptr::null_mut())
480}
481
482unsafe extern "C" fn base_sink_set_caps<T: BaseSinkBase>(
483    ptr: *mut gst_base_ffi::GstBaseSink,
484    caps: *mut gst_ffi::GstCaps,
485) -> glib_ffi::gboolean
486where
487    T::ImplType: BaseSinkImpl<T>,
488    T::InstanceStructType: PanicPoison,
489{
490    floating_reference_guard!(ptr);
491    let element = &*(ptr as *mut T::InstanceStructType);
492    let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
493    let imp = element.get_impl();
494    let caps = gst::CapsRef::from_ptr(caps);
495
496    panic_to_error!(&wrap, &element.panicked(), false, {
497        imp.set_caps(&wrap, caps)
498    })
499    .to_glib()
500}
501
502unsafe extern "C" fn base_sink_fixate<T: BaseSinkBase>(
503    ptr: *mut gst_base_ffi::GstBaseSink,
504    caps: *mut gst_ffi::GstCaps,
505) -> *mut gst_ffi::GstCaps
506where
507    T::ImplType: BaseSinkImpl<T>,
508    T::InstanceStructType: PanicPoison,
509{
510    floating_reference_guard!(ptr);
511    let element = &*(ptr as *mut T::InstanceStructType);
512    let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
513    let imp = element.get_impl();
514    let caps = from_glib_full(caps);
515
516    panic_to_error!(&wrap, &element.panicked(), gst::Caps::new_empty(), {
517        imp.fixate(&wrap, caps)
518    })
519    .into_ptr()
520}
521
522unsafe extern "C" fn base_sink_unlock<T: BaseSinkBase>(
523    ptr: *mut gst_base_ffi::GstBaseSink,
524) -> glib_ffi::gboolean
525where
526    T::ImplType: BaseSinkImpl<T>,
527    T::InstanceStructType: PanicPoison,
528{
529    floating_reference_guard!(ptr);
530    let element = &*(ptr as *mut T::InstanceStructType);
531    let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
532    let imp = element.get_impl();
533
534    panic_to_error!(&wrap, &element.panicked(), false, { imp.unlock(&wrap) }).to_glib()
535}
536
537unsafe extern "C" fn base_sink_unlock_stop<T: BaseSinkBase>(
538    ptr: *mut gst_base_ffi::GstBaseSink,
539) -> glib_ffi::gboolean
540where
541    T::ImplType: BaseSinkImpl<T>,
542    T::InstanceStructType: PanicPoison,
543{
544    floating_reference_guard!(ptr);
545    let element = &*(ptr as *mut T::InstanceStructType);
546    let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
547    let imp = element.get_impl();
548
549    panic_to_error!(&wrap, &element.panicked(), false, {
550        imp.unlock_stop(&wrap)
551    })
552    .to_glib()
553}