Skip to main content

gstreamer_video/auto/
video_decoder.rs

1// This file was generated by gir (https://github.com/gtk-rs/gir)
2// from gir-files (https://github.com/gtk-rs/gir-files)
3// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git)
4// DO NOT EDIT
5
6#[cfg(feature = "v1_20")]
7#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
8use crate::VideoDecoderRequestSyncPointFlags;
9use crate::{VideoCodecFrame, ffi};
10#[cfg(feature = "v1_18")]
11#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
12use glib::signal::{SignalHandlerId, connect_raw};
13use glib::{prelude::*, translate::*};
14#[cfg(feature = "v1_18")]
15#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
16use std::boxed::Box as Box_;
17
18glib::wrapper! {
19    #[doc(alias = "GstVideoDecoder")]
20    pub struct VideoDecoder(Object<ffi::GstVideoDecoder, ffi::GstVideoDecoderClass>) @extends gst::Element, gst::Object;
21
22    match fn {
23        type_ => || ffi::gst_video_decoder_get_type(),
24    }
25}
26
27impl VideoDecoder {
28    pub const NONE: Option<&'static VideoDecoder> = None;
29}
30
31unsafe impl Send for VideoDecoder {}
32unsafe impl Sync for VideoDecoder {}
33
34pub trait VideoDecoderExt: IsA<VideoDecoder> + 'static {
35    #[doc(alias = "gst_video_decoder_add_to_frame")]
36    fn add_to_frame(&self, n_bytes: i32) {
37        unsafe {
38            ffi::gst_video_decoder_add_to_frame(self.as_ref().to_glib_none().0, n_bytes);
39        }
40    }
41
42    #[doc(alias = "gst_video_decoder_allocate_output_buffer")]
43    fn allocate_output_buffer(&self) -> Result<gst::Buffer, glib::BoolError> {
44        unsafe {
45            Option::<_>::from_glib_full(ffi::gst_video_decoder_allocate_output_buffer(
46                self.as_ref().to_glib_none().0,
47            ))
48            .ok_or_else(|| glib::bool_error!("Failed to allocate output buffer"))
49        }
50    }
51
52    #[doc(alias = "gst_video_decoder_drop_frame")]
53    fn drop_frame(&self, frame: VideoCodecFrame) -> Result<gst::FlowSuccess, gst::FlowError> {
54        unsafe {
55            try_from_glib(ffi::gst_video_decoder_drop_frame(
56                self.as_ref().to_glib_none().0,
57                frame.into_glib_ptr(),
58            ))
59        }
60    }
61
62    #[cfg(feature = "v1_20")]
63    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
64    #[doc(alias = "gst_video_decoder_drop_subframe")]
65    fn drop_subframe(&self, frame: VideoCodecFrame) -> Result<gst::FlowSuccess, gst::FlowError> {
66        unsafe {
67            try_from_glib(ffi::gst_video_decoder_drop_subframe(
68                self.as_ref().to_glib_none().0,
69                frame.into_glib_ptr(),
70            ))
71        }
72    }
73
74    #[doc(alias = "gst_video_decoder_finish_frame")]
75    fn finish_frame(&self, frame: VideoCodecFrame) -> Result<gst::FlowSuccess, gst::FlowError> {
76        unsafe {
77            try_from_glib(ffi::gst_video_decoder_finish_frame(
78                self.as_ref().to_glib_none().0,
79                frame.into_glib_ptr(),
80            ))
81        }
82    }
83
84    #[cfg(feature = "v1_20")]
85    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
86    #[doc(alias = "gst_video_decoder_finish_subframe")]
87    fn finish_subframe(&self, frame: VideoCodecFrame) -> Result<gst::FlowSuccess, gst::FlowError> {
88        unsafe {
89            try_from_glib(ffi::gst_video_decoder_finish_subframe(
90                self.as_ref().to_glib_none().0,
91                frame.into_glib_ptr(),
92            ))
93        }
94    }
95
96    #[doc(alias = "gst_video_decoder_get_buffer_pool")]
97    #[doc(alias = "get_buffer_pool")]
98    fn buffer_pool(&self) -> Option<gst::BufferPool> {
99        unsafe {
100            from_glib_full(ffi::gst_video_decoder_get_buffer_pool(
101                self.as_ref().to_glib_none().0,
102            ))
103        }
104    }
105
106    #[doc(alias = "gst_video_decoder_get_estimate_rate")]
107    #[doc(alias = "get_estimate_rate")]
108    fn estimate_rate(&self) -> i32 {
109        unsafe { ffi::gst_video_decoder_get_estimate_rate(self.as_ref().to_glib_none().0) }
110    }
111
112    #[doc(alias = "gst_video_decoder_get_max_decode_time")]
113    #[doc(alias = "get_max_decode_time")]
114    fn max_decode_time(&self, frame: &VideoCodecFrame) -> gst::ClockTimeDiff {
115        unsafe {
116            ffi::gst_video_decoder_get_max_decode_time(
117                self.as_ref().to_glib_none().0,
118                frame.to_glib_none().0,
119            )
120        }
121    }
122
123    #[doc(alias = "gst_video_decoder_get_max_errors")]
124    #[doc(alias = "get_max_errors")]
125    #[doc(alias = "max-errors")]
126    fn max_errors(&self) -> i32 {
127        unsafe { ffi::gst_video_decoder_get_max_errors(self.as_ref().to_glib_none().0) }
128    }
129
130    #[doc(alias = "gst_video_decoder_get_needs_format")]
131    #[doc(alias = "get_needs_format")]
132    fn needs_format(&self) -> bool {
133        unsafe {
134            from_glib(ffi::gst_video_decoder_get_needs_format(
135                self.as_ref().to_glib_none().0,
136            ))
137        }
138    }
139
140    #[cfg(feature = "v1_20")]
141    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
142    #[doc(alias = "gst_video_decoder_get_needs_sync_point")]
143    #[doc(alias = "get_needs_sync_point")]
144    fn needs_sync_point(&self) -> bool {
145        unsafe {
146            from_glib(ffi::gst_video_decoder_get_needs_sync_point(
147                self.as_ref().to_glib_none().0,
148            ))
149        }
150    }
151
152    #[doc(alias = "gst_video_decoder_get_packetized")]
153    #[doc(alias = "get_packetized")]
154    fn is_packetized(&self) -> bool {
155        unsafe {
156            from_glib(ffi::gst_video_decoder_get_packetized(
157                self.as_ref().to_glib_none().0,
158            ))
159        }
160    }
161
162    #[doc(alias = "gst_video_decoder_get_pending_frame_size")]
163    #[doc(alias = "get_pending_frame_size")]
164    fn pending_frame_size(&self) -> usize {
165        unsafe { ffi::gst_video_decoder_get_pending_frame_size(self.as_ref().to_glib_none().0) }
166    }
167
168    #[doc(alias = "gst_video_decoder_get_qos_proportion")]
169    #[doc(alias = "get_qos_proportion")]
170    fn qos_proportion(&self) -> f64 {
171        unsafe { ffi::gst_video_decoder_get_qos_proportion(self.as_ref().to_glib_none().0) }
172    }
173
174    #[cfg(feature = "v1_20")]
175    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
176    #[doc(alias = "gst_video_decoder_get_subframe_mode")]
177    #[doc(alias = "get_subframe_mode")]
178    fn is_subframe_mode(&self) -> bool {
179        unsafe {
180            from_glib(ffi::gst_video_decoder_get_subframe_mode(
181                self.as_ref().to_glib_none().0,
182            ))
183        }
184    }
185
186    #[doc(alias = "gst_video_decoder_have_frame")]
187    fn have_frame(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
188        unsafe {
189            try_from_glib(ffi::gst_video_decoder_have_frame(
190                self.as_ref().to_glib_none().0,
191            ))
192        }
193    }
194
195    #[cfg(feature = "v1_20")]
196    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
197    #[doc(alias = "gst_video_decoder_have_last_subframe")]
198    fn have_last_subframe(
199        &self,
200        frame: &VideoCodecFrame,
201    ) -> Result<gst::FlowSuccess, gst::FlowError> {
202        unsafe {
203            try_from_glib(ffi::gst_video_decoder_have_last_subframe(
204                self.as_ref().to_glib_none().0,
205                frame.to_glib_none().0,
206            ))
207        }
208    }
209
210    #[doc(alias = "gst_video_decoder_merge_tags")]
211    fn merge_tags(&self, tags: Option<&gst::TagList>, mode: gst::TagMergeMode) {
212        unsafe {
213            ffi::gst_video_decoder_merge_tags(
214                self.as_ref().to_glib_none().0,
215                tags.to_glib_none().0,
216                mode.into_glib(),
217            );
218        }
219    }
220
221    #[doc(alias = "gst_video_decoder_proxy_getcaps")]
222    fn proxy_getcaps(&self, caps: Option<&gst::Caps>, filter: Option<&gst::Caps>) -> gst::Caps {
223        unsafe {
224            from_glib_full(ffi::gst_video_decoder_proxy_getcaps(
225                self.as_ref().to_glib_none().0,
226                caps.to_glib_none().0,
227                filter.to_glib_none().0,
228            ))
229        }
230    }
231
232    #[doc(alias = "gst_video_decoder_release_frame")]
233    fn release_frame(&self, frame: VideoCodecFrame) {
234        unsafe {
235            ffi::gst_video_decoder_release_frame(
236                self.as_ref().to_glib_none().0,
237                frame.into_glib_ptr(),
238            );
239        }
240    }
241
242    #[cfg(feature = "v1_20")]
243    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
244    #[doc(alias = "gst_video_decoder_request_sync_point")]
245    fn request_sync_point(
246        &self,
247        frame: &VideoCodecFrame,
248        flags: VideoDecoderRequestSyncPointFlags,
249    ) {
250        unsafe {
251            ffi::gst_video_decoder_request_sync_point(
252                self.as_ref().to_glib_none().0,
253                frame.to_glib_none().0,
254                flags.into_glib(),
255            );
256        }
257    }
258
259    #[doc(alias = "gst_video_decoder_set_estimate_rate")]
260    fn set_estimate_rate(&self, enabled: bool) {
261        unsafe {
262            ffi::gst_video_decoder_set_estimate_rate(
263                self.as_ref().to_glib_none().0,
264                enabled.into_glib(),
265            );
266        }
267    }
268
269    #[doc(alias = "gst_video_decoder_set_max_errors")]
270    #[doc(alias = "max-errors")]
271    fn set_max_errors(&self, num: i32) {
272        unsafe {
273            ffi::gst_video_decoder_set_max_errors(self.as_ref().to_glib_none().0, num);
274        }
275    }
276
277    #[doc(alias = "gst_video_decoder_set_needs_format")]
278    fn set_needs_format(&self, enabled: bool) {
279        unsafe {
280            ffi::gst_video_decoder_set_needs_format(
281                self.as_ref().to_glib_none().0,
282                enabled.into_glib(),
283            );
284        }
285    }
286
287    #[cfg(feature = "v1_20")]
288    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
289    #[doc(alias = "gst_video_decoder_set_needs_sync_point")]
290    fn set_needs_sync_point(&self, enabled: bool) {
291        unsafe {
292            ffi::gst_video_decoder_set_needs_sync_point(
293                self.as_ref().to_glib_none().0,
294                enabled.into_glib(),
295            );
296        }
297    }
298
299    #[doc(alias = "gst_video_decoder_set_packetized")]
300    fn set_packetized(&self, packetized: bool) {
301        unsafe {
302            ffi::gst_video_decoder_set_packetized(
303                self.as_ref().to_glib_none().0,
304                packetized.into_glib(),
305            );
306        }
307    }
308
309    #[cfg(feature = "v1_20")]
310    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
311    #[doc(alias = "gst_video_decoder_set_subframe_mode")]
312    fn set_subframe_mode(&self, subframe_mode: bool) {
313        unsafe {
314            ffi::gst_video_decoder_set_subframe_mode(
315                self.as_ref().to_glib_none().0,
316                subframe_mode.into_glib(),
317            );
318        }
319    }
320
321    #[doc(alias = "gst_video_decoder_set_use_default_pad_acceptcaps")]
322    fn set_use_default_pad_acceptcaps(&self, use_: bool) {
323        unsafe {
324            ffi::gst_video_decoder_set_use_default_pad_acceptcaps(
325                self.as_ref().to_glib_none().0,
326                use_.into_glib(),
327            );
328        }
329    }
330
331    #[cfg(feature = "v1_20")]
332    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
333    #[doc(alias = "automatic-request-sync-point-flags")]
334    fn automatic_request_sync_point_flags(&self) -> VideoDecoderRequestSyncPointFlags {
335        ObjectExt::property(self.as_ref(), "automatic-request-sync-point-flags")
336    }
337
338    #[cfg(feature = "v1_20")]
339    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
340    #[doc(alias = "automatic-request-sync-point-flags")]
341    fn set_automatic_request_sync_point_flags(
342        &self,
343        automatic_request_sync_point_flags: VideoDecoderRequestSyncPointFlags,
344    ) {
345        ObjectExt::set_property(
346            self.as_ref(),
347            "automatic-request-sync-point-flags",
348            automatic_request_sync_point_flags,
349        )
350    }
351
352    #[cfg(feature = "v1_20")]
353    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
354    #[doc(alias = "automatic-request-sync-points")]
355    fn is_automatic_request_sync_points(&self) -> bool {
356        ObjectExt::property(self.as_ref(), "automatic-request-sync-points")
357    }
358
359    #[cfg(feature = "v1_20")]
360    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
361    #[doc(alias = "automatic-request-sync-points")]
362    fn set_automatic_request_sync_points(&self, automatic_request_sync_points: bool) {
363        ObjectExt::set_property(
364            self.as_ref(),
365            "automatic-request-sync-points",
366            automatic_request_sync_points,
367        )
368    }
369
370    #[cfg(feature = "v1_20")]
371    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
372    #[doc(alias = "discard-corrupted-frames")]
373    fn is_discard_corrupted_frames(&self) -> bool {
374        ObjectExt::property(self.as_ref(), "discard-corrupted-frames")
375    }
376
377    #[cfg(feature = "v1_20")]
378    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
379    #[doc(alias = "discard-corrupted-frames")]
380    fn set_discard_corrupted_frames(&self, discard_corrupted_frames: bool) {
381        ObjectExt::set_property(
382            self.as_ref(),
383            "discard-corrupted-frames",
384            discard_corrupted_frames,
385        )
386    }
387
388    #[cfg(feature = "v1_20")]
389    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
390    #[doc(alias = "min-force-key-unit-interval")]
391    fn min_force_key_unit_interval(&self) -> u64 {
392        ObjectExt::property(self.as_ref(), "min-force-key-unit-interval")
393    }
394
395    #[cfg(feature = "v1_20")]
396    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
397    #[doc(alias = "min-force-key-unit-interval")]
398    fn set_min_force_key_unit_interval(&self, min_force_key_unit_interval: u64) {
399        ObjectExt::set_property(
400            self.as_ref(),
401            "min-force-key-unit-interval",
402            min_force_key_unit_interval,
403        )
404    }
405
406    #[cfg(feature = "v1_18")]
407    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
408    fn is_qos(&self) -> bool {
409        ObjectExt::property(self.as_ref(), "qos")
410    }
411
412    #[cfg(feature = "v1_18")]
413    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
414    fn set_qos(&self, qos: bool) {
415        ObjectExt::set_property(self.as_ref(), "qos", qos)
416    }
417
418    #[cfg(feature = "v1_20")]
419    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
420    #[doc(alias = "automatic-request-sync-point-flags")]
421    fn connect_automatic_request_sync_point_flags_notify<F: Fn(&Self) + Send + Sync + 'static>(
422        &self,
423        f: F,
424    ) -> SignalHandlerId {
425        unsafe extern "C" fn notify_automatic_request_sync_point_flags_trampoline<
426            P: IsA<VideoDecoder>,
427            F: Fn(&P) + Send + Sync + 'static,
428        >(
429            this: *mut ffi::GstVideoDecoder,
430            _param_spec: glib::ffi::gpointer,
431            f: glib::ffi::gpointer,
432        ) {
433            unsafe {
434                let f: &F = &*(f as *const F);
435                f(VideoDecoder::from_glib_borrow(this).unsafe_cast_ref())
436            }
437        }
438        unsafe {
439            let f: Box_<F> = Box_::new(f);
440            connect_raw(
441                self.as_ptr() as *mut _,
442                c"notify::automatic-request-sync-point-flags".as_ptr(),
443                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
444                    notify_automatic_request_sync_point_flags_trampoline::<Self, F> as *const (),
445                )),
446                Box_::into_raw(f),
447            )
448        }
449    }
450
451    #[cfg(feature = "v1_20")]
452    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
453    #[doc(alias = "automatic-request-sync-points")]
454    fn connect_automatic_request_sync_points_notify<F: Fn(&Self) + Send + Sync + 'static>(
455        &self,
456        f: F,
457    ) -> SignalHandlerId {
458        unsafe extern "C" fn notify_automatic_request_sync_points_trampoline<
459            P: IsA<VideoDecoder>,
460            F: Fn(&P) + Send + Sync + 'static,
461        >(
462            this: *mut ffi::GstVideoDecoder,
463            _param_spec: glib::ffi::gpointer,
464            f: glib::ffi::gpointer,
465        ) {
466            unsafe {
467                let f: &F = &*(f as *const F);
468                f(VideoDecoder::from_glib_borrow(this).unsafe_cast_ref())
469            }
470        }
471        unsafe {
472            let f: Box_<F> = Box_::new(f);
473            connect_raw(
474                self.as_ptr() as *mut _,
475                c"notify::automatic-request-sync-points".as_ptr(),
476                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
477                    notify_automatic_request_sync_points_trampoline::<Self, F> as *const (),
478                )),
479                Box_::into_raw(f),
480            )
481        }
482    }
483
484    #[cfg(feature = "v1_20")]
485    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
486    #[doc(alias = "discard-corrupted-frames")]
487    fn connect_discard_corrupted_frames_notify<F: Fn(&Self) + Send + Sync + 'static>(
488        &self,
489        f: F,
490    ) -> SignalHandlerId {
491        unsafe extern "C" fn notify_discard_corrupted_frames_trampoline<
492            P: IsA<VideoDecoder>,
493            F: Fn(&P) + Send + Sync + 'static,
494        >(
495            this: *mut ffi::GstVideoDecoder,
496            _param_spec: glib::ffi::gpointer,
497            f: glib::ffi::gpointer,
498        ) {
499            unsafe {
500                let f: &F = &*(f as *const F);
501                f(VideoDecoder::from_glib_borrow(this).unsafe_cast_ref())
502            }
503        }
504        unsafe {
505            let f: Box_<F> = Box_::new(f);
506            connect_raw(
507                self.as_ptr() as *mut _,
508                c"notify::discard-corrupted-frames".as_ptr(),
509                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
510                    notify_discard_corrupted_frames_trampoline::<Self, F> as *const (),
511                )),
512                Box_::into_raw(f),
513            )
514        }
515    }
516
517    #[cfg(feature = "v1_18")]
518    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
519    #[doc(alias = "max-errors")]
520    fn connect_max_errors_notify<F: Fn(&Self) + Send + Sync + 'static>(
521        &self,
522        f: F,
523    ) -> SignalHandlerId {
524        unsafe extern "C" fn notify_max_errors_trampoline<
525            P: IsA<VideoDecoder>,
526            F: Fn(&P) + Send + Sync + 'static,
527        >(
528            this: *mut ffi::GstVideoDecoder,
529            _param_spec: glib::ffi::gpointer,
530            f: glib::ffi::gpointer,
531        ) {
532            unsafe {
533                let f: &F = &*(f as *const F);
534                f(VideoDecoder::from_glib_borrow(this).unsafe_cast_ref())
535            }
536        }
537        unsafe {
538            let f: Box_<F> = Box_::new(f);
539            connect_raw(
540                self.as_ptr() as *mut _,
541                c"notify::max-errors".as_ptr(),
542                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
543                    notify_max_errors_trampoline::<Self, F> as *const (),
544                )),
545                Box_::into_raw(f),
546            )
547        }
548    }
549
550    #[cfg(feature = "v1_20")]
551    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
552    #[doc(alias = "min-force-key-unit-interval")]
553    fn connect_min_force_key_unit_interval_notify<F: Fn(&Self) + Send + Sync + 'static>(
554        &self,
555        f: F,
556    ) -> SignalHandlerId {
557        unsafe extern "C" fn notify_min_force_key_unit_interval_trampoline<
558            P: IsA<VideoDecoder>,
559            F: Fn(&P) + Send + Sync + 'static,
560        >(
561            this: *mut ffi::GstVideoDecoder,
562            _param_spec: glib::ffi::gpointer,
563            f: glib::ffi::gpointer,
564        ) {
565            unsafe {
566                let f: &F = &*(f as *const F);
567                f(VideoDecoder::from_glib_borrow(this).unsafe_cast_ref())
568            }
569        }
570        unsafe {
571            let f: Box_<F> = Box_::new(f);
572            connect_raw(
573                self.as_ptr() as *mut _,
574                c"notify::min-force-key-unit-interval".as_ptr(),
575                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
576                    notify_min_force_key_unit_interval_trampoline::<Self, F> as *const (),
577                )),
578                Box_::into_raw(f),
579            )
580        }
581    }
582
583    #[cfg(feature = "v1_18")]
584    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
585    #[doc(alias = "qos")]
586    fn connect_qos_notify<F: Fn(&Self) + Send + Sync + 'static>(&self, f: F) -> SignalHandlerId {
587        unsafe extern "C" fn notify_qos_trampoline<
588            P: IsA<VideoDecoder>,
589            F: Fn(&P) + Send + Sync + 'static,
590        >(
591            this: *mut ffi::GstVideoDecoder,
592            _param_spec: glib::ffi::gpointer,
593            f: glib::ffi::gpointer,
594        ) {
595            unsafe {
596                let f: &F = &*(f as *const F);
597                f(VideoDecoder::from_glib_borrow(this).unsafe_cast_ref())
598            }
599        }
600        unsafe {
601            let f: Box_<F> = Box_::new(f);
602            connect_raw(
603                self.as_ptr() as *mut _,
604                c"notify::qos".as_ptr(),
605                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
606                    notify_qos_trampoline::<Self, F> as *const (),
607                )),
608                Box_::into_raw(f),
609            )
610        }
611    }
612}
613
614impl<O: IsA<VideoDecoder>> VideoDecoderExt for O {}