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