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