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