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: RTPBaseDepayloadImplExt + ElementImpl {
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
42mod sealed {
43    pub trait Sealed {}
44    impl<T: super::RTPBaseDepayloadImplExt> Sealed for T {}
45}
46
47pub trait RTPBaseDepayloadImplExt: sealed::Sealed + ObjectSubclass {
48    fn parent_set_caps(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
49        unsafe {
50            let data = Self::type_data();
51            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPBaseDepayloadClass;
52            (*parent_class)
53                .set_caps
54                .map(|f| {
55                    gst::result_from_gboolean!(
56                        f(
57                            self.obj()
58                                .unsafe_cast_ref::<RTPBaseDepayload>()
59                                .to_glib_none()
60                                .0,
61                            caps.to_glib_none().0
62                        ),
63                        gst::CAT_RUST,
64                        "Parent function `set_caps` failed"
65                    )
66                })
67                .unwrap_or(Ok(()))
68        }
69    }
70
71    fn parent_handle_event(&self, event: gst::Event) -> bool {
72        unsafe {
73            let data = Self::type_data();
74            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPBaseDepayloadClass;
75            (*parent_class)
76                .handle_event
77                .map(|f| {
78                    from_glib(f(
79                        self.obj()
80                            .unsafe_cast_ref::<RTPBaseDepayload>()
81                            .to_glib_none()
82                            .0,
83                        event.into_glib_ptr(),
84                    ))
85                })
86                .unwrap_or(false)
87        }
88    }
89
90    fn parent_packet_lost(&self, event: &gst::EventRef) -> bool {
91        unsafe {
92            let data = Self::type_data();
93            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPBaseDepayloadClass;
94            (*parent_class)
95                .packet_lost
96                .map(|f| {
97                    from_glib(f(
98                        self.obj()
99                            .unsafe_cast_ref::<RTPBaseDepayload>()
100                            .to_glib_none()
101                            .0,
102                        event.as_mut_ptr(),
103                    ))
104                })
105                .unwrap_or(true)
106        }
107    }
108
109    fn parent_process_rtp_packet(
110        &self,
111        rtp_buffer: &crate::RTPBuffer<crate::rtp_buffer::Readable>,
112    ) -> Option<gst::Buffer> {
113        unsafe {
114            let data = Self::type_data();
115            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPBaseDepayloadClass;
116
117            let f = (*parent_class)
118                .process_rtp_packet
119                .expect("no parent \"process\" implementation");
120
121            from_glib_full(f(
122                self.obj()
123                    .unsafe_cast_ref::<crate::RTPBaseDepayload>()
124                    .to_glib_none()
125                    .0,
126                mut_override(rtp_buffer.as_ptr()),
127            ))
128        }
129    }
130}
131
132impl<T: RTPBaseDepayloadImpl> RTPBaseDepayloadImplExt for T {}
133
134unsafe impl<T: RTPBaseDepayloadImpl> IsSubclassable<T> for RTPBaseDepayload {
135    fn class_init(klass: &mut glib::Class<Self>) {
136        Self::parent_class_init::<T>(klass);
137        let klass = klass.as_mut();
138
139        klass.process = None;
140        klass.process_rtp_packet = Some(rtp_base_depayload_process_rtp_packet::<T>);
141        klass.set_caps = Some(rtp_base_depayload_set_caps::<T>);
142        klass.handle_event = Some(rtp_base_depayload_handle_event::<T>);
143        klass.packet_lost = Some(rtp_base_depayload_packet_lost::<T>);
144    }
145}
146
147unsafe extern "C" fn rtp_base_depayload_set_caps<T: RTPBaseDepayloadImpl>(
148    ptr: *mut ffi::GstRTPBaseDepayload,
149    caps: *mut gst::ffi::GstCaps,
150) -> glib::ffi::gboolean {
151    let instance = &*(ptr as *mut T::Instance);
152    let imp = instance.imp();
153    let caps = from_glib_borrow(caps);
154
155    gst::panic_to_error!(imp, false, {
156        match imp.set_caps(&caps) {
157            Ok(()) => true,
158            Err(err) => {
159                err.log_with_imp(imp);
160                false
161            }
162        }
163    })
164    .into_glib()
165}
166
167unsafe extern "C" fn rtp_base_depayload_handle_event<T: RTPBaseDepayloadImpl>(
168    ptr: *mut ffi::GstRTPBaseDepayload,
169    event: *mut gst::ffi::GstEvent,
170) -> glib::ffi::gboolean {
171    let instance = &*(ptr as *mut T::Instance);
172    let imp = instance.imp();
173
174    gst::panic_to_error!(imp, false, { imp.handle_event(from_glib_full(event)) }).into_glib()
175}
176
177unsafe extern "C" fn rtp_base_depayload_packet_lost<T: RTPBaseDepayloadImpl>(
178    ptr: *mut ffi::GstRTPBaseDepayload,
179    event: *mut gst::ffi::GstEvent,
180) -> glib::ffi::gboolean {
181    let instance = &*(ptr as *mut T::Instance);
182    let imp = instance.imp();
183
184    gst::panic_to_error!(imp, false, {
185        imp.packet_lost(gst::EventRef::from_ptr(event))
186    })
187    .into_glib()
188}
189
190unsafe extern "C" fn rtp_base_depayload_process_rtp_packet<T: RTPBaseDepayloadImpl>(
191    ptr: *mut ffi::GstRTPBaseDepayload,
192    rtp_packet: *mut ffi::GstRTPBuffer,
193) -> *mut gst::ffi::GstBuffer {
194    let instance = &*(ptr as *mut T::Instance);
195    let imp = instance.imp();
196
197    gst::panic_to_error!(imp, ptr::null_mut(), {
198        let bufwrap = crate::RTPBuffer::<crate::rtp_buffer::Readable>::from_glib_borrow(rtp_packet);
199
200        imp.process_rtp_packet(&bufwrap)
201            .map(|buffer| buffer.into_glib_ptr())
202            .unwrap_or(ptr::null_mut())
203    })
204}