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::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::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::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::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::panic_to_error!(imp, gst::FlowReturn::Error, { imp.finish().into() }).into_glib()
722    }
723}
724
725unsafe extern "C" fn video_decoder_drain<T: VideoDecoderImpl>(
726    ptr: *mut ffi::GstVideoDecoder,
727) -> gst::ffi::GstFlowReturn {
728    unsafe {
729        let instance = &*(ptr as *mut T::Instance);
730        let imp = instance.imp();
731
732        gst::panic_to_error!(imp, gst::FlowReturn::Error, { imp.drain().into() }).into_glib()
733    }
734}
735
736unsafe extern "C" fn video_decoder_set_format<T: VideoDecoderImpl>(
737    ptr: *mut ffi::GstVideoDecoder,
738    state: *mut ffi::GstVideoCodecState,
739) -> glib::ffi::gboolean {
740    unsafe {
741        let instance = &*(ptr as *mut T::Instance);
742        let imp = instance.imp();
743        ffi::gst_video_codec_state_ref(state);
744        let wrap_state = VideoCodecState::<Readable>::new(state);
745
746        gst::panic_to_error!(imp, false, {
747            match imp.set_format(&wrap_state) {
748                Ok(()) => true,
749                Err(err) => {
750                    err.log_with_imp(imp);
751                    false
752                }
753            }
754        })
755        .into_glib()
756    }
757}
758
759unsafe extern "C" fn video_decoder_parse<T: VideoDecoderImpl>(
760    ptr: *mut ffi::GstVideoDecoder,
761    frame: *mut ffi::GstVideoCodecFrame,
762    adapter: *mut gst_base::ffi::GstAdapter,
763    at_eos: glib::ffi::gboolean,
764) -> gst::ffi::GstFlowReturn {
765    unsafe {
766        let instance = &*(ptr as *mut T::Instance);
767        let imp = instance.imp();
768        ffi::gst_video_codec_frame_ref(frame);
769        let instance = imp.obj();
770        let instance = instance.unsafe_cast_ref::<VideoDecoder>();
771        let wrap_frame = VideoCodecFrame::new(frame, instance);
772        let wrap_adapter: Borrowed<gst_base::Adapter> = from_glib_borrow(adapter);
773        let at_eos: bool = from_glib(at_eos);
774
775        gst::panic_to_error!(imp, gst::FlowReturn::Error, {
776            imp.parse(&wrap_frame, &wrap_adapter, at_eos).into()
777        })
778        .into_glib()
779    }
780}
781
782unsafe extern "C" fn video_decoder_handle_frame<T: VideoDecoderImpl>(
783    ptr: *mut ffi::GstVideoDecoder,
784    frame: *mut ffi::GstVideoCodecFrame,
785) -> gst::ffi::GstFlowReturn {
786    unsafe {
787        let instance = &*(ptr as *mut T::Instance);
788        let imp = instance.imp();
789        let instance = imp.obj();
790        let instance = instance.unsafe_cast_ref::<VideoDecoder>();
791        let wrap_frame = VideoCodecFrame::new(frame, instance);
792
793        gst::panic_to_error!(imp, gst::FlowReturn::Error, {
794            imp.handle_frame(wrap_frame).into()
795        })
796        .into_glib()
797    }
798}
799
800unsafe extern "C" fn video_decoder_flush<T: VideoDecoderImpl>(
801    ptr: *mut ffi::GstVideoDecoder,
802) -> glib::ffi::gboolean {
803    unsafe {
804        let instance = &*(ptr as *mut T::Instance);
805        let imp = instance.imp();
806
807        gst::panic_to_error!(imp, false, { VideoDecoderImpl::flush(imp) }).into_glib()
808    }
809}
810
811unsafe extern "C" fn video_decoder_negotiate<T: VideoDecoderImpl>(
812    ptr: *mut ffi::GstVideoDecoder,
813) -> glib::ffi::gboolean {
814    unsafe {
815        let instance = &*(ptr as *mut T::Instance);
816        let imp = instance.imp();
817
818        gst::panic_to_error!(imp, false, {
819            match imp.negotiate() {
820                Ok(()) => true,
821                Err(err) => {
822                    err.log_with_imp(imp);
823                    false
824                }
825            }
826        })
827        .into_glib()
828    }
829}
830
831unsafe extern "C" fn video_decoder_getcaps<T: VideoDecoderImpl>(
832    ptr: *mut ffi::GstVideoDecoder,
833    filter: *mut gst::ffi::GstCaps,
834) -> *mut gst::ffi::GstCaps {
835    unsafe {
836        let instance = &*(ptr as *mut T::Instance);
837        let imp = instance.imp();
838
839        gst::panic_to_error!(imp, gst::Caps::new_empty(), {
840            VideoDecoderImpl::caps(
841                imp,
842                Option::<gst::Caps>::from_glib_borrow(filter)
843                    .as_ref()
844                    .as_ref(),
845            )
846        })
847        .into_glib_ptr()
848    }
849}
850
851unsafe extern "C" fn video_decoder_sink_event<T: VideoDecoderImpl>(
852    ptr: *mut ffi::GstVideoDecoder,
853    event: *mut gst::ffi::GstEvent,
854) -> glib::ffi::gboolean {
855    unsafe {
856        let instance = &*(ptr as *mut T::Instance);
857        let imp = instance.imp();
858
859        gst::panic_to_error!(imp, false, { imp.sink_event(from_glib_full(event)) }).into_glib()
860    }
861}
862
863unsafe extern "C" fn video_decoder_sink_query<T: VideoDecoderImpl>(
864    ptr: *mut ffi::GstVideoDecoder,
865    query: *mut gst::ffi::GstQuery,
866) -> glib::ffi::gboolean {
867    unsafe {
868        let instance = &*(ptr as *mut T::Instance);
869        let imp = instance.imp();
870
871        gst::panic_to_error!(imp, false, {
872            imp.sink_query(gst::QueryRef::from_mut_ptr(query))
873        })
874        .into_glib()
875    }
876}
877
878unsafe extern "C" fn video_decoder_src_event<T: VideoDecoderImpl>(
879    ptr: *mut ffi::GstVideoDecoder,
880    event: *mut gst::ffi::GstEvent,
881) -> glib::ffi::gboolean {
882    unsafe {
883        let instance = &*(ptr as *mut T::Instance);
884        let imp = instance.imp();
885
886        gst::panic_to_error!(imp, false, { imp.src_event(from_glib_full(event)) }).into_glib()
887    }
888}
889
890unsafe extern "C" fn video_decoder_src_query<T: VideoDecoderImpl>(
891    ptr: *mut ffi::GstVideoDecoder,
892    query: *mut gst::ffi::GstQuery,
893) -> glib::ffi::gboolean {
894    unsafe {
895        let instance = &*(ptr as *mut T::Instance);
896        let imp = instance.imp();
897
898        gst::panic_to_error!(imp, false, {
899            imp.src_query(gst::QueryRef::from_mut_ptr(query))
900        })
901        .into_glib()
902    }
903}
904
905unsafe extern "C" fn video_decoder_propose_allocation<T: VideoDecoderImpl>(
906    ptr: *mut ffi::GstVideoDecoder,
907    query: *mut gst::ffi::GstQuery,
908) -> glib::ffi::gboolean {
909    unsafe {
910        let instance = &*(ptr as *mut T::Instance);
911        let imp = instance.imp();
912        let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
913            gst::QueryViewMut::Allocation(allocation) => allocation,
914            _ => unreachable!(),
915        };
916
917        gst::panic_to_error!(imp, false, {
918            match imp.propose_allocation(query) {
919                Ok(()) => true,
920                Err(err) => {
921                    err.log_with_imp(imp);
922                    false
923                }
924            }
925        })
926        .into_glib()
927    }
928}
929
930unsafe extern "C" fn video_decoder_decide_allocation<T: VideoDecoderImpl>(
931    ptr: *mut ffi::GstVideoDecoder,
932    query: *mut gst::ffi::GstQuery,
933) -> glib::ffi::gboolean {
934    unsafe {
935        let instance = &*(ptr as *mut T::Instance);
936        let imp = instance.imp();
937        let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
938            gst::QueryViewMut::Allocation(allocation) => allocation,
939            _ => unreachable!(),
940        };
941
942        gst::panic_to_error!(imp, false, {
943            match imp.decide_allocation(query) {
944                Ok(()) => true,
945                Err(err) => {
946                    err.log_with_imp(imp);
947                    false
948                }
949            }
950        })
951        .into_glib()
952    }
953}
954
955#[cfg(feature = "v1_20")]
956unsafe extern "C" fn video_decoder_handle_missing_data<T: VideoDecoderImpl>(
957    ptr: *mut ffi::GstVideoDecoder,
958    timestamp: gst::ffi::GstClockTime,
959    duration: gst::ffi::GstClockTime,
960) -> glib::ffi::gboolean {
961    unsafe {
962        let instance = &*(ptr as *mut T::Instance);
963        let imp = instance.imp();
964
965        gst::panic_to_error!(imp, true, {
966            imp.handle_missing_data(
967                Option::<gst::ClockTime>::from_glib(timestamp).unwrap(),
968                from_glib(duration),
969            )
970        })
971        .into_glib()
972    }
973}