1use glib::translate::*;
4use gst::subclass::prelude::*;
5
6use crate::{
7 ffi,
8 prelude::*,
9 video_codec_state::{Readable, VideoCodecState},
10 VideoCodecFrame, VideoEncoder,
11};
12
13pub trait VideoEncoderImpl: VideoEncoderImplExt + ElementImpl {
14 fn open(&self) -> Result<(), gst::ErrorMessage> {
18 self.parent_open()
19 }
20
21 fn close(&self) -> Result<(), gst::ErrorMessage> {
25 self.parent_close()
26 }
27
28 fn start(&self) -> Result<(), gst::ErrorMessage> {
32 self.parent_start()
33 }
34
35 fn stop(&self) -> Result<(), gst::ErrorMessage> {
39 self.parent_stop()
40 }
41
42 fn finish(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
46 self.parent_finish()
47 }
48
49 fn set_format(
54 &self,
55 state: &VideoCodecState<'static, Readable>,
56 ) -> Result<(), gst::LoggableError> {
57 self.parent_set_format(state)
58 }
59
60 fn handle_frame(&self, frame: VideoCodecFrame) -> Result<gst::FlowSuccess, gst::FlowError> {
62 self.parent_handle_frame(frame)
63 }
64
65 fn flush(&self) -> bool {
69 self.parent_flush()
70 }
71
72 fn negotiate(&self) -> Result<(), gst::LoggableError> {
80 self.parent_negotiate()
81 }
82
83 fn caps(&self, filter: Option<&gst::Caps>) -> gst::Caps {
84 self.parent_caps(filter)
85 }
86
87 fn sink_event(&self, event: gst::Event) -> bool {
94 self.parent_sink_event(event)
95 }
96
97 fn sink_query(&self, query: &mut gst::QueryRef) -> bool {
103 self.parent_sink_query(query)
104 }
105
106 fn src_event(&self, event: gst::Event) -> bool {
113 self.parent_src_event(event)
114 }
115
116 fn src_query(&self, query: &mut gst::QueryRef) -> bool {
122 self.parent_src_query(query)
123 }
124
125 fn propose_allocation(
130 &self,
131 query: &mut gst::query::Allocation,
132 ) -> Result<(), gst::LoggableError> {
133 self.parent_propose_allocation(query)
134 }
135
136 fn decide_allocation(
143 &self,
144 query: &mut gst::query::Allocation,
145 ) -> Result<(), gst::LoggableError> {
146 self.parent_decide_allocation(query)
147 }
148}
149
150mod sealed {
151 pub trait Sealed {}
152 impl<T: super::VideoEncoderImplExt> Sealed for T {}
153}
154
155pub trait VideoEncoderImplExt: sealed::Sealed + ObjectSubclass {
156 fn parent_open(&self) -> Result<(), gst::ErrorMessage> {
157 unsafe {
158 let data = Self::type_data();
159 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
160 (*parent_class)
161 .open
162 .map(|f| {
163 if from_glib(f(self
164 .obj()
165 .unsafe_cast_ref::<VideoEncoder>()
166 .to_glib_none()
167 .0))
168 {
169 Ok(())
170 } else {
171 Err(gst::error_msg!(
172 gst::CoreError::StateChange,
173 ["Parent function `open` failed"]
174 ))
175 }
176 })
177 .unwrap_or(Ok(()))
178 }
179 }
180
181 fn parent_close(&self) -> Result<(), gst::ErrorMessage> {
182 unsafe {
183 let data = Self::type_data();
184 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
185 (*parent_class)
186 .close
187 .map(|f| {
188 if from_glib(f(self
189 .obj()
190 .unsafe_cast_ref::<VideoEncoder>()
191 .to_glib_none()
192 .0))
193 {
194 Ok(())
195 } else {
196 Err(gst::error_msg!(
197 gst::CoreError::StateChange,
198 ["Parent function `close` failed"]
199 ))
200 }
201 })
202 .unwrap_or(Ok(()))
203 }
204 }
205
206 fn parent_start(&self) -> Result<(), gst::ErrorMessage> {
207 unsafe {
208 let data = Self::type_data();
209 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
210 (*parent_class)
211 .start
212 .map(|f| {
213 if from_glib(f(self
214 .obj()
215 .unsafe_cast_ref::<VideoEncoder>()
216 .to_glib_none()
217 .0))
218 {
219 Ok(())
220 } else {
221 Err(gst::error_msg!(
222 gst::CoreError::StateChange,
223 ["Parent function `start` failed"]
224 ))
225 }
226 })
227 .unwrap_or(Ok(()))
228 }
229 }
230
231 fn parent_stop(&self) -> Result<(), gst::ErrorMessage> {
232 unsafe {
233 let data = Self::type_data();
234 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
235 (*parent_class)
236 .stop
237 .map(|f| {
238 if from_glib(f(self
239 .obj()
240 .unsafe_cast_ref::<VideoEncoder>()
241 .to_glib_none()
242 .0))
243 {
244 Ok(())
245 } else {
246 Err(gst::error_msg!(
247 gst::CoreError::StateChange,
248 ["Parent function `stop` failed"]
249 ))
250 }
251 })
252 .unwrap_or(Ok(()))
253 }
254 }
255
256 fn parent_finish(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
257 unsafe {
258 let data = Self::type_data();
259 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
260 (*parent_class)
261 .finish
262 .map(|f| {
263 try_from_glib(f(self
264 .obj()
265 .unsafe_cast_ref::<VideoEncoder>()
266 .to_glib_none()
267 .0))
268 })
269 .unwrap_or(Ok(gst::FlowSuccess::Ok))
270 }
271 }
272
273 fn parent_set_format(
274 &self,
275 state: &VideoCodecState<'static, Readable>,
276 ) -> Result<(), gst::LoggableError> {
277 unsafe {
278 let data = Self::type_data();
279 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
280 (*parent_class)
281 .set_format
282 .map(|f| {
283 gst::result_from_gboolean!(
284 f(
285 self.obj()
286 .unsafe_cast_ref::<VideoEncoder>()
287 .to_glib_none()
288 .0,
289 state.as_mut_ptr()
290 ),
291 gst::CAT_RUST,
292 "parent function `set_format` failed"
293 )
294 })
295 .unwrap_or(Ok(()))
296 }
297 }
298
299 fn parent_handle_frame(
300 &self,
301 frame: VideoCodecFrame,
302 ) -> Result<gst::FlowSuccess, gst::FlowError> {
303 unsafe {
304 let data = Self::type_data();
305 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
306 (*parent_class)
307 .handle_frame
308 .map(|f| {
309 try_from_glib(f(
310 self.obj()
311 .unsafe_cast_ref::<VideoEncoder>()
312 .to_glib_none()
313 .0,
314 frame.to_glib_none().0,
315 ))
316 })
317 .unwrap_or(Err(gst::FlowError::Error))
318 }
319 }
320
321 fn parent_flush(&self) -> bool {
322 unsafe {
323 let data = Self::type_data();
324 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
325 (*parent_class)
326 .flush
327 .map(|f| {
328 from_glib(f(self
329 .obj()
330 .unsafe_cast_ref::<VideoEncoder>()
331 .to_glib_none()
332 .0))
333 })
334 .unwrap_or(false)
335 }
336 }
337
338 fn parent_negotiate(&self) -> Result<(), gst::LoggableError> {
339 unsafe {
340 let data = Self::type_data();
341 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
342 (*parent_class)
343 .negotiate
344 .map(|f| {
345 gst::result_from_gboolean!(
346 f(self
347 .obj()
348 .unsafe_cast_ref::<VideoEncoder>()
349 .to_glib_none()
350 .0),
351 gst::CAT_RUST,
352 "Parent function `negotiate` failed"
353 )
354 })
355 .unwrap_or(Ok(()))
356 }
357 }
358
359 fn parent_caps(&self, filter: Option<&gst::Caps>) -> gst::Caps {
360 unsafe {
361 let data = Self::type_data();
362 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
363 (*parent_class)
364 .getcaps
365 .map(|f| {
366 from_glib_full(f(
367 self.obj()
368 .unsafe_cast_ref::<VideoEncoder>()
369 .to_glib_none()
370 .0,
371 filter.to_glib_none().0,
372 ))
373 })
374 .unwrap_or_else(|| {
375 self.obj()
376 .unsafe_cast_ref::<VideoEncoder>()
377 .proxy_getcaps(None, filter)
378 })
379 }
380 }
381
382 fn parent_sink_event(&self, event: gst::Event) -> bool {
383 unsafe {
384 let data = Self::type_data();
385 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
386 let f = (*parent_class)
387 .sink_event
388 .expect("Missing parent function `sink_event`");
389 from_glib(f(
390 self.obj()
391 .unsafe_cast_ref::<VideoEncoder>()
392 .to_glib_none()
393 .0,
394 event.into_glib_ptr(),
395 ))
396 }
397 }
398
399 fn parent_sink_query(&self, query: &mut gst::QueryRef) -> bool {
400 unsafe {
401 let data = Self::type_data();
402 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
403 let f = (*parent_class)
404 .sink_query
405 .expect("Missing parent function `sink_query`");
406 from_glib(f(
407 self.obj()
408 .unsafe_cast_ref::<VideoEncoder>()
409 .to_glib_none()
410 .0,
411 query.as_mut_ptr(),
412 ))
413 }
414 }
415
416 fn parent_src_event(&self, event: gst::Event) -> bool {
417 unsafe {
418 let data = Self::type_data();
419 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
420 let f = (*parent_class)
421 .src_event
422 .expect("Missing parent function `src_event`");
423 from_glib(f(
424 self.obj()
425 .unsafe_cast_ref::<VideoEncoder>()
426 .to_glib_none()
427 .0,
428 event.into_glib_ptr(),
429 ))
430 }
431 }
432
433 fn parent_src_query(&self, query: &mut gst::QueryRef) -> bool {
434 unsafe {
435 let data = Self::type_data();
436 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
437 let f = (*parent_class)
438 .src_query
439 .expect("Missing parent function `src_query`");
440 from_glib(f(
441 self.obj()
442 .unsafe_cast_ref::<VideoEncoder>()
443 .to_glib_none()
444 .0,
445 query.as_mut_ptr(),
446 ))
447 }
448 }
449
450 fn parent_propose_allocation(
451 &self,
452 query: &mut gst::query::Allocation,
453 ) -> Result<(), gst::LoggableError> {
454 unsafe {
455 let data = Self::type_data();
456 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
457 (*parent_class)
458 .propose_allocation
459 .map(|f| {
460 gst::result_from_gboolean!(
461 f(
462 self.obj()
463 .unsafe_cast_ref::<VideoEncoder>()
464 .to_glib_none()
465 .0,
466 query.as_mut_ptr(),
467 ),
468 gst::CAT_RUST,
469 "Parent function `propose_allocation` failed",
470 )
471 })
472 .unwrap_or(Ok(()))
473 }
474 }
475
476 fn parent_decide_allocation(
477 &self,
478 query: &mut gst::query::Allocation,
479 ) -> Result<(), gst::LoggableError> {
480 unsafe {
481 let data = Self::type_data();
482 let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoEncoderClass;
483 (*parent_class)
484 .decide_allocation
485 .map(|f| {
486 gst::result_from_gboolean!(
487 f(
488 self.obj()
489 .unsafe_cast_ref::<VideoEncoder>()
490 .to_glib_none()
491 .0,
492 query.as_mut_ptr(),
493 ),
494 gst::CAT_RUST,
495 "Parent function `decide_allocation` failed",
496 )
497 })
498 .unwrap_or(Ok(()))
499 }
500 }
501}
502
503impl<T: VideoEncoderImpl> VideoEncoderImplExt for T {}
504
505unsafe impl<T: VideoEncoderImpl> IsSubclassable<T> for VideoEncoder {
506 fn class_init(klass: &mut glib::Class<Self>) {
507 Self::parent_class_init::<T>(klass);
508 let klass = klass.as_mut();
509 klass.open = Some(video_encoder_open::<T>);
510 klass.close = Some(video_encoder_close::<T>);
511 klass.start = Some(video_encoder_start::<T>);
512 klass.stop = Some(video_encoder_stop::<T>);
513 klass.finish = Some(video_encoder_finish::<T>);
514 klass.set_format = Some(video_encoder_set_format::<T>);
515 klass.handle_frame = Some(video_encoder_handle_frame::<T>);
516 klass.flush = Some(video_encoder_flush::<T>);
517 klass.negotiate = Some(video_encoder_negotiate::<T>);
518 klass.getcaps = Some(video_encoder_getcaps::<T>);
519 klass.sink_event = Some(video_encoder_sink_event::<T>);
520 klass.src_event = Some(video_encoder_src_event::<T>);
521 klass.sink_query = Some(video_encoder_sink_query::<T>);
522 klass.src_query = Some(video_encoder_src_query::<T>);
523 klass.propose_allocation = Some(video_encoder_propose_allocation::<T>);
524 klass.decide_allocation = Some(video_encoder_decide_allocation::<T>);
525 }
526}
527
528unsafe extern "C" fn video_encoder_open<T: VideoEncoderImpl>(
529 ptr: *mut ffi::GstVideoEncoder,
530) -> glib::ffi::gboolean {
531 let instance = &*(ptr as *mut T::Instance);
532 let imp = instance.imp();
533
534 gst::panic_to_error!(imp, false, {
535 match imp.open() {
536 Ok(()) => true,
537 Err(err) => {
538 imp.post_error_message(err);
539 false
540 }
541 }
542 })
543 .into_glib()
544}
545
546unsafe extern "C" fn video_encoder_close<T: VideoEncoderImpl>(
547 ptr: *mut ffi::GstVideoEncoder,
548) -> glib::ffi::gboolean {
549 let instance = &*(ptr as *mut T::Instance);
550 let imp = instance.imp();
551
552 gst::panic_to_error!(imp, false, {
553 match imp.close() {
554 Ok(()) => true,
555 Err(err) => {
556 imp.post_error_message(err);
557 false
558 }
559 }
560 })
561 .into_glib()
562}
563
564unsafe extern "C" fn video_encoder_start<T: VideoEncoderImpl>(
565 ptr: *mut ffi::GstVideoEncoder,
566) -> glib::ffi::gboolean {
567 let instance = &*(ptr as *mut T::Instance);
568 let imp = instance.imp();
569
570 gst::panic_to_error!(imp, false, {
571 match imp.start() {
572 Ok(()) => true,
573 Err(err) => {
574 imp.post_error_message(err);
575 false
576 }
577 }
578 })
579 .into_glib()
580}
581
582unsafe extern "C" fn video_encoder_stop<T: VideoEncoderImpl>(
583 ptr: *mut ffi::GstVideoEncoder,
584) -> glib::ffi::gboolean {
585 let instance = &*(ptr as *mut T::Instance);
586 let imp = instance.imp();
587
588 gst::panic_to_error!(imp, false, {
589 match imp.stop() {
590 Ok(()) => true,
591 Err(err) => {
592 imp.post_error_message(err);
593 false
594 }
595 }
596 })
597 .into_glib()
598}
599
600unsafe extern "C" fn video_encoder_finish<T: VideoEncoderImpl>(
601 ptr: *mut ffi::GstVideoEncoder,
602) -> gst::ffi::GstFlowReturn {
603 let instance = &*(ptr as *mut T::Instance);
604 let imp = instance.imp();
605
606 gst::panic_to_error!(imp, gst::FlowReturn::Error, { imp.finish().into() }).into_glib()
607}
608
609unsafe extern "C" fn video_encoder_set_format<T: VideoEncoderImpl>(
610 ptr: *mut ffi::GstVideoEncoder,
611 state: *mut ffi::GstVideoCodecState,
612) -> glib::ffi::gboolean {
613 let instance = &*(ptr as *mut T::Instance);
614 let imp = instance.imp();
615 ffi::gst_video_codec_state_ref(state);
616 let wrap_state = VideoCodecState::<Readable>::new(state);
617
618 gst::panic_to_error!(imp, false, {
619 match imp.set_format(&wrap_state) {
620 Ok(()) => true,
621 Err(err) => {
622 err.log_with_imp(imp);
623 false
624 }
625 }
626 })
627 .into_glib()
628}
629
630unsafe extern "C" fn video_encoder_handle_frame<T: VideoEncoderImpl>(
631 ptr: *mut ffi::GstVideoEncoder,
632 frame: *mut ffi::GstVideoCodecFrame,
633) -> gst::ffi::GstFlowReturn {
634 let instance = &*(ptr as *mut T::Instance);
635 let imp = instance.imp();
636 let instance = imp.obj();
637 let instance = instance.unsafe_cast_ref::<VideoEncoder>();
638 let wrap_frame = VideoCodecFrame::new(frame, instance);
639
640 gst::panic_to_error!(imp, gst::FlowReturn::Error, {
641 imp.handle_frame(wrap_frame).into()
642 })
643 .into_glib()
644}
645
646unsafe extern "C" fn video_encoder_flush<T: VideoEncoderImpl>(
647 ptr: *mut ffi::GstVideoEncoder,
648) -> glib::ffi::gboolean {
649 let instance = &*(ptr as *mut T::Instance);
650 let imp = instance.imp();
651
652 gst::panic_to_error!(imp, false, { VideoEncoderImpl::flush(imp) }).into_glib()
653}
654
655unsafe extern "C" fn video_encoder_negotiate<T: VideoEncoderImpl>(
656 ptr: *mut ffi::GstVideoEncoder,
657) -> glib::ffi::gboolean {
658 let instance = &*(ptr as *mut T::Instance);
659 let imp = instance.imp();
660
661 gst::panic_to_error!(imp, false, {
662 match imp.negotiate() {
663 Ok(()) => true,
664 Err(err) => {
665 err.log_with_imp(imp);
666 false
667 }
668 }
669 })
670 .into_glib()
671}
672
673unsafe extern "C" fn video_encoder_getcaps<T: VideoEncoderImpl>(
674 ptr: *mut ffi::GstVideoEncoder,
675 filter: *mut gst::ffi::GstCaps,
676) -> *mut gst::ffi::GstCaps {
677 let instance = &*(ptr as *mut T::Instance);
678 let imp = instance.imp();
679
680 gst::panic_to_error!(imp, gst::Caps::new_empty(), {
681 VideoEncoderImpl::caps(
682 imp,
683 Option::<gst::Caps>::from_glib_borrow(filter)
684 .as_ref()
685 .as_ref(),
686 )
687 })
688 .into_glib_ptr()
689}
690
691unsafe extern "C" fn video_encoder_sink_event<T: VideoEncoderImpl>(
692 ptr: *mut ffi::GstVideoEncoder,
693 event: *mut gst::ffi::GstEvent,
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, { imp.sink_event(from_glib_full(event)) }).into_glib()
699}
700
701unsafe extern "C" fn video_encoder_sink_query<T: VideoEncoderImpl>(
702 ptr: *mut ffi::GstVideoEncoder,
703 query: *mut gst::ffi::GstQuery,
704) -> glib::ffi::gboolean {
705 let instance = &*(ptr as *mut T::Instance);
706 let imp = instance.imp();
707
708 gst::panic_to_error!(imp, false, {
709 imp.sink_query(gst::QueryRef::from_mut_ptr(query))
710 })
711 .into_glib()
712}
713
714unsafe extern "C" fn video_encoder_src_event<T: VideoEncoderImpl>(
715 ptr: *mut ffi::GstVideoEncoder,
716 event: *mut gst::ffi::GstEvent,
717) -> glib::ffi::gboolean {
718 let instance = &*(ptr as *mut T::Instance);
719 let imp = instance.imp();
720
721 gst::panic_to_error!(imp, false, { imp.src_event(from_glib_full(event)) }).into_glib()
722}
723
724unsafe extern "C" fn video_encoder_src_query<T: VideoEncoderImpl>(
725 ptr: *mut ffi::GstVideoEncoder,
726 query: *mut gst::ffi::GstQuery,
727) -> glib::ffi::gboolean {
728 let instance = &*(ptr as *mut T::Instance);
729 let imp = instance.imp();
730
731 gst::panic_to_error!(imp, false, {
732 imp.src_query(gst::QueryRef::from_mut_ptr(query))
733 })
734 .into_glib()
735}
736
737unsafe extern "C" fn video_encoder_propose_allocation<T: VideoEncoderImpl>(
738 ptr: *mut ffi::GstVideoEncoder,
739 query: *mut gst::ffi::GstQuery,
740) -> glib::ffi::gboolean {
741 let instance = &*(ptr as *mut T::Instance);
742 let imp = instance.imp();
743 let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
744 gst::QueryViewMut::Allocation(allocation) => allocation,
745 _ => unreachable!(),
746 };
747
748 gst::panic_to_error!(imp, false, {
749 match imp.propose_allocation(query) {
750 Ok(()) => true,
751 Err(err) => {
752 err.log_with_imp(imp);
753 false
754 }
755 }
756 })
757 .into_glib()
758}
759
760unsafe extern "C" fn video_encoder_decide_allocation<T: VideoEncoderImpl>(
761 ptr: *mut ffi::GstVideoEncoder,
762 query: *mut gst::ffi::GstQuery,
763) -> glib::ffi::gboolean {
764 let instance = &*(ptr as *mut T::Instance);
765 let imp = instance.imp();
766 let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
767 gst::QueryViewMut::Allocation(allocation) => allocation,
768 _ => unreachable!(),
769 };
770
771 gst::panic_to_error!(imp, false, {
772 match imp.decide_allocation(query) {
773 Ok(()) => true,
774 Err(err) => {
775 err.log_with_imp(imp);
776 false
777 }
778 }
779 })
780 .into_glib()
781}