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
19pub trait AggregatorExtManual: IsA<Aggregator> + 'static {
20    /// Lets [`Aggregator`][crate::Aggregator] sub-classes get the memory `allocator`
21    /// acquired by the base class and its `params`.
22    ///
23    /// Unref the `allocator` after use it.
24    ///
25    /// # Returns
26    ///
27    ///
28    /// ## `allocator`
29    /// the [`gst::Allocator`][crate::gst::Allocator]
30    /// used
31    ///
32    /// ## `params`
33    /// the
34    /// [`gst::AllocationParams`][crate::gst::AllocationParams] of `allocator`
35    #[doc(alias = "get_allocator")]
36    #[doc(alias = "gst_aggregator_get_allocator")]
37    fn allocator(&self) -> (Option<gst::Allocator>, gst::AllocationParams) {
38        unsafe {
39            let mut allocator = ptr::null_mut();
40            let mut params = mem::MaybeUninit::uninit();
41            ffi::gst_aggregator_get_allocator(
42                self.as_ref().to_glib_none().0,
43                &mut allocator,
44                params.as_mut_ptr(),
45            );
46            (from_glib_full(allocator), params.assume_init().into())
47        }
48    }
49
50    #[cfg(feature = "v1_16")]
51    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
52    #[doc(alias = "min-upstream-latency")]
53    fn min_upstream_latency(&self) -> gst::ClockTime {
54        self.as_ref().property("min-upstream-latency")
55    }
56
57    #[cfg(feature = "v1_16")]
58    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
59    #[doc(alias = "min-upstream-latency")]
60    fn set_min_upstream_latency(&self, min_upstream_latency: gst::ClockTime) {
61        self.as_ref()
62            .set_property("min-upstream-latency", min_upstream_latency);
63    }
64
65    #[cfg(feature = "v1_16")]
66    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
67    #[doc(alias = "min-upstream-latency")]
68    fn connect_min_upstream_latency_notify<F: Fn(&Self) + Send + Sync + 'static>(
69        &self,
70        f: F,
71    ) -> SignalHandlerId {
72        unsafe {
73            let f: Box_<F> = Box_::new(f);
74            connect_raw(
75                self.as_ptr() as *mut _,
76                b"notify::min-upstream-latency\0".as_ptr() as *const _,
77                Some(transmute::<*const (), unsafe extern "C" fn()>(
78                    notify_min_upstream_latency_trampoline::<Self, F> as *const (),
79                )),
80                Box_::into_raw(f),
81            )
82        }
83    }
84
85    /// Subclasses should use this to update the segment on their
86    /// source pad, instead of directly pushing new segment events
87    /// downstream.
88    ///
89    /// Subclasses MUST call this before [`selected_samples()`][Self::selected_samples()],
90    /// if it is used at all.
91    #[cfg(feature = "v1_18")]
92    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
93    #[doc(alias = "gst_aggregator_update_segment")]
94    fn update_segment<F: gst::format::FormattedValueIntrinsic>(
95        &self,
96        segment: &gst::FormattedSegment<F>,
97    ) {
98        unsafe {
99            ffi::gst_aggregator_update_segment(
100                self.as_ref().to_glib_none().0,
101                mut_override(segment.to_glib_none().0),
102            )
103        }
104    }
105
106    fn set_position(&self, position: impl FormattedValue) {
107        unsafe {
108            let ptr: *mut ffi::GstAggregator = self.as_ref().to_glib_none().0;
109            let ptr = &mut *ptr;
110            let _guard = self.as_ref().object_lock();
111
112            // gstaggregator.c asserts that the src pad is always of type GST_TYPE_AGGREGATOR_PAD,
113            // so the pointer cast here should be safe.
114            let srcpad = &mut *(ptr.srcpad as *mut ffi::GstAggregatorPad);
115
116            assert_eq!(srcpad.segment.format, position.format().into_glib());
117            srcpad.segment.position = position.into_raw_value() as u64;
118        }
119    }
120
121    /// Subclasses should call this when they have prepared the
122    /// buffers they will aggregate for each of their sink pads, but
123    /// before using any of the properties of the pads that govern
124    /// *how* aggregation should be performed, for example z-index
125    /// for video aggregators.
126    ///
127    /// If [`update_segment()`][Self::update_segment()] is used by the subclass,
128    /// it MUST be called before [`selected_samples()`][Self::selected_samples()].
129    ///
130    /// This function MUST only be called from the `GstAggregatorClass::aggregate()`
131    /// function.
132    /// ## `pts`
133    /// The presentation timestamp of the next output buffer
134    /// ## `dts`
135    /// The decoding timestamp of the next output buffer
136    /// ## `duration`
137    /// The duration of the next output buffer
138    /// ## `info`
139    /// a [`gst::Structure`][crate::gst::Structure] containing additional information
140    #[cfg(feature = "v1_18")]
141    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
142    #[doc(alias = "gst_aggregator_selected_samples")]
143    fn selected_samples(
144        &self,
145        pts: impl Into<Option<gst::ClockTime>>,
146        dts: impl Into<Option<gst::ClockTime>>,
147        duration: impl Into<Option<gst::ClockTime>>,
148        info: Option<&gst::StructureRef>,
149    ) {
150        unsafe {
151            ffi::gst_aggregator_selected_samples(
152                self.as_ref().to_glib_none().0,
153                pts.into().into_glib(),
154                dts.into().into_glib(),
155                duration.into().into_glib(),
156                info.as_ref()
157                    .map(|s| s.as_ptr() as *mut _)
158                    .unwrap_or(ptr::null_mut()),
159            );
160        }
161    }
162
163    #[cfg(feature = "v1_18")]
164    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
165    fn connect_samples_selected<
166        F: Fn(
167                &Self,
168                &gst::Segment,
169                Option<gst::ClockTime>,
170                Option<gst::ClockTime>,
171                Option<gst::ClockTime>,
172                Option<&gst::StructureRef>,
173            ) + Send
174            + 'static,
175    >(
176        &self,
177        f: F,
178    ) -> SignalHandlerId {
179        unsafe extern "C" fn samples_selected_trampoline<
180            P,
181            F: Fn(
182                    &P,
183                    &gst::Segment,
184                    Option<gst::ClockTime>,
185                    Option<gst::ClockTime>,
186                    Option<gst::ClockTime>,
187                    Option<&gst::StructureRef>,
188                ) + Send
189                + 'static,
190        >(
191            this: *mut ffi::GstAggregator,
192            segment: *mut gst::ffi::GstSegment,
193            pts: gst::ffi::GstClockTime,
194            dts: gst::ffi::GstClockTime,
195            duration: gst::ffi::GstClockTime,
196            info: *mut gst::ffi::GstStructure,
197            f: glib::ffi::gpointer,
198        ) where
199            P: IsA<Aggregator>,
200        {
201            let f: &F = &*(f as *const F);
202            f(
203                Aggregator::from_glib_borrow(this).unsafe_cast_ref(),
204                gst::Segment::from_glib_ptr_borrow(segment),
205                from_glib(pts),
206                from_glib(dts),
207                from_glib(duration),
208                if info.is_null() {
209                    None
210                } else {
211                    Some(gst::StructureRef::from_glib_borrow(info))
212                },
213            )
214        }
215
216        unsafe {
217            let f: Box_<F> = Box_::new(f);
218            connect_raw(
219                self.as_ptr() as *mut _,
220                b"samples-selected\0".as_ptr() as *const _,
221                Some(transmute::<*const (), unsafe extern "C" fn()>(
222                    samples_selected_trampoline::<Self, F> as *const (),
223                )),
224                Box_::into_raw(f),
225            )
226        }
227    }
228
229    fn src_pad(&self) -> &AggregatorPad {
230        unsafe {
231            let elt = &*(self.as_ptr() as *const ffi::GstAggregator);
232            &*(&elt.srcpad as *const *mut gst::ffi::GstPad as *const AggregatorPad)
233        }
234    }
235}
236
237impl<O: IsA<Aggregator>> AggregatorExtManual for O {}
238
239#[cfg(feature = "v1_16")]
240#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
241unsafe extern "C" fn notify_min_upstream_latency_trampoline<P, F: Fn(&P) + Send + Sync + 'static>(
242    this: *mut ffi::GstAggregator,
243    _param_spec: glib::ffi::gpointer,
244    f: glib::ffi::gpointer,
245) where
246    P: IsA<Aggregator>,
247{
248    let f: &F = &*(f as *const F);
249    f(Aggregator::from_glib_borrow(this).unsafe_cast_ref())
250}