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: VideoEncoderImplExt + ElementImpl {
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
150mod sealed {
151    pub trait Sealed {}
152    impl<T: super::VideoEncoderImplExt> Sealed for T {}
153}
154
155pub trait VideoEncoderImplExt: sealed::Sealed + ObjectSubclass {
156    fn parent_open(&self) -> Result<(), gst::ErrorMessage> {
157        unsafe {
158            let data = Self::type_data();
159            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
160            (*parent_class)
161                .open
162                .map(|f| {
163                    if from_glib(f(self
164                        .obj()
165                        .unsafe_cast_ref::<VideoEncoder>()
166                        .to_glib_none()
167                        .0))
168                    {
169                        Ok(())
170                    } else {
171                        Err(gst::error_msg!(
172                            gst::CoreError::StateChange,
173                            ["Parent function `open` failed"]
174                        ))
175                    }
176                })
177                .unwrap_or(Ok(()))
178        }
179    }
180
181    fn parent_close(&self) -> Result<(), gst::ErrorMessage> {
182        unsafe {
183            let data = Self::type_data();
184            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
185            (*parent_class)
186                .close
187                .map(|f| {
188                    if from_glib(f(self
189                        .obj()
190                        .unsafe_cast_ref::<VideoEncoder>()
191                        .to_glib_none()
192                        .0))
193                    {
194                        Ok(())
195                    } else {
196                        Err(gst::error_msg!(
197                            gst::CoreError::StateChange,
198                            ["Parent function `close` failed"]
199                        ))
200                    }
201                })
202                .unwrap_or(Ok(()))
203        }
204    }
205
206    fn parent_start(&self) -> Result<(), gst::ErrorMessage> {
207        unsafe {
208            let data = Self::type_data();
209            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
210            (*parent_class)
211                .start
212                .map(|f| {
213                    if from_glib(f(self
214                        .obj()
215                        .unsafe_cast_ref::<VideoEncoder>()
216                        .to_glib_none()
217                        .0))
218                    {
219                        Ok(())
220                    } else {
221                        Err(gst::error_msg!(
222                            gst::CoreError::StateChange,
223                            ["Parent function `start` failed"]
224                        ))
225                    }
226                })
227                .unwrap_or(Ok(()))
228        }
229    }
230
231    fn parent_stop(&self) -> Result<(), gst::ErrorMessage> {
232        unsafe {
233            let data = Self::type_data();
234            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
235            (*parent_class)
236                .stop
237                .map(|f| {
238                    if from_glib(f(self
239                        .obj()
240                        .unsafe_cast_ref::<VideoEncoder>()
241                        .to_glib_none()
242                        .0))
243                    {
244                        Ok(())
245                    } else {
246                        Err(gst::error_msg!(
247                            gst::CoreError::StateChange,
248                            ["Parent function `stop` failed"]
249                        ))
250                    }
251                })
252                .unwrap_or(Ok(()))
253        }
254    }
255
256    fn parent_finish(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
257        unsafe {
258            let data = Self::type_data();
259            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
260            (*parent_class)
261                .finish
262                .map(|f| {
263                    try_from_glib(f(self
264                        .obj()
265                        .unsafe_cast_ref::<VideoEncoder>()
266                        .to_glib_none()
267                        .0))
268                })
269                .unwrap_or(Ok(gst::FlowSuccess::Ok))
270        }
271    }
272
273    fn parent_set_format(
274        &self,
275        state: &VideoCodecState<'static, Readable>,
276    ) -> 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                .set_format
282                .map(|f| {
283                    gst::result_from_gboolean!(
284                        f(
285                            self.obj()
286                                .unsafe_cast_ref::<VideoEncoder>()
287                                .to_glib_none()
288                                .0,
289                            state.as_mut_ptr()
290                        ),
291                        gst::CAT_RUST,
292                        "parent function `set_format` failed"
293                    )
294                })
295                .unwrap_or(Ok(()))
296        }
297    }
298
299    fn parent_handle_frame(
300        &self,
301        frame: VideoCodecFrame,
302    ) -> Result<gst::FlowSuccess, gst::FlowError> {
303        unsafe {
304            let data = Self::type_data();
305            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
306            (*parent_class)
307                .handle_frame
308                .map(|f| {
309                    try_from_glib(f(
310                        self.obj()
311                            .unsafe_cast_ref::<VideoEncoder>()
312                            .to_glib_none()
313                            .0,
314                        frame.to_glib_none().0,
315                    ))
316                })
317                .unwrap_or(Err(gst::FlowError::Error))
318        }
319    }
320
321    fn parent_flush(&self) -> bool {
322        unsafe {
323            let data = Self::type_data();
324            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
325            (*parent_class)
326                .flush
327                .map(|f| {
328                    from_glib(f(self
329                        .obj()
330                        .unsafe_cast_ref::<VideoEncoder>()
331                        .to_glib_none()
332                        .0))
333                })
334                .unwrap_or(false)
335        }
336    }
337
338    fn parent_negotiate(&self) -> Result<(), gst::LoggableError> {
339        unsafe {
340            let data = Self::type_data();
341            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
342            (*parent_class)
343                .negotiate
344                .map(|f| {
345                    gst::result_from_gboolean!(
346                        f(self
347                            .obj()
348                            .unsafe_cast_ref::<VideoEncoder>()
349                            .to_glib_none()
350                            .0),
351                        gst::CAT_RUST,
352                        "Parent function `negotiate` failed"
353                    )
354                })
355                .unwrap_or(Ok(()))
356        }
357    }
358
359    fn parent_caps(&self, filter: Option<&gst::Caps>) -> gst::Caps {
360        unsafe {
361            let data = Self::type_data();
362            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
363            (*parent_class)
364                .getcaps
365                .map(|f| {
366                    from_glib_full(f(
367                        self.obj()
368                            .unsafe_cast_ref::<VideoEncoder>()
369                            .to_glib_none()
370                            .0,
371                        filter.to_glib_none().0,
372                    ))
373                })
374                .unwrap_or_else(|| {
375                    self.obj()
376                        .unsafe_cast_ref::<VideoEncoder>()
377                        .proxy_getcaps(None, filter)
378                })
379        }
380    }
381
382    fn parent_sink_event(&self, event: gst::Event) -> bool {
383        unsafe {
384            let data = Self::type_data();
385            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
386            let f = (*parent_class)
387                .sink_event
388                .expect("Missing parent function `sink_event`");
389            from_glib(f(
390                self.obj()
391                    .unsafe_cast_ref::<VideoEncoder>()
392                    .to_glib_none()
393                    .0,
394                event.into_glib_ptr(),
395            ))
396        }
397    }
398
399    fn parent_sink_query(&self, query: &mut gst::QueryRef) -> bool {
400        unsafe {
401            let data = Self::type_data();
402            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
403            let f = (*parent_class)
404                .sink_query
405                .expect("Missing parent function `sink_query`");
406            from_glib(f(
407                self.obj()
408                    .unsafe_cast_ref::<VideoEncoder>()
409                    .to_glib_none()
410                    .0,
411                query.as_mut_ptr(),
412            ))
413        }
414    }
415
416    fn parent_src_event(&self, event: gst::Event) -> bool {
417        unsafe {
418            let data = Self::type_data();
419            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
420            let f = (*parent_class)
421                .src_event
422                .expect("Missing parent function `src_event`");
423            from_glib(f(
424                self.obj()
425                    .unsafe_cast_ref::<VideoEncoder>()
426                    .to_glib_none()
427                    .0,
428                event.into_glib_ptr(),
429            ))
430        }
431    }
432
433    fn parent_src_query(&self, query: &mut gst::QueryRef) -> bool {
434        unsafe {
435            let data = Self::type_data();
436            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
437            let f = (*parent_class)
438                .src_query
439                .expect("Missing parent function `src_query`");
440            from_glib(f(
441                self.obj()
442                    .unsafe_cast_ref::<VideoEncoder>()
443                    .to_glib_none()
444                    .0,
445                query.as_mut_ptr(),
446            ))
447        }
448    }
449
450    fn parent_propose_allocation(
451        &self,
452        query: &mut gst::query::Allocation,
453    ) -> Result<(), gst::LoggableError> {
454        unsafe {
455            let data = Self::type_data();
456            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
457            (*parent_class)
458                .propose_allocation
459                .map(|f| {
460                    gst::result_from_gboolean!(
461                        f(
462                            self.obj()
463                                .unsafe_cast_ref::<VideoEncoder>()
464                                .to_glib_none()
465                                .0,
466                            query.as_mut_ptr(),
467                        ),
468                        gst::CAT_RUST,
469                        "Parent function `propose_allocation` failed",
470                    )
471                })
472                .unwrap_or(Ok(()))
473        }
474    }
475
476    fn parent_decide_allocation(
477        &self,
478        query: &mut gst::query::Allocation,
479    ) -> Result<(), gst::LoggableError> {
480        unsafe {
481            let data = Self::type_data();
482            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
483            (*parent_class)
484                .decide_allocation
485                .map(|f| {
486                    gst::result_from_gboolean!(
487                        f(
488                            self.obj()
489                                .unsafe_cast_ref::<VideoEncoder>()
490                                .to_glib_none()
491                                .0,
492                            query.as_mut_ptr(),
493                        ),
494                        gst::CAT_RUST,
495                        "Parent function `decide_allocation` failed",
496                    )
497                })
498                .unwrap_or(Ok(()))
499        }
500    }
501}
502
503impl<T: VideoEncoderImpl> VideoEncoderImplExt for T {}
504
505unsafe impl<T: VideoEncoderImpl> IsSubclassable<T> for VideoEncoder {
506    fn class_init(klass: &mut glib::Class<Self>) {
507        Self::parent_class_init::<T>(klass);
508        let klass = klass.as_mut();
509        klass.open = Some(video_encoder_open::<T>);
510        klass.close = Some(video_encoder_close::<T>);
511        klass.start = Some(video_encoder_start::<T>);
512        klass.stop = Some(video_encoder_stop::<T>);
513        klass.finish = Some(video_encoder_finish::<T>);
514        klass.set_format = Some(video_encoder_set_format::<T>);
515        klass.handle_frame = Some(video_encoder_handle_frame::<T>);
516        klass.flush = Some(video_encoder_flush::<T>);
517        klass.negotiate = Some(video_encoder_negotiate::<T>);
518        klass.getcaps = Some(video_encoder_getcaps::<T>);
519        klass.sink_event = Some(video_encoder_sink_event::<T>);
520        klass.src_event = Some(video_encoder_src_event::<T>);
521        klass.sink_query = Some(video_encoder_sink_query::<T>);
522        klass.src_query = Some(video_encoder_src_query::<T>);
523        klass.propose_allocation = Some(video_encoder_propose_allocation::<T>);
524        klass.decide_allocation = Some(video_encoder_decide_allocation::<T>);
525    }
526}
527
528unsafe extern "C" fn video_encoder_open<T: VideoEncoderImpl>(
529    ptr: *mut ffi::GstVideoEncoder,
530) -> glib::ffi::gboolean {
531    let instance = &*(ptr as *mut T::Instance);
532    let imp = instance.imp();
533
534    gst::panic_to_error!(imp, false, {
535        match imp.open() {
536            Ok(()) => true,
537            Err(err) => {
538                imp.post_error_message(err);
539                false
540            }
541        }
542    })
543    .into_glib()
544}
545
546unsafe extern "C" fn video_encoder_close<T: VideoEncoderImpl>(
547    ptr: *mut ffi::GstVideoEncoder,
548) -> glib::ffi::gboolean {
549    let instance = &*(ptr as *mut T::Instance);
550    let imp = instance.imp();
551
552    gst::panic_to_error!(imp, false, {
553        match imp.close() {
554            Ok(()) => true,
555            Err(err) => {
556                imp.post_error_message(err);
557                false
558            }
559        }
560    })
561    .into_glib()
562}
563
564unsafe extern "C" fn video_encoder_start<T: VideoEncoderImpl>(
565    ptr: *mut ffi::GstVideoEncoder,
566) -> glib::ffi::gboolean {
567    let instance = &*(ptr as *mut T::Instance);
568    let imp = instance.imp();
569
570    gst::panic_to_error!(imp, false, {
571        match imp.start() {
572            Ok(()) => true,
573            Err(err) => {
574                imp.post_error_message(err);
575                false
576            }
577        }
578    })
579    .into_glib()
580}
581
582unsafe extern "C" fn video_encoder_stop<T: VideoEncoderImpl>(
583    ptr: *mut ffi::GstVideoEncoder,
584) -> glib::ffi::gboolean {
585    let instance = &*(ptr as *mut T::Instance);
586    let imp = instance.imp();
587
588    gst::panic_to_error!(imp, false, {
589        match imp.stop() {
590            Ok(()) => true,
591            Err(err) => {
592                imp.post_error_message(err);
593                false
594            }
595        }
596    })
597    .into_glib()
598}
599
600unsafe extern "C" fn video_encoder_finish<T: VideoEncoderImpl>(
601    ptr: *mut ffi::GstVideoEncoder,
602) -> gst::ffi::GstFlowReturn {
603    let instance = &*(ptr as *mut T::Instance);
604    let imp = instance.imp();
605
606    gst::panic_to_error!(imp, gst::FlowReturn::Error, { imp.finish().into() }).into_glib()
607}
608
609unsafe extern "C" fn video_encoder_set_format<T: VideoEncoderImpl>(
610    ptr: *mut ffi::GstVideoEncoder,
611    state: *mut ffi::GstVideoCodecState,
612) -> glib::ffi::gboolean {
613    let instance = &*(ptr as *mut T::Instance);
614    let imp = instance.imp();
615    ffi::gst_video_codec_state_ref(state);
616    let wrap_state = VideoCodecState::<Readable>::new(state);
617
618    gst::panic_to_error!(imp, false, {
619        match imp.set_format(&wrap_state) {
620            Ok(()) => true,
621            Err(err) => {
622                err.log_with_imp(imp);
623                false
624            }
625        }
626    })
627    .into_glib()
628}
629
630unsafe extern "C" fn video_encoder_handle_frame<T: VideoEncoderImpl>(
631    ptr: *mut ffi::GstVideoEncoder,
632    frame: *mut ffi::GstVideoCodecFrame,
633) -> gst::ffi::GstFlowReturn {
634    let instance = &*(ptr as *mut T::Instance);
635    let imp = instance.imp();
636    let instance = imp.obj();
637    let instance = instance.unsafe_cast_ref::<VideoEncoder>();
638    let wrap_frame = VideoCodecFrame::new(frame, instance);
639
640    gst::panic_to_error!(imp, gst::FlowReturn::Error, {
641        imp.handle_frame(wrap_frame).into()
642    })
643    .into_glib()
644}
645
646unsafe extern "C" fn video_encoder_flush<T: VideoEncoderImpl>(
647    ptr: *mut ffi::GstVideoEncoder,
648) -> glib::ffi::gboolean {
649    let instance = &*(ptr as *mut T::Instance);
650    let imp = instance.imp();
651
652    gst::panic_to_error!(imp, false, { VideoEncoderImpl::flush(imp) }).into_glib()
653}
654
655unsafe extern "C" fn video_encoder_negotiate<T: VideoEncoderImpl>(
656    ptr: *mut ffi::GstVideoEncoder,
657) -> glib::ffi::gboolean {
658    let instance = &*(ptr as *mut T::Instance);
659    let imp = instance.imp();
660
661    gst::panic_to_error!(imp, false, {
662        match imp.negotiate() {
663            Ok(()) => true,
664            Err(err) => {
665                err.log_with_imp(imp);
666                false
667            }
668        }
669    })
670    .into_glib()
671}
672
673unsafe extern "C" fn video_encoder_getcaps<T: VideoEncoderImpl>(
674    ptr: *mut ffi::GstVideoEncoder,
675    filter: *mut gst::ffi::GstCaps,
676) -> *mut gst::ffi::GstCaps {
677    let instance = &*(ptr as *mut T::Instance);
678    let imp = instance.imp();
679
680    gst::panic_to_error!(imp, gst::Caps::new_empty(), {
681        VideoEncoderImpl::caps(
682            imp,
683            Option::<gst::Caps>::from_glib_borrow(filter)
684                .as_ref()
685                .as_ref(),
686        )
687    })
688    .into_glib_ptr()
689}
690
691unsafe extern "C" fn video_encoder_sink_event<T: VideoEncoderImpl>(
692    ptr: *mut ffi::GstVideoEncoder,
693    event: *mut gst::ffi::GstEvent,
694) -> glib::ffi::gboolean {
695    let instance = &*(ptr as *mut T::Instance);
696    let imp = instance.imp();
697
698    gst::panic_to_error!(imp, false, { imp.sink_event(from_glib_full(event)) }).into_glib()
699}
700
701unsafe extern "C" fn video_encoder_sink_query<T: VideoEncoderImpl>(
702    ptr: *mut ffi::GstVideoEncoder,
703    query: *mut gst::ffi::GstQuery,
704) -> glib::ffi::gboolean {
705    let instance = &*(ptr as *mut T::Instance);
706    let imp = instance.imp();
707
708    gst::panic_to_error!(imp, false, {
709        imp.sink_query(gst::QueryRef::from_mut_ptr(query))
710    })
711    .into_glib()
712}
713
714unsafe extern "C" fn video_encoder_src_event<T: VideoEncoderImpl>(
715    ptr: *mut ffi::GstVideoEncoder,
716    event: *mut gst::ffi::GstEvent,
717) -> glib::ffi::gboolean {
718    let instance = &*(ptr as *mut T::Instance);
719    let imp = instance.imp();
720
721    gst::panic_to_error!(imp, false, { imp.src_event(from_glib_full(event)) }).into_glib()
722}
723
724unsafe extern "C" fn video_encoder_src_query<T: VideoEncoderImpl>(
725    ptr: *mut ffi::GstVideoEncoder,
726    query: *mut gst::ffi::GstQuery,
727) -> glib::ffi::gboolean {
728    let instance = &*(ptr as *mut T::Instance);
729    let imp = instance.imp();
730
731    gst::panic_to_error!(imp, false, {
732        imp.src_query(gst::QueryRef::from_mut_ptr(query))
733    })
734    .into_glib()
735}
736
737unsafe extern "C" fn video_encoder_propose_allocation<T: VideoEncoderImpl>(
738    ptr: *mut ffi::GstVideoEncoder,
739    query: *mut gst::ffi::GstQuery,
740) -> glib::ffi::gboolean {
741    let instance = &*(ptr as *mut T::Instance);
742    let imp = instance.imp();
743    let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
744        gst::QueryViewMut::Allocation(allocation) => allocation,
745        _ => unreachable!(),
746    };
747
748    gst::panic_to_error!(imp, false, {
749        match imp.propose_allocation(query) {
750            Ok(()) => true,
751            Err(err) => {
752                err.log_with_imp(imp);
753                false
754            }
755        }
756    })
757    .into_glib()
758}
759
760unsafe extern "C" fn video_encoder_decide_allocation<T: VideoEncoderImpl>(
761    ptr: *mut ffi::GstVideoEncoder,
762    query: *mut gst::ffi::GstQuery,
763) -> glib::ffi::gboolean {
764    let instance = &*(ptr as *mut T::Instance);
765    let imp = instance.imp();
766    let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
767        gst::QueryViewMut::Allocation(allocation) => allocation,
768        _ => unreachable!(),
769    };
770
771    gst::panic_to_error!(imp, false, {
772        match imp.decide_allocation(query) {
773            Ok(()) => true,
774            Err(err) => {
775                err.log_with_imp(imp);
776                false
777            }
778        }
779    })
780    .into_glib()
781}