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