gstreamer_audio/subclass/
audio_encoder.rs

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