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