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    /// Orchestrates [`gst::BufferPool`][crate::gst::BufferPool] & [`gst::Allocator`][crate::gst::Allocator] configuration for
239    /// the negotiated `caps`. Default implementation relies on an
240    /// Allocation `GstQuery` & calls ``decide_allocation()``.
241    /// ## `caps`
242    /// the negotiated [`gst::Caps`][crate::gst::Caps]
243    ///
244    /// # Returns
245    ///
246    /// whether the [`gst::BufferPool`][crate::gst::BufferPool] & [`gst::Allocator`][crate::gst::Allocator] could be configured.
247    #[cfg(feature = "v1_30")]
248    #[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
249    fn prepare_allocator(&self, caps: Option<&gst::Caps>) -> Result<(), gst::LoggableError> {
250        self.parent_prepare_allocator(caps)
251    }
252
253    /// Negotiates src pad caps with downstream elements.
254    /// Unmarks GST_PAD_FLAG_NEED_RECONFIGURE in any case. But marks it again
255    /// if `GstAggregatorClass::negotiate` fails.
256    ///
257    /// # Returns
258    ///
259    /// [`true`] if the negotiation succeeded, else [`false`].
260    #[cfg(feature = "v1_18")]
261    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
262    fn negotiate(&self) -> bool {
263        self.parent_negotiate()
264    }
265
266    /// Use this function to determine what input buffers will be aggregated
267    /// to produce the next output buffer. This should only be called from
268    /// a [`samples-selected`][struct@crate::Aggregator#samples-selected] handler, and can be used to precisely
269    /// control aggregating parameters for a given set of input samples.
270    /// ## `aggregator_pad`
271    /// a [`AggregatorPad`][crate::AggregatorPad]
272    ///
273    /// # Returns
274    ///
275    /// The sample that is about to be aggregated. It may hold a [`gst::Buffer`][crate::gst::Buffer]
276    ///  or a [`gst::BufferList`][crate::gst::BufferList]. The contents of its info structure is subclass-dependent,
277    ///  and documented on a subclass basis. The buffers held by the sample are
278    ///  not writable.
279    #[cfg(feature = "v1_18")]
280    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
281    fn peek_next_sample(&self, pad: &AggregatorPad) -> Option<gst::Sample> {
282        self.parent_peek_next_sample(pad)
283    }
284}
285
286pub trait AggregatorImplExt: AggregatorImpl {
287    fn parent_flush(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
288        unsafe {
289            let data = Self::type_data();
290            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
291            (*parent_class)
292                .flush
293                .map(|f| {
294                    try_from_glib(f(self
295                        .obj()
296                        .unsafe_cast_ref::<Aggregator>()
297                        .to_glib_none()
298                        .0))
299                })
300                .unwrap_or(Ok(gst::FlowSuccess::Ok))
301        }
302    }
303
304    fn parent_clip(
305        &self,
306        aggregator_pad: &AggregatorPad,
307        buffer: gst::Buffer,
308    ) -> Option<gst::Buffer> {
309        unsafe {
310            let data = Self::type_data();
311            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
312            match (*parent_class).clip {
313                None => Some(buffer),
314                Some(ref func) => from_glib_full(func(
315                    self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
316                    aggregator_pad.to_glib_none().0,
317                    buffer.into_glib_ptr(),
318                )),
319            }
320        }
321    }
322
323    fn parent_finish_buffer(
324        &self,
325        buffer: gst::Buffer,
326    ) -> Result<gst::FlowSuccess, gst::FlowError> {
327        unsafe {
328            let data = Self::type_data();
329            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
330            let f = (*parent_class)
331                .finish_buffer
332                .expect("Missing parent function `finish_buffer`");
333            try_from_glib(f(
334                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
335                buffer.into_glib_ptr(),
336            ))
337        }
338    }
339
340    #[cfg(feature = "v1_18")]
341    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
342    fn parent_finish_buffer_list(
343        &self,
344        buffer_list: gst::BufferList,
345    ) -> Result<gst::FlowSuccess, gst::FlowError> {
346        unsafe {
347            let data = Self::type_data();
348            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
349            let f = (*parent_class)
350                .finish_buffer_list
351                .expect("Missing parent function `finish_buffer_list`");
352            try_from_glib(f(
353                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
354                buffer_list.into_glib_ptr(),
355            ))
356        }
357    }
358
359    fn parent_sink_event(&self, aggregator_pad: &AggregatorPad, event: gst::Event) -> bool {
360        unsafe {
361            let data = Self::type_data();
362            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
363            let f = (*parent_class)
364                .sink_event
365                .expect("Missing parent function `sink_event`");
366            from_glib(f(
367                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
368                aggregator_pad.to_glib_none().0,
369                event.into_glib_ptr(),
370            ))
371        }
372    }
373
374    #[cfg(feature = "v1_18")]
375    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
376    fn parent_sink_event_pre_queue(
377        &self,
378        aggregator_pad: &AggregatorPad,
379        event: gst::Event,
380    ) -> Result<gst::FlowSuccess, gst::FlowError> {
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_event_pre_queue
386                .expect("Missing parent function `sink_event_pre_queue`");
387            try_from_glib(f(
388                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
389                aggregator_pad.to_glib_none().0,
390                event.into_glib_ptr(),
391            ))
392        }
393    }
394
395    fn parent_sink_query(&self, aggregator_pad: &AggregatorPad, query: &mut gst::QueryRef) -> bool {
396        unsafe {
397            let data = Self::type_data();
398            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
399            let f = (*parent_class)
400                .sink_query
401                .expect("Missing parent function `sink_query`");
402            from_glib(f(
403                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
404                aggregator_pad.to_glib_none().0,
405                query.as_mut_ptr(),
406            ))
407        }
408    }
409
410    #[cfg(feature = "v1_18")]
411    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
412    fn parent_sink_query_pre_queue(
413        &self,
414        aggregator_pad: &AggregatorPad,
415        query: &mut gst::QueryRef,
416    ) -> 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                .sink_query_pre_queue
422                .expect("Missing parent function `sink_query`");
423            from_glib(f(
424                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
425                aggregator_pad.to_glib_none().0,
426                query.as_mut_ptr(),
427            ))
428        }
429    }
430
431    fn parent_src_event(&self, event: gst::Event) -> bool {
432        unsafe {
433            let data = Self::type_data();
434            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
435            let f = (*parent_class)
436                .src_event
437                .expect("Missing parent function `src_event`");
438            from_glib(f(
439                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
440                event.into_glib_ptr(),
441            ))
442        }
443    }
444
445    fn parent_src_query(&self, query: &mut gst::QueryRef) -> bool {
446        unsafe {
447            let data = Self::type_data();
448            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
449            let f = (*parent_class)
450                .src_query
451                .expect("Missing parent function `src_query`");
452            from_glib(f(
453                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
454                query.as_mut_ptr(),
455            ))
456        }
457    }
458
459    fn parent_src_activate(
460        &self,
461        mode: gst::PadMode,
462        active: bool,
463    ) -> Result<(), gst::LoggableError> {
464        unsafe {
465            let data = Self::type_data();
466            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
467            match (*parent_class).src_activate {
468                None => Ok(()),
469                Some(f) => gst::result_from_gboolean!(
470                    f(
471                        self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
472                        mode.into_glib(),
473                        active.into_glib()
474                    ),
475                    gst::CAT_RUST,
476                    "Parent function `src_activate` failed"
477                ),
478            }
479        }
480    }
481
482    fn parent_aggregate(&self, timeout: bool) -> Result<gst::FlowSuccess, gst::FlowError> {
483        unsafe {
484            let data = Self::type_data();
485            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
486            let f = (*parent_class)
487                .aggregate
488                .expect("Missing parent function `aggregate`");
489            try_from_glib(f(
490                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
491                timeout.into_glib(),
492            ))
493        }
494    }
495
496    fn parent_start(&self) -> Result<(), gst::ErrorMessage> {
497        unsafe {
498            let data = Self::type_data();
499            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
500            (*parent_class)
501                .start
502                .map(|f| {
503                    if from_glib(f(self
504                        .obj()
505                        .unsafe_cast_ref::<Aggregator>()
506                        .to_glib_none()
507                        .0))
508                    {
509                        Ok(())
510                    } else {
511                        Err(gst::error_msg!(
512                            gst::CoreError::Failed,
513                            ["Parent function `start` failed"]
514                        ))
515                    }
516                })
517                .unwrap_or(Ok(()))
518        }
519    }
520
521    fn parent_stop(&self) -> Result<(), gst::ErrorMessage> {
522        unsafe {
523            let data = Self::type_data();
524            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
525            (*parent_class)
526                .stop
527                .map(|f| {
528                    if from_glib(f(self
529                        .obj()
530                        .unsafe_cast_ref::<Aggregator>()
531                        .to_glib_none()
532                        .0))
533                    {
534                        Ok(())
535                    } else {
536                        Err(gst::error_msg!(
537                            gst::CoreError::Failed,
538                            ["Parent function `stop` failed"]
539                        ))
540                    }
541                })
542                .unwrap_or(Ok(()))
543        }
544    }
545
546    fn parent_next_time(&self) -> Option<gst::ClockTime> {
547        unsafe {
548            let data = Self::type_data();
549            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
550            (*parent_class)
551                .get_next_time
552                .map(|f| {
553                    from_glib(f(self
554                        .obj()
555                        .unsafe_cast_ref::<Aggregator>()
556                        .to_glib_none()
557                        .0))
558                })
559                .unwrap_or(gst::ClockTime::NONE)
560        }
561    }
562
563    fn parent_create_new_pad(
564        &self,
565        templ: &gst::PadTemplate,
566        req_name: Option<&str>,
567        caps: Option<&gst::Caps>,
568    ) -> Option<AggregatorPad> {
569        unsafe {
570            let data = Self::type_data();
571            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
572            let f = (*parent_class)
573                .create_new_pad
574                .expect("Missing parent function `create_new_pad`");
575            from_glib_full(f(
576                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
577                templ.to_glib_none().0,
578                req_name.to_glib_none().0,
579                caps.to_glib_none().0,
580            ))
581        }
582    }
583
584    fn parent_update_src_caps(&self, caps: &gst::Caps) -> Result<gst::Caps, gst::FlowError> {
585        unsafe {
586            let data = Self::type_data();
587            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
588            let f = (*parent_class)
589                .update_src_caps
590                .expect("Missing parent function `update_src_caps`");
591
592            let mut out_caps = ptr::null_mut();
593            gst::FlowSuccess::try_from_glib(f(
594                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
595                caps.as_mut_ptr(),
596                &mut out_caps,
597            ))
598            .map(|_| from_glib_full(out_caps))
599        }
600    }
601
602    fn parent_fixate_src_caps(&self, caps: gst::Caps) -> gst::Caps {
603        unsafe {
604            let data = Self::type_data();
605            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
606
607            let f = (*parent_class)
608                .fixate_src_caps
609                .expect("Missing parent function `fixate_src_caps`");
610            from_glib_full(f(
611                self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
612                caps.into_glib_ptr(),
613            ))
614        }
615    }
616
617    fn parent_negotiated_src_caps(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
618        unsafe {
619            let data = Self::type_data();
620            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
621            (*parent_class)
622                .negotiated_src_caps
623                .map(|f| {
624                    gst::result_from_gboolean!(
625                        f(
626                            self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
627                            caps.to_glib_none().0
628                        ),
629                        gst::CAT_RUST,
630                        "Parent function `negotiated_src_caps` failed"
631                    )
632                })
633                .unwrap_or(Ok(()))
634        }
635    }
636
637    fn parent_propose_allocation(
638        &self,
639        pad: &AggregatorPad,
640        decide_query: Option<&gst::query::Allocation>,
641        query: &mut gst::query::Allocation,
642    ) -> Result<(), gst::LoggableError> {
643        unsafe {
644            let data = Self::type_data();
645            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
646            (*parent_class)
647                .propose_allocation
648                .map(|f| {
649                    gst::result_from_gboolean!(
650                        f(
651                            self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
652                            pad.to_glib_none().0,
653                            decide_query
654                                .as_ref()
655                                .map(|q| q.as_mut_ptr())
656                                .unwrap_or(ptr::null_mut()),
657                            query.as_mut_ptr()
658                        ),
659                        gst::CAT_RUST,
660                        "Parent function `propose_allocation` failed",
661                    )
662                })
663                .unwrap_or(Ok(()))
664        }
665    }
666
667    fn parent_decide_allocation(
668        &self,
669        query: &mut gst::query::Allocation,
670    ) -> Result<(), gst::LoggableError> {
671        unsafe {
672            let data = Self::type_data();
673            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
674            (*parent_class)
675                .decide_allocation
676                .map(|f| {
677                    gst::result_from_gboolean!(
678                        f(
679                            self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
680                            query.as_mut_ptr(),
681                        ),
682                        gst::CAT_RUST,
683                        "Parent function `decide_allocation` failed",
684                    )
685                })
686                .unwrap_or(Ok(()))
687        }
688    }
689
690    #[cfg(feature = "v1_30")]
691    #[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
692    fn parent_prepare_allocator(&self, caps: Option<&gst::Caps>) -> Result<(), gst::LoggableError> {
693        unsafe {
694            let data = Self::type_data();
695            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
696            (*parent_class)
697                .prepare_allocator
698                .map(|f| {
699                    gst::result_from_gboolean!(
700                        f(
701                            self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
702                            caps.to_glib_none().0
703                        ),
704                        gst::CAT_RUST,
705                        "Parent function `prepare_allocator` failed",
706                    )
707                })
708                .unwrap_or(Ok(()))
709        }
710    }
711
712    #[cfg(feature = "v1_18")]
713    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
714    fn parent_negotiate(&self) -> bool {
715        unsafe {
716            let data = Self::type_data();
717            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
718            (*parent_class)
719                .negotiate
720                .map(|f| {
721                    from_glib(f(self
722                        .obj()
723                        .unsafe_cast_ref::<Aggregator>()
724                        .to_glib_none()
725                        .0))
726                })
727                .unwrap_or(true)
728        }
729    }
730
731    #[cfg(feature = "v1_18")]
732    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
733    fn parent_peek_next_sample(&self, pad: &AggregatorPad) -> Option<gst::Sample> {
734        unsafe {
735            let data = Self::type_data();
736            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAggregatorClass;
737            (*parent_class)
738                .peek_next_sample
739                .map(|f| {
740                    from_glib_full(f(
741                        self.obj().unsafe_cast_ref::<Aggregator>().to_glib_none().0,
742                        pad.to_glib_none().0,
743                    ))
744                })
745                .unwrap_or(None)
746        }
747    }
748}
749
750impl<T: AggregatorImpl> AggregatorImplExt for T {}
751
752unsafe impl<T: AggregatorImpl> IsSubclassable<T> for Aggregator {
753    fn class_init(klass: &mut glib::Class<Self>) {
754        Self::parent_class_init::<T>(klass);
755        let klass = klass.as_mut();
756        klass.flush = Some(aggregator_flush::<T>);
757        klass.clip = Some(aggregator_clip::<T>);
758        klass.finish_buffer = Some(aggregator_finish_buffer::<T>);
759        klass.sink_event = Some(aggregator_sink_event::<T>);
760        klass.sink_query = Some(aggregator_sink_query::<T>);
761        klass.src_event = Some(aggregator_src_event::<T>);
762        klass.src_query = Some(aggregator_src_query::<T>);
763        klass.src_activate = Some(aggregator_src_activate::<T>);
764        klass.aggregate = Some(aggregator_aggregate::<T>);
765        klass.start = Some(aggregator_start::<T>);
766        klass.stop = Some(aggregator_stop::<T>);
767        klass.get_next_time = Some(aggregator_get_next_time::<T>);
768        klass.create_new_pad = Some(aggregator_create_new_pad::<T>);
769        klass.update_src_caps = Some(aggregator_update_src_caps::<T>);
770        klass.fixate_src_caps = Some(aggregator_fixate_src_caps::<T>);
771        klass.negotiated_src_caps = Some(aggregator_negotiated_src_caps::<T>);
772        klass.propose_allocation = Some(aggregator_propose_allocation::<T>);
773        klass.decide_allocation = Some(aggregator_decide_allocation::<T>);
774        #[cfg(feature = "v1_18")]
775        {
776            klass.sink_event_pre_queue = Some(aggregator_sink_event_pre_queue::<T>);
777            klass.sink_query_pre_queue = Some(aggregator_sink_query_pre_queue::<T>);
778            klass.negotiate = Some(aggregator_negotiate::<T>);
779            klass.peek_next_sample = Some(aggregator_peek_next_sample::<T>);
780            klass.finish_buffer_list = Some(aggregator_finish_buffer_list::<T>);
781        }
782        #[cfg(feature = "v1_30")]
783        {
784            klass.prepare_allocator = Some(aggregator_prepare_allocator::<T>);
785        }
786    }
787}
788
789unsafe extern "C" fn aggregator_flush<T: AggregatorImpl>(
790    ptr: *mut ffi::GstAggregator,
791) -> gst::ffi::GstFlowReturn {
792    unsafe {
793        let instance = &*(ptr as *mut T::Instance);
794        let imp = instance.imp();
795
796        gst::panic_to_error!(imp, gst::FlowReturn::Error, { imp.flush().into() }).into_glib()
797    }
798}
799
800unsafe extern "C" fn aggregator_clip<T: AggregatorImpl>(
801    ptr: *mut ffi::GstAggregator,
802    aggregator_pad: *mut ffi::GstAggregatorPad,
803    buffer: *mut gst::ffi::GstBuffer,
804) -> *mut gst::ffi::GstBuffer {
805    unsafe {
806        let instance = &*(ptr as *mut T::Instance);
807        let imp = instance.imp();
808
809        let ret = gst::panic_to_error!(imp, None, {
810            imp.clip(&from_glib_borrow(aggregator_pad), from_glib_full(buffer))
811        });
812
813        ret.map(|r| r.into_glib_ptr()).unwrap_or(ptr::null_mut())
814    }
815}
816
817unsafe extern "C" fn aggregator_finish_buffer<T: AggregatorImpl>(
818    ptr: *mut ffi::GstAggregator,
819    buffer: *mut gst::ffi::GstBuffer,
820) -> gst::ffi::GstFlowReturn {
821    unsafe {
822        let instance = &*(ptr as *mut T::Instance);
823        let imp = instance.imp();
824
825        gst::panic_to_error!(imp, gst::FlowReturn::Error, {
826            imp.finish_buffer(from_glib_full(buffer)).into()
827        })
828        .into_glib()
829    }
830}
831
832#[cfg(feature = "v1_18")]
833#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
834unsafe extern "C" fn aggregator_finish_buffer_list<T: AggregatorImpl>(
835    ptr: *mut ffi::GstAggregator,
836    buffer_list: *mut gst::ffi::GstBufferList,
837) -> gst::ffi::GstFlowReturn {
838    unsafe {
839        let instance = &*(ptr as *mut T::Instance);
840        let imp = instance.imp();
841
842        gst::panic_to_error!(imp, gst::FlowReturn::Error, {
843            imp.finish_buffer_list(from_glib_full(buffer_list)).into()
844        })
845        .into_glib()
846    }
847}
848
849unsafe extern "C" fn aggregator_sink_event<T: AggregatorImpl>(
850    ptr: *mut ffi::GstAggregator,
851    aggregator_pad: *mut ffi::GstAggregatorPad,
852    event: *mut gst::ffi::GstEvent,
853) -> glib::ffi::gboolean {
854    unsafe {
855        let instance = &*(ptr as *mut T::Instance);
856        let imp = instance.imp();
857
858        gst::panic_to_error!(imp, false, {
859            imp.sink_event(&from_glib_borrow(aggregator_pad), from_glib_full(event))
860        })
861        .into_glib()
862    }
863}
864
865#[cfg(feature = "v1_18")]
866#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
867unsafe extern "C" fn aggregator_sink_event_pre_queue<T: AggregatorImpl>(
868    ptr: *mut ffi::GstAggregator,
869    aggregator_pad: *mut ffi::GstAggregatorPad,
870    event: *mut gst::ffi::GstEvent,
871) -> gst::ffi::GstFlowReturn {
872    unsafe {
873        let instance = &*(ptr as *mut T::Instance);
874        let imp = instance.imp();
875
876        gst::panic_to_error!(imp, gst::FlowReturn::Error, {
877            imp.sink_event_pre_queue(&from_glib_borrow(aggregator_pad), from_glib_full(event))
878                .into()
879        })
880        .into_glib()
881    }
882}
883
884unsafe extern "C" fn aggregator_sink_query<T: AggregatorImpl>(
885    ptr: *mut ffi::GstAggregator,
886    aggregator_pad: *mut ffi::GstAggregatorPad,
887    query: *mut gst::ffi::GstQuery,
888) -> glib::ffi::gboolean {
889    unsafe {
890        let instance = &*(ptr as *mut T::Instance);
891        let imp = instance.imp();
892
893        gst::panic_to_error!(imp, false, {
894            imp.sink_query(
895                &from_glib_borrow(aggregator_pad),
896                gst::QueryRef::from_mut_ptr(query),
897            )
898        })
899        .into_glib()
900    }
901}
902
903#[cfg(feature = "v1_18")]
904#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
905unsafe extern "C" fn aggregator_sink_query_pre_queue<T: AggregatorImpl>(
906    ptr: *mut ffi::GstAggregator,
907    aggregator_pad: *mut ffi::GstAggregatorPad,
908    query: *mut gst::ffi::GstQuery,
909) -> glib::ffi::gboolean {
910    unsafe {
911        let instance = &*(ptr as *mut T::Instance);
912        let imp = instance.imp();
913
914        gst::panic_to_error!(imp, false, {
915            imp.sink_query_pre_queue(
916                &from_glib_borrow(aggregator_pad),
917                gst::QueryRef::from_mut_ptr(query),
918            )
919        })
920        .into_glib()
921    }
922}
923
924unsafe extern "C" fn aggregator_src_event<T: AggregatorImpl>(
925    ptr: *mut ffi::GstAggregator,
926    event: *mut gst::ffi::GstEvent,
927) -> glib::ffi::gboolean {
928    unsafe {
929        let instance = &*(ptr as *mut T::Instance);
930        let imp = instance.imp();
931
932        gst::panic_to_error!(imp, false, { imp.src_event(from_glib_full(event)) }).into_glib()
933    }
934}
935
936unsafe extern "C" fn aggregator_src_query<T: AggregatorImpl>(
937    ptr: *mut ffi::GstAggregator,
938    query: *mut gst::ffi::GstQuery,
939) -> glib::ffi::gboolean {
940    unsafe {
941        let instance = &*(ptr as *mut T::Instance);
942        let imp = instance.imp();
943
944        gst::panic_to_error!(imp, false, {
945            imp.src_query(gst::QueryRef::from_mut_ptr(query))
946        })
947        .into_glib()
948    }
949}
950
951unsafe extern "C" fn aggregator_src_activate<T: AggregatorImpl>(
952    ptr: *mut ffi::GstAggregator,
953    mode: gst::ffi::GstPadMode,
954    active: glib::ffi::gboolean,
955) -> glib::ffi::gboolean {
956    unsafe {
957        let instance = &*(ptr as *mut T::Instance);
958        let imp = instance.imp();
959
960        gst::panic_to_error!(imp, false, {
961            match imp.src_activate(from_glib(mode), from_glib(active)) {
962                Ok(()) => true,
963                Err(err) => {
964                    err.log_with_imp(imp);
965                    false
966                }
967            }
968        })
969        .into_glib()
970    }
971}
972
973unsafe extern "C" fn aggregator_aggregate<T: AggregatorImpl>(
974    ptr: *mut ffi::GstAggregator,
975    timeout: glib::ffi::gboolean,
976) -> gst::ffi::GstFlowReturn {
977    unsafe {
978        let instance = &*(ptr as *mut T::Instance);
979        let imp = instance.imp();
980
981        gst::panic_to_error!(imp, gst::FlowReturn::Error, {
982            imp.aggregate(from_glib(timeout)).into()
983        })
984        .into_glib()
985    }
986}
987
988unsafe extern "C" fn aggregator_start<T: AggregatorImpl>(
989    ptr: *mut ffi::GstAggregator,
990) -> glib::ffi::gboolean {
991    unsafe {
992        let instance = &*(ptr as *mut T::Instance);
993        let imp = instance.imp();
994
995        gst::panic_to_error!(imp, false, {
996            match imp.start() {
997                Ok(()) => true,
998                Err(err) => {
999                    imp.post_error_message(err);
1000                    false
1001                }
1002            }
1003        })
1004        .into_glib()
1005    }
1006}
1007
1008unsafe extern "C" fn aggregator_stop<T: AggregatorImpl>(
1009    ptr: *mut ffi::GstAggregator,
1010) -> glib::ffi::gboolean {
1011    unsafe {
1012        let instance = &*(ptr as *mut T::Instance);
1013        let imp = instance.imp();
1014
1015        gst::panic_to_error!(imp, false, {
1016            match imp.stop() {
1017                Ok(()) => true,
1018                Err(err) => {
1019                    imp.post_error_message(err);
1020                    false
1021                }
1022            }
1023        })
1024        .into_glib()
1025    }
1026}
1027
1028unsafe extern "C" fn aggregator_get_next_time<T: AggregatorImpl>(
1029    ptr: *mut ffi::GstAggregator,
1030) -> gst::ffi::GstClockTime {
1031    unsafe {
1032        let instance = &*(ptr as *mut T::Instance);
1033        let imp = instance.imp();
1034
1035        gst::panic_to_error!(imp, gst::ClockTime::NONE, { imp.next_time() }).into_glib()
1036    }
1037}
1038
1039unsafe extern "C" fn aggregator_create_new_pad<T: AggregatorImpl>(
1040    ptr: *mut ffi::GstAggregator,
1041    templ: *mut gst::ffi::GstPadTemplate,
1042    req_name: *const libc::c_char,
1043    caps: *const gst::ffi::GstCaps,
1044) -> *mut ffi::GstAggregatorPad {
1045    unsafe {
1046        let instance = &*(ptr as *mut T::Instance);
1047        let imp = instance.imp();
1048
1049        gst::panic_to_error!(imp, None, {
1050            let req_name: Borrowed<Option<glib::GString>> = from_glib_borrow(req_name);
1051
1052            imp.create_new_pad(
1053                &from_glib_borrow(templ),
1054                req_name.as_ref().as_ref().map(|s| s.as_str()),
1055                Option::<gst::Caps>::from_glib_borrow(caps)
1056                    .as_ref()
1057                    .as_ref(),
1058            )
1059        })
1060        .into_glib_ptr()
1061    }
1062}
1063
1064unsafe extern "C" fn aggregator_update_src_caps<T: AggregatorImpl>(
1065    ptr: *mut ffi::GstAggregator,
1066    caps: *mut gst::ffi::GstCaps,
1067    res: *mut *mut gst::ffi::GstCaps,
1068) -> gst::ffi::GstFlowReturn {
1069    unsafe {
1070        let instance = &*(ptr as *mut T::Instance);
1071        let imp = instance.imp();
1072
1073        *res = ptr::null_mut();
1074
1075        gst::panic_to_error!(imp, gst::FlowReturn::Error, {
1076            match imp.update_src_caps(&from_glib_borrow(caps)) {
1077                Ok(res_caps) => {
1078                    *res = res_caps.into_glib_ptr();
1079                    gst::FlowReturn::Ok
1080                }
1081                Err(err) => err.into(),
1082            }
1083        })
1084        .into_glib()
1085    }
1086}
1087
1088unsafe extern "C" fn aggregator_fixate_src_caps<T: AggregatorImpl>(
1089    ptr: *mut ffi::GstAggregator,
1090    caps: *mut gst::ffi::GstCaps,
1091) -> *mut gst::ffi::GstCaps {
1092    unsafe {
1093        let instance = &*(ptr as *mut T::Instance);
1094        let imp = instance.imp();
1095
1096        gst::panic_to_error!(imp, gst::Caps::new_empty(), {
1097            imp.fixate_src_caps(from_glib_full(caps))
1098        })
1099        .into_glib_ptr()
1100    }
1101}
1102
1103unsafe extern "C" fn aggregator_negotiated_src_caps<T: AggregatorImpl>(
1104    ptr: *mut ffi::GstAggregator,
1105    caps: *mut gst::ffi::GstCaps,
1106) -> glib::ffi::gboolean {
1107    unsafe {
1108        let instance = &*(ptr as *mut T::Instance);
1109        let imp = instance.imp();
1110
1111        gst::panic_to_error!(imp, false, {
1112            match imp.negotiated_src_caps(&from_glib_borrow(caps)) {
1113                Ok(()) => true,
1114                Err(err) => {
1115                    err.log_with_imp(imp);
1116                    false
1117                }
1118            }
1119        })
1120        .into_glib()
1121    }
1122}
1123
1124unsafe extern "C" fn aggregator_propose_allocation<T: AggregatorImpl>(
1125    ptr: *mut ffi::GstAggregator,
1126    pad: *mut ffi::GstAggregatorPad,
1127    decide_query: *mut gst::ffi::GstQuery,
1128    query: *mut gst::ffi::GstQuery,
1129) -> glib::ffi::gboolean {
1130    unsafe {
1131        let instance = &*(ptr as *mut T::Instance);
1132        let imp = instance.imp();
1133        let decide_query = if decide_query.is_null() {
1134            None
1135        } else {
1136            match gst::QueryRef::from_ptr(decide_query).view() {
1137                gst::QueryView::Allocation(allocation) => Some(allocation),
1138                _ => unreachable!(),
1139            }
1140        };
1141        let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
1142            gst::QueryViewMut::Allocation(allocation) => allocation,
1143            _ => unreachable!(),
1144        };
1145
1146        gst::panic_to_error!(imp, false, {
1147            match imp.propose_allocation(&from_glib_borrow(pad), decide_query, query) {
1148                Ok(()) => true,
1149                Err(err) => {
1150                    err.log_with_imp(imp);
1151                    false
1152                }
1153            }
1154        })
1155        .into_glib()
1156    }
1157}
1158
1159unsafe extern "C" fn aggregator_decide_allocation<T: AggregatorImpl>(
1160    ptr: *mut ffi::GstAggregator,
1161    query: *mut gst::ffi::GstQuery,
1162) -> glib::ffi::gboolean {
1163    unsafe {
1164        let instance = &*(ptr as *mut T::Instance);
1165        let imp = instance.imp();
1166        let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
1167            gst::QueryViewMut::Allocation(allocation) => allocation,
1168            _ => unreachable!(),
1169        };
1170
1171        gst::panic_to_error!(imp, false, {
1172            match imp.decide_allocation(query) {
1173                Ok(()) => true,
1174                Err(err) => {
1175                    err.log_with_imp(imp);
1176                    false
1177                }
1178            }
1179        })
1180        .into_glib()
1181    }
1182}
1183
1184#[cfg(feature = "v1_18")]
1185#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
1186unsafe extern "C" fn aggregator_negotiate<T: AggregatorImpl>(
1187    ptr: *mut ffi::GstAggregator,
1188) -> glib::ffi::gboolean {
1189    unsafe {
1190        let instance = &*(ptr as *mut T::Instance);
1191        let imp = instance.imp();
1192
1193        gst::panic_to_error!(imp, false, { imp.negotiate() }).into_glib()
1194    }
1195}
1196
1197#[cfg(feature = "v1_18")]
1198#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
1199unsafe extern "C" fn aggregator_peek_next_sample<T: AggregatorImpl>(
1200    ptr: *mut ffi::GstAggregator,
1201    pad: *mut ffi::GstAggregatorPad,
1202) -> *mut gst::ffi::GstSample {
1203    unsafe {
1204        let instance = &*(ptr as *mut T::Instance);
1205        let imp = instance.imp();
1206
1207        gst::panic_to_error!(imp, None, { imp.peek_next_sample(&from_glib_borrow(pad)) })
1208            .into_glib_ptr()
1209    }
1210}
1211
1212#[cfg(feature = "v1_30")]
1213#[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
1214unsafe extern "C" fn aggregator_prepare_allocator<T: AggregatorImpl>(
1215    ptr: *mut ffi::GstAggregator,
1216    caps: *mut gst::ffi::GstCaps,
1217) -> glib::ffi::gboolean {
1218    unsafe {
1219        let instance = &*(ptr as *mut T::Instance);
1220        let imp = instance.imp();
1221        let caps = Option::<gst::Caps>::from_glib_none(caps);
1222
1223        gst::panic_to_error!(imp, false, {
1224            match imp.prepare_allocator(caps.as_ref()) {
1225                Ok(()) => true,
1226                Err(err) => {
1227                    err.log_with_imp(imp);
1228                    false
1229                }
1230            }
1231        })
1232        .into_glib()
1233    }
1234}