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    /// 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 at EOS. Sub-classes can refuse to decode new data after.
44    fn finish(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
45        self.parent_finish()
46    }
47
48    /// Optional.
49    ///  Called to request subclass to decode any data it can at this
50    ///  point, but that more data may arrive after. (e.g. at segment end).
51    ///  Sub-classes should be prepared to handle new data afterward,
52    ///  or seamless segment processing will break. Since: 1.6
53    fn drain(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
54        self.parent_drain()
55    }
56
57    /// Notifies subclass of incoming data format (caps).
58    fn set_format(
59        &self,
60        state: &VideoCodecState<'static, Readable>,
61    ) -> Result<(), gst::LoggableError> {
62        self.parent_set_format(state)
63    }
64
65    /// Required for non-packetized input.
66    ///  Allows chopping incoming data into manageable units (frames)
67    ///  for subsequent decoding.
68    fn parse(
69        &self,
70        frame: &VideoCodecFrame,
71        adapter: &gst_base::Adapter,
72        at_eos: bool,
73    ) -> Result<gst::FlowSuccess, gst::FlowError> {
74        self.parent_parse(frame, adapter, at_eos)
75    }
76
77    /// ## `frame`
78    /// The frame to handle
79    fn handle_frame(&self, frame: VideoCodecFrame) -> Result<gst::FlowSuccess, gst::FlowError> {
80        self.parent_handle_frame(frame)
81    }
82
83    /// Optional.
84    ///  Flush all remaining data from the decoder without
85    ///  pushing it downstream. Since: 1.2
86    fn flush(&self) -> bool {
87        self.parent_flush()
88    }
89
90    /// Negotiate with downstream elements to currently configured [`VideoCodecState`][crate::VideoCodecState].
91    /// Unmark GST_PAD_FLAG_NEED_RECONFIGURE in any case. But mark it again if
92    /// negotiate fails.
93    ///
94    /// # Returns
95    ///
96    /// [`true`] if the negotiation succeeded, else [`false`].
97    fn negotiate(&self) -> Result<(), gst::LoggableError> {
98        self.parent_negotiate()
99    }
100
101    fn caps(&self, filter: Option<&gst::Caps>) -> gst::Caps {
102        self.parent_caps(filter)
103    }
104
105    /// Optional.
106    ///  Event handler on the sink 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 sink_event(&self, event: gst::Event) -> bool {
112        self.parent_sink_event(event)
113    }
114
115    /// Optional.
116    ///  Query handler on the sink 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 sink_query(&self, query: &mut gst::QueryRef) -> bool {
121        self.parent_sink_query(query)
122    }
123
124    /// Optional.
125    ///  Event handler on the source pad. This function should return
126    ///  TRUE if the event was handled and should be discarded
127    ///  (i.e. not unref'ed).
128    ///  Subclasses should chain up to the parent implementation to
129    ///  invoke the default handler.
130    fn src_event(&self, event: gst::Event) -> bool {
131        self.parent_src_event(event)
132    }
133
134    /// Optional.
135    ///  Query handler on the source pad. This function should
136    ///  return TRUE if the query could be performed. Subclasses
137    ///  should chain up to the parent implementation to invoke the
138    ///  default handler. Since: 1.4
139    fn src_query(&self, query: &mut gst::QueryRef) -> bool {
140        self.parent_src_query(query)
141    }
142
143    /// Optional.
144    ///  Propose buffer allocation parameters for upstream elements.
145    ///  Subclasses should chain up to the parent implementation to
146    ///  invoke the default handler.
147    fn propose_allocation(
148        &self,
149        query: &mut gst::query::Allocation,
150    ) -> Result<(), gst::LoggableError> {
151        self.parent_propose_allocation(query)
152    }
153
154    /// Optional.
155    ///  Setup the allocation parameters for allocating output
156    ///  buffers. The passed in query contains the result of the
157    ///  downstream allocation query.
158    ///  Subclasses should chain up to the parent implementation to
159    ///  invoke the default handler.
160    fn decide_allocation(
161        &self,
162        query: &mut gst::query::Allocation,
163    ) -> Result<(), gst::LoggableError> {
164        self.parent_decide_allocation(query)
165    }
166
167    /// ## `timestamp`
168    /// Timestamp of the missing data
169    /// ## `duration`
170    /// Duration of the missing data
171    ///
172    /// # Returns
173    ///
174    /// [`true`] if the decoder should be drained afterwards.
175    #[cfg(feature = "v1_20")]
176    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
177    fn handle_missing_data(
178        &self,
179        timestamp: gst::ClockTime,
180        duration: Option<gst::ClockTime>,
181    ) -> bool {
182        self.parent_handle_missing_data(timestamp, duration)
183    }
184}
185
186pub trait VideoDecoderImplExt: VideoDecoderImpl {
187    fn parent_open(&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                .open
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 `open` failed"]
205                        ))
206                    }
207                })
208                .unwrap_or(Ok(()))
209        }
210    }
211
212    fn parent_close(&self) -> Result<(), gst::ErrorMessage> {
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                .close
218                .map(|f| {
219                    if from_glib(f(self
220                        .obj()
221                        .unsafe_cast_ref::<VideoDecoder>()
222                        .to_glib_none()
223                        .0))
224                    {
225                        Ok(())
226                    } else {
227                        Err(gst::error_msg!(
228                            gst::CoreError::StateChange,
229                            ["Parent function `close` failed"]
230                        ))
231                    }
232                })
233                .unwrap_or(Ok(()))
234        }
235    }
236
237    fn parent_start(&self) -> Result<(), gst::ErrorMessage> {
238        unsafe {
239            let data = Self::type_data();
240            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
241            (*parent_class)
242                .start
243                .map(|f| {
244                    if from_glib(f(self
245                        .obj()
246                        .unsafe_cast_ref::<VideoDecoder>()
247                        .to_glib_none()
248                        .0))
249                    {
250                        Ok(())
251                    } else {
252                        Err(gst::error_msg!(
253                            gst::CoreError::StateChange,
254                            ["Parent function `start` failed"]
255                        ))
256                    }
257                })
258                .unwrap_or(Ok(()))
259        }
260    }
261
262    fn parent_stop(&self) -> Result<(), gst::ErrorMessage> {
263        unsafe {
264            let data = Self::type_data();
265            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
266            (*parent_class)
267                .stop
268                .map(|f| {
269                    if from_glib(f(self
270                        .obj()
271                        .unsafe_cast_ref::<VideoDecoder>()
272                        .to_glib_none()
273                        .0))
274                    {
275                        Ok(())
276                    } else {
277                        Err(gst::error_msg!(
278                            gst::CoreError::StateChange,
279                            ["Parent function `stop` failed"]
280                        ))
281                    }
282                })
283                .unwrap_or(Ok(()))
284        }
285    }
286
287    fn parent_finish(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
288        unsafe {
289            let data = Self::type_data();
290            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
291            (*parent_class)
292                .finish
293                .map(|f| {
294                    try_from_glib(f(self
295                        .obj()
296                        .unsafe_cast_ref::<VideoDecoder>()
297                        .to_glib_none()
298                        .0))
299                })
300                .unwrap_or(Ok(gst::FlowSuccess::Ok))
301        }
302    }
303
304    fn parent_drain(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
305        unsafe {
306            let data = Self::type_data();
307            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
308            (*parent_class)
309                .drain
310                .map(|f| {
311                    try_from_glib(f(self
312                        .obj()
313                        .unsafe_cast_ref::<VideoDecoder>()
314                        .to_glib_none()
315                        .0))
316                })
317                .unwrap_or(Ok(gst::FlowSuccess::Ok))
318        }
319    }
320
321    fn parent_set_format(
322        &self,
323        state: &VideoCodecState<'static, Readable>,
324    ) -> Result<(), gst::LoggableError> {
325        unsafe {
326            let data = Self::type_data();
327            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
328            (*parent_class)
329                .set_format
330                .map(|f| {
331                    gst::result_from_gboolean!(
332                        f(
333                            self.obj()
334                                .unsafe_cast_ref::<VideoDecoder>()
335                                .to_glib_none()
336                                .0,
337                            state.as_mut_ptr()
338                        ),
339                        gst::CAT_RUST,
340                        "parent function `set_format` failed"
341                    )
342                })
343                .unwrap_or(Ok(()))
344        }
345    }
346
347    fn parent_parse(
348        &self,
349        frame: &VideoCodecFrame,
350        adapter: &gst_base::Adapter,
351        at_eos: bool,
352    ) -> Result<gst::FlowSuccess, gst::FlowError> {
353        unsafe {
354            let data = Self::type_data();
355            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
356            (*parent_class)
357                .parse
358                .map(|f| {
359                    try_from_glib(f(
360                        self.obj()
361                            .unsafe_cast_ref::<VideoDecoder>()
362                            .to_glib_none()
363                            .0,
364                        frame.to_glib_none().0,
365                        adapter.to_glib_none().0,
366                        at_eos.into_glib(),
367                    ))
368                })
369                .unwrap_or(Ok(gst::FlowSuccess::Ok))
370        }
371    }
372
373    fn parent_handle_frame(
374        &self,
375        frame: VideoCodecFrame,
376    ) -> Result<gst::FlowSuccess, gst::FlowError> {
377        unsafe {
378            let data = Self::type_data();
379            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
380            (*parent_class)
381                .handle_frame
382                .map(|f| {
383                    try_from_glib(f(
384                        self.obj()
385                            .unsafe_cast_ref::<VideoDecoder>()
386                            .to_glib_none()
387                            .0,
388                        frame.to_glib_none().0,
389                    ))
390                })
391                .unwrap_or(Err(gst::FlowError::Error))
392        }
393    }
394
395    fn parent_flush(&self) -> bool {
396        unsafe {
397            let data = Self::type_data();
398            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
399            (*parent_class)
400                .flush
401                .map(|f| {
402                    from_glib(f(self
403                        .obj()
404                        .unsafe_cast_ref::<VideoDecoder>()
405                        .to_glib_none()
406                        .0))
407                })
408                .unwrap_or(false)
409        }
410    }
411
412    fn parent_negotiate(&self) -> Result<(), gst::LoggableError> {
413        unsafe {
414            let data = Self::type_data();
415            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
416            (*parent_class)
417                .negotiate
418                .map(|f| {
419                    gst::result_from_gboolean!(
420                        f(self
421                            .obj()
422                            .unsafe_cast_ref::<VideoDecoder>()
423                            .to_glib_none()
424                            .0),
425                        gst::CAT_RUST,
426                        "Parent function `negotiate` failed"
427                    )
428                })
429                .unwrap_or(Ok(()))
430        }
431    }
432
433    fn parent_caps(&self, filter: Option<&gst::Caps>) -> gst::Caps {
434        unsafe {
435            let data = Self::type_data();
436            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
437            (*parent_class)
438                .getcaps
439                .map(|f| {
440                    from_glib_full(f(
441                        self.obj()
442                            .unsafe_cast_ref::<VideoDecoder>()
443                            .to_glib_none()
444                            .0,
445                        filter.to_glib_none().0,
446                    ))
447                })
448                .unwrap_or_else(|| {
449                    self.obj()
450                        .unsafe_cast_ref::<VideoDecoder>()
451                        .proxy_getcaps(None, filter)
452                })
453        }
454    }
455
456    fn parent_sink_event(&self, event: gst::Event) -> bool {
457        unsafe {
458            let data = Self::type_data();
459            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
460            let f = (*parent_class)
461                .sink_event
462                .expect("Missing parent function `sink_event`");
463            from_glib(f(
464                self.obj()
465                    .unsafe_cast_ref::<VideoDecoder>()
466                    .to_glib_none()
467                    .0,
468                event.into_glib_ptr(),
469            ))
470        }
471    }
472
473    fn parent_sink_query(&self, query: &mut gst::QueryRef) -> bool {
474        unsafe {
475            let data = Self::type_data();
476            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
477            let f = (*parent_class)
478                .sink_query
479                .expect("Missing parent function `sink_query`");
480            from_glib(f(
481                self.obj()
482                    .unsafe_cast_ref::<VideoDecoder>()
483                    .to_glib_none()
484                    .0,
485                query.as_mut_ptr(),
486            ))
487        }
488    }
489
490    fn parent_src_event(&self, event: gst::Event) -> bool {
491        unsafe {
492            let data = Self::type_data();
493            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
494            let f = (*parent_class)
495                .src_event
496                .expect("Missing parent function `src_event`");
497            from_glib(f(
498                self.obj()
499                    .unsafe_cast_ref::<VideoDecoder>()
500                    .to_glib_none()
501                    .0,
502                event.into_glib_ptr(),
503            ))
504        }
505    }
506
507    fn parent_src_query(&self, query: &mut gst::QueryRef) -> bool {
508        unsafe {
509            let data = Self::type_data();
510            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
511            let f = (*parent_class)
512                .src_query
513                .expect("Missing parent function `src_query`");
514            from_glib(f(
515                self.obj()
516                    .unsafe_cast_ref::<VideoDecoder>()
517                    .to_glib_none()
518                    .0,
519                query.as_mut_ptr(),
520            ))
521        }
522    }
523
524    fn parent_propose_allocation(
525        &self,
526        query: &mut gst::query::Allocation,
527    ) -> Result<(), gst::LoggableError> {
528        unsafe {
529            let data = Self::type_data();
530            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
531            (*parent_class)
532                .propose_allocation
533                .map(|f| {
534                    gst::result_from_gboolean!(
535                        f(
536                            self.obj()
537                                .unsafe_cast_ref::<VideoDecoder>()
538                                .to_glib_none()
539                                .0,
540                            query.as_mut_ptr(),
541                        ),
542                        gst::CAT_RUST,
543                        "Parent function `propose_allocation` failed",
544                    )
545                })
546                .unwrap_or(Ok(()))
547        }
548    }
549
550    fn parent_decide_allocation(
551        &self,
552        query: &mut gst::query::Allocation,
553    ) -> Result<(), gst::LoggableError> {
554        unsafe {
555            let data = Self::type_data();
556            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
557            (*parent_class)
558                .decide_allocation
559                .map(|f| {
560                    gst::result_from_gboolean!(
561                        f(
562                            self.obj()
563                                .unsafe_cast_ref::<VideoDecoder>()
564                                .to_glib_none()
565                                .0,
566                            query.as_mut_ptr(),
567                        ),
568                        gst::CAT_RUST,
569                        "Parent function `decide_allocation` failed",
570                    )
571                })
572                .unwrap_or(Ok(()))
573        }
574    }
575
576    #[cfg(feature = "v1_20")]
577    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
578    fn parent_handle_missing_data(
579        &self,
580        timestamp: gst::ClockTime,
581        duration: Option<gst::ClockTime>,
582    ) -> bool {
583        unsafe {
584            let data = Self::type_data();
585            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
586            (*parent_class)
587                .handle_missing_data
588                .map(|f| {
589                    from_glib(f(
590                        self.obj()
591                            .unsafe_cast_ref::<VideoDecoder>()
592                            .to_glib_none()
593                            .0,
594                        timestamp.into_glib(),
595                        duration.into_glib(),
596                    ))
597                })
598                .unwrap_or(true)
599        }
600    }
601}
602
603impl<T: VideoDecoderImpl> VideoDecoderImplExt for T {}
604
605unsafe impl<T: VideoDecoderImpl> IsSubclassable<T> for VideoDecoder {
606    fn class_init(klass: &mut glib::Class<Self>) {
607        Self::parent_class_init::<T>(klass);
608        let klass = klass.as_mut();
609        klass.open = Some(video_decoder_open::<T>);
610        klass.close = Some(video_decoder_close::<T>);
611        klass.start = Some(video_decoder_start::<T>);
612        klass.stop = Some(video_decoder_stop::<T>);
613        klass.finish = Some(video_decoder_finish::<T>);
614        klass.drain = Some(video_decoder_drain::<T>);
615        klass.set_format = Some(video_decoder_set_format::<T>);
616        klass.parse = Some(video_decoder_parse::<T>);
617        klass.handle_frame = Some(video_decoder_handle_frame::<T>);
618        klass.flush = Some(video_decoder_flush::<T>);
619        klass.negotiate = Some(video_decoder_negotiate::<T>);
620        klass.getcaps = Some(video_decoder_getcaps::<T>);
621        klass.sink_event = Some(video_decoder_sink_event::<T>);
622        klass.src_event = Some(video_decoder_src_event::<T>);
623        klass.sink_query = Some(video_decoder_sink_query::<T>);
624        klass.src_query = Some(video_decoder_src_query::<T>);
625        klass.propose_allocation = Some(video_decoder_propose_allocation::<T>);
626        klass.decide_allocation = Some(video_decoder_decide_allocation::<T>);
627        #[cfg(feature = "v1_20")]
628        {
629            klass.handle_missing_data = Some(video_decoder_handle_missing_data::<T>);
630        }
631    }
632}
633
634unsafe extern "C" fn video_decoder_open<T: VideoDecoderImpl>(
635    ptr: *mut ffi::GstVideoDecoder,
636) -> glib::ffi::gboolean {
637    unsafe {
638        let instance = &*(ptr as *mut T::Instance);
639        let imp = instance.imp();
640
641        gst::element_panic_to_error!(imp, false, {
642            match imp.open() {
643                Ok(()) => true,
644                Err(err) => {
645                    imp.post_error_message(err);
646                    false
647                }
648            }
649        })
650        .into_glib()
651    }
652}
653
654unsafe extern "C" fn video_decoder_close<T: VideoDecoderImpl>(
655    ptr: *mut ffi::GstVideoDecoder,
656) -> glib::ffi::gboolean {
657    unsafe {
658        let instance = &*(ptr as *mut T::Instance);
659        let imp = instance.imp();
660
661        gst::element_panic_to_error!(imp, false, {
662            match imp.close() {
663                Ok(()) => true,
664                Err(err) => {
665                    imp.post_error_message(err);
666                    false
667                }
668            }
669        })
670        .into_glib()
671    }
672}
673
674unsafe extern "C" fn video_decoder_start<T: VideoDecoderImpl>(
675    ptr: *mut ffi::GstVideoDecoder,
676) -> glib::ffi::gboolean {
677    unsafe {
678        let instance = &*(ptr as *mut T::Instance);
679        let imp = instance.imp();
680
681        gst::element_panic_to_error!(imp, false, {
682            match imp.start() {
683                Ok(()) => true,
684                Err(err) => {
685                    imp.post_error_message(err);
686                    false
687                }
688            }
689        })
690        .into_glib()
691    }
692}
693
694unsafe extern "C" fn video_decoder_stop<T: VideoDecoderImpl>(
695    ptr: *mut ffi::GstVideoDecoder,
696) -> glib::ffi::gboolean {
697    unsafe {
698        let instance = &*(ptr as *mut T::Instance);
699        let imp = instance.imp();
700
701        gst::element_panic_to_error!(imp, false, {
702            match imp.stop() {
703                Ok(()) => true,
704                Err(err) => {
705                    imp.post_error_message(err);
706                    false
707                }
708            }
709        })
710        .into_glib()
711    }
712}
713
714unsafe extern "C" fn video_decoder_finish<T: VideoDecoderImpl>(
715    ptr: *mut ffi::GstVideoDecoder,
716) -> gst::ffi::GstFlowReturn {
717    unsafe {
718        let instance = &*(ptr as *mut T::Instance);
719        let imp = instance.imp();
720
721        gst::element_panic_to_error!(imp, gst::FlowReturn::Error, { imp.finish().into() })
722            .into_glib()
723    }
724}
725
726unsafe extern "C" fn video_decoder_drain<T: VideoDecoderImpl>(
727    ptr: *mut ffi::GstVideoDecoder,
728) -> gst::ffi::GstFlowReturn {
729    unsafe {
730        let instance = &*(ptr as *mut T::Instance);
731        let imp = instance.imp();
732
733        gst::element_panic_to_error!(imp, gst::FlowReturn::Error, { imp.drain().into() })
734            .into_glib()
735    }
736}
737
738unsafe extern "C" fn video_decoder_set_format<T: VideoDecoderImpl>(
739    ptr: *mut ffi::GstVideoDecoder,
740    state: *mut ffi::GstVideoCodecState,
741) -> glib::ffi::gboolean {
742    unsafe {
743        let instance = &*(ptr as *mut T::Instance);
744        let imp = instance.imp();
745        ffi::gst_video_codec_state_ref(state);
746        let wrap_state = VideoCodecState::<Readable>::new(state);
747
748        gst::element_panic_to_error!(imp, false, {
749            match imp.set_format(&wrap_state) {
750                Ok(()) => true,
751                Err(err) => {
752                    err.log_with_imp(imp);
753                    false
754                }
755            }
756        })
757        .into_glib()
758    }
759}
760
761unsafe extern "C" fn video_decoder_parse<T: VideoDecoderImpl>(
762    ptr: *mut ffi::GstVideoDecoder,
763    frame: *mut ffi::GstVideoCodecFrame,
764    adapter: *mut gst_base::ffi::GstAdapter,
765    at_eos: glib::ffi::gboolean,
766) -> gst::ffi::GstFlowReturn {
767    unsafe {
768        let instance = &*(ptr as *mut T::Instance);
769        let imp = instance.imp();
770        ffi::gst_video_codec_frame_ref(frame);
771        let instance = imp.obj();
772        let instance = instance.unsafe_cast_ref::<VideoDecoder>();
773        let wrap_frame = VideoCodecFrame::new(frame, instance);
774        let wrap_adapter: Borrowed<gst_base::Adapter> = from_glib_borrow(adapter);
775        let at_eos: bool = from_glib(at_eos);
776
777        gst::element_panic_to_error!(imp, gst::FlowReturn::Error, {
778            imp.parse(&wrap_frame, &wrap_adapter, at_eos).into()
779        })
780        .into_glib()
781    }
782}
783
784unsafe extern "C" fn video_decoder_handle_frame<T: VideoDecoderImpl>(
785    ptr: *mut ffi::GstVideoDecoder,
786    frame: *mut ffi::GstVideoCodecFrame,
787) -> gst::ffi::GstFlowReturn {
788    unsafe {
789        let instance = &*(ptr as *mut T::Instance);
790        let imp = instance.imp();
791        let instance = imp.obj();
792        let instance = instance.unsafe_cast_ref::<VideoDecoder>();
793        let wrap_frame = VideoCodecFrame::new(frame, instance);
794
795        gst::element_panic_to_error!(imp, gst::FlowReturn::Error, {
796            imp.handle_frame(wrap_frame).into()
797        })
798        .into_glib()
799    }
800}
801
802unsafe extern "C" fn video_decoder_flush<T: VideoDecoderImpl>(
803    ptr: *mut ffi::GstVideoDecoder,
804) -> glib::ffi::gboolean {
805    unsafe {
806        let instance = &*(ptr as *mut T::Instance);
807        let imp = instance.imp();
808
809        gst::element_panic_to_error!(imp, false, { VideoDecoderImpl::flush(imp) }).into_glib()
810    }
811}
812
813unsafe extern "C" fn video_decoder_negotiate<T: VideoDecoderImpl>(
814    ptr: *mut ffi::GstVideoDecoder,
815) -> glib::ffi::gboolean {
816    unsafe {
817        let instance = &*(ptr as *mut T::Instance);
818        let imp = instance.imp();
819
820        gst::element_panic_to_error!(imp, false, {
821            match imp.negotiate() {
822                Ok(()) => true,
823                Err(err) => {
824                    err.log_with_imp(imp);
825                    false
826                }
827            }
828        })
829        .into_glib()
830    }
831}
832
833unsafe extern "C" fn video_decoder_getcaps<T: VideoDecoderImpl>(
834    ptr: *mut ffi::GstVideoDecoder,
835    filter: *mut gst::ffi::GstCaps,
836) -> *mut gst::ffi::GstCaps {
837    unsafe {
838        let instance = &*(ptr as *mut T::Instance);
839        let imp = instance.imp();
840
841        gst::element_panic_to_error!(imp, gst::Caps::new_empty(), {
842            VideoDecoderImpl::caps(
843                imp,
844                Option::<gst::Caps>::from_glib_borrow(filter)
845                    .as_ref()
846                    .as_ref(),
847            )
848        })
849        .into_glib_ptr()
850    }
851}
852
853unsafe extern "C" fn video_decoder_sink_event<T: VideoDecoderImpl>(
854    ptr: *mut ffi::GstVideoDecoder,
855    event: *mut gst::ffi::GstEvent,
856) -> glib::ffi::gboolean {
857    unsafe {
858        let instance = &*(ptr as *mut T::Instance);
859        let imp = instance.imp();
860
861        gst::element_panic_to_error!(imp, false, { imp.sink_event(from_glib_full(event)) })
862            .into_glib()
863    }
864}
865
866unsafe extern "C" fn video_decoder_sink_query<T: VideoDecoderImpl>(
867    ptr: *mut ffi::GstVideoDecoder,
868    query: *mut gst::ffi::GstQuery,
869) -> glib::ffi::gboolean {
870    unsafe {
871        let instance = &*(ptr as *mut T::Instance);
872        let imp = instance.imp();
873
874        gst::element_panic_to_error!(imp, false, {
875            imp.sink_query(gst::QueryRef::from_mut_ptr(query))
876        })
877        .into_glib()
878    }
879}
880
881unsafe extern "C" fn video_decoder_src_event<T: VideoDecoderImpl>(
882    ptr: *mut ffi::GstVideoDecoder,
883    event: *mut gst::ffi::GstEvent,
884) -> glib::ffi::gboolean {
885    unsafe {
886        let instance = &*(ptr as *mut T::Instance);
887        let imp = instance.imp();
888
889        gst::element_panic_to_error!(imp, false, { imp.src_event(from_glib_full(event)) })
890            .into_glib()
891    }
892}
893
894unsafe extern "C" fn video_decoder_src_query<T: VideoDecoderImpl>(
895    ptr: *mut ffi::GstVideoDecoder,
896    query: *mut gst::ffi::GstQuery,
897) -> glib::ffi::gboolean {
898    unsafe {
899        let instance = &*(ptr as *mut T::Instance);
900        let imp = instance.imp();
901
902        gst::element_panic_to_error!(imp, false, {
903            imp.src_query(gst::QueryRef::from_mut_ptr(query))
904        })
905        .into_glib()
906    }
907}
908
909unsafe extern "C" fn video_decoder_propose_allocation<T: VideoDecoderImpl>(
910    ptr: *mut ffi::GstVideoDecoder,
911    query: *mut gst::ffi::GstQuery,
912) -> glib::ffi::gboolean {
913    unsafe {
914        let instance = &*(ptr as *mut T::Instance);
915        let imp = instance.imp();
916        let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
917            gst::QueryViewMut::Allocation(allocation) => allocation,
918            _ => unreachable!(),
919        };
920
921        gst::element_panic_to_error!(imp, false, {
922            match imp.propose_allocation(query) {
923                Ok(()) => true,
924                Err(err) => {
925                    err.log_with_imp(imp);
926                    false
927                }
928            }
929        })
930        .into_glib()
931    }
932}
933
934unsafe extern "C" fn video_decoder_decide_allocation<T: VideoDecoderImpl>(
935    ptr: *mut ffi::GstVideoDecoder,
936    query: *mut gst::ffi::GstQuery,
937) -> glib::ffi::gboolean {
938    unsafe {
939        let instance = &*(ptr as *mut T::Instance);
940        let imp = instance.imp();
941        let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
942            gst::QueryViewMut::Allocation(allocation) => allocation,
943            _ => unreachable!(),
944        };
945
946        gst::element_panic_to_error!(imp, false, {
947            match imp.decide_allocation(query) {
948                Ok(()) => true,
949                Err(err) => {
950                    err.log_with_imp(imp);
951                    false
952                }
953            }
954        })
955        .into_glib()
956    }
957}
958
959#[cfg(feature = "v1_20")]
960unsafe extern "C" fn video_decoder_handle_missing_data<T: VideoDecoderImpl>(
961    ptr: *mut ffi::GstVideoDecoder,
962    timestamp: gst::ffi::GstClockTime,
963    duration: gst::ffi::GstClockTime,
964) -> glib::ffi::gboolean {
965    unsafe {
966        let instance = &*(ptr as *mut T::Instance);
967        let imp = instance.imp();
968
969        gst::element_panic_to_error!(imp, true, {
970            imp.handle_missing_data(
971                Option::<gst::ClockTime>::from_glib(timestamp).unwrap(),
972                from_glib(duration),
973            )
974        })
975        .into_glib()
976    }
977}