gstreamer_audio/subclass/
audio_encoder.rs1use std::ptr;
4
5use glib::translate::*;
6use gst::subclass::prelude::*;
7
8use crate::{ffi, prelude::*, AudioEncoder, AudioInfo};
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 let instance = &*(ptr as *mut T::Instance);
464 let imp = instance.imp();
465
466 gst::panic_to_error!(imp, false, {
467 match imp.open() {
468 Ok(()) => true,
469 Err(err) => {
470 imp.post_error_message(err);
471 false
472 }
473 }
474 })
475 .into_glib()
476}
477
478unsafe extern "C" fn audio_encoder_close<T: AudioEncoderImpl>(
479 ptr: *mut ffi::GstAudioEncoder,
480) -> glib::ffi::gboolean {
481 let instance = &*(ptr as *mut T::Instance);
482 let imp = instance.imp();
483
484 gst::panic_to_error!(imp, false, {
485 match imp.close() {
486 Ok(()) => true,
487 Err(err) => {
488 imp.post_error_message(err);
489 false
490 }
491 }
492 })
493 .into_glib()
494}
495
496unsafe extern "C" fn audio_encoder_start<T: AudioEncoderImpl>(
497 ptr: *mut ffi::GstAudioEncoder,
498) -> glib::ffi::gboolean {
499 let instance = &*(ptr as *mut T::Instance);
500 let imp = instance.imp();
501
502 gst::panic_to_error!(imp, false, {
503 match imp.start() {
504 Ok(()) => true,
505 Err(err) => {
506 imp.post_error_message(err);
507 false
508 }
509 }
510 })
511 .into_glib()
512}
513
514unsafe extern "C" fn audio_encoder_stop<T: AudioEncoderImpl>(
515 ptr: *mut ffi::GstAudioEncoder,
516) -> glib::ffi::gboolean {
517 let instance = &*(ptr as *mut T::Instance);
518 let imp = instance.imp();
519
520 gst::panic_to_error!(imp, false, {
521 match imp.stop() {
522 Ok(()) => true,
523 Err(err) => {
524 imp.post_error_message(err);
525 false
526 }
527 }
528 })
529 .into_glib()
530}
531
532unsafe extern "C" fn audio_encoder_set_format<T: AudioEncoderImpl>(
533 ptr: *mut ffi::GstAudioEncoder,
534 info: *mut ffi::GstAudioInfo,
535) -> glib::ffi::gboolean {
536 let instance = &*(ptr as *mut T::Instance);
537 let imp = instance.imp();
538
539 gst::panic_to_error!(imp, false, {
540 match imp.set_format(&from_glib_none(info)) {
541 Ok(()) => true,
542 Err(err) => {
543 err.log_with_imp(imp);
544 false
545 }
546 }
547 })
548 .into_glib()
549}
550
551unsafe extern "C" fn audio_encoder_handle_frame<T: AudioEncoderImpl>(
552 ptr: *mut ffi::GstAudioEncoder,
553 buffer: *mut *mut gst::ffi::GstBuffer,
554) -> gst::ffi::GstFlowReturn {
555 let buffer = buffer as *mut gst::ffi::GstBuffer;
557 let instance = &*(ptr as *mut T::Instance);
558 let imp = instance.imp();
559
560 gst::panic_to_error!(imp, gst::FlowReturn::Error, {
561 imp.handle_frame(Option::<gst::Buffer>::from_glib_none(buffer).as_ref())
562 .into()
563 })
564 .into_glib()
565}
566
567unsafe extern "C" fn audio_encoder_pre_push<T: AudioEncoderImpl>(
568 ptr: *mut ffi::GstAudioEncoder,
569 buffer: *mut *mut gst::ffi::GstBuffer,
570) -> gst::ffi::GstFlowReturn {
571 let instance = &*(ptr as *mut T::Instance);
572 let imp = instance.imp();
573
574 gst::panic_to_error!(imp, gst::FlowReturn::Error, {
575 match imp.pre_push(from_glib_full(*buffer)) {
576 Ok(Some(new_buffer)) => {
577 *buffer = new_buffer.into_glib_ptr();
578 Ok(gst::FlowSuccess::Ok)
579 }
580 Ok(None) => {
581 *buffer = ptr::null_mut();
582 Ok(gst::FlowSuccess::Ok)
583 }
584 Err(err) => Err(err),
585 }
586 .into()
587 })
588 .into_glib()
589}
590
591unsafe extern "C" fn audio_encoder_flush<T: AudioEncoderImpl>(ptr: *mut ffi::GstAudioEncoder) {
592 let instance = &*(ptr as *mut T::Instance);
593 let imp = instance.imp();
594
595 gst::panic_to_error!(imp, (), { AudioEncoderImpl::flush(imp,) })
596}
597
598unsafe extern "C" fn audio_encoder_negotiate<T: AudioEncoderImpl>(
599 ptr: *mut ffi::GstAudioEncoder,
600) -> glib::ffi::gboolean {
601 let instance = &*(ptr as *mut T::Instance);
602 let imp = instance.imp();
603
604 gst::panic_to_error!(imp, false, {
605 match imp.negotiate() {
606 Ok(()) => true,
607 Err(err) => {
608 err.log_with_imp(imp);
609 false
610 }
611 }
612 })
613 .into_glib()
614}
615
616unsafe extern "C" fn audio_encoder_getcaps<T: AudioEncoderImpl>(
617 ptr: *mut ffi::GstAudioEncoder,
618 filter: *mut gst::ffi::GstCaps,
619) -> *mut gst::ffi::GstCaps {
620 let instance = &*(ptr as *mut T::Instance);
621 let imp = instance.imp();
622
623 gst::panic_to_error!(imp, gst::Caps::new_empty(), {
624 AudioEncoderImpl::caps(
625 imp,
626 Option::<gst::Caps>::from_glib_borrow(filter)
627 .as_ref()
628 .as_ref(),
629 )
630 })
631 .into_glib_ptr()
632}
633
634unsafe extern "C" fn audio_encoder_sink_event<T: AudioEncoderImpl>(
635 ptr: *mut ffi::GstAudioEncoder,
636 event: *mut gst::ffi::GstEvent,
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, { imp.sink_event(from_glib_full(event)) }).into_glib()
642}
643
644unsafe extern "C" fn audio_encoder_sink_query<T: AudioEncoderImpl>(
645 ptr: *mut ffi::GstAudioEncoder,
646 query: *mut gst::ffi::GstQuery,
647) -> glib::ffi::gboolean {
648 let instance = &*(ptr as *mut T::Instance);
649 let imp = instance.imp();
650
651 gst::panic_to_error!(imp, false, {
652 imp.sink_query(gst::QueryRef::from_mut_ptr(query))
653 })
654 .into_glib()
655}
656
657unsafe extern "C" fn audio_encoder_src_event<T: AudioEncoderImpl>(
658 ptr: *mut ffi::GstAudioEncoder,
659 event: *mut gst::ffi::GstEvent,
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, { imp.src_event(from_glib_full(event)) }).into_glib()
665}
666
667unsafe extern "C" fn audio_encoder_src_query<T: AudioEncoderImpl>(
668 ptr: *mut ffi::GstAudioEncoder,
669 query: *mut gst::ffi::GstQuery,
670) -> glib::ffi::gboolean {
671 let instance = &*(ptr as *mut T::Instance);
672 let imp = instance.imp();
673
674 gst::panic_to_error!(imp, false, {
675 imp.src_query(gst::QueryRef::from_mut_ptr(query))
676 })
677 .into_glib()
678}
679
680unsafe extern "C" fn audio_encoder_propose_allocation<T: AudioEncoderImpl>(
681 ptr: *mut ffi::GstAudioEncoder,
682 query: *mut gst::ffi::GstQuery,
683) -> glib::ffi::gboolean {
684 let instance = &*(ptr as *mut T::Instance);
685 let imp = instance.imp();
686 let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
687 gst::QueryViewMut::Allocation(allocation) => allocation,
688 _ => unreachable!(),
689 };
690
691 gst::panic_to_error!(imp, false, {
692 match imp.propose_allocation(query) {
693 Ok(()) => true,
694 Err(err) => {
695 err.log_with_imp(imp);
696 false
697 }
698 }
699 })
700 .into_glib()
701}
702
703unsafe extern "C" fn audio_encoder_decide_allocation<T: AudioEncoderImpl>(
704 ptr: *mut ffi::GstAudioEncoder,
705 query: *mut gst::ffi::GstQuery,
706) -> glib::ffi::gboolean {
707 let instance = &*(ptr as *mut T::Instance);
708 let imp = instance.imp();
709 let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
710 gst::QueryViewMut::Allocation(allocation) => allocation,
711 _ => unreachable!(),
712 };
713
714 gst::panic_to_error!(imp, false, {
715 match imp.decide_allocation(query) {
716 Ok(()) => true,
717 Err(err) => {
718 err.log_with_imp(imp);
719 false
720 }
721 }
722 })
723 .into_glib()
724}