gstreamer_rtp/subclass/
rtp_base_depayload.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::ptr;
4
5use glib::translate::*;
6use gst::subclass::prelude::*;
7
8use crate::{ffi, prelude::*, RTPBaseDepayload};
9
10pub trait RTPBaseDepayloadImpl: ElementImpl + ObjectSubclass<Type: IsA<RTPBaseDepayload>> {
11    /// configure the depayloader
12    fn set_caps(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
13        self.parent_set_caps(caps)
14    }
15
16    /// custom event handling
17    fn handle_event(&self, event: gst::Event) -> bool {
18        self.parent_handle_event(event)
19    }
20
21    /// signal the depayloader about packet loss
22    fn packet_lost(&self, event: &gst::EventRef) -> bool {
23        self.parent_packet_lost(event)
24    }
25
26    /// Same as the process virtual function, but slightly more
27    /// efficient, since it is passed the rtp buffer structure that has already
28    /// been mapped (with GST_MAP_READ) by the base class and thus does not have
29    /// to be mapped again by the subclass. Can be used by the subclass to process
30    /// incoming rtp packets. If the subclass returns a buffer without a valid
31    /// timestamp, the timestamp of the input buffer will be applied to the result
32    /// buffer and the output buffer will be pushed out. If this function returns
33    /// [`None`], nothing is pushed out. Since: 1.6.
34    fn process_rtp_packet(
35        &self,
36        rtp_buffer: &crate::RTPBuffer<crate::rtp_buffer::Readable>,
37    ) -> Option<gst::Buffer> {
38        self.parent_process_rtp_packet(rtp_buffer)
39    }
40}
41
42pub trait RTPBaseDepayloadImplExt: RTPBaseDepayloadImpl {
43    fn parent_set_caps(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
44        unsafe {
45            let data = Self::type_data();
46            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPBaseDepayloadClass;
47            (*parent_class)
48                .set_caps
49                .map(|f| {
50                    gst::result_from_gboolean!(
51                        f(
52                            self.obj()
53                                .unsafe_cast_ref::<RTPBaseDepayload>()
54                                .to_glib_none()
55                                .0,
56                            caps.to_glib_none().0
57                        ),
58                        gst::CAT_RUST,
59                        "Parent function `set_caps` failed"
60                    )
61                })
62                .unwrap_or(Ok(()))
63        }
64    }
65
66    fn parent_handle_event(&self, event: gst::Event) -> bool {
67        unsafe {
68            let data = Self::type_data();
69            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPBaseDepayloadClass;
70            (*parent_class)
71                .handle_event
72                .map(|f| {
73                    from_glib(f(
74                        self.obj()
75                            .unsafe_cast_ref::<RTPBaseDepayload>()
76                            .to_glib_none()
77                            .0,
78                        event.into_glib_ptr(),
79                    ))
80                })
81                .unwrap_or(false)
82        }
83    }
84
85    fn parent_packet_lost(&self, event: &gst::EventRef) -> bool {
86        unsafe {
87            let data = Self::type_data();
88            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPBaseDepayloadClass;
89            (*parent_class)
90                .packet_lost
91                .map(|f| {
92                    from_glib(f(
93                        self.obj()
94                            .unsafe_cast_ref::<RTPBaseDepayload>()
95                            .to_glib_none()
96                            .0,
97                        event.as_mut_ptr(),
98                    ))
99                })
100                .unwrap_or(true)
101        }
102    }
103
104    fn parent_process_rtp_packet(
105        &self,
106        rtp_buffer: &crate::RTPBuffer<crate::rtp_buffer::Readable>,
107    ) -> Option<gst::Buffer> {
108        unsafe {
109            let data = Self::type_data();
110            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPBaseDepayloadClass;
111
112            let f = (*parent_class)
113                .process_rtp_packet
114                .expect("no parent \"process\" implementation");
115
116            from_glib_full(f(
117                self.obj()
118                    .unsafe_cast_ref::<crate::RTPBaseDepayload>()
119                    .to_glib_none()
120                    .0,
121                mut_override(rtp_buffer.as_ptr()),
122            ))
123        }
124    }
125}
126
127impl<T: RTPBaseDepayloadImpl> RTPBaseDepayloadImplExt for T {}
128
129unsafe impl<T: RTPBaseDepayloadImpl> IsSubclassable<T> for RTPBaseDepayload {
130    fn class_init(klass: &mut glib::Class<Self>) {
131        Self::parent_class_init::<T>(klass);
132        let klass = klass.as_mut();
133
134        klass.process = None;
135        klass.process_rtp_packet = Some(rtp_base_depayload_process_rtp_packet::<T>);
136        klass.set_caps = Some(rtp_base_depayload_set_caps::<T>);
137        klass.handle_event = Some(rtp_base_depayload_handle_event::<T>);
138        klass.packet_lost = Some(rtp_base_depayload_packet_lost::<T>);
139    }
140}
141
142unsafe extern "C" fn rtp_base_depayload_set_caps<T: RTPBaseDepayloadImpl>(
143    ptr: *mut ffi::GstRTPBaseDepayload,
144    caps: *mut gst::ffi::GstCaps,
145) -> glib::ffi::gboolean {
146    let instance = &*(ptr as *mut T::Instance);
147    let imp = instance.imp();
148    let caps = from_glib_borrow(caps);
149
150    gst::panic_to_error!(imp, false, {
151        match imp.set_caps(&caps) {
152            Ok(()) => true,
153            Err(err) => {
154                err.log_with_imp(imp);
155                false
156            }
157        }
158    })
159    .into_glib()
160}
161
162unsafe extern "C" fn rtp_base_depayload_handle_event<T: RTPBaseDepayloadImpl>(
163    ptr: *mut ffi::GstRTPBaseDepayload,
164    event: *mut gst::ffi::GstEvent,
165) -> glib::ffi::gboolean {
166    let instance = &*(ptr as *mut T::Instance);
167    let imp = instance.imp();
168
169    gst::panic_to_error!(imp, false, { imp.handle_event(from_glib_full(event)) }).into_glib()
170}
171
172unsafe extern "C" fn rtp_base_depayload_packet_lost<T: RTPBaseDepayloadImpl>(
173    ptr: *mut ffi::GstRTPBaseDepayload,
174    event: *mut gst::ffi::GstEvent,
175) -> glib::ffi::gboolean {
176    let instance = &*(ptr as *mut T::Instance);
177    let imp = instance.imp();
178
179    gst::panic_to_error!(imp, false, {
180        imp.packet_lost(gst::EventRef::from_ptr(event))
181    })
182    .into_glib()
183}
184
185unsafe extern "C" fn rtp_base_depayload_process_rtp_packet<T: RTPBaseDepayloadImpl>(
186    ptr: *mut ffi::GstRTPBaseDepayload,
187    rtp_packet: *mut ffi::GstRTPBuffer,
188) -> *mut gst::ffi::GstBuffer {
189    let instance = &*(ptr as *mut T::Instance);
190    let imp = instance.imp();
191
192    gst::panic_to_error!(imp, ptr::null_mut(), {
193        let bufwrap = crate::RTPBuffer::<crate::rtp_buffer::Readable>::from_glib_borrow(rtp_packet);
194
195        imp.process_rtp_packet(&bufwrap)
196            .map(|buffer| buffer.into_glib_ptr())
197            .unwrap_or(ptr::null_mut())
198    })
199}