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    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    let instance = &*(ptr as *mut T::Instance);
184    let imp = instance.imp();
185
186    gst::panic_to_error!(imp, gst::Caps::new_empty(), {
187        RTPBasePayloadImpl::caps(
188            imp,
189            &from_glib_borrow(pad),
190            Option::<gst::Caps>::from_glib_borrow(filter)
191                .as_ref()
192                .as_ref(),
193        )
194    })
195    .into_glib_ptr()
196}
197
198unsafe extern "C" fn rtp_base_payload_set_caps<T: RTPBasePayloadImpl>(
199    ptr: *mut ffi::GstRTPBasePayload,
200    caps: *mut gst::ffi::GstCaps,
201) -> glib::ffi::gboolean {
202    let instance = &*(ptr as *mut T::Instance);
203    let imp = instance.imp();
204    let caps = from_glib_borrow(caps);
205
206    gst::panic_to_error!(imp, false, {
207        match imp.set_caps(&caps) {
208            Ok(()) => true,
209            Err(err) => {
210                err.log_with_imp(imp);
211                false
212            }
213        }
214    })
215    .into_glib()
216}
217
218unsafe extern "C" fn rtp_base_payload_handle_buffer<T: RTPBasePayloadImpl>(
219    ptr: *mut ffi::GstRTPBasePayload,
220    buffer: *mut gst::ffi::GstBuffer,
221) -> gst::ffi::GstFlowReturn {
222    let instance = &*(ptr as *mut T::Instance);
223    let imp = instance.imp();
224
225    gst::panic_to_error!(imp, gst::FlowReturn::Error, {
226        imp.handle_buffer(from_glib_full(buffer)).into()
227    })
228    .into_glib()
229}
230
231unsafe extern "C" fn rtp_base_payload_query<T: RTPBasePayloadImpl>(
232    ptr: *mut ffi::GstRTPBasePayload,
233    pad: *mut gst::ffi::GstPad,
234    query: *mut gst::ffi::GstQuery,
235) -> glib::ffi::gboolean {
236    let instance = &*(ptr as *mut T::Instance);
237    let imp = instance.imp();
238
239    gst::panic_to_error!(imp, false, {
240        RTPBasePayloadImpl::query(
241            imp,
242            &from_glib_borrow(pad),
243            gst::QueryRef::from_mut_ptr(query),
244        )
245    })
246    .into_glib()
247}
248
249unsafe extern "C" fn rtp_base_payload_sink_event<T: RTPBasePayloadImpl>(
250    ptr: *mut ffi::GstRTPBasePayload,
251    event: *mut gst::ffi::GstEvent,
252) -> glib::ffi::gboolean {
253    let instance = &*(ptr as *mut T::Instance);
254    let imp = instance.imp();
255
256    gst::panic_to_error!(imp, false, { imp.sink_event(from_glib_full(event)) }).into_glib()
257}
258
259unsafe extern "C" fn rtp_base_payload_src_event<T: RTPBasePayloadImpl>(
260    ptr: *mut ffi::GstRTPBasePayload,
261    event: *mut gst::ffi::GstEvent,
262) -> glib::ffi::gboolean {
263    let instance = &*(ptr as *mut T::Instance);
264    let imp = instance.imp();
265
266    gst::panic_to_error!(imp, false, { imp.src_event(from_glib_full(event)) }).into_glib()
267}