gstreamer_video/subclass/
video_decoder.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, VideoDecoder,
11};
12
13pub trait VideoDecoderImpl: ElementImpl + ObjectSubclass<Type: IsA<VideoDecoder>> {
14    fn open(&self) -> Result<(), gst::ErrorMessage> {
15        self.parent_open()
16    }
17
18    fn close(&self) -> Result<(), gst::ErrorMessage> {
19        self.parent_close()
20    }
21
22    fn start(&self) -> Result<(), gst::ErrorMessage> {
23        self.parent_start()
24    }
25
26    fn stop(&self) -> Result<(), gst::ErrorMessage> {
27        self.parent_stop()
28    }
29
30    fn finish(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
31        self.parent_finish()
32    }
33
34    fn drain(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
35        self.parent_drain()
36    }
37
38    fn set_format(
39        &self,
40        state: &VideoCodecState<'static, Readable>,
41    ) -> Result<(), gst::LoggableError> {
42        self.parent_set_format(state)
43    }
44
45    fn parse(
46        &self,
47        frame: &VideoCodecFrame,
48        adapter: &gst_base::Adapter,
49        at_eos: bool,
50    ) -> Result<gst::FlowSuccess, gst::FlowError> {
51        self.parent_parse(frame, adapter, at_eos)
52    }
53
54    fn handle_frame(&self, frame: VideoCodecFrame) -> Result<gst::FlowSuccess, gst::FlowError> {
55        self.parent_handle_frame(frame)
56    }
57
58    fn flush(&self) -> bool {
59        self.parent_flush()
60    }
61
62    fn negotiate(&self) -> Result<(), gst::LoggableError> {
63        self.parent_negotiate()
64    }
65
66    fn caps(&self, filter: Option<&gst::Caps>) -> gst::Caps {
67        self.parent_caps(filter)
68    }
69
70    fn sink_event(&self, event: gst::Event) -> bool {
71        self.parent_sink_event(event)
72    }
73
74    fn sink_query(&self, query: &mut gst::QueryRef) -> bool {
75        self.parent_sink_query(query)
76    }
77
78    fn src_event(&self, event: gst::Event) -> bool {
79        self.parent_src_event(event)
80    }
81
82    fn src_query(&self, query: &mut gst::QueryRef) -> bool {
83        self.parent_src_query(query)
84    }
85
86    fn propose_allocation(
87        &self,
88        query: &mut gst::query::Allocation,
89    ) -> Result<(), gst::LoggableError> {
90        self.parent_propose_allocation(query)
91    }
92
93    fn decide_allocation(
94        &self,
95        query: &mut gst::query::Allocation,
96    ) -> Result<(), gst::LoggableError> {
97        self.parent_decide_allocation(query)
98    }
99
100    #[cfg(feature = "v1_20")]
101    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
102    fn handle_missing_data(
103        &self,
104        timestamp: gst::ClockTime,
105        duration: Option<gst::ClockTime>,
106    ) -> bool {
107        self.parent_handle_missing_data(timestamp, duration)
108    }
109}
110
111pub trait VideoDecoderImplExt: VideoDecoderImpl {
112    fn parent_open(&self) -> Result<(), gst::ErrorMessage> {
113        unsafe {
114            let data = Self::type_data();
115            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
116            (*parent_class)
117                .open
118                .map(|f| {
119                    if from_glib(f(self
120                        .obj()
121                        .unsafe_cast_ref::<VideoDecoder>()
122                        .to_glib_none()
123                        .0))
124                    {
125                        Ok(())
126                    } else {
127                        Err(gst::error_msg!(
128                            gst::CoreError::StateChange,
129                            ["Parent function `open` failed"]
130                        ))
131                    }
132                })
133                .unwrap_or(Ok(()))
134        }
135    }
136
137    fn parent_close(&self) -> Result<(), gst::ErrorMessage> {
138        unsafe {
139            let data = Self::type_data();
140            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
141            (*parent_class)
142                .close
143                .map(|f| {
144                    if from_glib(f(self
145                        .obj()
146                        .unsafe_cast_ref::<VideoDecoder>()
147                        .to_glib_none()
148                        .0))
149                    {
150                        Ok(())
151                    } else {
152                        Err(gst::error_msg!(
153                            gst::CoreError::StateChange,
154                            ["Parent function `close` failed"]
155                        ))
156                    }
157                })
158                .unwrap_or(Ok(()))
159        }
160    }
161
162    fn parent_start(&self) -> Result<(), gst::ErrorMessage> {
163        unsafe {
164            let data = Self::type_data();
165            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
166            (*parent_class)
167                .start
168                .map(|f| {
169                    if from_glib(f(self
170                        .obj()
171                        .unsafe_cast_ref::<VideoDecoder>()
172                        .to_glib_none()
173                        .0))
174                    {
175                        Ok(())
176                    } else {
177                        Err(gst::error_msg!(
178                            gst::CoreError::StateChange,
179                            ["Parent function `start` failed"]
180                        ))
181                    }
182                })
183                .unwrap_or(Ok(()))
184        }
185    }
186
187    fn parent_stop(&self) -> Result<(), gst::ErrorMessage> {
188        unsafe {
189            let data = Self::type_data();
190            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
191            (*parent_class)
192                .stop
193                .map(|f| {
194                    if from_glib(f(self
195                        .obj()
196                        .unsafe_cast_ref::<VideoDecoder>()
197                        .to_glib_none()
198                        .0))
199                    {
200                        Ok(())
201                    } else {
202                        Err(gst::error_msg!(
203                            gst::CoreError::StateChange,
204                            ["Parent function `stop` failed"]
205                        ))
206                    }
207                })
208                .unwrap_or(Ok(()))
209        }
210    }
211
212    fn parent_finish(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
213        unsafe {
214            let data = Self::type_data();
215            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
216            (*parent_class)
217                .finish
218                .map(|f| {
219                    try_from_glib(f(self
220                        .obj()
221                        .unsafe_cast_ref::<VideoDecoder>()
222                        .to_glib_none()
223                        .0))
224                })
225                .unwrap_or(Ok(gst::FlowSuccess::Ok))
226        }
227    }
228
229    fn parent_drain(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
230        unsafe {
231            let data = Self::type_data();
232            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
233            (*parent_class)
234                .drain
235                .map(|f| {
236                    try_from_glib(f(self
237                        .obj()
238                        .unsafe_cast_ref::<VideoDecoder>()
239                        .to_glib_none()
240                        .0))
241                })
242                .unwrap_or(Ok(gst::FlowSuccess::Ok))
243        }
244    }
245
246    fn parent_set_format(
247        &self,
248        state: &VideoCodecState<'static, Readable>,
249    ) -> Result<(), gst::LoggableError> {
250        unsafe {
251            let data = Self::type_data();
252            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
253            (*parent_class)
254                .set_format
255                .map(|f| {
256                    gst::result_from_gboolean!(
257                        f(
258                            self.obj()
259                                .unsafe_cast_ref::<VideoDecoder>()
260                                .to_glib_none()
261                                .0,
262                            state.as_mut_ptr()
263                        ),
264                        gst::CAT_RUST,
265                        "parent function `set_format` failed"
266                    )
267                })
268                .unwrap_or(Ok(()))
269        }
270    }
271
272    fn parent_parse(
273        &self,
274        frame: &VideoCodecFrame,
275        adapter: &gst_base::Adapter,
276        at_eos: bool,
277    ) -> Result<gst::FlowSuccess, gst::FlowError> {
278        unsafe {
279            let data = Self::type_data();
280            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
281            (*parent_class)
282                .parse
283                .map(|f| {
284                    try_from_glib(f(
285                        self.obj()
286                            .unsafe_cast_ref::<VideoDecoder>()
287                            .to_glib_none()
288                            .0,
289                        frame.to_glib_none().0,
290                        adapter.to_glib_none().0,
291                        at_eos.into_glib(),
292                    ))
293                })
294                .unwrap_or(Ok(gst::FlowSuccess::Ok))
295        }
296    }
297
298    fn parent_handle_frame(
299        &self,
300        frame: VideoCodecFrame,
301    ) -> Result<gst::FlowSuccess, gst::FlowError> {
302        unsafe {
303            let data = Self::type_data();
304            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
305            (*parent_class)
306                .handle_frame
307                .map(|f| {
308                    try_from_glib(f(
309                        self.obj()
310                            .unsafe_cast_ref::<VideoDecoder>()
311                            .to_glib_none()
312                            .0,
313                        frame.to_glib_none().0,
314                    ))
315                })
316                .unwrap_or(Err(gst::FlowError::Error))
317        }
318    }
319
320    fn parent_flush(&self) -> bool {
321        unsafe {
322            let data = Self::type_data();
323            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
324            (*parent_class)
325                .flush
326                .map(|f| {
327                    from_glib(f(self
328                        .obj()
329                        .unsafe_cast_ref::<VideoDecoder>()
330                        .to_glib_none()
331                        .0))
332                })
333                .unwrap_or(false)
334        }
335    }
336
337    fn parent_negotiate(&self) -> Result<(), gst::LoggableError> {
338        unsafe {
339            let data = Self::type_data();
340            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
341            (*parent_class)
342                .negotiate
343                .map(|f| {
344                    gst::result_from_gboolean!(
345                        f(self
346                            .obj()
347                            .unsafe_cast_ref::<VideoDecoder>()
348                            .to_glib_none()
349                            .0),
350                        gst::CAT_RUST,
351                        "Parent function `negotiate` failed"
352                    )
353                })
354                .unwrap_or(Ok(()))
355        }
356    }
357
358    fn parent_caps(&self, filter: Option<&gst::Caps>) -> gst::Caps {
359        unsafe {
360            let data = Self::type_data();
361            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
362            (*parent_class)
363                .getcaps
364                .map(|f| {
365                    from_glib_full(f(
366                        self.obj()
367                            .unsafe_cast_ref::<VideoDecoder>()
368                            .to_glib_none()
369                            .0,
370                        filter.to_glib_none().0,
371                    ))
372                })
373                .unwrap_or_else(|| {
374                    self.obj()
375                        .unsafe_cast_ref::<VideoDecoder>()
376                        .proxy_getcaps(None, filter)
377                })
378        }
379    }
380
381    fn parent_sink_event(&self, event: gst::Event) -> bool {
382        unsafe {
383            let data = Self::type_data();
384            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
385            let f = (*parent_class)
386                .sink_event
387                .expect("Missing parent function `sink_event`");
388            from_glib(f(
389                self.obj()
390                    .unsafe_cast_ref::<VideoDecoder>()
391                    .to_glib_none()
392                    .0,
393                event.into_glib_ptr(),
394            ))
395        }
396    }
397
398    fn parent_sink_query(&self, query: &mut gst::QueryRef) -> bool {
399        unsafe {
400            let data = Self::type_data();
401            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
402            let f = (*parent_class)
403                .sink_query
404                .expect("Missing parent function `sink_query`");
405            from_glib(f(
406                self.obj()
407                    .unsafe_cast_ref::<VideoDecoder>()
408                    .to_glib_none()
409                    .0,
410                query.as_mut_ptr(),
411            ))
412        }
413    }
414
415    fn parent_src_event(&self, event: gst::Event) -> bool {
416        unsafe {
417            let data = Self::type_data();
418            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
419            let f = (*parent_class)
420                .src_event
421                .expect("Missing parent function `src_event`");
422            from_glib(f(
423                self.obj()
424                    .unsafe_cast_ref::<VideoDecoder>()
425                    .to_glib_none()
426                    .0,
427                event.into_glib_ptr(),
428            ))
429        }
430    }
431
432    fn parent_src_query(&self, query: &mut gst::QueryRef) -> bool {
433        unsafe {
434            let data = Self::type_data();
435            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
436            let f = (*parent_class)
437                .src_query
438                .expect("Missing parent function `src_query`");
439            from_glib(f(
440                self.obj()
441                    .unsafe_cast_ref::<VideoDecoder>()
442                    .to_glib_none()
443                    .0,
444                query.as_mut_ptr(),
445            ))
446        }
447    }
448
449    fn parent_propose_allocation(
450        &self,
451        query: &mut gst::query::Allocation,
452    ) -> Result<(), gst::LoggableError> {
453        unsafe {
454            let data = Self::type_data();
455            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
456            (*parent_class)
457                .propose_allocation
458                .map(|f| {
459                    gst::result_from_gboolean!(
460                        f(
461                            self.obj()
462                                .unsafe_cast_ref::<VideoDecoder>()
463                                .to_glib_none()
464                                .0,
465                            query.as_mut_ptr(),
466                        ),
467                        gst::CAT_RUST,
468                        "Parent function `propose_allocation` failed",
469                    )
470                })
471                .unwrap_or(Ok(()))
472        }
473    }
474
475    fn parent_decide_allocation(
476        &self,
477        query: &mut gst::query::Allocation,
478    ) -> Result<(), gst::LoggableError> {
479        unsafe {
480            let data = Self::type_data();
481            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
482            (*parent_class)
483                .decide_allocation
484                .map(|f| {
485                    gst::result_from_gboolean!(
486                        f(
487                            self.obj()
488                                .unsafe_cast_ref::<VideoDecoder>()
489                                .to_glib_none()
490                                .0,
491                            query.as_mut_ptr(),
492                        ),
493                        gst::CAT_RUST,
494                        "Parent function `decide_allocation` failed",
495                    )
496                })
497                .unwrap_or(Ok(()))
498        }
499    }
500
501    #[cfg(feature = "v1_20")]
502    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
503    fn parent_handle_missing_data(
504        &self,
505        timestamp: gst::ClockTime,
506        duration: Option<gst::ClockTime>,
507    ) -> bool {
508        unsafe {
509            let data = Self::type_data();
510            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
511            (*parent_class)
512                .handle_missing_data
513                .map(|f| {
514                    from_glib(f(
515                        self.obj()
516                            .unsafe_cast_ref::<VideoDecoder>()
517                            .to_glib_none()
518                            .0,
519                        timestamp.into_glib(),
520                        duration.into_glib(),
521                    ))
522                })
523                .unwrap_or(true)
524        }
525    }
526}
527
528impl<T: VideoDecoderImpl> VideoDecoderImplExt for T {}
529
530unsafe impl<T: VideoDecoderImpl> IsSubclassable<T> for VideoDecoder {
531    fn class_init(klass: &mut glib::Class<Self>) {
532        Self::parent_class_init::<T>(klass);
533        let klass = klass.as_mut();
534        klass.open = Some(video_decoder_open::<T>);
535        klass.close = Some(video_decoder_close::<T>);
536        klass.start = Some(video_decoder_start::<T>);
537        klass.stop = Some(video_decoder_stop::<T>);
538        klass.finish = Some(video_decoder_finish::<T>);
539        klass.drain = Some(video_decoder_drain::<T>);
540        klass.set_format = Some(video_decoder_set_format::<T>);
541        klass.parse = Some(video_decoder_parse::<T>);
542        klass.handle_frame = Some(video_decoder_handle_frame::<T>);
543        klass.flush = Some(video_decoder_flush::<T>);
544        klass.negotiate = Some(video_decoder_negotiate::<T>);
545        klass.getcaps = Some(video_decoder_getcaps::<T>);
546        klass.sink_event = Some(video_decoder_sink_event::<T>);
547        klass.src_event = Some(video_decoder_src_event::<T>);
548        klass.sink_query = Some(video_decoder_sink_query::<T>);
549        klass.src_query = Some(video_decoder_src_query::<T>);
550        klass.propose_allocation = Some(video_decoder_propose_allocation::<T>);
551        klass.decide_allocation = Some(video_decoder_decide_allocation::<T>);
552        #[cfg(feature = "v1_20")]
553        {
554            klass.handle_missing_data = Some(video_decoder_handle_missing_data::<T>);
555        }
556    }
557}
558
559unsafe extern "C" fn video_decoder_open<T: VideoDecoderImpl>(
560    ptr: *mut ffi::GstVideoDecoder,
561) -> glib::ffi::gboolean {
562    let instance = &*(ptr as *mut T::Instance);
563    let imp = instance.imp();
564
565    gst::panic_to_error!(imp, false, {
566        match imp.open() {
567            Ok(()) => true,
568            Err(err) => {
569                imp.post_error_message(err);
570                false
571            }
572        }
573    })
574    .into_glib()
575}
576
577unsafe extern "C" fn video_decoder_close<T: VideoDecoderImpl>(
578    ptr: *mut ffi::GstVideoDecoder,
579) -> glib::ffi::gboolean {
580    let instance = &*(ptr as *mut T::Instance);
581    let imp = instance.imp();
582
583    gst::panic_to_error!(imp, false, {
584        match imp.close() {
585            Ok(()) => true,
586            Err(err) => {
587                imp.post_error_message(err);
588                false
589            }
590        }
591    })
592    .into_glib()
593}
594
595unsafe extern "C" fn video_decoder_start<T: VideoDecoderImpl>(
596    ptr: *mut ffi::GstVideoDecoder,
597) -> glib::ffi::gboolean {
598    let instance = &*(ptr as *mut T::Instance);
599    let imp = instance.imp();
600
601    gst::panic_to_error!(imp, false, {
602        match imp.start() {
603            Ok(()) => true,
604            Err(err) => {
605                imp.post_error_message(err);
606                false
607            }
608        }
609    })
610    .into_glib()
611}
612
613unsafe extern "C" fn video_decoder_stop<T: VideoDecoderImpl>(
614    ptr: *mut ffi::GstVideoDecoder,
615) -> glib::ffi::gboolean {
616    let instance = &*(ptr as *mut T::Instance);
617    let imp = instance.imp();
618
619    gst::panic_to_error!(imp, false, {
620        match imp.stop() {
621            Ok(()) => true,
622            Err(err) => {
623                imp.post_error_message(err);
624                false
625            }
626        }
627    })
628    .into_glib()
629}
630
631unsafe extern "C" fn video_decoder_finish<T: VideoDecoderImpl>(
632    ptr: *mut ffi::GstVideoDecoder,
633) -> gst::ffi::GstFlowReturn {
634    let instance = &*(ptr as *mut T::Instance);
635    let imp = instance.imp();
636
637    gst::panic_to_error!(imp, gst::FlowReturn::Error, { imp.finish().into() }).into_glib()
638}
639
640unsafe extern "C" fn video_decoder_drain<T: VideoDecoderImpl>(
641    ptr: *mut ffi::GstVideoDecoder,
642) -> gst::ffi::GstFlowReturn {
643    let instance = &*(ptr as *mut T::Instance);
644    let imp = instance.imp();
645
646    gst::panic_to_error!(imp, gst::FlowReturn::Error, { imp.drain().into() }).into_glib()
647}
648
649unsafe extern "C" fn video_decoder_set_format<T: VideoDecoderImpl>(
650    ptr: *mut ffi::GstVideoDecoder,
651    state: *mut ffi::GstVideoCodecState,
652) -> glib::ffi::gboolean {
653    let instance = &*(ptr as *mut T::Instance);
654    let imp = instance.imp();
655    ffi::gst_video_codec_state_ref(state);
656    let wrap_state = VideoCodecState::<Readable>::new(state);
657
658    gst::panic_to_error!(imp, false, {
659        match imp.set_format(&wrap_state) {
660            Ok(()) => true,
661            Err(err) => {
662                err.log_with_imp(imp);
663                false
664            }
665        }
666    })
667    .into_glib()
668}
669
670unsafe extern "C" fn video_decoder_parse<T: VideoDecoderImpl>(
671    ptr: *mut ffi::GstVideoDecoder,
672    frame: *mut ffi::GstVideoCodecFrame,
673    adapter: *mut gst_base::ffi::GstAdapter,
674    at_eos: glib::ffi::gboolean,
675) -> gst::ffi::GstFlowReturn {
676    let instance = &*(ptr as *mut T::Instance);
677    let imp = instance.imp();
678    ffi::gst_video_codec_frame_ref(frame);
679    let instance = imp.obj();
680    let instance = instance.unsafe_cast_ref::<VideoDecoder>();
681    let wrap_frame = VideoCodecFrame::new(frame, instance);
682    let wrap_adapter: Borrowed<gst_base::Adapter> = from_glib_borrow(adapter);
683    let at_eos: bool = from_glib(at_eos);
684
685    gst::panic_to_error!(imp, gst::FlowReturn::Error, {
686        imp.parse(&wrap_frame, &wrap_adapter, at_eos).into()
687    })
688    .into_glib()
689}
690
691unsafe extern "C" fn video_decoder_handle_frame<T: VideoDecoderImpl>(
692    ptr: *mut ffi::GstVideoDecoder,
693    frame: *mut ffi::GstVideoCodecFrame,
694) -> gst::ffi::GstFlowReturn {
695    let instance = &*(ptr as *mut T::Instance);
696    let imp = instance.imp();
697    let instance = imp.obj();
698    let instance = instance.unsafe_cast_ref::<VideoDecoder>();
699    let wrap_frame = VideoCodecFrame::new(frame, instance);
700
701    gst::panic_to_error!(imp, gst::FlowReturn::Error, {
702        imp.handle_frame(wrap_frame).into()
703    })
704    .into_glib()
705}
706
707unsafe extern "C" fn video_decoder_flush<T: VideoDecoderImpl>(
708    ptr: *mut ffi::GstVideoDecoder,
709) -> glib::ffi::gboolean {
710    let instance = &*(ptr as *mut T::Instance);
711    let imp = instance.imp();
712
713    gst::panic_to_error!(imp, false, { VideoDecoderImpl::flush(imp) }).into_glib()
714}
715
716unsafe extern "C" fn video_decoder_negotiate<T: VideoDecoderImpl>(
717    ptr: *mut ffi::GstVideoDecoder,
718) -> glib::ffi::gboolean {
719    let instance = &*(ptr as *mut T::Instance);
720    let imp = instance.imp();
721
722    gst::panic_to_error!(imp, false, {
723        match imp.negotiate() {
724            Ok(()) => true,
725            Err(err) => {
726                err.log_with_imp(imp);
727                false
728            }
729        }
730    })
731    .into_glib()
732}
733
734unsafe extern "C" fn video_decoder_getcaps<T: VideoDecoderImpl>(
735    ptr: *mut ffi::GstVideoDecoder,
736    filter: *mut gst::ffi::GstCaps,
737) -> *mut gst::ffi::GstCaps {
738    let instance = &*(ptr as *mut T::Instance);
739    let imp = instance.imp();
740
741    gst::panic_to_error!(imp, gst::Caps::new_empty(), {
742        VideoDecoderImpl::caps(
743            imp,
744            Option::<gst::Caps>::from_glib_borrow(filter)
745                .as_ref()
746                .as_ref(),
747        )
748    })
749    .into_glib_ptr()
750}
751
752unsafe extern "C" fn video_decoder_sink_event<T: VideoDecoderImpl>(
753    ptr: *mut ffi::GstVideoDecoder,
754    event: *mut gst::ffi::GstEvent,
755) -> glib::ffi::gboolean {
756    let instance = &*(ptr as *mut T::Instance);
757    let imp = instance.imp();
758
759    gst::panic_to_error!(imp, false, { imp.sink_event(from_glib_full(event)) }).into_glib()
760}
761
762unsafe extern "C" fn video_decoder_sink_query<T: VideoDecoderImpl>(
763    ptr: *mut ffi::GstVideoDecoder,
764    query: *mut gst::ffi::GstQuery,
765) -> glib::ffi::gboolean {
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
775unsafe extern "C" fn video_decoder_src_event<T: VideoDecoderImpl>(
776    ptr: *mut ffi::GstVideoDecoder,
777    event: *mut gst::ffi::GstEvent,
778) -> glib::ffi::gboolean {
779    let instance = &*(ptr as *mut T::Instance);
780    let imp = instance.imp();
781
782    gst::panic_to_error!(imp, false, { imp.src_event(from_glib_full(event)) }).into_glib()
783}
784
785unsafe extern "C" fn video_decoder_src_query<T: VideoDecoderImpl>(
786    ptr: *mut ffi::GstVideoDecoder,
787    query: *mut gst::ffi::GstQuery,
788) -> glib::ffi::gboolean {
789    let instance = &*(ptr as *mut T::Instance);
790    let imp = instance.imp();
791
792    gst::panic_to_error!(imp, false, {
793        imp.src_query(gst::QueryRef::from_mut_ptr(query))
794    })
795    .into_glib()
796}
797
798unsafe extern "C" fn video_decoder_propose_allocation<T: VideoDecoderImpl>(
799    ptr: *mut ffi::GstVideoDecoder,
800    query: *mut gst::ffi::GstQuery,
801) -> glib::ffi::gboolean {
802    let instance = &*(ptr as *mut T::Instance);
803    let imp = instance.imp();
804    let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
805        gst::QueryViewMut::Allocation(allocation) => allocation,
806        _ => unreachable!(),
807    };
808
809    gst::panic_to_error!(imp, false, {
810        match imp.propose_allocation(query) {
811            Ok(()) => true,
812            Err(err) => {
813                err.log_with_imp(imp);
814                false
815            }
816        }
817    })
818    .into_glib()
819}
820
821unsafe extern "C" fn video_decoder_decide_allocation<T: VideoDecoderImpl>(
822    ptr: *mut ffi::GstVideoDecoder,
823    query: *mut gst::ffi::GstQuery,
824) -> glib::ffi::gboolean {
825    let instance = &*(ptr as *mut T::Instance);
826    let imp = instance.imp();
827    let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
828        gst::QueryViewMut::Allocation(allocation) => allocation,
829        _ => unreachable!(),
830    };
831
832    gst::panic_to_error!(imp, false, {
833        match imp.decide_allocation(query) {
834            Ok(()) => true,
835            Err(err) => {
836                err.log_with_imp(imp);
837                false
838            }
839        }
840    })
841    .into_glib()
842}
843
844#[cfg(feature = "v1_20")]
845unsafe extern "C" fn video_decoder_handle_missing_data<T: VideoDecoderImpl>(
846    ptr: *mut ffi::GstVideoDecoder,
847    timestamp: gst::ffi::GstClockTime,
848    duration: gst::ffi::GstClockTime,
849) -> glib::ffi::gboolean {
850    let instance = &*(ptr as *mut T::Instance);
851    let imp = instance.imp();
852
853    gst::panic_to_error!(imp, true, {
854        imp.handle_missing_data(
855            Option::<gst::ClockTime>::from_glib(timestamp).unwrap(),
856            from_glib(duration),
857        )
858    })
859    .into_glib()
860}