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