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