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