gstreamer_audio/
audio_decoder.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{mem, ptr};
4
5use glib::{prelude::*, translate::*};
6
7use crate::{ffi, AudioDecoder, AudioInfo};
8
9extern "C" {
10    fn _gst_audio_decoder_error(
11        dec: *mut ffi::GstAudioDecoder,
12        weight: i32,
13        domain: glib::ffi::GQuark,
14        code: i32,
15        txt: *mut libc::c_char,
16        debug: *mut libc::c_char,
17        file: *const libc::c_char,
18        function: *const libc::c_char,
19        line: i32,
20    ) -> gst::ffi::GstFlowReturn;
21}
22
23pub trait AudioDecoderExtManual: IsA<AudioDecoder> + 'static {
24    /// Negotiate with downstream elements to currently configured [`AudioInfo`][crate::AudioInfo].
25    /// Unmark GST_PAD_FLAG_NEED_RECONFIGURE in any case. But mark it again if
26    /// negotiate fails.
27    ///
28    /// # Returns
29    ///
30    /// [`true`] if the negotiation succeeded, else [`false`].
31    #[doc(alias = "gst_audio_decoder_negotiate")]
32    fn negotiate(&self) -> Result<(), gst::FlowError> {
33        unsafe {
34            let ret = from_glib(ffi::gst_audio_decoder_negotiate(
35                self.as_ref().to_glib_none().0,
36            ));
37            if ret {
38                Ok(())
39            } else {
40                Err(gst::FlowError::NotNegotiated)
41            }
42        }
43    }
44
45    /// Configure output caps on the srcpad of `self`. Similar to
46    /// [`set_output_format()`][Self::set_output_format()], but allows subclasses to specify
47    /// output caps that can't be expressed via [`AudioInfo`][crate::AudioInfo] e.g. caps that have
48    /// caps features.
49    /// ## `caps`
50    /// (fixed) [`gst::Caps`][crate::gst::Caps]
51    ///
52    /// # Returns
53    ///
54    /// [`true`] on success.
55    #[cfg(feature = "v1_16")]
56    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
57    #[doc(alias = "gst_audio_decoder_set_output_caps")]
58    fn set_output_caps(&self, caps: &gst::Caps) -> Result<(), gst::FlowError> {
59        unsafe {
60            let ret = from_glib(ffi::gst_audio_decoder_set_output_caps(
61                self.as_ref().to_glib_none().0,
62                caps.to_glib_none().0,
63            ));
64            if ret {
65                Ok(())
66            } else {
67                Err(gst::FlowError::NotNegotiated)
68            }
69        }
70    }
71
72    /// Configure output info on the srcpad of `self`.
73    /// ## `info`
74    /// [`AudioInfo`][crate::AudioInfo]
75    ///
76    /// # Returns
77    ///
78    /// [`true`] on success.
79    #[doc(alias = "gst_audio_decoder_set_output_format")]
80    fn set_output_format(&self, info: &AudioInfo) -> Result<(), gst::FlowError> {
81        unsafe {
82            let ret = from_glib(ffi::gst_audio_decoder_set_output_format(
83                self.as_ref().to_glib_none().0,
84                info.to_glib_none().0,
85            ));
86            if ret {
87                Ok(())
88            } else {
89                Err(gst::FlowError::NotNegotiated)
90            }
91        }
92    }
93
94    /// Lets [`AudioDecoder`][crate::AudioDecoder] sub-classes to know the memory `allocator`
95    /// used by the base class and its `params`.
96    ///
97    /// Unref the `allocator` after use it.
98    ///
99    /// # Returns
100    ///
101    ///
102    /// ## `allocator`
103    /// the [`gst::Allocator`][crate::gst::Allocator]
104    /// used
105    ///
106    /// ## `params`
107    /// the
108    /// [`gst::AllocationParams`][crate::gst::AllocationParams] of `allocator`
109    #[doc(alias = "get_allocator")]
110    #[doc(alias = "gst_audio_decoder_get_allocator")]
111    fn allocator(&self) -> (Option<gst::Allocator>, gst::AllocationParams) {
112        unsafe {
113            let mut allocator = ptr::null_mut();
114            let mut params = mem::MaybeUninit::uninit();
115            ffi::gst_audio_decoder_get_allocator(
116                self.as_ref().to_glib_none().0,
117                &mut allocator,
118                params.as_mut_ptr(),
119            );
120            (from_glib_full(allocator), params.assume_init().into())
121        }
122    }
123
124    #[allow(clippy::too_many_arguments)]
125    fn error<T: gst::MessageErrorDomain>(
126        &self,
127        weight: i32,
128        code: T,
129        message: Option<&str>,
130        debug: Option<&str>,
131        file: &str,
132        function: &str,
133        line: u32,
134    ) -> Result<gst::FlowSuccess, gst::FlowError> {
135        unsafe {
136            try_from_glib(_gst_audio_decoder_error(
137                self.as_ref().to_glib_none().0,
138                weight,
139                T::domain().into_glib(),
140                code.code(),
141                message.to_glib_full(),
142                debug.to_glib_full(),
143                file.to_glib_none().0,
144                function.to_glib_none().0,
145                line as i32,
146            ))
147        }
148    }
149
150    fn sink_pad(&self) -> &gst::Pad {
151        unsafe {
152            let elt = &*(self.as_ptr() as *const ffi::GstAudioDecoder);
153            &*(&elt.sinkpad as *const *mut gst::ffi::GstPad as *const gst::Pad)
154        }
155    }
156
157    fn src_pad(&self) -> &gst::Pad {
158        unsafe {
159            let elt = &*(self.as_ptr() as *const ffi::GstAudioDecoder);
160            &*(&elt.srcpad as *const *mut gst::ffi::GstPad as *const gst::Pad)
161        }
162    }
163
164    fn input_segment(&self) -> gst::Segment {
165        unsafe {
166            let ptr: &ffi::GstAudioDecoder = &*(self.as_ptr() as *const _);
167            glib::ffi::g_rec_mutex_lock(mut_override(&ptr.stream_lock));
168            let segment = ptr.input_segment;
169            glib::ffi::g_rec_mutex_unlock(mut_override(&ptr.stream_lock));
170            from_glib_none(&segment as *const gst::ffi::GstSegment)
171        }
172    }
173
174    fn output_segment(&self) -> gst::Segment {
175        unsafe {
176            let ptr: &ffi::GstAudioDecoder = &*(self.as_ptr() as *const _);
177            glib::ffi::g_rec_mutex_lock(mut_override(&ptr.stream_lock));
178            let segment = ptr.output_segment;
179            glib::ffi::g_rec_mutex_unlock(mut_override(&ptr.stream_lock));
180            from_glib_none(&segment as *const gst::ffi::GstSegment)
181        }
182    }
183}
184
185impl<O: IsA<AudioDecoder>> AudioDecoderExtManual for O {}
186
187#[macro_export]
188macro_rules! audio_decoder_error(
189    ($obj:expr, $weight:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
190        use $crate::prelude::AudioDecoderExtManual;
191        $obj.error(
192            $weight,
193            $err,
194            Some(&format!($($msg)*)),
195            Some(&format!($($debug)*)),
196            file!(),
197            $crate::glib::function_name!(),
198            line!(),
199        )
200    }};
201    ($obj:expr, $weight:expr, $err:expr, ($($msg:tt)*)) => { {
202        use $crate::prelude::AudioDecoderExtManual;
203        $obj.error(
204            $weight,
205            $err,
206            Some(&format!($($msg)*)),
207            None,
208            file!(),
209            $crate::glib::function_name!(),
210            line!(),
211        )
212    }};
213    ($obj:expr, $weight:expr, $err:expr, [$($debug:tt)*]) => { {
214        use $crate::prelude::AudioDecoderExtManual;
215        $obj.error(
216            $weight,
217            $err,
218            None,
219            Some(&format!($($debug)*)),
220            file!(),
221            $crate::glib::function_name!(),
222            line!(),
223        )
224    }};
225);