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