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