Skip to main content

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::{SignalHandlerId, connect_raw};
14use glib::{prelude::*, translate::*};
15use gst::{format::FormattedValue, prelude::*};
16
17use crate::{Aggregator, AggregatorPad, ffi};
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    /// Allows [`Aggregator`][crate::Aggregator] sub-classes to set the buffer `pool`, memory `allocator`,
51    /// its `params` and the `query` if they originate from an Allocation `GstQuery`.
52    /// ## `pool`
53    /// the [`gst::BufferPool`][crate::gst::BufferPool]
54    /// ## `allocator`
55    /// the [`gst::Allocator`][crate::gst::Allocator]
56    /// ## `params`
57    /// the [`gst::AllocationParams`][crate::gst::AllocationParams] of `allocator`
58    /// ## `query`
59    /// the Allocation `GstQuery` if any
60    ///
61    /// # Returns
62    ///
63    /// TRUE on success or FALSE if buffer `pool` activation failed
64    #[cfg(feature = "v1_30")]
65    #[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
66    #[doc(alias = "gst_aggregator_set_allocator")]
67    fn set_allocator(
68        &self,
69        pool: Option<impl IsA<gst::BufferPool>>,
70        allocator: Option<impl IsA<gst::Allocator>>,
71        params: Option<&gst::AllocationParams>,
72        query: Option<gst::query::Allocation<gst::Query>>,
73    ) -> Result<(), gst::LoggableError> {
74        unsafe {
75            gst::result_from_gboolean!(
76                ffi::gst_aggregator_set_allocator(
77                    self.as_ref().to_glib_none().0,
78                    pool.map(|p| p.upcast()).into_glib_ptr(),
79                    allocator.map(|p| p.upcast()).into_glib_ptr(),
80                    params.to_glib_none().0,
81                    query.map(gst::Query::from).into_glib_ptr(),
82                ),
83                gst::CAT_RUST,
84                "Failed to set allocator"
85            )
86        }
87    }
88
89    #[cfg(feature = "v1_16")]
90    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
91    #[doc(alias = "min-upstream-latency")]
92    fn min_upstream_latency(&self) -> gst::ClockTime {
93        self.as_ref().property("min-upstream-latency")
94    }
95
96    #[cfg(feature = "v1_16")]
97    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
98    #[doc(alias = "min-upstream-latency")]
99    fn set_min_upstream_latency(&self, min_upstream_latency: gst::ClockTime) {
100        self.as_ref()
101            .set_property("min-upstream-latency", min_upstream_latency);
102    }
103
104    #[cfg(feature = "v1_16")]
105    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
106    #[doc(alias = "min-upstream-latency")]
107    fn connect_min_upstream_latency_notify<F: Fn(&Self) + Send + Sync + 'static>(
108        &self,
109        f: F,
110    ) -> SignalHandlerId {
111        unsafe {
112            let f: Box_<F> = Box_::new(f);
113            connect_raw(
114                self.as_ptr() as *mut _,
115                b"notify::min-upstream-latency\0".as_ptr() as *const _,
116                Some(transmute::<*const (), unsafe extern "C" fn()>(
117                    notify_min_upstream_latency_trampoline::<Self, F> as *const (),
118                )),
119                Box_::into_raw(f),
120            )
121        }
122    }
123
124    /// Subclasses should use this to update the segment on their
125    /// source pad, instead of directly pushing new segment events
126    /// downstream.
127    ///
128    /// Subclasses MUST call this before [`selected_samples()`][Self::selected_samples()],
129    /// if it is used at all.
130    /// ## `segment`
131    /// The new [`gst::Segment`][crate::gst::Segment]
132    #[cfg(feature = "v1_18")]
133    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
134    #[doc(alias = "gst_aggregator_update_segment")]
135    fn update_segment<F: gst::format::FormattedValueIntrinsic>(
136        &self,
137        segment: &gst::FormattedSegment<F>,
138    ) {
139        unsafe {
140            ffi::gst_aggregator_update_segment(
141                self.as_ref().to_glib_none().0,
142                mut_override(segment.to_glib_none().0),
143            )
144        }
145    }
146
147    fn set_position(&self, position: impl FormattedValue) {
148        unsafe {
149            let ptr: *mut ffi::GstAggregator = self.as_ref().to_glib_none().0;
150            let ptr = &mut *ptr;
151            let _guard = self.as_ref().object_lock();
152
153            // gstaggregator.c asserts that the src pad is always of type GST_TYPE_AGGREGATOR_PAD,
154            // so the pointer cast here should be safe.
155            let srcpad = &mut *(ptr.srcpad as *mut ffi::GstAggregatorPad);
156
157            assert_eq!(srcpad.segment.format, position.format().into_glib());
158            srcpad.segment.position = position.into_raw_value() as u64;
159        }
160    }
161
162    /// Subclasses should call this when they have prepared the
163    /// buffers they will aggregate for each of their sink pads, but
164    /// before using any of the properties of the pads that govern
165    /// *how* aggregation should be performed, for example z-index
166    /// for video aggregators.
167    ///
168    /// If [`update_segment()`][Self::update_segment()] is used by the subclass,
169    /// it MUST be called before [`selected_samples()`][Self::selected_samples()].
170    ///
171    /// This function MUST only be called from the `GstAggregatorClass::aggregate()`
172    /// function.
173    /// ## `pts`
174    /// The presentation timestamp of the next output buffer
175    /// ## `dts`
176    /// The decoding timestamp of the next output buffer
177    /// ## `duration`
178    /// The duration of the next output buffer
179    /// ## `info`
180    /// a [`gst::Structure`][crate::gst::Structure] containing additional information
181    #[cfg(feature = "v1_18")]
182    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
183    #[doc(alias = "gst_aggregator_selected_samples")]
184    fn selected_samples(
185        &self,
186        pts: impl Into<Option<gst::ClockTime>>,
187        dts: impl Into<Option<gst::ClockTime>>,
188        duration: impl Into<Option<gst::ClockTime>>,
189        info: Option<&gst::StructureRef>,
190    ) {
191        unsafe {
192            ffi::gst_aggregator_selected_samples(
193                self.as_ref().to_glib_none().0,
194                pts.into().into_glib(),
195                dts.into().into_glib(),
196                duration.into().into_glib(),
197                info.as_ref()
198                    .map(|s| s.as_ptr() as *mut _)
199                    .unwrap_or(ptr::null_mut()),
200            );
201        }
202    }
203
204    #[cfg(feature = "v1_18")]
205    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
206    fn connect_samples_selected<
207        F: Fn(
208                &Self,
209                &gst::Segment,
210                Option<gst::ClockTime>,
211                Option<gst::ClockTime>,
212                Option<gst::ClockTime>,
213                Option<&gst::StructureRef>,
214            ) + Send
215            + 'static,
216    >(
217        &self,
218        f: F,
219    ) -> SignalHandlerId {
220        unsafe extern "C" fn samples_selected_trampoline<
221            P,
222            F: Fn(
223                    &P,
224                    &gst::Segment,
225                    Option<gst::ClockTime>,
226                    Option<gst::ClockTime>,
227                    Option<gst::ClockTime>,
228                    Option<&gst::StructureRef>,
229                ) + Send
230                + 'static,
231        >(
232            this: *mut ffi::GstAggregator,
233            segment: *mut gst::ffi::GstSegment,
234            pts: gst::ffi::GstClockTime,
235            dts: gst::ffi::GstClockTime,
236            duration: gst::ffi::GstClockTime,
237            info: *mut gst::ffi::GstStructure,
238            f: glib::ffi::gpointer,
239        ) where
240            P: IsA<Aggregator>,
241        {
242            unsafe {
243                let f: &F = &*(f as *const F);
244                f(
245                    Aggregator::from_glib_borrow(this).unsafe_cast_ref(),
246                    gst::Segment::from_glib_ptr_borrow(segment),
247                    from_glib(pts),
248                    from_glib(dts),
249                    from_glib(duration),
250                    if info.is_null() {
251                        None
252                    } else {
253                        Some(gst::StructureRef::from_glib_borrow(info))
254                    },
255                )
256            }
257        }
258
259        unsafe {
260            let f: Box_<F> = Box_::new(f);
261            connect_raw(
262                self.as_ptr() as *mut _,
263                b"samples-selected\0".as_ptr() as *const _,
264                Some(transmute::<*const (), unsafe extern "C" fn()>(
265                    samples_selected_trampoline::<Self, F> as *const (),
266                )),
267                Box_::into_raw(f),
268            )
269        }
270    }
271
272    fn src_pad(&self) -> &AggregatorPad {
273        unsafe {
274            let elt = &*(self.as_ptr() as *const ffi::GstAggregator);
275            &*(&elt.srcpad as *const *mut gst::ffi::GstPad as *const AggregatorPad)
276        }
277    }
278}
279
280impl<O: IsA<Aggregator>> AggregatorExtManual for O {}
281
282#[cfg(feature = "v1_16")]
283#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
284unsafe extern "C" fn notify_min_upstream_latency_trampoline<P, F: Fn(&P) + Send + Sync + 'static>(
285    this: *mut ffi::GstAggregator,
286    _param_spec: glib::ffi::gpointer,
287    f: glib::ffi::gpointer,
288) where
289    P: IsA<Aggregator>,
290{
291    unsafe {
292        let f: &F = &*(f as *const F);
293        f(Aggregator::from_glib_borrow(this).unsafe_cast_ref())
294    }
295}