Skip to main content

gstreamer_base/subclass/
aggregator.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::ptr;
4
5use glib::{prelude::*, translate::*};
6use gst::subclass::prelude::*;
7
8use crate::{Aggregator, AggregatorPad, ffi};
9
10pub trait AggregatorImpl: ElementImpl + ObjectSubclass<Type: IsA<Aggregator>> {
11    /// Optional.
12    ///  Called after a successful flushing seek, once all the flush
13    ///  stops have been received. Flush pad-specific data in
14    ///  [`AggregatorPad`][crate::AggregatorPad]->flush.
15    fn flush(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
16        self.parent_flush()
17    }
18
19    /// Called when a buffer is received on a sink pad, the task of
20    /// clipping it and translating it to the current segment falls
21    /// on the subclass. The function should use the segment of data
22    /// and the negotiated media type on the pad to perform
23    /// clipping of input buffer. This function takes ownership of
24    /// buf and should output a buffer or return NULL in
25    /// if the buffer should be dropped.
26    /// ## `aggregator_pad`
27    /// a [`AggregatorPad`][crate::AggregatorPad]
28    /// ## `buf`
29    /// a [`gst::Buffer`][crate::gst::Buffer]
30    ///
31    /// # Returns
32    ///
33    /// a [`gst::Buffer`][crate::gst::Buffer].
34    fn clip(&self, aggregator_pad: &AggregatorPad, buffer: gst::Buffer) -> Option<gst::Buffer> {
35        self.parent_clip(aggregator_pad, buffer)
36    }
37
38    /// This method will push the provided output buffer list downstream. If needed,
39    /// mandatory events such as stream-start, caps, and segment events will be
40    /// sent before pushing the buffer.
41    /// ## `bufferlist`
42    /// the [`gst::BufferList`][crate::gst::BufferList] to push.
43    #[cfg(feature = "v1_18")]
44    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
45    fn finish_buffer_list(
46        &self,
47        buffer_list: gst::BufferList,
48    ) -> Result<gst::FlowSuccess, gst::FlowError> {
49        self.parent_finish_buffer_list(buffer_list)
50    }
51
52    /// This method will push the provided output buffer downstream. If needed,
53    /// mandatory events such as stream-start, caps, and segment events will be
54    /// sent before pushing the buffer.
55    /// ## `buffer`
56    /// the [`gst::Buffer`][crate::gst::Buffer] to push.
57    fn finish_buffer(&self, buffer: gst::Buffer) -> Result<gst::FlowSuccess, gst::FlowError> {
58        self.parent_finish_buffer(buffer)
59    }
60
61    /// Called when an event is received on a sink pad, the subclass
62    /// should always chain up.
63    /// ## `aggregator_pad`
64    /// a [`AggregatorPad`][crate::AggregatorPad]
65    /// ## `event`
66    /// a [`gst::Event`][crate::gst::Event]
67    fn sink_event(&self, aggregator_pad: &AggregatorPad, event: gst::Event) -> bool {
68        self.parent_sink_event(aggregator_pad, event)
69    }
70
71    /// Called when an event is received on a sink pad before queueing up
72    /// serialized events. The subclass should always chain up (Since: 1.18).
73    /// ## `aggregator_pad`
74    /// a [`AggregatorPad`][crate::AggregatorPad]
75    /// ## `event`
76    /// a [`gst::Event`][crate::gst::Event]
77    #[cfg(feature = "v1_18")]
78    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
79    fn sink_event_pre_queue(
80        &self,
81        aggregator_pad: &AggregatorPad,
82        event: gst::Event,
83    ) -> Result<gst::FlowSuccess, gst::FlowError> {
84        self.parent_sink_event_pre_queue(aggregator_pad, event)
85    }
86
87    /// Optional.
88    ///  Called when a query is received on a sink pad, the subclass
89    ///  should always chain up.
90    fn sink_query(&self, aggregator_pad: &AggregatorPad, query: &mut gst::QueryRef) -> bool {
91        self.parent_sink_query(aggregator_pad, query)
92    }
93
94    /// Optional.
95    ///  Called when a query is received on a sink pad before queueing up
96    ///  serialized queries. The subclass should always chain up (Since: 1.18).
97    #[cfg(feature = "v1_18")]
98    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
99    fn sink_query_pre_queue(
100        &self,
101        aggregator_pad: &AggregatorPad,
102        query: &mut gst::QueryRef,
103    ) -> bool {
104        self.parent_sink_query_pre_queue(aggregator_pad, query)
105    }
106
107    /// Called when an event is received on the src pad, the subclass
108    /// should always chain up.
109    /// ## `event`
110    /// a [`gst::Event`][crate::gst::Event]
111    fn src_event(&self, event: gst::Event) -> bool {
112        self.parent_src_event(event)
113    }
114
115    /// Optional.
116    ///  Called when a query is received on the src pad, the subclass
117    ///  should always chain up.
118    fn src_query(&self, query: &mut gst::QueryRef) -> bool {
119        self.parent_src_query(query)
120    }
121
122    /// Optional.
123    ///  Called when the src pad is activated, it will start/stop its
124    ///  pad task right after that call.
125    fn src_activate(&self, mode: gst::PadMode, active: bool) -> Result<(), gst::LoggableError> {
126        self.parent_src_activate(mode, active)
127    }
128
129    /// Mandatory.
130    ///  Called when buffers are queued on all sinkpads. Classes
131    ///  should iterate the GstElement->sinkpads and peek or steal
132    ///  buffers from the `GstAggregatorPads`. If the subclass returns
133    ///  GST_FLOW_EOS, sending of the eos event will be taken care
134    ///  of. Once / if a buffer has been constructed from the
135    ///  aggregated buffers, the subclass should call _finish_buffer.
136    fn aggregate(&self, timeout: bool) -> Result<gst::FlowSuccess, gst::FlowError> {
137        self.parent_aggregate(timeout)
138    }
139
140    /// Optional.
141    ///  Called when the element goes from READY to PAUSED.
142    ///  The subclass should get ready to process
143    ///  aggregated buffers.
144    fn start(&self) -> Result<(), gst::ErrorMessage> {
145        self.parent_start()
146    }
147
148    /// Optional.
149    ///  Called when the element goes from PAUSED to READY.
150    ///  The subclass should free all resources and reset its state.
151    fn stop(&self) -> Result<(), gst::ErrorMessage> {
152        self.parent_stop()
153    }
154
155    /// Optional.
156    ///  Called when the element needs to know the running time of the next
157    ///  rendered buffer for live pipelines. This causes deadline
158    ///  based aggregation to occur. Defaults to returning
159    ///  GST_CLOCK_TIME_NONE causing the element to wait for buffers
160    ///  on all sink pads before aggregating.
161    fn next_time(&self) -> Option<gst::ClockTime> {
162        self.parent_next_time()
163    }
164
165    /// Called when a new pad needs to be created. Allows subclass that
166    /// don't have a single sink pad template to provide a pad based
167    /// on the provided information.
168    /// ## `templ`
169    /// the pad template to use
170    /// ## `req_name`
171    /// requested pad name
172    /// ## `caps`
173    /// caps for the pad
174    ///
175    /// # Returns
176    ///
177    /// a new [`AggregatorPad`][crate::AggregatorPad].
178    fn create_new_pad(
179        &self,
180        templ: &gst::PadTemplate,
181        req_name: Option<&str>,
182        caps: Option<&gst::Caps>,
183    ) -> Option<AggregatorPad> {
184        self.parent_create_new_pad(templ, req_name, caps)
185    }
186
187    /// ## `caps`
188    /// the new source pad [`gst::Caps`][crate::gst::Caps]
189    ///
190    /// # Returns
191    ///
192    fn update_src_caps(&self, caps: &gst::Caps) -> Result<gst::Caps, gst::FlowError> {
193        self.parent_update_src_caps(caps)
194    }
195
196    /// Fixate and return the src pad caps provided. The function takes
197    /// ownership of `caps` and returns a fixated version of
198    /// `caps`. `caps` is not guaranteed to be writable.
199    /// ## `caps`
200    /// a [`gst::Caps`][crate::gst::Caps] to fixate
201    ///
202    /// # Returns
203    ///
204    /// the fixated caps [`gst::Caps`][crate::gst::Caps].
205    fn fixate_src_caps(&self, caps: gst::Caps) -> gst::Caps {
206        self.parent_fixate_src_caps(caps)
207    }
208
209    /// Optional.
210    ///  Notifies subclasses what caps format has been negotiated
211    fn negotiated_src_caps(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
212        self.parent_negotiated_src_caps(caps)
213    }
214
215    /// Optional.
216    ///  Allows the subclass to handle the allocation query from upstream.
217    fn propose_allocation(
218        &self,
219        pad: &AggregatorPad,
220        decide_query: Option<&gst::query::Allocation>,
221        query: &mut gst::query::Allocation,
222    ) -> Result<(), gst::LoggableError> {
223        self.parent_propose_allocation(pad, decide_query, query)
224    }
225
226    /// Optional.
227    ///  Allows the subclass to influence the allocation choices.
228    ///  Setup the allocation parameters for allocating output
229    ///  buffers. The passed in query contains the result of the
230    ///  downstream allocation query.
231    fn decide_allocation(
232        &self,
233        query: &mut gst::query::Allocation,
234    ) -> Result<(), gst::LoggableError> {
235        self.parent_decide_allocation(query)
236    }
237
238    /// Negotiates src pad caps with downstream elements.
239    /// Unmarks GST_PAD_FLAG_NEED_RECONFIGURE in any case. But marks it again
240    /// if `GstAggregatorClass::negotiate` fails.
241    ///
242    /// # Returns
243    ///
244    /// [`true`] if the negotiation succeeded, else [`false`].
245    #[cfg(feature = "v1_18")]
246    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
247    fn negotiate(&self) -> bool {
248        self.parent_negotiate()
249    }
250
251    /// Use this function to determine what input buffers will be aggregated
252    /// to produce the next output buffer. This should only be called from
253    /// a [`samples-selected`][struct@crate::Aggregator#samples-selected] handler, and can be used to precisely
254    /// control aggregating parameters for a given set of input samples.
255    /// ## `aggregator_pad`
256    /// a [`AggregatorPad`][crate::AggregatorPad]
257    ///
258    /// # Returns
259    ///
260    /// The sample that is about to be aggregated. It may hold a [`gst::Buffer`][crate::gst::Buffer]
261    ///  or a [`gst::BufferList`][crate::gst::BufferList]. The contents of its info structure is subclass-dependent,
262    ///  and documented on a subclass basis. The buffers held by the sample are
263    ///  not writable.
264    #[cfg(feature = "v1_18")]
265    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
266    fn peek_next_sample(&self, pad: &AggregatorPad) -> Option<gst::Sample> {
267        self.parent_peek_next_sample(pad)
268    }
269}
270
271pub trait AggregatorImplExt: AggregatorImpl {
272    fn parent_flush(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
273        unsafe {
274            let data = Self::type_data();
275            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
276            (*parent_class)
277                .flush
278                .map(|f| {
279                    try_from_glib(f(self
280                        .obj()
281                        .unsafe_cast_ref::<Aggregator>()
282                        .to_glib_none()
283                        .0))
284                })
285                .unwrap_or(Ok(gst::FlowSuccess::Ok))
286        }
287    }
288
289    fn parent_clip(
290        &self,
291        aggregator_pad: &AggregatorPad,
292        buffer: gst::Buffer,
293    ) -> Option<gst::Buffer> {
294        unsafe {
295            let data = Self::type_data();
296            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
297            match (*parent_class).clip {
298                None => Some(buffer),
299                Some(ref func) => from_glib_full(func(
300                    self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
301                    aggregator_pad.to_glib_none().0,
302                    buffer.into_glib_ptr(),
303                )),
304            }
305        }
306    }
307
308    fn parent_finish_buffer(
309        &self,
310        buffer: gst::Buffer,
311    ) -> Result<gst::FlowSuccess, gst::FlowError> {
312        unsafe {
313            let data = Self::type_data();
314            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
315            let f = (*parent_class)
316                .finish_buffer
317                .expect("Missing parent function `finish_buffer`");
318            try_from_glib(f(
319                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
320                buffer.into_glib_ptr(),
321            ))
322        }
323    }
324
325    #[cfg(feature = "v1_18")]
326    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
327    fn parent_finish_buffer_list(
328        &self,
329        buffer_list: gst::BufferList,
330    ) -> Result<gst::FlowSuccess, gst::FlowError> {
331        unsafe {
332            let data = Self::type_data();
333            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
334            let f = (*parent_class)
335                .finish_buffer_list
336                .expect("Missing parent function `finish_buffer_list`");
337            try_from_glib(f(
338                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
339                buffer_list.into_glib_ptr(),
340            ))
341        }
342    }
343
344    fn parent_sink_event(&self, aggregator_pad: &AggregatorPad, event: gst::Event) -> bool {
345        unsafe {
346            let data = Self::type_data();
347            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
348            let f = (*parent_class)
349                .sink_event
350                .expect("Missing parent function `sink_event`");
351            from_glib(f(
352                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
353                aggregator_pad.to_glib_none().0,
354                event.into_glib_ptr(),
355            ))
356        }
357    }
358
359    #[cfg(feature = "v1_18")]
360    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
361    fn parent_sink_event_pre_queue(
362        &self,
363        aggregator_pad: &AggregatorPad,
364        event: gst::Event,
365    ) -> Result<gst::FlowSuccess, gst::FlowError> {
366        unsafe {
367            let data = Self::type_data();
368            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
369            let f = (*parent_class)
370                .sink_event_pre_queue
371                .expect("Missing parent function `sink_event_pre_queue`");
372            try_from_glib(f(
373                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
374                aggregator_pad.to_glib_none().0,
375                event.into_glib_ptr(),
376            ))
377        }
378    }
379
380    fn parent_sink_query(&self, aggregator_pad: &AggregatorPad, query: &mut gst::QueryRef) -> bool {
381        unsafe {
382            let data = Self::type_data();
383            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
384            let f = (*parent_class)
385                .sink_query
386                .expect("Missing parent function `sink_query`");
387            from_glib(f(
388                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
389                aggregator_pad.to_glib_none().0,
390                query.as_mut_ptr(),
391            ))
392        }
393    }
394
395    #[cfg(feature = "v1_18")]
396    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
397    fn parent_sink_query_pre_queue(
398        &self,
399        aggregator_pad: &AggregatorPad,
400        query: &mut gst::QueryRef,
401    ) -> bool {
402        unsafe {
403            let data = Self::type_data();
404            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
405            let f = (*parent_class)
406                .sink_query_pre_queue
407                .expect("Missing parent function `sink_query`");
408            from_glib(f(
409                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
410                aggregator_pad.to_glib_none().0,
411                query.as_mut_ptr(),
412            ))
413        }
414    }
415
416    fn parent_src_event(&self, event: gst::Event) -> bool {
417        unsafe {
418            let data = Self::type_data();
419            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
420            let f = (*parent_class)
421                .src_event
422                .expect("Missing parent function `src_event`");
423            from_glib(f(
424                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
425                event.into_glib_ptr(),
426            ))
427        }
428    }
429
430    fn parent_src_query(&self, query: &mut gst::QueryRef) -> bool {
431        unsafe {
432            let data = Self::type_data();
433            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
434            let f = (*parent_class)
435                .src_query
436                .expect("Missing parent function `src_query`");
437            from_glib(f(
438                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
439                query.as_mut_ptr(),
440            ))
441        }
442    }
443
444    fn parent_src_activate(
445        &self,
446        mode: gst::PadMode,
447        active: bool,
448    ) -> Result<(), gst::LoggableError> {
449        unsafe {
450            let data = Self::type_data();
451            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
452            match (*parent_class).src_activate {
453                None => Ok(()),
454                Some(f) => gst::result_from_gboolean!(
455                    f(
456                        self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
457                        mode.into_glib(),
458                        active.into_glib()
459                    ),
460                    gst::CAT_RUST,
461                    "Parent function `src_activate` failed"
462                ),
463            }
464        }
465    }
466
467    fn parent_aggregate(&self, timeout: bool) -> Result<gst::FlowSuccess, gst::FlowError> {
468        unsafe {
469            let data = Self::type_data();
470            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
471            let f = (*parent_class)
472                .aggregate
473                .expect("Missing parent function `aggregate`");
474            try_from_glib(f(
475                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
476                timeout.into_glib(),
477            ))
478        }
479    }
480
481    fn parent_start(&self) -> Result<(), gst::ErrorMessage> {
482        unsafe {
483            let data = Self::type_data();
484            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
485            (*parent_class)
486                .start
487                .map(|f| {
488                    if from_glib(f(self
489                        .obj()
490                        .unsafe_cast_ref::<Aggregator>()
491                        .to_glib_none()
492                        .0))
493                    {
494                        Ok(())
495                    } else {
496                        Err(gst::error_msg!(
497                            gst::CoreError::Failed,
498                            ["Parent function `start` failed"]
499                        ))
500                    }
501                })
502                .unwrap_or(Ok(()))
503        }
504    }
505
506    fn parent_stop(&self) -> Result<(), gst::ErrorMessage> {
507        unsafe {
508            let data = Self::type_data();
509            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
510            (*parent_class)
511                .stop
512                .map(|f| {
513                    if from_glib(f(self
514                        .obj()
515                        .unsafe_cast_ref::<Aggregator>()
516                        .to_glib_none()
517                        .0))
518                    {
519                        Ok(())
520                    } else {
521                        Err(gst::error_msg!(
522                            gst::CoreError::Failed,
523                            ["Parent function `stop` failed"]
524                        ))
525                    }
526                })
527                .unwrap_or(Ok(()))
528        }
529    }
530
531    fn parent_next_time(&self) -> Option<gst::ClockTime> {
532        unsafe {
533            let data = Self::type_data();
534            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
535            (*parent_class)
536                .get_next_time
537                .map(|f| {
538                    from_glib(f(self
539                        .obj()
540                        .unsafe_cast_ref::<Aggregator>()
541                        .to_glib_none()
542                        .0))
543                })
544                .unwrap_or(gst::ClockTime::NONE)
545        }
546    }
547
548    fn parent_create_new_pad(
549        &self,
550        templ: &gst::PadTemplate,
551        req_name: Option<&str>,
552        caps: Option<&gst::Caps>,
553    ) -> Option<AggregatorPad> {
554        unsafe {
555            let data = Self::type_data();
556            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
557            let f = (*parent_class)
558                .create_new_pad
559                .expect("Missing parent function `create_new_pad`");
560            from_glib_full(f(
561                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
562                templ.to_glib_none().0,
563                req_name.to_glib_none().0,
564                caps.to_glib_none().0,
565            ))
566        }
567    }
568
569    fn parent_update_src_caps(&self, caps: &gst::Caps) -> Result<gst::Caps, gst::FlowError> {
570        unsafe {
571            let data = Self::type_data();
572            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
573            let f = (*parent_class)
574                .update_src_caps
575                .expect("Missing parent function `update_src_caps`");
576
577            let mut out_caps = ptr::null_mut();
578            gst::FlowSuccess::try_from_glib(f(
579                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
580                caps.as_mut_ptr(),
581                &mut out_caps,
582            ))
583            .map(|_| from_glib_full(out_caps))
584        }
585    }
586
587    fn parent_fixate_src_caps(&self, caps: gst::Caps) -> gst::Caps {
588        unsafe {
589            let data = Self::type_data();
590            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
591
592            let f = (*parent_class)
593                .fixate_src_caps
594                .expect("Missing parent function `fixate_src_caps`");
595            from_glib_full(f(
596                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
597                caps.into_glib_ptr(),
598            ))
599        }
600    }
601
602    fn parent_negotiated_src_caps(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
603        unsafe {
604            let data = Self::type_data();
605            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
606            (*parent_class)
607                .negotiated_src_caps
608                .map(|f| {
609                    gst::result_from_gboolean!(
610                        f(
611                            self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
612                            caps.to_glib_none().0
613                        ),
614                        gst::CAT_RUST,
615                        "Parent function `negotiated_src_caps` failed"
616                    )
617                })
618                .unwrap_or(Ok(()))
619        }
620    }
621
622    fn parent_propose_allocation(
623        &self,
624        pad: &AggregatorPad,
625        decide_query: Option<&gst::query::Allocation>,
626        query: &mut gst::query::Allocation,
627    ) -> Result<(), gst::LoggableError> {
628        unsafe {
629            let data = Self::type_data();
630            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
631            (*parent_class)
632                .propose_allocation
633                .map(|f| {
634                    gst::result_from_gboolean!(
635                        f(
636                            self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
637                            pad.to_glib_none().0,
638                            decide_query
639                                .as_ref()
640                                .map(|q| q.as_mut_ptr())
641                                .unwrap_or(ptr::null_mut()),
642                            query.as_mut_ptr()
643                        ),
644                        gst::CAT_RUST,
645                        "Parent function `propose_allocation` failed",
646                    )
647                })
648                .unwrap_or(Ok(()))
649        }
650    }
651
652    fn parent_decide_allocation(
653        &self,
654        query: &mut gst::query::Allocation,
655    ) -> Result<(), gst::LoggableError> {
656        unsafe {
657            let data = Self::type_data();
658            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
659            (*parent_class)
660                .decide_allocation
661                .map(|f| {
662                    gst::result_from_gboolean!(
663                        f(
664                            self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
665                            query.as_mut_ptr(),
666                        ),
667                        gst::CAT_RUST,
668                        "Parent function `decide_allocation` failed",
669                    )
670                })
671                .unwrap_or(Ok(()))
672        }
673    }
674
675    #[cfg(feature = "v1_18")]
676    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
677    fn parent_negotiate(&self) -> bool {
678        unsafe {
679            let data = Self::type_data();
680            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
681            (*parent_class)
682                .negotiate
683                .map(|f| {
684                    from_glib(f(self
685                        .obj()
686                        .unsafe_cast_ref::<Aggregator>()
687                        .to_glib_none()
688                        .0))
689                })
690                .unwrap_or(true)
691        }
692    }
693
694    #[cfg(feature = "v1_18")]
695    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
696    fn parent_peek_next_sample(&self, pad: &AggregatorPad) -> Option<gst::Sample> {
697        unsafe {
698            let data = Self::type_data();
699            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
700            (*parent_class)
701                .peek_next_sample
702                .map(|f| {
703                    from_glib_full(f(
704                        self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
705                        pad.to_glib_none().0,
706                    ))
707                })
708                .unwrap_or(None)
709        }
710    }
711}
712
713impl<T: AggregatorImpl> AggregatorImplExt for T {}
714
715unsafe impl<T: AggregatorImpl> IsSubclassable<T> for Aggregator {
716    fn class_init(klass: &mut glib::Class<Self>) {
717        Self::parent_class_init::<T>(klass);
718        let klass = klass.as_mut();
719        klass.flush = Some(aggregator_flush::<T>);
720        klass.clip = Some(aggregator_clip::<T>);
721        klass.finish_buffer = Some(aggregator_finish_buffer::<T>);
722        klass.sink_event = Some(aggregator_sink_event::<T>);
723        klass.sink_query = Some(aggregator_sink_query::<T>);
724        klass.src_event = Some(aggregator_src_event::<T>);
725        klass.src_query = Some(aggregator_src_query::<T>);
726        klass.src_activate = Some(aggregator_src_activate::<T>);
727        klass.aggregate = Some(aggregator_aggregate::<T>);
728        klass.start = Some(aggregator_start::<T>);
729        klass.stop = Some(aggregator_stop::<T>);
730        klass.get_next_time = Some(aggregator_get_next_time::<T>);
731        klass.create_new_pad = Some(aggregator_create_new_pad::<T>);
732        klass.update_src_caps = Some(aggregator_update_src_caps::<T>);
733        klass.fixate_src_caps = Some(aggregator_fixate_src_caps::<T>);
734        klass.negotiated_src_caps = Some(aggregator_negotiated_src_caps::<T>);
735        klass.propose_allocation = Some(aggregator_propose_allocation::<T>);
736        klass.decide_allocation = Some(aggregator_decide_allocation::<T>);
737        #[cfg(feature = "v1_18")]
738        {
739            klass.sink_event_pre_queue = Some(aggregator_sink_event_pre_queue::<T>);
740            klass.sink_query_pre_queue = Some(aggregator_sink_query_pre_queue::<T>);
741            klass.negotiate = Some(aggregator_negotiate::<T>);
742            klass.peek_next_sample = Some(aggregator_peek_next_sample::<T>);
743            klass.finish_buffer_list = Some(aggregator_finish_buffer_list::<T>);
744        }
745    }
746}
747
748unsafe extern "C" fn aggregator_flush<T: AggregatorImpl>(
749    ptr: *mut ffi::GstAggregator,
750) -> gst::ffi::GstFlowReturn {
751    unsafe {
752        let instance = &*(ptr as *mut T::Instance);
753        let imp = instance.imp();
754
755        gst::panic_to_error!(imp, gst::FlowReturn::Error, { imp.flush().into() }).into_glib()
756    }
757}
758
759unsafe extern "C" fn aggregator_clip<T: AggregatorImpl>(
760    ptr: *mut ffi::GstAggregator,
761    aggregator_pad: *mut ffi::GstAggregatorPad,
762    buffer: *mut gst::ffi::GstBuffer,
763) -> *mut gst::ffi::GstBuffer {
764    unsafe {
765        let instance = &*(ptr as *mut T::Instance);
766        let imp = instance.imp();
767
768        let ret = gst::panic_to_error!(imp, None, {
769            imp.clip(&from_glib_borrow(aggregator_pad), from_glib_full(buffer))
770        });
771
772        ret.map(|r| r.into_glib_ptr()).unwrap_or(ptr::null_mut())
773    }
774}
775
776unsafe extern "C" fn aggregator_finish_buffer<T: AggregatorImpl>(
777    ptr: *mut ffi::GstAggregator,
778    buffer: *mut gst::ffi::GstBuffer,
779) -> gst::ffi::GstFlowReturn {
780    unsafe {
781        let instance = &*(ptr as *mut T::Instance);
782        let imp = instance.imp();
783
784        gst::panic_to_error!(imp, gst::FlowReturn::Error, {
785            imp.finish_buffer(from_glib_full(buffer)).into()
786        })
787        .into_glib()
788    }
789}
790
791#[cfg(feature = "v1_18")]
792#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
793unsafe extern "C" fn aggregator_finish_buffer_list<T: AggregatorImpl>(
794    ptr: *mut ffi::GstAggregator,
795    buffer_list: *mut gst::ffi::GstBufferList,
796) -> gst::ffi::GstFlowReturn {
797    unsafe {
798        let instance = &*(ptr as *mut T::Instance);
799        let imp = instance.imp();
800
801        gst::panic_to_error!(imp, gst::FlowReturn::Error, {
802            imp.finish_buffer_list(from_glib_full(buffer_list)).into()
803        })
804        .into_glib()
805    }
806}
807
808unsafe extern "C" fn aggregator_sink_event<T: AggregatorImpl>(
809    ptr: *mut ffi::GstAggregator,
810    aggregator_pad: *mut ffi::GstAggregatorPad,
811    event: *mut gst::ffi::GstEvent,
812) -> glib::ffi::gboolean {
813    unsafe {
814        let instance = &*(ptr as *mut T::Instance);
815        let imp = instance.imp();
816
817        gst::panic_to_error!(imp, false, {
818            imp.sink_event(&from_glib_borrow(aggregator_pad), from_glib_full(event))
819        })
820        .into_glib()
821    }
822}
823
824#[cfg(feature = "v1_18")]
825#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
826unsafe extern "C" fn aggregator_sink_event_pre_queue<T: AggregatorImpl>(
827    ptr: *mut ffi::GstAggregator,
828    aggregator_pad: *mut ffi::GstAggregatorPad,
829    event: *mut gst::ffi::GstEvent,
830) -> gst::ffi::GstFlowReturn {
831    unsafe {
832        let instance = &*(ptr as *mut T::Instance);
833        let imp = instance.imp();
834
835        gst::panic_to_error!(imp, gst::FlowReturn::Error, {
836            imp.sink_event_pre_queue(&from_glib_borrow(aggregator_pad), from_glib_full(event))
837                .into()
838        })
839        .into_glib()
840    }
841}
842
843unsafe extern "C" fn aggregator_sink_query<T: AggregatorImpl>(
844    ptr: *mut ffi::GstAggregator,
845    aggregator_pad: *mut ffi::GstAggregatorPad,
846    query: *mut gst::ffi::GstQuery,
847) -> glib::ffi::gboolean {
848    unsafe {
849        let instance = &*(ptr as *mut T::Instance);
850        let imp = instance.imp();
851
852        gst::panic_to_error!(imp, false, {
853            imp.sink_query(
854                &from_glib_borrow(aggregator_pad),
855                gst::QueryRef::from_mut_ptr(query),
856            )
857        })
858        .into_glib()
859    }
860}
861
862#[cfg(feature = "v1_18")]
863#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
864unsafe extern "C" fn aggregator_sink_query_pre_queue<T: AggregatorImpl>(
865    ptr: *mut ffi::GstAggregator,
866    aggregator_pad: *mut ffi::GstAggregatorPad,
867    query: *mut gst::ffi::GstQuery,
868) -> glib::ffi::gboolean {
869    unsafe {
870        let instance = &*(ptr as *mut T::Instance);
871        let imp = instance.imp();
872
873        gst::panic_to_error!(imp, false, {
874            imp.sink_query_pre_queue(
875                &from_glib_borrow(aggregator_pad),
876                gst::QueryRef::from_mut_ptr(query),
877            )
878        })
879        .into_glib()
880    }
881}
882
883unsafe extern "C" fn aggregator_src_event<T: AggregatorImpl>(
884    ptr: *mut ffi::GstAggregator,
885    event: *mut gst::ffi::GstEvent,
886) -> glib::ffi::gboolean {
887    unsafe {
888        let instance = &*(ptr as *mut T::Instance);
889        let imp = instance.imp();
890
891        gst::panic_to_error!(imp, false, { imp.src_event(from_glib_full(event)) }).into_glib()
892    }
893}
894
895unsafe extern "C" fn aggregator_src_query<T: AggregatorImpl>(
896    ptr: *mut ffi::GstAggregator,
897    query: *mut gst::ffi::GstQuery,
898) -> glib::ffi::gboolean {
899    unsafe {
900        let instance = &*(ptr as *mut T::Instance);
901        let imp = instance.imp();
902
903        gst::panic_to_error!(imp, false, {
904            imp.src_query(gst::QueryRef::from_mut_ptr(query))
905        })
906        .into_glib()
907    }
908}
909
910unsafe extern "C" fn aggregator_src_activate<T: AggregatorImpl>(
911    ptr: *mut ffi::GstAggregator,
912    mode: gst::ffi::GstPadMode,
913    active: glib::ffi::gboolean,
914) -> glib::ffi::gboolean {
915    unsafe {
916        let instance = &*(ptr as *mut T::Instance);
917        let imp = instance.imp();
918
919        gst::panic_to_error!(imp, false, {
920            match imp.src_activate(from_glib(mode), from_glib(active)) {
921                Ok(()) => true,
922                Err(err) => {
923                    err.log_with_imp(imp);
924                    false
925                }
926            }
927        })
928        .into_glib()
929    }
930}
931
932unsafe extern "C" fn aggregator_aggregate<T: AggregatorImpl>(
933    ptr: *mut ffi::GstAggregator,
934    timeout: glib::ffi::gboolean,
935) -> gst::ffi::GstFlowReturn {
936    unsafe {
937        let instance = &*(ptr as *mut T::Instance);
938        let imp = instance.imp();
939
940        gst::panic_to_error!(imp, gst::FlowReturn::Error, {
941            imp.aggregate(from_glib(timeout)).into()
942        })
943        .into_glib()
944    }
945}
946
947unsafe extern "C" fn aggregator_start<T: AggregatorImpl>(
948    ptr: *mut ffi::GstAggregator,
949) -> glib::ffi::gboolean {
950    unsafe {
951        let instance = &*(ptr as *mut T::Instance);
952        let imp = instance.imp();
953
954        gst::panic_to_error!(imp, false, {
955            match imp.start() {
956                Ok(()) => true,
957                Err(err) => {
958                    imp.post_error_message(err);
959                    false
960                }
961            }
962        })
963        .into_glib()
964    }
965}
966
967unsafe extern "C" fn aggregator_stop<T: AggregatorImpl>(
968    ptr: *mut ffi::GstAggregator,
969) -> glib::ffi::gboolean {
970    unsafe {
971        let instance = &*(ptr as *mut T::Instance);
972        let imp = instance.imp();
973
974        gst::panic_to_error!(imp, false, {
975            match imp.stop() {
976                Ok(()) => true,
977                Err(err) => {
978                    imp.post_error_message(err);
979                    false
980                }
981            }
982        })
983        .into_glib()
984    }
985}
986
987unsafe extern "C" fn aggregator_get_next_time<T: AggregatorImpl>(
988    ptr: *mut ffi::GstAggregator,
989) -> gst::ffi::GstClockTime {
990    unsafe {
991        let instance = &*(ptr as *mut T::Instance);
992        let imp = instance.imp();
993
994        gst::panic_to_error!(imp, gst::ClockTime::NONE, { imp.next_time() }).into_glib()
995    }
996}
997
998unsafe extern "C" fn aggregator_create_new_pad<T: AggregatorImpl>(
999    ptr: *mut ffi::GstAggregator,
1000    templ: *mut gst::ffi::GstPadTemplate,
1001    req_name: *const libc::c_char,
1002    caps: *const gst::ffi::GstCaps,
1003) -> *mut ffi::GstAggregatorPad {
1004    unsafe {
1005        let instance = &*(ptr as *mut T::Instance);
1006        let imp = instance.imp();
1007
1008        gst::panic_to_error!(imp, None, {
1009            let req_name: Borrowed<Option<glib::GString>> = from_glib_borrow(req_name);
1010
1011            imp.create_new_pad(
1012                &from_glib_borrow(templ),
1013                req_name.as_ref().as_ref().map(|s| s.as_str()),
1014                Option::<gst::Caps>::from_glib_borrow(caps)
1015                    .as_ref()
1016                    .as_ref(),
1017            )
1018        })
1019        .into_glib_ptr()
1020    }
1021}
1022
1023unsafe extern "C" fn aggregator_update_src_caps<T: AggregatorImpl>(
1024    ptr: *mut ffi::GstAggregator,
1025    caps: *mut gst::ffi::GstCaps,
1026    res: *mut *mut gst::ffi::GstCaps,
1027) -> gst::ffi::GstFlowReturn {
1028    unsafe {
1029        let instance = &*(ptr as *mut T::Instance);
1030        let imp = instance.imp();
1031
1032        *res = ptr::null_mut();
1033
1034        gst::panic_to_error!(imp, gst::FlowReturn::Error, {
1035            match imp.update_src_caps(&from_glib_borrow(caps)) {
1036                Ok(res_caps) => {
1037                    *res = res_caps.into_glib_ptr();
1038                    gst::FlowReturn::Ok
1039                }
1040                Err(err) => err.into(),
1041            }
1042        })
1043        .into_glib()
1044    }
1045}
1046
1047unsafe extern "C" fn aggregator_fixate_src_caps<T: AggregatorImpl>(
1048    ptr: *mut ffi::GstAggregator,
1049    caps: *mut gst::ffi::GstCaps,
1050) -> *mut gst::ffi::GstCaps {
1051    unsafe {
1052        let instance = &*(ptr as *mut T::Instance);
1053        let imp = instance.imp();
1054
1055        gst::panic_to_error!(imp, gst::Caps::new_empty(), {
1056            imp.fixate_src_caps(from_glib_full(caps))
1057        })
1058        .into_glib_ptr()
1059    }
1060}
1061
1062unsafe extern "C" fn aggregator_negotiated_src_caps<T: AggregatorImpl>(
1063    ptr: *mut ffi::GstAggregator,
1064    caps: *mut gst::ffi::GstCaps,
1065) -> glib::ffi::gboolean {
1066    unsafe {
1067        let instance = &*(ptr as *mut T::Instance);
1068        let imp = instance.imp();
1069
1070        gst::panic_to_error!(imp, false, {
1071            match imp.negotiated_src_caps(&from_glib_borrow(caps)) {
1072                Ok(()) => true,
1073                Err(err) => {
1074                    err.log_with_imp(imp);
1075                    false
1076                }
1077            }
1078        })
1079        .into_glib()
1080    }
1081}
1082
1083unsafe extern "C" fn aggregator_propose_allocation<T: AggregatorImpl>(
1084    ptr: *mut ffi::GstAggregator,
1085    pad: *mut ffi::GstAggregatorPad,
1086    decide_query: *mut gst::ffi::GstQuery,
1087    query: *mut gst::ffi::GstQuery,
1088) -> glib::ffi::gboolean {
1089    unsafe {
1090        let instance = &*(ptr as *mut T::Instance);
1091        let imp = instance.imp();
1092        let decide_query = if decide_query.is_null() {
1093            None
1094        } else {
1095            match gst::QueryRef::from_ptr(decide_query).view() {
1096                gst::QueryView::Allocation(allocation) => Some(allocation),
1097                _ => unreachable!(),
1098            }
1099        };
1100        let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
1101            gst::QueryViewMut::Allocation(allocation) => allocation,
1102            _ => unreachable!(),
1103        };
1104
1105        gst::panic_to_error!(imp, false, {
1106            match imp.propose_allocation(&from_glib_borrow(pad), decide_query, query) {
1107                Ok(()) => true,
1108                Err(err) => {
1109                    err.log_with_imp(imp);
1110                    false
1111                }
1112            }
1113        })
1114        .into_glib()
1115    }
1116}
1117
1118unsafe extern "C" fn aggregator_decide_allocation<T: AggregatorImpl>(
1119    ptr: *mut ffi::GstAggregator,
1120    query: *mut gst::ffi::GstQuery,
1121) -> glib::ffi::gboolean {
1122    unsafe {
1123        let instance = &*(ptr as *mut T::Instance);
1124        let imp = instance.imp();
1125        let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
1126            gst::QueryViewMut::Allocation(allocation) => allocation,
1127            _ => unreachable!(),
1128        };
1129
1130        gst::panic_to_error!(imp, false, {
1131            match imp.decide_allocation(query) {
1132                Ok(()) => true,
1133                Err(err) => {
1134                    err.log_with_imp(imp);
1135                    false
1136                }
1137            }
1138        })
1139        .into_glib()
1140    }
1141}
1142
1143#[cfg(feature = "v1_18")]
1144#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
1145unsafe extern "C" fn aggregator_negotiate<T: AggregatorImpl>(
1146    ptr: *mut ffi::GstAggregator,
1147) -> glib::ffi::gboolean {
1148    unsafe {
1149        let instance = &*(ptr as *mut T::Instance);
1150        let imp = instance.imp();
1151
1152        gst::panic_to_error!(imp, false, { imp.negotiate() }).into_glib()
1153    }
1154}
1155
1156#[cfg(feature = "v1_18")]
1157#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
1158unsafe extern "C" fn aggregator_peek_next_sample<T: AggregatorImpl>(
1159    ptr: *mut ffi::GstAggregator,
1160    pad: *mut ffi::GstAggregatorPad,
1161) -> *mut gst::ffi::GstSample {
1162    unsafe {
1163        let instance = &*(ptr as *mut T::Instance);
1164        let imp = instance.imp();
1165
1166        gst::panic_to_error!(imp, None, { imp.peek_next_sample(&from_glib_borrow(pad)) })
1167            .into_glib_ptr()
1168    }
1169}