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