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