Skip to main content

gstreamer_rtp/subclass/
rtp_base_payload.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::translate::*;
4use gst::subclass::prelude::*;
5
6use crate::{RTPBasePayload, ffi, prelude::*};
7
8pub trait RTPBasePayloadImpl: ElementImpl + ObjectSubclass<Type: IsA<RTPBasePayload>> {
9    fn caps(&self, pad: &gst::Pad, filter: Option<&gst::Caps>) -> gst::Caps {
10        self.parent_caps(pad, filter)
11    }
12
13    fn set_caps(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
14        self.parent_set_caps(caps)
15    }
16
17    fn handle_buffer(&self, buffer: gst::Buffer) -> Result<gst::FlowSuccess, gst::FlowError> {
18        self.parent_handle_buffer(buffer)
19    }
20
21    fn query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
22        RTPBasePayloadImplExt::parent_query(self, pad, query)
23    }
24
25    fn sink_event(&self, event: gst::Event) -> bool {
26        self.parent_sink_event(event)
27    }
28
29    fn src_event(&self, event: gst::Event) -> bool {
30        self.parent_src_event(event)
31    }
32}
33
34pub trait RTPBasePayloadImplExt: RTPBasePayloadImpl {
35    fn parent_caps(&self, pad: &gst::Pad, filter: Option<&gst::Caps>) -> gst::Caps {
36        unsafe {
37            let data = Self::type_data();
38            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPBasePayloadClass;
39            let f = (*parent_class)
40                .get_caps
41                .expect("Missing parent function `get_caps`");
42            from_glib_full(f(
43                self.obj()
44                    .unsafe_cast_ref::<RTPBasePayload>()
45                    .to_glib_none()
46                    .0,
47                pad.to_glib_none().0,
48                filter.to_glib_none().0,
49            ))
50        }
51    }
52
53    fn parent_set_caps(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
54        unsafe {
55            let data = Self::type_data();
56            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPBasePayloadClass;
57            (*parent_class)
58                .set_caps
59                .map(|f| {
60                    gst::result_from_gboolean!(
61                        f(
62                            self.obj()
63                                .unsafe_cast_ref::<RTPBasePayload>()
64                                .to_glib_none()
65                                .0,
66                            caps.to_glib_none().0
67                        ),
68                        gst::CAT_RUST,
69                        "Parent function `set_caps` failed"
70                    )
71                })
72                .unwrap_or_else(|| {
73                    // Trigger negotiation as the base class does
74                    self.obj()
75                        .unsafe_cast_ref::<RTPBasePayload>()
76                        .set_outcaps(None)
77                        .map_err(|_| gst::loggable_error!(gst::CAT_RUST, "Failed to negotiate"))
78                })
79        }
80    }
81
82    fn parent_handle_buffer(
83        &self,
84        buffer: gst::Buffer,
85    ) -> Result<gst::FlowSuccess, gst::FlowError> {
86        unsafe {
87            let data = Self::type_data();
88            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPBasePayloadClass;
89            (*parent_class)
90                .handle_buffer
91                .map(|f| {
92                    try_from_glib(f(
93                        self.obj()
94                            .unsafe_cast_ref::<RTPBasePayload>()
95                            .to_glib_none()
96                            .0,
97                        buffer.into_glib_ptr(),
98                    ))
99                })
100                .unwrap_or(Err(gst::FlowError::Error))
101        }
102    }
103
104    fn parent_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
105        unsafe {
106            let data = Self::type_data();
107            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPBasePayloadClass;
108            (*parent_class)
109                .query
110                .map(|f| {
111                    from_glib(f(
112                        self.obj()
113                            .unsafe_cast_ref::<RTPBasePayload>()
114                            .to_glib_none()
115                            .0,
116                        pad.to_glib_none().0,
117                        query.as_mut_ptr(),
118                    ))
119                })
120                .unwrap_or(false)
121        }
122    }
123
124    fn parent_sink_event(&self, event: gst::Event) -> bool {
125        unsafe {
126            let data = Self::type_data();
127            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPBasePayloadClass;
128            (*parent_class)
129                .sink_event
130                .map(|f| {
131                    from_glib(f(
132                        self.obj()
133                            .unsafe_cast_ref::<RTPBasePayload>()
134                            .to_glib_none()
135                            .0,
136                        event.into_glib_ptr(),
137                    ))
138                })
139                .unwrap_or(false)
140        }
141    }
142
143    fn parent_src_event(&self, event: gst::Event) -> bool {
144        unsafe {
145            let data = Self::type_data();
146            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPBasePayloadClass;
147            (*parent_class)
148                .src_event
149                .map(|f| {
150                    from_glib(f(
151                        self.obj()
152                            .unsafe_cast_ref::<RTPBasePayload>()
153                            .to_glib_none()
154                            .0,
155                        event.into_glib_ptr(),
156                    ))
157                })
158                .unwrap_or(false)
159        }
160    }
161}
162
163impl<T: RTPBasePayloadImpl> RTPBasePayloadImplExt for T {}
164
165unsafe impl<T: RTPBasePayloadImpl> IsSubclassable<T> for RTPBasePayload {
166    fn class_init(klass: &mut glib::Class<Self>) {
167        Self::parent_class_init::<T>(klass);
168        let klass = klass.as_mut();
169        klass.get_caps = Some(rtp_base_payload_get_caps::<T>);
170        klass.set_caps = Some(rtp_base_payload_set_caps::<T>);
171        klass.handle_buffer = Some(rtp_base_payload_handle_buffer::<T>);
172        klass.query = Some(rtp_base_payload_query::<T>);
173        klass.sink_event = Some(rtp_base_payload_sink_event::<T>);
174        klass.src_event = Some(rtp_base_payload_src_event::<T>);
175    }
176}
177
178unsafe extern "C" fn rtp_base_payload_get_caps<T: RTPBasePayloadImpl>(
179    ptr: *mut ffi::GstRTPBasePayload,
180    pad: *mut gst::ffi::GstPad,
181    filter: *mut gst::ffi::GstCaps,
182) -> *mut gst::ffi::GstCaps {
183    unsafe {
184        let instance = &*(ptr as *mut T::Instance);
185        let imp = instance.imp();
186
187        gst::panic_to_error!(imp, gst::Caps::new_empty(), {
188            RTPBasePayloadImpl::caps(
189                imp,
190                &from_glib_borrow(pad),
191                Option::<gst::Caps>::from_glib_borrow(filter)
192                    .as_ref()
193                    .as_ref(),
194            )
195        })
196        .into_glib_ptr()
197    }
198}
199
200unsafe extern "C" fn rtp_base_payload_set_caps<T: RTPBasePayloadImpl>(
201    ptr: *mut ffi::GstRTPBasePayload,
202    caps: *mut gst::ffi::GstCaps,
203) -> glib::ffi::gboolean {
204    unsafe {
205        let instance = &*(ptr as *mut T::Instance);
206        let imp = instance.imp();
207        let caps = from_glib_borrow(caps);
208
209        gst::panic_to_error!(imp, false, {
210            match imp.set_caps(&caps) {
211                Ok(()) => true,
212                Err(err) => {
213                    err.log_with_imp(imp);
214                    false
215                }
216            }
217        })
218        .into_glib()
219    }
220}
221
222unsafe extern "C" fn rtp_base_payload_handle_buffer<T: RTPBasePayloadImpl>(
223    ptr: *mut ffi::GstRTPBasePayload,
224    buffer: *mut gst::ffi::GstBuffer,
225) -> gst::ffi::GstFlowReturn {
226    unsafe {
227        let instance = &*(ptr as *mut T::Instance);
228        let imp = instance.imp();
229
230        gst::panic_to_error!(imp, gst::FlowReturn::Error, {
231            imp.handle_buffer(from_glib_full(buffer)).into()
232        })
233        .into_glib()
234    }
235}
236
237unsafe extern "C" fn rtp_base_payload_query<T: RTPBasePayloadImpl>(
238    ptr: *mut ffi::GstRTPBasePayload,
239    pad: *mut gst::ffi::GstPad,
240    query: *mut gst::ffi::GstQuery,
241) -> glib::ffi::gboolean {
242    unsafe {
243        let instance = &*(ptr as *mut T::Instance);
244        let imp = instance.imp();
245
246        gst::panic_to_error!(imp, false, {
247            RTPBasePayloadImpl::query(
248                imp,
249                &from_glib_borrow(pad),
250                gst::QueryRef::from_mut_ptr(query),
251            )
252        })
253        .into_glib()
254    }
255}
256
257unsafe extern "C" fn rtp_base_payload_sink_event<T: RTPBasePayloadImpl>(
258    ptr: *mut ffi::GstRTPBasePayload,
259    event: *mut gst::ffi::GstEvent,
260) -> glib::ffi::gboolean {
261    unsafe {
262        let instance = &*(ptr as *mut T::Instance);
263        let imp = instance.imp();
264
265        gst::panic_to_error!(imp, false, { imp.sink_event(from_glib_full(event)) }).into_glib()
266    }
267}
268
269unsafe extern "C" fn rtp_base_payload_src_event<T: RTPBasePayloadImpl>(
270    ptr: *mut ffi::GstRTPBasePayload,
271    event: *mut gst::ffi::GstEvent,
272) -> glib::ffi::gboolean {
273    unsafe {
274        let instance = &*(ptr as *mut T::Instance);
275        let imp = instance.imp();
276
277        gst::panic_to_error!(imp, false, { imp.src_event(from_glib_full(event)) }).into_glib()
278    }
279}