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