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