gstreamer_video/subclass/
video_decoder.rs

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