Skip to main content

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