Skip to main content

gstreamer_video/subclass/
video_encoder.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::translate::*;
4use gst::subclass::prelude::*;
5
6use crate::{
7    VideoCodecFrame, VideoEncoder, ffi,
8    prelude::*,
9    video_codec_state::{Readable, VideoCodecState},
10};
11
12pub trait VideoEncoderImpl: ElementImpl + ObjectSubclass<Type: IsA<VideoEncoder>> {
13    fn open(&self) -> Result<(), gst::ErrorMessage> {
14        self.parent_open()
15    }
16
17    fn close(&self) -> Result<(), gst::ErrorMessage> {
18        self.parent_close()
19    }
20
21    fn start(&self) -> Result<(), gst::ErrorMessage> {
22        self.parent_start()
23    }
24
25    fn stop(&self) -> Result<(), gst::ErrorMessage> {
26        self.parent_stop()
27    }
28
29    fn finish(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
30        self.parent_finish()
31    }
32
33    fn set_format(
34        &self,
35        state: &VideoCodecState<'static, Readable>,
36    ) -> Result<(), gst::LoggableError> {
37        self.parent_set_format(state)
38    }
39
40    fn handle_frame(&self, frame: VideoCodecFrame) -> Result<gst::FlowSuccess, gst::FlowError> {
41        self.parent_handle_frame(frame)
42    }
43
44    fn flush(&self) -> bool {
45        self.parent_flush()
46    }
47
48    fn negotiate(&self) -> Result<(), gst::LoggableError> {
49        self.parent_negotiate()
50    }
51
52    fn caps(&self, filter: Option<&gst::Caps>) -> gst::Caps {
53        self.parent_caps(filter)
54    }
55
56    fn sink_event(&self, event: gst::Event) -> bool {
57        self.parent_sink_event(event)
58    }
59
60    fn sink_query(&self, query: &mut gst::QueryRef) -> bool {
61        self.parent_sink_query(query)
62    }
63
64    fn src_event(&self, event: gst::Event) -> bool {
65        self.parent_src_event(event)
66    }
67
68    fn src_query(&self, query: &mut gst::QueryRef) -> bool {
69        self.parent_src_query(query)
70    }
71
72    fn propose_allocation(
73        &self,
74        query: &mut gst::query::Allocation,
75    ) -> Result<(), gst::LoggableError> {
76        self.parent_propose_allocation(query)
77    }
78
79    fn decide_allocation(
80        &self,
81        query: &mut gst::query::Allocation,
82    ) -> Result<(), gst::LoggableError> {
83        self.parent_decide_allocation(query)
84    }
85
86    #[cfg(feature = "v1_30")]
87    #[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
88    fn prepare_allocator(&self, caps: Option<&gst::Caps>) -> Result<(), gst::LoggableError> {
89        self.parent_prepare_allocator(caps)
90    }
91}
92
93pub trait VideoEncoderImplExt: VideoEncoderImpl {
94    fn parent_open(&self) -> Result<(), gst::ErrorMessage> {
95        unsafe {
96            let data = Self::type_data();
97            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
98            (*parent_class)
99                .open
100                .map(|f| {
101                    if from_glib(f(self
102                        .obj()
103                        .unsafe_cast_ref::<VideoEncoder>()
104                        .to_glib_none()
105                        .0))
106                    {
107                        Ok(())
108                    } else {
109                        Err(gst::error_msg!(
110                            gst::CoreError::StateChange,
111                            ["Parent function `open` failed"]
112                        ))
113                    }
114                })
115                .unwrap_or(Ok(()))
116        }
117    }
118
119    fn parent_close(&self) -> Result<(), gst::ErrorMessage> {
120        unsafe {
121            let data = Self::type_data();
122            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
123            (*parent_class)
124                .close
125                .map(|f| {
126                    if from_glib(f(self
127                        .obj()
128                        .unsafe_cast_ref::<VideoEncoder>()
129                        .to_glib_none()
130                        .0))
131                    {
132                        Ok(())
133                    } else {
134                        Err(gst::error_msg!(
135                            gst::CoreError::StateChange,
136                            ["Parent function `close` failed"]
137                        ))
138                    }
139                })
140                .unwrap_or(Ok(()))
141        }
142    }
143
144    fn parent_start(&self) -> Result<(), gst::ErrorMessage> {
145        unsafe {
146            let data = Self::type_data();
147            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
148            (*parent_class)
149                .start
150                .map(|f| {
151                    if from_glib(f(self
152                        .obj()
153                        .unsafe_cast_ref::<VideoEncoder>()
154                        .to_glib_none()
155                        .0))
156                    {
157                        Ok(())
158                    } else {
159                        Err(gst::error_msg!(
160                            gst::CoreError::StateChange,
161                            ["Parent function `start` failed"]
162                        ))
163                    }
164                })
165                .unwrap_or(Ok(()))
166        }
167    }
168
169    fn parent_stop(&self) -> Result<(), gst::ErrorMessage> {
170        unsafe {
171            let data = Self::type_data();
172            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
173            (*parent_class)
174                .stop
175                .map(|f| {
176                    if from_glib(f(self
177                        .obj()
178                        .unsafe_cast_ref::<VideoEncoder>()
179                        .to_glib_none()
180                        .0))
181                    {
182                        Ok(())
183                    } else {
184                        Err(gst::error_msg!(
185                            gst::CoreError::StateChange,
186                            ["Parent function `stop` failed"]
187                        ))
188                    }
189                })
190                .unwrap_or(Ok(()))
191        }
192    }
193
194    fn parent_finish(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
195        unsafe {
196            let data = Self::type_data();
197            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
198            (*parent_class)
199                .finish
200                .map(|f| {
201                    try_from_glib(f(self
202                        .obj()
203                        .unsafe_cast_ref::<VideoEncoder>()
204                        .to_glib_none()
205                        .0))
206                })
207                .unwrap_or(Ok(gst::FlowSuccess::Ok))
208        }
209    }
210
211    fn parent_set_format(
212        &self,
213        state: &VideoCodecState<'static, Readable>,
214    ) -> Result<(), gst::LoggableError> {
215        unsafe {
216            let data = Self::type_data();
217            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
218            (*parent_class)
219                .set_format
220                .map(|f| {
221                    gst::result_from_gboolean!(
222                        f(
223                            self.obj()
224                                .unsafe_cast_ref::<VideoEncoder>()
225                                .to_glib_none()
226                                .0,
227                            state.as_mut_ptr()
228                        ),
229                        gst::CAT_RUST,
230                        "parent function `set_format` failed"
231                    )
232                })
233                .unwrap_or(Ok(()))
234        }
235    }
236
237    fn parent_handle_frame(
238        &self,
239        frame: VideoCodecFrame,
240    ) -> Result<gst::FlowSuccess, gst::FlowError> {
241        unsafe {
242            let data = Self::type_data();
243            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
244            (*parent_class)
245                .handle_frame
246                .map(|f| {
247                    try_from_glib(f(
248                        self.obj()
249                            .unsafe_cast_ref::<VideoEncoder>()
250                            .to_glib_none()
251                            .0,
252                        frame.to_glib_none().0,
253                    ))
254                })
255                .unwrap_or(Err(gst::FlowError::Error))
256        }
257    }
258
259    fn parent_flush(&self) -> bool {
260        unsafe {
261            let data = Self::type_data();
262            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
263            (*parent_class)
264                .flush
265                .map(|f| {
266                    from_glib(f(self
267                        .obj()
268                        .unsafe_cast_ref::<VideoEncoder>()
269                        .to_glib_none()
270                        .0))
271                })
272                .unwrap_or(false)
273        }
274    }
275
276    fn parent_negotiate(&self) -> Result<(), gst::LoggableError> {
277        unsafe {
278            let data = Self::type_data();
279            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
280            (*parent_class)
281                .negotiate
282                .map(|f| {
283                    gst::result_from_gboolean!(
284                        f(self
285                            .obj()
286                            .unsafe_cast_ref::<VideoEncoder>()
287                            .to_glib_none()
288                            .0),
289                        gst::CAT_RUST,
290                        "Parent function `negotiate` failed"
291                    )
292                })
293                .unwrap_or(Ok(()))
294        }
295    }
296
297    fn parent_caps(&self, filter: Option<&gst::Caps>) -> gst::Caps {
298        unsafe {
299            let data = Self::type_data();
300            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
301            (*parent_class)
302                .getcaps
303                .map(|f| {
304                    from_glib_full(f(
305                        self.obj()
306                            .unsafe_cast_ref::<VideoEncoder>()
307                            .to_glib_none()
308                            .0,
309                        filter.to_glib_none().0,
310                    ))
311                })
312                .unwrap_or_else(|| {
313                    self.obj()
314                        .unsafe_cast_ref::<VideoEncoder>()
315                        .proxy_getcaps(None, filter)
316                })
317        }
318    }
319
320    fn parent_sink_event(&self, event: gst::Event) -> bool {
321        unsafe {
322            let data = Self::type_data();
323            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
324            let f = (*parent_class)
325                .sink_event
326                .expect("Missing parent function `sink_event`");
327            from_glib(f(
328                self.obj()
329                    .unsafe_cast_ref::<VideoEncoder>()
330                    .to_glib_none()
331                    .0,
332                event.into_glib_ptr(),
333            ))
334        }
335    }
336
337    fn parent_sink_query(&self, query: &mut gst::QueryRef) -> bool {
338        unsafe {
339            let data = Self::type_data();
340            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
341            let f = (*parent_class)
342                .sink_query
343                .expect("Missing parent function `sink_query`");
344            from_glib(f(
345                self.obj()
346                    .unsafe_cast_ref::<VideoEncoder>()
347                    .to_glib_none()
348                    .0,
349                query.as_mut_ptr(),
350            ))
351        }
352    }
353
354    fn parent_src_event(&self, event: gst::Event) -> bool {
355        unsafe {
356            let data = Self::type_data();
357            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
358            let f = (*parent_class)
359                .src_event
360                .expect("Missing parent function `src_event`");
361            from_glib(f(
362                self.obj()
363                    .unsafe_cast_ref::<VideoEncoder>()
364                    .to_glib_none()
365                    .0,
366                event.into_glib_ptr(),
367            ))
368        }
369    }
370
371    fn parent_src_query(&self, query: &mut gst::QueryRef) -> bool {
372        unsafe {
373            let data = Self::type_data();
374            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
375            let f = (*parent_class)
376                .src_query
377                .expect("Missing parent function `src_query`");
378            from_glib(f(
379                self.obj()
380                    .unsafe_cast_ref::<VideoEncoder>()
381                    .to_glib_none()
382                    .0,
383                query.as_mut_ptr(),
384            ))
385        }
386    }
387
388    fn parent_propose_allocation(
389        &self,
390        query: &mut gst::query::Allocation,
391    ) -> Result<(), gst::LoggableError> {
392        unsafe {
393            let data = Self::type_data();
394            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
395            (*parent_class)
396                .propose_allocation
397                .map(|f| {
398                    gst::result_from_gboolean!(
399                        f(
400                            self.obj()
401                                .unsafe_cast_ref::<VideoEncoder>()
402                                .to_glib_none()
403                                .0,
404                            query.as_mut_ptr(),
405                        ),
406                        gst::CAT_RUST,
407                        "Parent function `propose_allocation` failed",
408                    )
409                })
410                .unwrap_or(Ok(()))
411        }
412    }
413
414    fn parent_decide_allocation(
415        &self,
416        query: &mut gst::query::Allocation,
417    ) -> Result<(), gst::LoggableError> {
418        unsafe {
419            let data = Self::type_data();
420            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
421            (*parent_class)
422                .decide_allocation
423                .map(|f| {
424                    gst::result_from_gboolean!(
425                        f(
426                            self.obj()
427                                .unsafe_cast_ref::<VideoEncoder>()
428                                .to_glib_none()
429                                .0,
430                            query.as_mut_ptr(),
431                        ),
432                        gst::CAT_RUST,
433                        "Parent function `decide_allocation` failed",
434                    )
435                })
436                .unwrap_or(Ok(()))
437        }
438    }
439
440    #[cfg(feature = "v1_30")]
441    #[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
442    fn parent_prepare_allocator(&self, caps: Option<&gst::Caps>) -> Result<(), gst::LoggableError> {
443        unsafe {
444            let data = Self::type_data();
445            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
446            (*parent_class)
447                .prepare_allocator
448                .map(|f| {
449                    gst::result_from_gboolean!(
450                        f(
451                            self.obj()
452                                .unsafe_cast_ref::<VideoEncoder>()
453                                .to_glib_none()
454                                .0,
455                            caps.to_glib_none().0
456                        ),
457                        gst::CAT_RUST,
458                        "Parent function `prepare_allocator` failed",
459                    )
460                })
461                .unwrap_or(Ok(()))
462        }
463    }
464}
465
466impl<T: VideoEncoderImpl> VideoEncoderImplExt for T {}
467
468unsafe impl<T: VideoEncoderImpl> IsSubclassable<T> for VideoEncoder {
469    fn class_init(klass: &mut glib::Class<Self>) {
470        Self::parent_class_init::<T>(klass);
471        let klass = klass.as_mut();
472        klass.open = Some(video_encoder_open::<T>);
473        klass.close = Some(video_encoder_close::<T>);
474        klass.start = Some(video_encoder_start::<T>);
475        klass.stop = Some(video_encoder_stop::<T>);
476        klass.finish = Some(video_encoder_finish::<T>);
477        klass.set_format = Some(video_encoder_set_format::<T>);
478        klass.handle_frame = Some(video_encoder_handle_frame::<T>);
479        klass.flush = Some(video_encoder_flush::<T>);
480        klass.negotiate = Some(video_encoder_negotiate::<T>);
481        klass.getcaps = Some(video_encoder_getcaps::<T>);
482        klass.sink_event = Some(video_encoder_sink_event::<T>);
483        klass.src_event = Some(video_encoder_src_event::<T>);
484        klass.sink_query = Some(video_encoder_sink_query::<T>);
485        klass.src_query = Some(video_encoder_src_query::<T>);
486        klass.propose_allocation = Some(video_encoder_propose_allocation::<T>);
487        klass.decide_allocation = Some(video_encoder_decide_allocation::<T>);
488        #[cfg(feature = "v1_30")]
489        {
490            klass.prepare_allocator = Some(video_encoder_prepare_allocator::<T>);
491        }
492    }
493}
494
495unsafe extern "C" fn video_encoder_open<T: VideoEncoderImpl>(
496    ptr: *mut ffi::GstVideoEncoder,
497) -> glib::ffi::gboolean {
498    unsafe {
499        let instance = &*(ptr as *mut T::Instance);
500        let imp = instance.imp();
501
502        gst::panic_to_error!(imp, false, {
503            match imp.open() {
504                Ok(()) => true,
505                Err(err) => {
506                    imp.post_error_message(err);
507                    false
508                }
509            }
510        })
511        .into_glib()
512    }
513}
514
515unsafe extern "C" fn video_encoder_close<T: VideoEncoderImpl>(
516    ptr: *mut ffi::GstVideoEncoder,
517) -> glib::ffi::gboolean {
518    unsafe {
519        let instance = &*(ptr as *mut T::Instance);
520        let imp = instance.imp();
521
522        gst::panic_to_error!(imp, false, {
523            match imp.close() {
524                Ok(()) => true,
525                Err(err) => {
526                    imp.post_error_message(err);
527                    false
528                }
529            }
530        })
531        .into_glib()
532    }
533}
534
535unsafe extern "C" fn video_encoder_start<T: VideoEncoderImpl>(
536    ptr: *mut ffi::GstVideoEncoder,
537) -> glib::ffi::gboolean {
538    unsafe {
539        let instance = &*(ptr as *mut T::Instance);
540        let imp = instance.imp();
541
542        gst::panic_to_error!(imp, false, {
543            match imp.start() {
544                Ok(()) => true,
545                Err(err) => {
546                    imp.post_error_message(err);
547                    false
548                }
549            }
550        })
551        .into_glib()
552    }
553}
554
555unsafe extern "C" fn video_encoder_stop<T: VideoEncoderImpl>(
556    ptr: *mut ffi::GstVideoEncoder,
557) -> glib::ffi::gboolean {
558    unsafe {
559        let instance = &*(ptr as *mut T::Instance);
560        let imp = instance.imp();
561
562        gst::panic_to_error!(imp, false, {
563            match imp.stop() {
564                Ok(()) => true,
565                Err(err) => {
566                    imp.post_error_message(err);
567                    false
568                }
569            }
570        })
571        .into_glib()
572    }
573}
574
575unsafe extern "C" fn video_encoder_finish<T: VideoEncoderImpl>(
576    ptr: *mut ffi::GstVideoEncoder,
577) -> gst::ffi::GstFlowReturn {
578    unsafe {
579        let instance = &*(ptr as *mut T::Instance);
580        let imp = instance.imp();
581
582        gst::panic_to_error!(imp, gst::FlowReturn::Error, { imp.finish().into() }).into_glib()
583    }
584}
585
586unsafe extern "C" fn video_encoder_set_format<T: VideoEncoderImpl>(
587    ptr: *mut ffi::GstVideoEncoder,
588    state: *mut ffi::GstVideoCodecState,
589) -> glib::ffi::gboolean {
590    unsafe {
591        let instance = &*(ptr as *mut T::Instance);
592        let imp = instance.imp();
593        ffi::gst_video_codec_state_ref(state);
594        let wrap_state = VideoCodecState::<Readable>::new(state);
595
596        gst::panic_to_error!(imp, false, {
597            match imp.set_format(&wrap_state) {
598                Ok(()) => true,
599                Err(err) => {
600                    err.log_with_imp(imp);
601                    false
602                }
603            }
604        })
605        .into_glib()
606    }
607}
608
609unsafe extern "C" fn video_encoder_handle_frame<T: VideoEncoderImpl>(
610    ptr: *mut ffi::GstVideoEncoder,
611    frame: *mut ffi::GstVideoCodecFrame,
612) -> gst::ffi::GstFlowReturn {
613    unsafe {
614        let instance = &*(ptr as *mut T::Instance);
615        let imp = instance.imp();
616        let instance = imp.obj();
617        let instance = instance.unsafe_cast_ref::<VideoEncoder>();
618        let wrap_frame = VideoCodecFrame::new(frame, instance);
619
620        gst::panic_to_error!(imp, gst::FlowReturn::Error, {
621            imp.handle_frame(wrap_frame).into()
622        })
623        .into_glib()
624    }
625}
626
627unsafe extern "C" fn video_encoder_flush<T: VideoEncoderImpl>(
628    ptr: *mut ffi::GstVideoEncoder,
629) -> glib::ffi::gboolean {
630    unsafe {
631        let instance = &*(ptr as *mut T::Instance);
632        let imp = instance.imp();
633
634        gst::panic_to_error!(imp, false, { VideoEncoderImpl::flush(imp) }).into_glib()
635    }
636}
637
638unsafe extern "C" fn video_encoder_negotiate<T: VideoEncoderImpl>(
639    ptr: *mut ffi::GstVideoEncoder,
640) -> glib::ffi::gboolean {
641    unsafe {
642        let instance = &*(ptr as *mut T::Instance);
643        let imp = instance.imp();
644
645        gst::panic_to_error!(imp, false, {
646            match imp.negotiate() {
647                Ok(()) => true,
648                Err(err) => {
649                    err.log_with_imp(imp);
650                    false
651                }
652            }
653        })
654        .into_glib()
655    }
656}
657
658unsafe extern "C" fn video_encoder_getcaps<T: VideoEncoderImpl>(
659    ptr: *mut ffi::GstVideoEncoder,
660    filter: *mut gst::ffi::GstCaps,
661) -> *mut gst::ffi::GstCaps {
662    unsafe {
663        let instance = &*(ptr as *mut T::Instance);
664        let imp = instance.imp();
665
666        gst::panic_to_error!(imp, gst::Caps::new_empty(), {
667            VideoEncoderImpl::caps(
668                imp,
669                Option::<gst::Caps>::from_glib_borrow(filter)
670                    .as_ref()
671                    .as_ref(),
672            )
673        })
674        .into_glib_ptr()
675    }
676}
677
678unsafe extern "C" fn video_encoder_sink_event<T: VideoEncoderImpl>(
679    ptr: *mut ffi::GstVideoEncoder,
680    event: *mut gst::ffi::GstEvent,
681) -> glib::ffi::gboolean {
682    unsafe {
683        let instance = &*(ptr as *mut T::Instance);
684        let imp = instance.imp();
685
686        gst::panic_to_error!(imp, false, { imp.sink_event(from_glib_full(event)) }).into_glib()
687    }
688}
689
690unsafe extern "C" fn video_encoder_sink_query<T: VideoEncoderImpl>(
691    ptr: *mut ffi::GstVideoEncoder,
692    query: *mut gst::ffi::GstQuery,
693) -> glib::ffi::gboolean {
694    unsafe {
695        let instance = &*(ptr as *mut T::Instance);
696        let imp = instance.imp();
697
698        gst::panic_to_error!(imp, false, {
699            imp.sink_query(gst::QueryRef::from_mut_ptr(query))
700        })
701        .into_glib()
702    }
703}
704
705unsafe extern "C" fn video_encoder_src_event<T: VideoEncoderImpl>(
706    ptr: *mut ffi::GstVideoEncoder,
707    event: *mut gst::ffi::GstEvent,
708) -> glib::ffi::gboolean {
709    unsafe {
710        let instance = &*(ptr as *mut T::Instance);
711        let imp = instance.imp();
712
713        gst::panic_to_error!(imp, false, { imp.src_event(from_glib_full(event)) }).into_glib()
714    }
715}
716
717unsafe extern "C" fn video_encoder_src_query<T: VideoEncoderImpl>(
718    ptr: *mut ffi::GstVideoEncoder,
719    query: *mut gst::ffi::GstQuery,
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            imp.src_query(gst::QueryRef::from_mut_ptr(query))
727        })
728        .into_glib()
729    }
730}
731
732unsafe extern "C" fn video_encoder_propose_allocation<T: VideoEncoderImpl>(
733    ptr: *mut ffi::GstVideoEncoder,
734    query: *mut gst::ffi::GstQuery,
735) -> glib::ffi::gboolean {
736    unsafe {
737        let instance = &*(ptr as *mut T::Instance);
738        let imp = instance.imp();
739        let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
740            gst::QueryViewMut::Allocation(allocation) => allocation,
741            _ => unreachable!(),
742        };
743
744        gst::panic_to_error!(imp, false, {
745            match imp.propose_allocation(query) {
746                Ok(()) => true,
747                Err(err) => {
748                    err.log_with_imp(imp);
749                    false
750                }
751            }
752        })
753        .into_glib()
754    }
755}
756
757unsafe extern "C" fn video_encoder_decide_allocation<T: VideoEncoderImpl>(
758    ptr: *mut ffi::GstVideoEncoder,
759    query: *mut gst::ffi::GstQuery,
760) -> glib::ffi::gboolean {
761    unsafe {
762        let instance = &*(ptr as *mut T::Instance);
763        let imp = instance.imp();
764        let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
765            gst::QueryViewMut::Allocation(allocation) => allocation,
766            _ => unreachable!(),
767        };
768
769        gst::panic_to_error!(imp, false, {
770            match imp.decide_allocation(query) {
771                Ok(()) => true,
772                Err(err) => {
773                    err.log_with_imp(imp);
774                    false
775                }
776            }
777        })
778        .into_glib()
779    }
780}
781
782#[cfg(feature = "v1_30")]
783#[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
784unsafe extern "C" fn video_encoder_prepare_allocator<T: VideoEncoderImpl>(
785    ptr: *mut ffi::GstVideoEncoder,
786    caps: *mut gst::ffi::GstCaps,
787) -> glib::ffi::gboolean {
788    unsafe {
789        let instance = &*(ptr as *mut T::Instance);
790        let imp = instance.imp();
791        let caps = Option::<gst::Caps>::from_glib_none(caps);
792
793        gst::panic_to_error!(imp, false, {
794            match imp.prepare_allocator(caps.as_ref()) {
795                Ok(()) => true,
796                Err(err) => {
797                    err.log_with_imp(imp);
798                    false
799                }
800            }
801        })
802        .into_glib()
803    }
804}