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::element_panic_to_error!(imp, gst::FlowReturn::Error, { imp.flush().into() })
797            .into_glib()
798    }
799}
800
801unsafe extern "C" fn aggregator_clip<T: AggregatorImpl>(
802    ptr: *mut ffi::GstAggregator,
803    aggregator_pad: *mut ffi::GstAggregatorPad,
804    buffer: *mut gst::ffi::GstBuffer,
805) -> *mut gst::ffi::GstBuffer {
806    unsafe {
807        let instance = &*(ptr as *mut T::Instance);
808        let imp = instance.imp();
809
810        let ret = gst::element_panic_to_error!(imp, None, {
811            imp.clip(&from_glib_borrow(aggregator_pad), from_glib_full(buffer))
812        });
813
814        ret.map(|r| r.into_glib_ptr()).unwrap_or(ptr::null_mut())
815    }
816}
817
818unsafe extern "C" fn aggregator_finish_buffer<T: AggregatorImpl>(
819    ptr: *mut ffi::GstAggregator,
820    buffer: *mut gst::ffi::GstBuffer,
821) -> gst::ffi::GstFlowReturn {
822    unsafe {
823        let instance = &*(ptr as *mut T::Instance);
824        let imp = instance.imp();
825
826        gst::element_panic_to_error!(imp, gst::FlowReturn::Error, {
827            imp.finish_buffer(from_glib_full(buffer)).into()
828        })
829        .into_glib()
830    }
831}
832
833#[cfg(feature = "v1_18")]
834#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
835unsafe extern "C" fn aggregator_finish_buffer_list<T: AggregatorImpl>(
836    ptr: *mut ffi::GstAggregator,
837    buffer_list: *mut gst::ffi::GstBufferList,
838) -> gst::ffi::GstFlowReturn {
839    unsafe {
840        let instance = &*(ptr as *mut T::Instance);
841        let imp = instance.imp();
842
843        gst::element_panic_to_error!(imp, gst::FlowReturn::Error, {
844            imp.finish_buffer_list(from_glib_full(buffer_list)).into()
845        })
846        .into_glib()
847    }
848}
849
850unsafe extern "C" fn aggregator_sink_event<T: AggregatorImpl>(
851    ptr: *mut ffi::GstAggregator,
852    aggregator_pad: *mut ffi::GstAggregatorPad,
853    event: *mut gst::ffi::GstEvent,
854) -> glib::ffi::gboolean {
855    unsafe {
856        let instance = &*(ptr as *mut T::Instance);
857        let imp = instance.imp();
858
859        gst::element_panic_to_error!(imp, false, {
860            imp.sink_event(&from_glib_borrow(aggregator_pad), from_glib_full(event))
861        })
862        .into_glib()
863    }
864}
865
866#[cfg(feature = "v1_18")]
867#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
868unsafe extern "C" fn aggregator_sink_event_pre_queue<T: AggregatorImpl>(
869    ptr: *mut ffi::GstAggregator,
870    aggregator_pad: *mut ffi::GstAggregatorPad,
871    event: *mut gst::ffi::GstEvent,
872) -> gst::ffi::GstFlowReturn {
873    unsafe {
874        let instance = &*(ptr as *mut T::Instance);
875        let imp = instance.imp();
876
877        gst::element_panic_to_error!(imp, gst::FlowReturn::Error, {
878            imp.sink_event_pre_queue(&from_glib_borrow(aggregator_pad), from_glib_full(event))
879                .into()
880        })
881        .into_glib()
882    }
883}
884
885unsafe extern "C" fn aggregator_sink_query<T: AggregatorImpl>(
886    ptr: *mut ffi::GstAggregator,
887    aggregator_pad: *mut ffi::GstAggregatorPad,
888    query: *mut gst::ffi::GstQuery,
889) -> glib::ffi::gboolean {
890    unsafe {
891        let instance = &*(ptr as *mut T::Instance);
892        let imp = instance.imp();
893
894        gst::element_panic_to_error!(imp, false, {
895            imp.sink_query(
896                &from_glib_borrow(aggregator_pad),
897                gst::QueryRef::from_mut_ptr(query),
898            )
899        })
900        .into_glib()
901    }
902}
903
904#[cfg(feature = "v1_18")]
905#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
906unsafe extern "C" fn aggregator_sink_query_pre_queue<T: AggregatorImpl>(
907    ptr: *mut ffi::GstAggregator,
908    aggregator_pad: *mut ffi::GstAggregatorPad,
909    query: *mut gst::ffi::GstQuery,
910) -> glib::ffi::gboolean {
911    unsafe {
912        let instance = &*(ptr as *mut T::Instance);
913        let imp = instance.imp();
914
915        gst::element_panic_to_error!(imp, false, {
916            imp.sink_query_pre_queue(
917                &from_glib_borrow(aggregator_pad),
918                gst::QueryRef::from_mut_ptr(query),
919            )
920        })
921        .into_glib()
922    }
923}
924
925unsafe extern "C" fn aggregator_src_event<T: AggregatorImpl>(
926    ptr: *mut ffi::GstAggregator,
927    event: *mut gst::ffi::GstEvent,
928) -> glib::ffi::gboolean {
929    unsafe {
930        let instance = &*(ptr as *mut T::Instance);
931        let imp = instance.imp();
932
933        gst::element_panic_to_error!(imp, false, { imp.src_event(from_glib_full(event)) })
934            .into_glib()
935    }
936}
937
938unsafe extern "C" fn aggregator_src_query<T: AggregatorImpl>(
939    ptr: *mut ffi::GstAggregator,
940    query: *mut gst::ffi::GstQuery,
941) -> glib::ffi::gboolean {
942    unsafe {
943        let instance = &*(ptr as *mut T::Instance);
944        let imp = instance.imp();
945
946        gst::element_panic_to_error!(imp, false, {
947            imp.src_query(gst::QueryRef::from_mut_ptr(query))
948        })
949        .into_glib()
950    }
951}
952
953unsafe extern "C" fn aggregator_src_activate<T: AggregatorImpl>(
954    ptr: *mut ffi::GstAggregator,
955    mode: gst::ffi::GstPadMode,
956    active: glib::ffi::gboolean,
957) -> glib::ffi::gboolean {
958    unsafe {
959        let instance = &*(ptr as *mut T::Instance);
960        let imp = instance.imp();
961
962        gst::element_panic_to_error!(imp, false, {
963            match imp.src_activate(from_glib(mode), from_glib(active)) {
964                Ok(()) => true,
965                Err(err) => {
966                    err.log_with_imp(imp);
967                    false
968                }
969            }
970        })
971        .into_glib()
972    }
973}
974
975unsafe extern "C" fn aggregator_aggregate<T: AggregatorImpl>(
976    ptr: *mut ffi::GstAggregator,
977    timeout: glib::ffi::gboolean,
978) -> gst::ffi::GstFlowReturn {
979    unsafe {
980        let instance = &*(ptr as *mut T::Instance);
981        let imp = instance.imp();
982
983        gst::element_panic_to_error!(imp, gst::FlowReturn::Error, {
984            imp.aggregate(from_glib(timeout)).into()
985        })
986        .into_glib()
987    }
988}
989
990unsafe extern "C" fn aggregator_start<T: AggregatorImpl>(
991    ptr: *mut ffi::GstAggregator,
992) -> glib::ffi::gboolean {
993    unsafe {
994        let instance = &*(ptr as *mut T::Instance);
995        let imp = instance.imp();
996
997        gst::element_panic_to_error!(imp, false, {
998            match imp.start() {
999                Ok(()) => true,
1000                Err(err) => {
1001                    imp.post_error_message(err);
1002                    false
1003                }
1004            }
1005        })
1006        .into_glib()
1007    }
1008}
1009
1010unsafe extern "C" fn aggregator_stop<T: AggregatorImpl>(
1011    ptr: *mut ffi::GstAggregator,
1012) -> glib::ffi::gboolean {
1013    unsafe {
1014        let instance = &*(ptr as *mut T::Instance);
1015        let imp = instance.imp();
1016
1017        gst::element_panic_to_error!(imp, false, {
1018            match imp.stop() {
1019                Ok(()) => true,
1020                Err(err) => {
1021                    imp.post_error_message(err);
1022                    false
1023                }
1024            }
1025        })
1026        .into_glib()
1027    }
1028}
1029
1030unsafe extern "C" fn aggregator_get_next_time<T: AggregatorImpl>(
1031    ptr: *mut ffi::GstAggregator,
1032) -> gst::ffi::GstClockTime {
1033    unsafe {
1034        let instance = &*(ptr as *mut T::Instance);
1035        let imp = instance.imp();
1036
1037        gst::element_panic_to_error!(imp, gst::ClockTime::NONE, { imp.next_time() }).into_glib()
1038    }
1039}
1040
1041unsafe extern "C" fn aggregator_create_new_pad<T: AggregatorImpl>(
1042    ptr: *mut ffi::GstAggregator,
1043    templ: *mut gst::ffi::GstPadTemplate,
1044    req_name: *const libc::c_char,
1045    caps: *const gst::ffi::GstCaps,
1046) -> *mut ffi::GstAggregatorPad {
1047    unsafe {
1048        let instance = &*(ptr as *mut T::Instance);
1049        let imp = instance.imp();
1050
1051        gst::element_panic_to_error!(imp, None, {
1052            let req_name: Borrowed<Option<glib::GString>> = from_glib_borrow(req_name);
1053
1054            imp.create_new_pad(
1055                &from_glib_borrow(templ),
1056                req_name.as_ref().as_ref().map(|s| s.as_str()),
1057                Option::<gst::Caps>::from_glib_borrow(caps)
1058                    .as_ref()
1059                    .as_ref(),
1060            )
1061        })
1062        .into_glib_ptr()
1063    }
1064}
1065
1066unsafe extern "C" fn aggregator_update_src_caps<T: AggregatorImpl>(
1067    ptr: *mut ffi::GstAggregator,
1068    caps: *mut gst::ffi::GstCaps,
1069    res: *mut *mut gst::ffi::GstCaps,
1070) -> gst::ffi::GstFlowReturn {
1071    unsafe {
1072        let instance = &*(ptr as *mut T::Instance);
1073        let imp = instance.imp();
1074
1075        *res = ptr::null_mut();
1076
1077        gst::element_panic_to_error!(imp, gst::FlowReturn::Error, {
1078            match imp.update_src_caps(&from_glib_borrow(caps)) {
1079                Ok(res_caps) => {
1080                    *res = res_caps.into_glib_ptr();
1081                    gst::FlowReturn::Ok
1082                }
1083                Err(err) => err.into(),
1084            }
1085        })
1086        .into_glib()
1087    }
1088}
1089
1090unsafe extern "C" fn aggregator_fixate_src_caps<T: AggregatorImpl>(
1091    ptr: *mut ffi::GstAggregator,
1092    caps: *mut gst::ffi::GstCaps,
1093) -> *mut gst::ffi::GstCaps {
1094    unsafe {
1095        let instance = &*(ptr as *mut T::Instance);
1096        let imp = instance.imp();
1097
1098        gst::element_panic_to_error!(imp, gst::Caps::new_empty(), {
1099            imp.fixate_src_caps(from_glib_full(caps))
1100        })
1101        .into_glib_ptr()
1102    }
1103}
1104
1105unsafe extern "C" fn aggregator_negotiated_src_caps<T: AggregatorImpl>(
1106    ptr: *mut ffi::GstAggregator,
1107    caps: *mut gst::ffi::GstCaps,
1108) -> glib::ffi::gboolean {
1109    unsafe {
1110        let instance = &*(ptr as *mut T::Instance);
1111        let imp = instance.imp();
1112
1113        gst::element_panic_to_error!(imp, false, {
1114            match imp.negotiated_src_caps(&from_glib_borrow(caps)) {
1115                Ok(()) => true,
1116                Err(err) => {
1117                    err.log_with_imp(imp);
1118                    false
1119                }
1120            }
1121        })
1122        .into_glib()
1123    }
1124}
1125
1126unsafe extern "C" fn aggregator_propose_allocation<T: AggregatorImpl>(
1127    ptr: *mut ffi::GstAggregator,
1128    pad: *mut ffi::GstAggregatorPad,
1129    decide_query: *mut gst::ffi::GstQuery,
1130    query: *mut gst::ffi::GstQuery,
1131) -> glib::ffi::gboolean {
1132    unsafe {
1133        let instance = &*(ptr as *mut T::Instance);
1134        let imp = instance.imp();
1135        let decide_query = if decide_query.is_null() {
1136            None
1137        } else {
1138            match gst::QueryRef::from_ptr(decide_query).view() {
1139                gst::QueryView::Allocation(allocation) => Some(allocation),
1140                _ => unreachable!(),
1141            }
1142        };
1143        let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
1144            gst::QueryViewMut::Allocation(allocation) => allocation,
1145            _ => unreachable!(),
1146        };
1147
1148        gst::element_panic_to_error!(imp, false, {
1149            match imp.propose_allocation(&from_glib_borrow(pad), decide_query, query) {
1150                Ok(()) => true,
1151                Err(err) => {
1152                    err.log_with_imp(imp);
1153                    false
1154                }
1155            }
1156        })
1157        .into_glib()
1158    }
1159}
1160
1161unsafe extern "C" fn aggregator_decide_allocation<T: AggregatorImpl>(
1162    ptr: *mut ffi::GstAggregator,
1163    query: *mut gst::ffi::GstQuery,
1164) -> glib::ffi::gboolean {
1165    unsafe {
1166        let instance = &*(ptr as *mut T::Instance);
1167        let imp = instance.imp();
1168        let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
1169            gst::QueryViewMut::Allocation(allocation) => allocation,
1170            _ => unreachable!(),
1171        };
1172
1173        gst::element_panic_to_error!(imp, false, {
1174            match imp.decide_allocation(query) {
1175                Ok(()) => true,
1176                Err(err) => {
1177                    err.log_with_imp(imp);
1178                    false
1179                }
1180            }
1181        })
1182        .into_glib()
1183    }
1184}
1185
1186#[cfg(feature = "v1_18")]
1187#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
1188unsafe extern "C" fn aggregator_negotiate<T: AggregatorImpl>(
1189    ptr: *mut ffi::GstAggregator,
1190) -> glib::ffi::gboolean {
1191    unsafe {
1192        let instance = &*(ptr as *mut T::Instance);
1193        let imp = instance.imp();
1194
1195        gst::element_panic_to_error!(imp, false, { imp.negotiate() }).into_glib()
1196    }
1197}
1198
1199#[cfg(feature = "v1_18")]
1200#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
1201unsafe extern "C" fn aggregator_peek_next_sample<T: AggregatorImpl>(
1202    ptr: *mut ffi::GstAggregator,
1203    pad: *mut ffi::GstAggregatorPad,
1204) -> *mut gst::ffi::GstSample {
1205    unsafe {
1206        let instance = &*(ptr as *mut T::Instance);
1207        let imp = instance.imp();
1208
1209        gst::element_panic_to_error!(imp, None, { imp.peek_next_sample(&from_glib_borrow(pad)) })
1210            .into_glib_ptr()
1211    }
1212}
1213
1214#[cfg(feature = "v1_30")]
1215#[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
1216unsafe extern "C" fn aggregator_prepare_allocator<T: AggregatorImpl>(
1217    ptr: *mut ffi::GstAggregator,
1218    caps: *mut gst::ffi::GstCaps,
1219) -> glib::ffi::gboolean {
1220    unsafe {
1221        let instance = &*(ptr as *mut T::Instance);
1222        let imp = instance.imp();
1223        let caps = Option::<gst::Caps>::from_glib_none(caps);
1224
1225        gst::element_panic_to_error!(imp, false, {
1226            match imp.prepare_allocator(caps.as_ref()) {
1227                Ok(()) => true,
1228                Err(err) => {
1229                    err.log_with_imp(imp);
1230                    false
1231                }
1232            }
1233        })
1234        .into_glib()
1235    }
1236}