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