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