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: VideoDecoderImplExt + ElementImpl {
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}
186mod sealed {
187    pub trait Sealed {}
188    impl<T: super::VideoDecoderImplExt> Sealed for T {}
189}
190pub trait VideoDecoderImplExt: sealed::Sealed + ObjectSubclass {
191    fn parent_open(&self) -> Result<(), gst::ErrorMessage> {
192        unsafe {
193            let data = Self::type_data();
194            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
195            (*parent_class)
196                .open
197                .map(|f| {
198                    if from_glib(f(self
199                        .obj()
200                        .unsafe_cast_ref::<VideoDecoder>()
201                        .to_glib_none()
202                        .0))
203                    {
204                        Ok(())
205                    } else {
206                        Err(gst::error_msg!(
207                            gst::CoreError::StateChange,
208                            ["Parent function `open` failed"]
209                        ))
210                    }
211                })
212                .unwrap_or(Ok(()))
213        }
214    }
215
216    fn parent_close(&self) -> Result<(), gst::ErrorMessage> {
217        unsafe {
218            let data = Self::type_data();
219            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
220            (*parent_class)
221                .close
222                .map(|f| {
223                    if from_glib(f(self
224                        .obj()
225                        .unsafe_cast_ref::<VideoDecoder>()
226                        .to_glib_none()
227                        .0))
228                    {
229                        Ok(())
230                    } else {
231                        Err(gst::error_msg!(
232                            gst::CoreError::StateChange,
233                            ["Parent function `close` failed"]
234                        ))
235                    }
236                })
237                .unwrap_or(Ok(()))
238        }
239    }
240
241    fn parent_start(&self) -> Result<(), gst::ErrorMessage> {
242        unsafe {
243            let data = Self::type_data();
244            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
245            (*parent_class)
246                .start
247                .map(|f| {
248                    if from_glib(f(self
249                        .obj()
250                        .unsafe_cast_ref::<VideoDecoder>()
251                        .to_glib_none()
252                        .0))
253                    {
254                        Ok(())
255                    } else {
256                        Err(gst::error_msg!(
257                            gst::CoreError::StateChange,
258                            ["Parent function `start` failed"]
259                        ))
260                    }
261                })
262                .unwrap_or(Ok(()))
263        }
264    }
265
266    fn parent_stop(&self) -> Result<(), gst::ErrorMessage> {
267        unsafe {
268            let data = Self::type_data();
269            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
270            (*parent_class)
271                .stop
272                .map(|f| {
273                    if from_glib(f(self
274                        .obj()
275                        .unsafe_cast_ref::<VideoDecoder>()
276                        .to_glib_none()
277                        .0))
278                    {
279                        Ok(())
280                    } else {
281                        Err(gst::error_msg!(
282                            gst::CoreError::StateChange,
283                            ["Parent function `stop` failed"]
284                        ))
285                    }
286                })
287                .unwrap_or(Ok(()))
288        }
289    }
290
291    fn parent_finish(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
292        unsafe {
293            let data = Self::type_data();
294            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
295            (*parent_class)
296                .finish
297                .map(|f| {
298                    try_from_glib(f(self
299                        .obj()
300                        .unsafe_cast_ref::<VideoDecoder>()
301                        .to_glib_none()
302                        .0))
303                })
304                .unwrap_or(Ok(gst::FlowSuccess::Ok))
305        }
306    }
307
308    fn parent_drain(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
309        unsafe {
310            let data = Self::type_data();
311            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
312            (*parent_class)
313                .drain
314                .map(|f| {
315                    try_from_glib(f(self
316                        .obj()
317                        .unsafe_cast_ref::<VideoDecoder>()
318                        .to_glib_none()
319                        .0))
320                })
321                .unwrap_or(Ok(gst::FlowSuccess::Ok))
322        }
323    }
324
325    fn parent_set_format(
326        &self,
327        state: &VideoCodecState<'static, Readable>,
328    ) -> Result<(), gst::LoggableError> {
329        unsafe {
330            let data = Self::type_data();
331            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
332            (*parent_class)
333                .set_format
334                .map(|f| {
335                    gst::result_from_gboolean!(
336                        f(
337                            self.obj()
338                                .unsafe_cast_ref::<VideoDecoder>()
339                                .to_glib_none()
340                                .0,
341                            state.as_mut_ptr()
342                        ),
343                        gst::CAT_RUST,
344                        "parent function `set_format` failed"
345                    )
346                })
347                .unwrap_or(Ok(()))
348        }
349    }
350
351    fn parent_parse(
352        &self,
353        frame: &VideoCodecFrame,
354        adapter: &gst_base::Adapter,
355        at_eos: bool,
356    ) -> Result<gst::FlowSuccess, gst::FlowError> {
357        unsafe {
358            let data = Self::type_data();
359            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
360            (*parent_class)
361                .parse
362                .map(|f| {
363                    try_from_glib(f(
364                        self.obj()
365                            .unsafe_cast_ref::<VideoDecoder>()
366                            .to_glib_none()
367                            .0,
368                        frame.to_glib_none().0,
369                        adapter.to_glib_none().0,
370                        at_eos.into_glib(),
371                    ))
372                })
373                .unwrap_or(Ok(gst::FlowSuccess::Ok))
374        }
375    }
376
377    fn parent_handle_frame(
378        &self,
379        frame: VideoCodecFrame,
380    ) -> Result<gst::FlowSuccess, gst::FlowError> {
381        unsafe {
382            let data = Self::type_data();
383            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
384            (*parent_class)
385                .handle_frame
386                .map(|f| {
387                    try_from_glib(f(
388                        self.obj()
389                            .unsafe_cast_ref::<VideoDecoder>()
390                            .to_glib_none()
391                            .0,
392                        frame.to_glib_none().0,
393                    ))
394                })
395                .unwrap_or(Err(gst::FlowError::Error))
396        }
397    }
398
399    fn parent_flush(&self) -> bool {
400        unsafe {
401            let data = Self::type_data();
402            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
403            (*parent_class)
404                .flush
405                .map(|f| {
406                    from_glib(f(self
407                        .obj()
408                        .unsafe_cast_ref::<VideoDecoder>()
409                        .to_glib_none()
410                        .0))
411                })
412                .unwrap_or(false)
413        }
414    }
415
416    fn parent_negotiate(&self) -> Result<(), gst::LoggableError> {
417        unsafe {
418            let data = Self::type_data();
419            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
420            (*parent_class)
421                .negotiate
422                .map(|f| {
423                    gst::result_from_gboolean!(
424                        f(self
425                            .obj()
426                            .unsafe_cast_ref::<VideoDecoder>()
427                            .to_glib_none()
428                            .0),
429                        gst::CAT_RUST,
430                        "Parent function `negotiate` failed"
431                    )
432                })
433                .unwrap_or(Ok(()))
434        }
435    }
436
437    fn parent_caps(&self, filter: Option<&gst::Caps>) -> gst::Caps {
438        unsafe {
439            let data = Self::type_data();
440            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
441            (*parent_class)
442                .getcaps
443                .map(|f| {
444                    from_glib_full(f(
445                        self.obj()
446                            .unsafe_cast_ref::<VideoDecoder>()
447                            .to_glib_none()
448                            .0,
449                        filter.to_glib_none().0,
450                    ))
451                })
452                .unwrap_or_else(|| {
453                    self.obj()
454                        .unsafe_cast_ref::<VideoDecoder>()
455                        .proxy_getcaps(None, filter)
456                })
457        }
458    }
459
460    fn parent_sink_event(&self, event: gst::Event) -> bool {
461        unsafe {
462            let data = Self::type_data();
463            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
464            let f = (*parent_class)
465                .sink_event
466                .expect("Missing parent function `sink_event`");
467            from_glib(f(
468                self.obj()
469                    .unsafe_cast_ref::<VideoDecoder>()
470                    .to_glib_none()
471                    .0,
472                event.into_glib_ptr(),
473            ))
474        }
475    }
476
477    fn parent_sink_query(&self, query: &mut gst::QueryRef) -> bool {
478        unsafe {
479            let data = Self::type_data();
480            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
481            let f = (*parent_class)
482                .sink_query
483                .expect("Missing parent function `sink_query`");
484            from_glib(f(
485                self.obj()
486                    .unsafe_cast_ref::<VideoDecoder>()
487                    .to_glib_none()
488                    .0,
489                query.as_mut_ptr(),
490            ))
491        }
492    }
493
494    fn parent_src_event(&self, event: gst::Event) -> bool {
495        unsafe {
496            let data = Self::type_data();
497            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
498            let f = (*parent_class)
499                .src_event
500                .expect("Missing parent function `src_event`");
501            from_glib(f(
502                self.obj()
503                    .unsafe_cast_ref::<VideoDecoder>()
504                    .to_glib_none()
505                    .0,
506                event.into_glib_ptr(),
507            ))
508        }
509    }
510
511    fn parent_src_query(&self, query: &mut gst::QueryRef) -> bool {
512        unsafe {
513            let data = Self::type_data();
514            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
515            let f = (*parent_class)
516                .src_query
517                .expect("Missing parent function `src_query`");
518            from_glib(f(
519                self.obj()
520                    .unsafe_cast_ref::<VideoDecoder>()
521                    .to_glib_none()
522                    .0,
523                query.as_mut_ptr(),
524            ))
525        }
526    }
527
528    fn parent_propose_allocation(
529        &self,
530        query: &mut gst::query::Allocation,
531    ) -> Result<(), gst::LoggableError> {
532        unsafe {
533            let data = Self::type_data();
534            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
535            (*parent_class)
536                .propose_allocation
537                .map(|f| {
538                    gst::result_from_gboolean!(
539                        f(
540                            self.obj()
541                                .unsafe_cast_ref::<VideoDecoder>()
542                                .to_glib_none()
543                                .0,
544                            query.as_mut_ptr(),
545                        ),
546                        gst::CAT_RUST,
547                        "Parent function `propose_allocation` failed",
548                    )
549                })
550                .unwrap_or(Ok(()))
551        }
552    }
553
554    fn parent_decide_allocation(
555        &self,
556        query: &mut gst::query::Allocation,
557    ) -> Result<(), gst::LoggableError> {
558        unsafe {
559            let data = Self::type_data();
560            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
561            (*parent_class)
562                .decide_allocation
563                .map(|f| {
564                    gst::result_from_gboolean!(
565                        f(
566                            self.obj()
567                                .unsafe_cast_ref::<VideoDecoder>()
568                                .to_glib_none()
569                                .0,
570                            query.as_mut_ptr(),
571                        ),
572                        gst::CAT_RUST,
573                        "Parent function `decide_allocation` failed",
574                    )
575                })
576                .unwrap_or(Ok(()))
577        }
578    }
579
580    #[cfg(feature = "v1_20")]
581    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
582    fn parent_handle_missing_data(
583        &self,
584        timestamp: gst::ClockTime,
585        duration: Option<gst::ClockTime>,
586    ) -> bool {
587        unsafe {
588            let data = Self::type_data();
589            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoDecoderClass;
590            (*parent_class)
591                .handle_missing_data
592                .map(|f| {
593                    from_glib(f(
594                        self.obj()
595                            .unsafe_cast_ref::<VideoDecoder>()
596                            .to_glib_none()
597                            .0,
598                        timestamp.into_glib(),
599                        duration.into_glib(),
600                    ))
601                })
602                .unwrap_or(true)
603        }
604    }
605}
606
607impl<T: VideoDecoderImpl> VideoDecoderImplExt for T {}
608
609unsafe impl<T: VideoDecoderImpl> IsSubclassable<T> for VideoDecoder {
610    fn class_init(klass: &mut glib::Class<Self>) {
611        Self::parent_class_init::<T>(klass);
612        let klass = klass.as_mut();
613        klass.open = Some(video_decoder_open::<T>);
614        klass.close = Some(video_decoder_close::<T>);
615        klass.start = Some(video_decoder_start::<T>);
616        klass.stop = Some(video_decoder_stop::<T>);
617        klass.finish = Some(video_decoder_finish::<T>);
618        klass.drain = Some(video_decoder_drain::<T>);
619        klass.set_format = Some(video_decoder_set_format::<T>);
620        klass.parse = Some(video_decoder_parse::<T>);
621        klass.handle_frame = Some(video_decoder_handle_frame::<T>);
622        klass.flush = Some(video_decoder_flush::<T>);
623        klass.negotiate = Some(video_decoder_negotiate::<T>);
624        klass.getcaps = Some(video_decoder_getcaps::<T>);
625        klass.sink_event = Some(video_decoder_sink_event::<T>);
626        klass.src_event = Some(video_decoder_src_event::<T>);
627        klass.sink_query = Some(video_decoder_sink_query::<T>);
628        klass.src_query = Some(video_decoder_src_query::<T>);
629        klass.propose_allocation = Some(video_decoder_propose_allocation::<T>);
630        klass.decide_allocation = Some(video_decoder_decide_allocation::<T>);
631        #[cfg(feature = "v1_20")]
632        {
633            klass.handle_missing_data = Some(video_decoder_handle_missing_data::<T>);
634        }
635    }
636}
637
638unsafe extern "C" fn video_decoder_open<T: VideoDecoderImpl>(
639    ptr: *mut ffi::GstVideoDecoder,
640) -> glib::ffi::gboolean {
641    let instance = &*(ptr as *mut T::Instance);
642    let imp = instance.imp();
643
644    gst::panic_to_error!(imp, false, {
645        match imp.open() {
646            Ok(()) => true,
647            Err(err) => {
648                imp.post_error_message(err);
649                false
650            }
651        }
652    })
653    .into_glib()
654}
655
656unsafe extern "C" fn video_decoder_close<T: VideoDecoderImpl>(
657    ptr: *mut ffi::GstVideoDecoder,
658) -> glib::ffi::gboolean {
659    let instance = &*(ptr as *mut T::Instance);
660    let imp = instance.imp();
661
662    gst::panic_to_error!(imp, false, {
663        match imp.close() {
664            Ok(()) => true,
665            Err(err) => {
666                imp.post_error_message(err);
667                false
668            }
669        }
670    })
671    .into_glib()
672}
673
674unsafe extern "C" fn video_decoder_start<T: VideoDecoderImpl>(
675    ptr: *mut ffi::GstVideoDecoder,
676) -> glib::ffi::gboolean {
677    let instance = &*(ptr as *mut T::Instance);
678    let imp = instance.imp();
679
680    gst::panic_to_error!(imp, false, {
681        match imp.start() {
682            Ok(()) => true,
683            Err(err) => {
684                imp.post_error_message(err);
685                false
686            }
687        }
688    })
689    .into_glib()
690}
691
692unsafe extern "C" fn video_decoder_stop<T: VideoDecoderImpl>(
693    ptr: *mut ffi::GstVideoDecoder,
694) -> glib::ffi::gboolean {
695    let instance = &*(ptr as *mut T::Instance);
696    let imp = instance.imp();
697
698    gst::panic_to_error!(imp, false, {
699        match imp.stop() {
700            Ok(()) => true,
701            Err(err) => {
702                imp.post_error_message(err);
703                false
704            }
705        }
706    })
707    .into_glib()
708}
709
710unsafe extern "C" fn video_decoder_finish<T: VideoDecoderImpl>(
711    ptr: *mut ffi::GstVideoDecoder,
712) -> gst::ffi::GstFlowReturn {
713    let instance = &*(ptr as *mut T::Instance);
714    let imp = instance.imp();
715
716    gst::panic_to_error!(imp, gst::FlowReturn::Error, { imp.finish().into() }).into_glib()
717}
718
719unsafe extern "C" fn video_decoder_drain<T: VideoDecoderImpl>(
720    ptr: *mut ffi::GstVideoDecoder,
721) -> gst::ffi::GstFlowReturn {
722    let instance = &*(ptr as *mut T::Instance);
723    let imp = instance.imp();
724
725    gst::panic_to_error!(imp, gst::FlowReturn::Error, { imp.drain().into() }).into_glib()
726}
727
728unsafe extern "C" fn video_decoder_set_format<T: VideoDecoderImpl>(
729    ptr: *mut ffi::GstVideoDecoder,
730    state: *mut ffi::GstVideoCodecState,
731) -> glib::ffi::gboolean {
732    let instance = &*(ptr as *mut T::Instance);
733    let imp = instance.imp();
734    ffi::gst_video_codec_state_ref(state);
735    let wrap_state = VideoCodecState::<Readable>::new(state);
736
737    gst::panic_to_error!(imp, false, {
738        match imp.set_format(&wrap_state) {
739            Ok(()) => true,
740            Err(err) => {
741                err.log_with_imp(imp);
742                false
743            }
744        }
745    })
746    .into_glib()
747}
748
749unsafe extern "C" fn video_decoder_parse<T: VideoDecoderImpl>(
750    ptr: *mut ffi::GstVideoDecoder,
751    frame: *mut ffi::GstVideoCodecFrame,
752    adapter: *mut gst_base::ffi::GstAdapter,
753    at_eos: glib::ffi::gboolean,
754) -> gst::ffi::GstFlowReturn {
755    let instance = &*(ptr as *mut T::Instance);
756    let imp = instance.imp();
757    ffi::gst_video_codec_frame_ref(frame);
758    let instance = imp.obj();
759    let instance = instance.unsafe_cast_ref::<VideoDecoder>();
760    let wrap_frame = VideoCodecFrame::new(frame, instance);
761    let wrap_adapter: Borrowed<gst_base::Adapter> = from_glib_borrow(adapter);
762    let at_eos: bool = from_glib(at_eos);
763
764    gst::panic_to_error!(imp, gst::FlowReturn::Error, {
765        imp.parse(&wrap_frame, &wrap_adapter, at_eos).into()
766    })
767    .into_glib()
768}
769
770unsafe extern "C" fn video_decoder_handle_frame<T: VideoDecoderImpl>(
771    ptr: *mut ffi::GstVideoDecoder,
772    frame: *mut ffi::GstVideoCodecFrame,
773) -> gst::ffi::GstFlowReturn {
774    let instance = &*(ptr as *mut T::Instance);
775    let imp = instance.imp();
776    let instance = imp.obj();
777    let instance = instance.unsafe_cast_ref::<VideoDecoder>();
778    let wrap_frame = VideoCodecFrame::new(frame, instance);
779
780    gst::panic_to_error!(imp, gst::FlowReturn::Error, {
781        imp.handle_frame(wrap_frame).into()
782    })
783    .into_glib()
784}
785
786unsafe extern "C" fn video_decoder_flush<T: VideoDecoderImpl>(
787    ptr: *mut ffi::GstVideoDecoder,
788) -> glib::ffi::gboolean {
789    let instance = &*(ptr as *mut T::Instance);
790    let imp = instance.imp();
791
792    gst::panic_to_error!(imp, false, { VideoDecoderImpl::flush(imp) }).into_glib()
793}
794
795unsafe extern "C" fn video_decoder_negotiate<T: VideoDecoderImpl>(
796    ptr: *mut ffi::GstVideoDecoder,
797) -> glib::ffi::gboolean {
798    let instance = &*(ptr as *mut T::Instance);
799    let imp = instance.imp();
800
801    gst::panic_to_error!(imp, false, {
802        match imp.negotiate() {
803            Ok(()) => true,
804            Err(err) => {
805                err.log_with_imp(imp);
806                false
807            }
808        }
809    })
810    .into_glib()
811}
812
813unsafe extern "C" fn video_decoder_getcaps<T: VideoDecoderImpl>(
814    ptr: *mut ffi::GstVideoDecoder,
815    filter: *mut gst::ffi::GstCaps,
816) -> *mut gst::ffi::GstCaps {
817    let instance = &*(ptr as *mut T::Instance);
818    let imp = instance.imp();
819
820    gst::panic_to_error!(imp, gst::Caps::new_empty(), {
821        VideoDecoderImpl::caps(
822            imp,
823            Option::<gst::Caps>::from_glib_borrow(filter)
824                .as_ref()
825                .as_ref(),
826        )
827    })
828    .into_glib_ptr()
829}
830
831unsafe extern "C" fn video_decoder_sink_event<T: VideoDecoderImpl>(
832    ptr: *mut ffi::GstVideoDecoder,
833    event: *mut gst::ffi::GstEvent,
834) -> glib::ffi::gboolean {
835    let instance = &*(ptr as *mut T::Instance);
836    let imp = instance.imp();
837
838    gst::panic_to_error!(imp, false, { imp.sink_event(from_glib_full(event)) }).into_glib()
839}
840
841unsafe extern "C" fn video_decoder_sink_query<T: VideoDecoderImpl>(
842    ptr: *mut ffi::GstVideoDecoder,
843    query: *mut gst::ffi::GstQuery,
844) -> glib::ffi::gboolean {
845    let instance = &*(ptr as *mut T::Instance);
846    let imp = instance.imp();
847
848    gst::panic_to_error!(imp, false, {
849        imp.sink_query(gst::QueryRef::from_mut_ptr(query))
850    })
851    .into_glib()
852}
853
854unsafe extern "C" fn video_decoder_src_event<T: VideoDecoderImpl>(
855    ptr: *mut ffi::GstVideoDecoder,
856    event: *mut gst::ffi::GstEvent,
857) -> glib::ffi::gboolean {
858    let instance = &*(ptr as *mut T::Instance);
859    let imp = instance.imp();
860
861    gst::panic_to_error!(imp, false, { imp.src_event(from_glib_full(event)) }).into_glib()
862}
863
864unsafe extern "C" fn video_decoder_src_query<T: VideoDecoderImpl>(
865    ptr: *mut ffi::GstVideoDecoder,
866    query: *mut gst::ffi::GstQuery,
867) -> glib::ffi::gboolean {
868    let instance = &*(ptr as *mut T::Instance);
869    let imp = instance.imp();
870
871    gst::panic_to_error!(imp, false, {
872        imp.src_query(gst::QueryRef::from_mut_ptr(query))
873    })
874    .into_glib()
875}
876
877unsafe extern "C" fn video_decoder_propose_allocation<T: VideoDecoderImpl>(
878    ptr: *mut ffi::GstVideoDecoder,
879    query: *mut gst::ffi::GstQuery,
880) -> glib::ffi::gboolean {
881    let instance = &*(ptr as *mut T::Instance);
882    let imp = instance.imp();
883    let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
884        gst::QueryViewMut::Allocation(allocation) => allocation,
885        _ => unreachable!(),
886    };
887
888    gst::panic_to_error!(imp, false, {
889        match imp.propose_allocation(query) {
890            Ok(()) => true,
891            Err(err) => {
892                err.log_with_imp(imp);
893                false
894            }
895        }
896    })
897    .into_glib()
898}
899
900unsafe extern "C" fn video_decoder_decide_allocation<T: VideoDecoderImpl>(
901    ptr: *mut ffi::GstVideoDecoder,
902    query: *mut gst::ffi::GstQuery,
903) -> glib::ffi::gboolean {
904    let instance = &*(ptr as *mut T::Instance);
905    let imp = instance.imp();
906    let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
907        gst::QueryViewMut::Allocation(allocation) => allocation,
908        _ => unreachable!(),
909    };
910
911    gst::panic_to_error!(imp, false, {
912        match imp.decide_allocation(query) {
913            Ok(()) => true,
914            Err(err) => {
915                err.log_with_imp(imp);
916                false
917            }
918        }
919    })
920    .into_glib()
921}
922
923#[cfg(feature = "v1_20")]
924unsafe extern "C" fn video_decoder_handle_missing_data<T: VideoDecoderImpl>(
925    ptr: *mut ffi::GstVideoDecoder,
926    timestamp: gst::ffi::GstClockTime,
927    duration: gst::ffi::GstClockTime,
928) -> glib::ffi::gboolean {
929    let instance = &*(ptr as *mut T::Instance);
930    let imp = instance.imp();
931
932    gst::panic_to_error!(imp, true, {
933        imp.handle_missing_data(
934            Option::<gst::ClockTime>::from_glib(timestamp).unwrap(),
935            from_glib(duration),
936        )
937    })
938    .into_glib()
939}