Skip to main content

gstreamer_audio/subclass/
audio_encoder.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::translate::*;
6use gst::subclass::prelude::*;
7
8use crate::{AudioEncoder, AudioInfo, ffi, prelude::*};
9
10pub trait AudioEncoderImpl: ElementImpl + ObjectSubclass<Type: IsA<AudioEncoder>> {
11    /// Optional.
12    ///  Called when the element changes to GST_STATE_READY.
13    ///  Allows opening external resources.
14    fn open(&self) -> Result<(), gst::ErrorMessage> {
15        self.parent_open()
16    }
17
18    /// Optional.
19    ///  Called when the element changes to GST_STATE_NULL.
20    ///  Allows closing external resources.
21    fn close(&self) -> Result<(), gst::ErrorMessage> {
22        self.parent_close()
23    }
24
25    /// Optional.
26    ///  Called when the element starts processing.
27    ///  Allows opening external resources.
28    fn start(&self) -> Result<(), gst::ErrorMessage> {
29        self.parent_start()
30    }
31
32    /// Optional.
33    ///  Called when the element stops processing.
34    ///  Allows closing external resources.
35    fn stop(&self) -> Result<(), gst::ErrorMessage> {
36        self.parent_stop()
37    }
38
39    /// Notifies subclass of incoming data format.
40    ///  GstAudioInfo contains the format according to provided caps.
41    fn set_format(&self, info: &AudioInfo) -> Result<(), gst::LoggableError> {
42        self.parent_set_format(info)
43    }
44
45    /// Provides input samples (or NULL to clear any remaining data)
46    ///  according to directions as configured by the subclass
47    ///  using the API. Input data ref management is performed
48    ///  by base class, subclass should not care or intervene,
49    ///  and input data is only valid until next call to base class,
50    ///  most notably a call to [`AudioEncoderExt::finish_frame()`][crate::prelude::AudioEncoderExt::finish_frame()].
51    fn handle_frame(
52        &self,
53        buffer: Option<&gst::Buffer>,
54    ) -> Result<gst::FlowSuccess, gst::FlowError> {
55        self.parent_handle_frame(buffer)
56    }
57
58    /// Optional.
59    ///  Called just prior to pushing (encoded data) buffer downstream.
60    ///  Subclass has full discretionary access to buffer,
61    ///  and a not OK flow return will abort downstream pushing.
62    fn pre_push(&self, buffer: gst::Buffer) -> Result<Option<gst::Buffer>, gst::FlowError> {
63        self.parent_pre_push(buffer)
64    }
65
66    /// Optional.
67    ///  Instructs subclass to clear any codec caches and discard
68    ///  any pending samples and not yet returned encoded data.
69    fn flush(&self) {
70        self.parent_flush()
71    }
72
73    /// Negotiate with downstream elements to currently configured [`gst::Caps`][crate::gst::Caps].
74    /// Unmark GST_PAD_FLAG_NEED_RECONFIGURE in any case. But mark it again if
75    /// negotiate fails.
76    ///
77    /// # Returns
78    ///
79    /// [`true`] if the negotiation succeeded, else [`false`].
80    fn negotiate(&self) -> Result<(), gst::LoggableError> {
81        self.parent_negotiate()
82    }
83
84    fn caps(&self, filter: Option<&gst::Caps>) -> gst::Caps {
85        self.parent_caps(filter)
86    }
87
88    /// Optional.
89    ///  Event handler on the sink pad. Subclasses should chain up to
90    ///  the parent implementation to invoke the default handler.
91    fn sink_event(&self, event: gst::Event) -> bool {
92        self.parent_sink_event(event)
93    }
94
95    /// Optional.
96    ///  Query handler on the sink pad. This function should
97    ///  return TRUE if the query could be performed. Subclasses
98    ///  should chain up to the parent implementation to invoke the
99    ///  default handler. Since: 1.6
100    fn sink_query(&self, query: &mut gst::QueryRef) -> bool {
101        self.parent_sink_query(query)
102    }
103
104    /// Optional.
105    ///  Event handler on the src pad. Subclasses should chain up to
106    ///  the parent implementation to invoke the default handler.
107    fn src_event(&self, event: gst::Event) -> bool {
108        self.parent_src_event(event)
109    }
110
111    /// Optional.
112    ///  Query handler on the source pad. This function should
113    ///  return TRUE if the query could be performed. Subclasses
114    ///  should chain up to the parent implementation to invoke the
115    ///  default handler. Since: 1.6
116    fn src_query(&self, query: &mut gst::QueryRef) -> bool {
117        self.parent_src_query(query)
118    }
119
120    /// Optional.
121    ///  Propose buffer allocation parameters for upstream elements.
122    ///  Subclasses should chain up to the parent implementation to
123    ///  invoke the default handler.
124    fn propose_allocation(
125        &self,
126        query: &mut gst::query::Allocation,
127    ) -> Result<(), gst::LoggableError> {
128        self.parent_propose_allocation(query)
129    }
130
131    /// Optional.
132    ///  Setup the allocation parameters for allocating output
133    ///  buffers. The passed in query contains the result of the
134    ///  downstream allocation query.
135    ///  Subclasses should chain up to the parent implementation to
136    ///  invoke the default handler.
137    fn decide_allocation(
138        &self,
139        query: &mut gst::query::Allocation,
140    ) -> Result<(), gst::LoggableError> {
141        self.parent_decide_allocation(query)
142    }
143
144    /// Orchestrates [`gst::Allocator`][crate::gst::Allocator] configuration for the negotiated `caps`.
145    /// Default implementation relies on an Allocation `GstQuery` &
146    /// calls ``decide_allocation()``.
147    /// ## `caps`
148    /// the negotiated [`gst::Caps`][crate::gst::Caps]
149    ///
150    /// # Returns
151    ///
152    /// whether the [`gst::Allocator`][crate::gst::Allocator] could be configured.
153    #[cfg(feature = "v1_30")]
154    #[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
155    fn prepare_allocator(&self, caps: Option<&gst::Caps>) -> Result<(), gst::LoggableError> {
156        self.parent_prepare_allocator(caps)
157    }
158}
159
160pub trait AudioEncoderImplExt: AudioEncoderImpl {
161    fn parent_open(&self) -> Result<(), gst::ErrorMessage> {
162        unsafe {
163            let data = Self::type_data();
164            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
165            (*parent_class)
166                .open
167                .map(|f| {
168                    if from_glib(f(self
169                        .obj()
170                        .unsafe_cast_ref::<AudioEncoder>()
171                        .to_glib_none()
172                        .0))
173                    {
174                        Ok(())
175                    } else {
176                        Err(gst::error_msg!(
177                            gst::CoreError::StateChange,
178                            ["Parent function `open` failed"]
179                        ))
180                    }
181                })
182                .unwrap_or(Ok(()))
183        }
184    }
185
186    fn parent_close(&self) -> Result<(), gst::ErrorMessage> {
187        unsafe {
188            let data = Self::type_data();
189            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
190            (*parent_class)
191                .close
192                .map(|f| {
193                    if from_glib(f(self
194                        .obj()
195                        .unsafe_cast_ref::<AudioEncoder>()
196                        .to_glib_none()
197                        .0))
198                    {
199                        Ok(())
200                    } else {
201                        Err(gst::error_msg!(
202                            gst::CoreError::StateChange,
203                            ["Parent function `close` failed"]
204                        ))
205                    }
206                })
207                .unwrap_or(Ok(()))
208        }
209    }
210
211    fn parent_start(&self) -> Result<(), gst::ErrorMessage> {
212        unsafe {
213            let data = Self::type_data();
214            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
215            (*parent_class)
216                .start
217                .map(|f| {
218                    if from_glib(f(self
219                        .obj()
220                        .unsafe_cast_ref::<AudioEncoder>()
221                        .to_glib_none()
222                        .0))
223                    {
224                        Ok(())
225                    } else {
226                        Err(gst::error_msg!(
227                            gst::CoreError::StateChange,
228                            ["Parent function `start` failed"]
229                        ))
230                    }
231                })
232                .unwrap_or(Ok(()))
233        }
234    }
235
236    fn parent_stop(&self) -> Result<(), gst::ErrorMessage> {
237        unsafe {
238            let data = Self::type_data();
239            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
240            (*parent_class)
241                .stop
242                .map(|f| {
243                    if from_glib(f(self
244                        .obj()
245                        .unsafe_cast_ref::<AudioEncoder>()
246                        .to_glib_none()
247                        .0))
248                    {
249                        Ok(())
250                    } else {
251                        Err(gst::error_msg!(
252                            gst::CoreError::StateChange,
253                            ["Parent function `stop` failed"]
254                        ))
255                    }
256                })
257                .unwrap_or(Ok(()))
258        }
259    }
260
261    fn parent_set_format(&self, info: &AudioInfo) -> Result<(), gst::LoggableError> {
262        unsafe {
263            let data = Self::type_data();
264            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
265            (*parent_class)
266                .set_format
267                .map(|f| {
268                    gst::result_from_gboolean!(
269                        f(
270                            self.obj()
271                                .unsafe_cast_ref::<AudioEncoder>()
272                                .to_glib_none()
273                                .0,
274                            info.to_glib_none().0 as *mut _
275                        ),
276                        gst::CAT_RUST,
277                        "parent function `set_format` failed"
278                    )
279                })
280                .unwrap_or(Ok(()))
281        }
282    }
283
284    fn parent_handle_frame(
285        &self,
286        buffer: Option<&gst::Buffer>,
287    ) -> Result<gst::FlowSuccess, gst::FlowError> {
288        unsafe {
289            let data = Self::type_data();
290            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
291            (*parent_class)
292                .handle_frame
293                .map(|f| {
294                    try_from_glib(f(
295                        self.obj()
296                            .unsafe_cast_ref::<AudioEncoder>()
297                            .to_glib_none()
298                            .0,
299                        buffer
300                            .map(|buffer| buffer.as_mut_ptr() as *mut *mut gst::ffi::GstBuffer)
301                            .unwrap_or(ptr::null_mut()),
302                    ))
303                })
304                .unwrap_or(Err(gst::FlowError::Error))
305        }
306    }
307
308    fn parent_pre_push(&self, buffer: gst::Buffer) -> Result<Option<gst::Buffer>, gst::FlowError> {
309        unsafe {
310            let data = Self::type_data();
311            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
312            if let Some(f) = (*parent_class).pre_push {
313                let mut buffer = buffer.into_glib_ptr();
314                gst::FlowSuccess::try_from_glib(f(
315                    self.obj()
316                        .unsafe_cast_ref::<AudioEncoder>()
317                        .to_glib_none()
318                        .0,
319                    &mut buffer,
320                ))
321                .map(|_| from_glib_full(buffer))
322            } else {
323                Ok(Some(buffer))
324            }
325        }
326    }
327
328    fn parent_flush(&self) {
329        unsafe {
330            let data = Self::type_data();
331            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
332            (*parent_class)
333                .flush
334                .map(|f| {
335                    f(self
336                        .obj()
337                        .unsafe_cast_ref::<AudioEncoder>()
338                        .to_glib_none()
339                        .0)
340                })
341                .unwrap_or(())
342        }
343    }
344
345    fn parent_negotiate(&self) -> Result<(), gst::LoggableError> {
346        unsafe {
347            let data = Self::type_data();
348            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
349            (*parent_class)
350                .negotiate
351                .map(|f| {
352                    gst::result_from_gboolean!(
353                        f(self
354                            .obj()
355                            .unsafe_cast_ref::<AudioEncoder>()
356                            .to_glib_none()
357                            .0),
358                        gst::CAT_RUST,
359                        "Parent function `negotiate` failed"
360                    )
361                })
362                .unwrap_or(Ok(()))
363        }
364    }
365
366    fn parent_caps(&self, filter: Option<&gst::Caps>) -> gst::Caps {
367        unsafe {
368            let data = Self::type_data();
369            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
370            (*parent_class)
371                .getcaps
372                .map(|f| {
373                    from_glib_full(f(
374                        self.obj()
375                            .unsafe_cast_ref::<AudioEncoder>()
376                            .to_glib_none()
377                            .0,
378                        filter.to_glib_none().0,
379                    ))
380                })
381                .unwrap_or_else(|| {
382                    self.obj()
383                        .unsafe_cast_ref::<AudioEncoder>()
384                        .proxy_getcaps(None, filter)
385                })
386        }
387    }
388
389    fn parent_sink_event(&self, event: gst::Event) -> bool {
390        unsafe {
391            let data = Self::type_data();
392            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
393            let f = (*parent_class)
394                .sink_event
395                .expect("Missing parent function `sink_event`");
396            from_glib(f(
397                self.obj()
398                    .unsafe_cast_ref::<AudioEncoder>()
399                    .to_glib_none()
400                    .0,
401                event.into_glib_ptr(),
402            ))
403        }
404    }
405
406    fn parent_sink_query(&self, query: &mut gst::QueryRef) -> bool {
407        unsafe {
408            let data = Self::type_data();
409            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
410            let f = (*parent_class)
411                .sink_query
412                .expect("Missing parent function `sink_query`");
413            from_glib(f(
414                self.obj()
415                    .unsafe_cast_ref::<AudioEncoder>()
416                    .to_glib_none()
417                    .0,
418                query.as_mut_ptr(),
419            ))
420        }
421    }
422
423    fn parent_src_event(&self, event: gst::Event) -> bool {
424        unsafe {
425            let data = Self::type_data();
426            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
427            let f = (*parent_class)
428                .src_event
429                .expect("Missing parent function `src_event`");
430            from_glib(f(
431                self.obj()
432                    .unsafe_cast_ref::<AudioEncoder>()
433                    .to_glib_none()
434                    .0,
435                event.into_glib_ptr(),
436            ))
437        }
438    }
439
440    fn parent_src_query(&self, query: &mut gst::QueryRef) -> bool {
441        unsafe {
442            let data = Self::type_data();
443            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
444            let f = (*parent_class)
445                .src_query
446                .expect("Missing parent function `src_query`");
447            from_glib(f(
448                self.obj()
449                    .unsafe_cast_ref::<AudioEncoder>()
450                    .to_glib_none()
451                    .0,
452                query.as_mut_ptr(),
453            ))
454        }
455    }
456
457    fn parent_propose_allocation(
458        &self,
459        query: &mut gst::query::Allocation,
460    ) -> Result<(), gst::LoggableError> {
461        unsafe {
462            let data = Self::type_data();
463            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
464            (*parent_class)
465                .propose_allocation
466                .map(|f| {
467                    gst::result_from_gboolean!(
468                        f(
469                            self.obj()
470                                .unsafe_cast_ref::<AudioEncoder>()
471                                .to_glib_none()
472                                .0,
473                            query.as_mut_ptr(),
474                        ),
475                        gst::CAT_RUST,
476                        "Parent function `propose_allocation` failed",
477                    )
478                })
479                .unwrap_or(Ok(()))
480        }
481    }
482
483    fn parent_decide_allocation(
484        &self,
485        query: &mut gst::query::Allocation,
486    ) -> Result<(), gst::LoggableError> {
487        unsafe {
488            let data = Self::type_data();
489            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
490            (*parent_class)
491                .decide_allocation
492                .map(|f| {
493                    gst::result_from_gboolean!(
494                        f(
495                            self.obj()
496                                .unsafe_cast_ref::<AudioEncoder>()
497                                .to_glib_none()
498                                .0,
499                            query.as_mut_ptr(),
500                        ),
501                        gst::CAT_RUST,
502                        "Parent function `decide_allocation` failed",
503                    )
504                })
505                .unwrap_or(Ok(()))
506        }
507    }
508
509    #[cfg(feature = "v1_30")]
510    #[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
511    fn parent_prepare_allocator(&self, caps: Option<&gst::Caps>) -> Result<(), gst::LoggableError> {
512        unsafe {
513            let data = Self::type_data();
514            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
515            (*parent_class)
516                .prepare_allocator
517                .map(|f| {
518                    gst::result_from_gboolean!(
519                        f(
520                            self.obj()
521                                .unsafe_cast_ref::<AudioEncoder>()
522                                .to_glib_none()
523                                .0,
524                            caps.to_glib_none().0
525                        ),
526                        gst::CAT_RUST,
527                        "Parent function `prepare_allocator` failed",
528                    )
529                })
530                .unwrap_or(Ok(()))
531        }
532    }
533}
534
535impl<T: AudioEncoderImpl> AudioEncoderImplExt for T {}
536
537unsafe impl<T: AudioEncoderImpl> IsSubclassable<T> for AudioEncoder {
538    fn class_init(klass: &mut glib::Class<Self>) {
539        Self::parent_class_init::<T>(klass);
540        let klass = klass.as_mut();
541        klass.open = Some(audio_encoder_open::<T>);
542        klass.close = Some(audio_encoder_close::<T>);
543        klass.start = Some(audio_encoder_start::<T>);
544        klass.stop = Some(audio_encoder_stop::<T>);
545        klass.set_format = Some(audio_encoder_set_format::<T>);
546        klass.handle_frame = Some(audio_encoder_handle_frame::<T>);
547        klass.pre_push = Some(audio_encoder_pre_push::<T>);
548        klass.flush = Some(audio_encoder_flush::<T>);
549        klass.negotiate = Some(audio_encoder_negotiate::<T>);
550        klass.getcaps = Some(audio_encoder_getcaps::<T>);
551        klass.sink_event = Some(audio_encoder_sink_event::<T>);
552        klass.src_event = Some(audio_encoder_src_event::<T>);
553        klass.sink_query = Some(audio_encoder_sink_query::<T>);
554        klass.src_query = Some(audio_encoder_src_query::<T>);
555        klass.propose_allocation = Some(audio_encoder_propose_allocation::<T>);
556        klass.decide_allocation = Some(audio_encoder_decide_allocation::<T>);
557        #[cfg(feature = "v1_30")]
558        {
559            klass.prepare_allocator = Some(audio_encoder_prepare_allocator::<T>);
560        }
561    }
562}
563
564unsafe extern "C" fn audio_encoder_open<T: AudioEncoderImpl>(
565    ptr: *mut ffi::GstAudioEncoder,
566) -> glib::ffi::gboolean {
567    unsafe {
568        let instance = &*(ptr as *mut T::Instance);
569        let imp = instance.imp();
570
571        gst::panic_to_error!(imp, false, {
572            match imp.open() {
573                Ok(()) => true,
574                Err(err) => {
575                    imp.post_error_message(err);
576                    false
577                }
578            }
579        })
580        .into_glib()
581    }
582}
583
584unsafe extern "C" fn audio_encoder_close<T: AudioEncoderImpl>(
585    ptr: *mut ffi::GstAudioEncoder,
586) -> glib::ffi::gboolean {
587    unsafe {
588        let instance = &*(ptr as *mut T::Instance);
589        let imp = instance.imp();
590
591        gst::panic_to_error!(imp, false, {
592            match imp.close() {
593                Ok(()) => true,
594                Err(err) => {
595                    imp.post_error_message(err);
596                    false
597                }
598            }
599        })
600        .into_glib()
601    }
602}
603
604unsafe extern "C" fn audio_encoder_start<T: AudioEncoderImpl>(
605    ptr: *mut ffi::GstAudioEncoder,
606) -> glib::ffi::gboolean {
607    unsafe {
608        let instance = &*(ptr as *mut T::Instance);
609        let imp = instance.imp();
610
611        gst::panic_to_error!(imp, false, {
612            match imp.start() {
613                Ok(()) => true,
614                Err(err) => {
615                    imp.post_error_message(err);
616                    false
617                }
618            }
619        })
620        .into_glib()
621    }
622}
623
624unsafe extern "C" fn audio_encoder_stop<T: AudioEncoderImpl>(
625    ptr: *mut ffi::GstAudioEncoder,
626) -> glib::ffi::gboolean {
627    unsafe {
628        let instance = &*(ptr as *mut T::Instance);
629        let imp = instance.imp();
630
631        gst::panic_to_error!(imp, false, {
632            match imp.stop() {
633                Ok(()) => true,
634                Err(err) => {
635                    imp.post_error_message(err);
636                    false
637                }
638            }
639        })
640        .into_glib()
641    }
642}
643
644unsafe extern "C" fn audio_encoder_set_format<T: AudioEncoderImpl>(
645    ptr: *mut ffi::GstAudioEncoder,
646    info: *mut ffi::GstAudioInfo,
647) -> glib::ffi::gboolean {
648    unsafe {
649        let instance = &*(ptr as *mut T::Instance);
650        let imp = instance.imp();
651
652        gst::panic_to_error!(imp, false, {
653            match imp.set_format(&from_glib_none(info)) {
654                Ok(()) => true,
655                Err(err) => {
656                    err.log_with_imp(imp);
657                    false
658                }
659            }
660        })
661        .into_glib()
662    }
663}
664
665unsafe extern "C" fn audio_encoder_handle_frame<T: AudioEncoderImpl>(
666    ptr: *mut ffi::GstAudioEncoder,
667    buffer: *mut *mut gst::ffi::GstBuffer,
668) -> gst::ffi::GstFlowReturn {
669    unsafe {
670        // FIXME: Misgenerated in gstreamer-audio-sys
671        let buffer = buffer as *mut gst::ffi::GstBuffer;
672        let instance = &*(ptr as *mut T::Instance);
673        let imp = instance.imp();
674
675        gst::panic_to_error!(imp, gst::FlowReturn::Error, {
676            imp.handle_frame(Option::<gst::Buffer>::from_glib_none(buffer).as_ref())
677                .into()
678        })
679        .into_glib()
680    }
681}
682
683unsafe extern "C" fn audio_encoder_pre_push<T: AudioEncoderImpl>(
684    ptr: *mut ffi::GstAudioEncoder,
685    buffer: *mut *mut gst::ffi::GstBuffer,
686) -> gst::ffi::GstFlowReturn {
687    unsafe {
688        let instance = &*(ptr as *mut T::Instance);
689        let imp = instance.imp();
690
691        gst::panic_to_error!(imp, gst::FlowReturn::Error, {
692            match imp.pre_push(from_glib_full(*buffer)) {
693                Ok(Some(new_buffer)) => {
694                    *buffer = new_buffer.into_glib_ptr();
695                    Ok(gst::FlowSuccess::Ok)
696                }
697                Ok(None) => {
698                    *buffer = ptr::null_mut();
699                    Ok(gst::FlowSuccess::Ok)
700                }
701                Err(err) => Err(err),
702            }
703            .into()
704        })
705        .into_glib()
706    }
707}
708
709unsafe extern "C" fn audio_encoder_flush<T: AudioEncoderImpl>(ptr: *mut ffi::GstAudioEncoder) {
710    unsafe {
711        let instance = &*(ptr as *mut T::Instance);
712        let imp = instance.imp();
713
714        gst::panic_to_error!(imp, (), { AudioEncoderImpl::flush(imp,) })
715    }
716}
717
718unsafe extern "C" fn audio_encoder_negotiate<T: AudioEncoderImpl>(
719    ptr: *mut ffi::GstAudioEncoder,
720) -> glib::ffi::gboolean {
721    unsafe {
722        let instance = &*(ptr as *mut T::Instance);
723        let imp = instance.imp();
724
725        gst::panic_to_error!(imp, false, {
726            match imp.negotiate() {
727                Ok(()) => true,
728                Err(err) => {
729                    err.log_with_imp(imp);
730                    false
731                }
732            }
733        })
734        .into_glib()
735    }
736}
737
738unsafe extern "C" fn audio_encoder_getcaps<T: AudioEncoderImpl>(
739    ptr: *mut ffi::GstAudioEncoder,
740    filter: *mut gst::ffi::GstCaps,
741) -> *mut gst::ffi::GstCaps {
742    unsafe {
743        let instance = &*(ptr as *mut T::Instance);
744        let imp = instance.imp();
745
746        gst::panic_to_error!(imp, gst::Caps::new_empty(), {
747            AudioEncoderImpl::caps(
748                imp,
749                Option::<gst::Caps>::from_glib_borrow(filter)
750                    .as_ref()
751                    .as_ref(),
752            )
753        })
754        .into_glib_ptr()
755    }
756}
757
758unsafe extern "C" fn audio_encoder_sink_event<T: AudioEncoderImpl>(
759    ptr: *mut ffi::GstAudioEncoder,
760    event: *mut gst::ffi::GstEvent,
761) -> glib::ffi::gboolean {
762    unsafe {
763        let instance = &*(ptr as *mut T::Instance);
764        let imp = instance.imp();
765
766        gst::panic_to_error!(imp, false, { imp.sink_event(from_glib_full(event)) }).into_glib()
767    }
768}
769
770unsafe extern "C" fn audio_encoder_sink_query<T: AudioEncoderImpl>(
771    ptr: *mut ffi::GstAudioEncoder,
772    query: *mut gst::ffi::GstQuery,
773) -> glib::ffi::gboolean {
774    unsafe {
775        let instance = &*(ptr as *mut T::Instance);
776        let imp = instance.imp();
777
778        gst::panic_to_error!(imp, false, {
779            imp.sink_query(gst::QueryRef::from_mut_ptr(query))
780        })
781        .into_glib()
782    }
783}
784
785unsafe extern "C" fn audio_encoder_src_event<T: AudioEncoderImpl>(
786    ptr: *mut ffi::GstAudioEncoder,
787    event: *mut gst::ffi::GstEvent,
788) -> glib::ffi::gboolean {
789    unsafe {
790        let instance = &*(ptr as *mut T::Instance);
791        let imp = instance.imp();
792
793        gst::panic_to_error!(imp, false, { imp.src_event(from_glib_full(event)) }).into_glib()
794    }
795}
796
797unsafe extern "C" fn audio_encoder_src_query<T: AudioEncoderImpl>(
798    ptr: *mut ffi::GstAudioEncoder,
799    query: *mut gst::ffi::GstQuery,
800) -> glib::ffi::gboolean {
801    unsafe {
802        let instance = &*(ptr as *mut T::Instance);
803        let imp = instance.imp();
804
805        gst::panic_to_error!(imp, false, {
806            imp.src_query(gst::QueryRef::from_mut_ptr(query))
807        })
808        .into_glib()
809    }
810}
811
812unsafe extern "C" fn audio_encoder_propose_allocation<T: AudioEncoderImpl>(
813    ptr: *mut ffi::GstAudioEncoder,
814    query: *mut gst::ffi::GstQuery,
815) -> glib::ffi::gboolean {
816    unsafe {
817        let instance = &*(ptr as *mut T::Instance);
818        let imp = instance.imp();
819        let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
820            gst::QueryViewMut::Allocation(allocation) => allocation,
821            _ => unreachable!(),
822        };
823
824        gst::panic_to_error!(imp, false, {
825            match imp.propose_allocation(query) {
826                Ok(()) => true,
827                Err(err) => {
828                    err.log_with_imp(imp);
829                    false
830                }
831            }
832        })
833        .into_glib()
834    }
835}
836
837unsafe extern "C" fn audio_encoder_decide_allocation<T: AudioEncoderImpl>(
838    ptr: *mut ffi::GstAudioEncoder,
839    query: *mut gst::ffi::GstQuery,
840) -> glib::ffi::gboolean {
841    unsafe {
842        let instance = &*(ptr as *mut T::Instance);
843        let imp = instance.imp();
844        let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
845            gst::QueryViewMut::Allocation(allocation) => allocation,
846            _ => unreachable!(),
847        };
848
849        gst::panic_to_error!(imp, false, {
850            match imp.decide_allocation(query) {
851                Ok(()) => true,
852                Err(err) => {
853                    err.log_with_imp(imp);
854                    false
855                }
856            }
857        })
858        .into_glib()
859    }
860}
861
862#[cfg(feature = "v1_30")]
863#[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
864unsafe extern "C" fn audio_encoder_prepare_allocator<T: AudioEncoderImpl>(
865    ptr: *mut ffi::GstAudioEncoder,
866    caps: *mut gst::ffi::GstCaps,
867) -> glib::ffi::gboolean {
868    unsafe {
869        let instance = &*(ptr as *mut T::Instance);
870        let imp = instance.imp();
871        let caps = Option::<gst::Caps>::from_glib_none(caps);
872
873        gst::panic_to_error!(imp, false, {
874            match imp.prepare_allocator(caps.as_ref()) {
875                Ok(()) => true,
876                Err(err) => {
877                    err.log_with_imp(imp);
878                    false
879                }
880            }
881        })
882        .into_glib()
883    }
884}