gstreamer_base/
aggregator.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3#[cfg(feature = "v1_16")]
4#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
5use std::boxed::Box as Box_;
6#[cfg(feature = "v1_16")]
7#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
8use std::mem::transmute;
9use std::{mem, ptr};
10
11#[cfg(feature = "v1_16")]
12#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
13use glib::signal::{connect_raw, SignalHandlerId};
14use glib::{prelude::*, translate::*};
15use gst::{format::FormattedValue, prelude::*};
16
17use crate::{ffi, Aggregator, AggregatorPad};
18
19mod sealed {
20    pub trait Sealed {}
21    impl<T: super::IsA<super::Aggregator>> Sealed for T {}
22}
23
24pub trait AggregatorExtManual: sealed::Sealed + IsA<Aggregator> + 'static {
25    #[doc(alias = "get_allocator")]
26    #[doc(alias = "gst_aggregator_get_allocator")]
27    fn allocator(&self) -> (Option<gst::Allocator>, gst::AllocationParams) {
28        unsafe {
29            let mut allocator = ptr::null_mut();
30            let mut params = mem::MaybeUninit::uninit();
31            ffi::gst_aggregator_get_allocator(
32                self.as_ref().to_glib_none().0,
33                &mut allocator,
34                params.as_mut_ptr(),
35            );
36            (from_glib_full(allocator), params.assume_init().into())
37        }
38    }
39
40    #[cfg(feature = "v1_16")]
41    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
42    #[doc(alias = "min-upstream-latency")]
43    fn min_upstream_latency(&self) -> gst::ClockTime {
44        self.as_ref().property("min-upstream-latency")
45    }
46
47    #[cfg(feature = "v1_16")]
48    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
49    #[doc(alias = "min-upstream-latency")]
50    fn set_min_upstream_latency(&self, min_upstream_latency: gst::ClockTime) {
51        self.as_ref()
52            .set_property("min-upstream-latency", min_upstream_latency);
53    }
54
55    #[cfg(feature = "v1_16")]
56    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
57    #[doc(alias = "min-upstream-latency")]
58    fn connect_min_upstream_latency_notify<F: Fn(&Self) + Send + Sync + 'static>(
59        &self,
60        f: F,
61    ) -> SignalHandlerId {
62        unsafe {
63            let f: Box_<F> = Box_::new(f);
64            connect_raw(
65                self.as_ptr() as *mut _,
66                b"notify::min-upstream-latency\0".as_ptr() as *const _,
67                Some(transmute::<*const (), unsafe extern "C" fn()>(
68                    notify_min_upstream_latency_trampoline::<Self, F> as *const (),
69                )),
70                Box_::into_raw(f),
71            )
72        }
73    }
74
75    #[cfg(feature = "v1_18")]
76    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
77    #[doc(alias = "gst_aggregator_update_segment")]
78    fn update_segment<F: gst::format::FormattedValueIntrinsic>(
79        &self,
80        segment: &gst::FormattedSegment<F>,
81    ) {
82        unsafe {
83            ffi::gst_aggregator_update_segment(
84                self.as_ref().to_glib_none().0,
85                mut_override(segment.to_glib_none().0),
86            )
87        }
88    }
89
90    fn set_position(&self, position: impl FormattedValue) {
91        unsafe {
92            let ptr: *mut ffi::GstAggregator = self.as_ref().to_glib_none().0;
93            let ptr = &mut *ptr;
94            let _guard = self.as_ref().object_lock();
95
96            // gstaggregator.c asserts that the src pad is always of type GST_TYPE_AGGREGATOR_PAD,
97            // so the pointer cast here should be safe.
98            let srcpad = &mut *(ptr.srcpad as *mut ffi::GstAggregatorPad);
99
100            assert_eq!(srcpad.segment.format, position.format().into_glib());
101            srcpad.segment.position = position.into_raw_value() as u64;
102        }
103    }
104
105    #[cfg(feature = "v1_18")]
106    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
107    #[doc(alias = "gst_aggregator_selected_samples")]
108    fn selected_samples(
109        &self,
110        pts: impl Into<Option<gst::ClockTime>>,
111        dts: impl Into<Option<gst::ClockTime>>,
112        duration: impl Into<Option<gst::ClockTime>>,
113        info: Option<&gst::StructureRef>,
114    ) {
115        unsafe {
116            ffi::gst_aggregator_selected_samples(
117                self.as_ref().to_glib_none().0,
118                pts.into().into_glib(),
119                dts.into().into_glib(),
120                duration.into().into_glib(),
121                info.as_ref()
122                    .map(|s| s.as_ptr() as *mut _)
123                    .unwrap_or(ptr::null_mut()),
124            );
125        }
126    }
127
128    #[cfg(feature = "v1_18")]
129    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
130    fn connect_samples_selected<
131        F: Fn(
132                &Self,
133                &gst::Segment,
134                Option<gst::ClockTime>,
135                Option<gst::ClockTime>,
136                Option<gst::ClockTime>,
137                Option<&gst::StructureRef>,
138            ) + Send
139            + 'static,
140    >(
141        &self,
142        f: F,
143    ) -> SignalHandlerId {
144        unsafe extern "C" fn samples_selected_trampoline<
145            P,
146            F: Fn(
147                    &P,
148                    &gst::Segment,
149                    Option<gst::ClockTime>,
150                    Option<gst::ClockTime>,
151                    Option<gst::ClockTime>,
152                    Option<&gst::StructureRef>,
153                ) + Send
154                + 'static,
155        >(
156            this: *mut ffi::GstAggregator,
157            segment: *mut gst::ffi::GstSegment,
158            pts: gst::ffi::GstClockTime,
159            dts: gst::ffi::GstClockTime,
160            duration: gst::ffi::GstClockTime,
161            info: *mut gst::ffi::GstStructure,
162            f: glib::ffi::gpointer,
163        ) where
164            P: IsA<Aggregator>,
165        {
166            let f: &F = &*(f as *const F);
167            f(
168                Aggregator::from_glib_borrow(this).unsafe_cast_ref(),
169                gst::Segment::from_glib_ptr_borrow(segment),
170                from_glib(pts),
171                from_glib(dts),
172                from_glib(duration),
173                if info.is_null() {
174                    None
175                } else {
176                    Some(gst::StructureRef::from_glib_borrow(info))
177                },
178            )
179        }
180
181        unsafe {
182            let f: Box_<F> = Box_::new(f);
183            connect_raw(
184                self.as_ptr() as *mut _,
185                b"samples-selected\0".as_ptr() as *const _,
186                Some(transmute::<*const (), unsafe extern "C" fn()>(
187                    samples_selected_trampoline::<Self, F> as *const (),
188                )),
189                Box_::into_raw(f),
190            )
191        }
192    }
193
194    fn src_pad(&self) -> &AggregatorPad {
195        unsafe {
196            let elt = &*(self.as_ptr() as *const ffi::GstAggregator);
197            &*(&elt.srcpad as *const *mut gst::ffi::GstPad as *const AggregatorPad)
198        }
199    }
200}
201
202impl<O: IsA<Aggregator>> AggregatorExtManual for O {}
203
204#[cfg(feature = "v1_16")]
205#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
206unsafe extern "C" fn notify_min_upstream_latency_trampoline<P, F: Fn(&P) + Send + Sync + 'static>(
207    this: *mut ffi::GstAggregator,
208    _param_spec: glib::ffi::gpointer,
209    f: glib::ffi::gpointer,
210) where
211    P: IsA<Aggregator>,
212{
213    let f: &F = &*(f as *const F);
214    f(Aggregator::from_glib_borrow(this).unsafe_cast_ref())
215}