Skip to main content

gstreamer_rtp/subclass/
rtp_header_extension.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::{prelude::*, subclass::prelude::*, translate::*};
4
5use super::prelude::*;
6use crate::RTPHeaderExtension;
7use crate::ffi;
8
9pub trait RTPHeaderExtensionImpl:
10    ElementImpl + ObjectSubclass<Type: IsA<RTPHeaderExtension>>
11{
12    const URI: &'static str;
13
14    fn supported_flags(&self) -> crate::RTPHeaderExtensionFlags {
15        self.parent_supported_flags()
16    }
17
18    fn max_size(&self, input: &gst::BufferRef) -> usize {
19        self.parent_max_size(input)
20    }
21
22    fn write(
23        &self,
24        input: &gst::BufferRef,
25        write_flags: crate::RTPHeaderExtensionFlags,
26        output: &gst::BufferRef,
27        output_data: &mut [u8],
28    ) -> Result<usize, gst::LoggableError> {
29        self.parent_write(input, write_flags, output, output_data)
30    }
31
32    fn read(
33        &self,
34        read_flags: crate::RTPHeaderExtensionFlags,
35        input_data: &[u8],
36        output: &mut gst::BufferRef,
37    ) -> Result<(), gst::LoggableError> {
38        self.parent_read(read_flags, input_data, output)
39    }
40
41    fn set_non_rtp_sink_caps(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
42        self.parent_set_non_rtp_sink_caps(caps)
43    }
44
45    fn update_non_rtp_src_caps(&self, caps: &mut gst::CapsRef) -> Result<(), gst::LoggableError> {
46        self.parent_update_non_rtp_src_caps(caps)
47    }
48
49    fn set_attributes(
50        &self,
51        direction: crate::RTPHeaderExtensionDirection,
52        attributes: &str,
53    ) -> Result<(), gst::LoggableError> {
54        self.parent_set_attributes(direction, attributes)
55    }
56
57    fn set_caps_from_attributes(&self, caps: &mut gst::CapsRef) -> Result<(), gst::LoggableError> {
58        self.parent_set_caps_from_attributes(caps)
59    }
60}
61
62pub trait RTPHeaderExtensionImplExt: RTPHeaderExtensionImpl {
63    fn parent_supported_flags(&self) -> crate::RTPHeaderExtensionFlags {
64        unsafe {
65            let data = Self::type_data();
66            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPHeaderExtensionClass;
67            let f = (*parent_class)
68                .get_supported_flags
69                .expect("no parent \"get_supported_flags\" implementation");
70            from_glib(f(self
71                .obj()
72                .unsafe_cast_ref::<RTPHeaderExtension>()
73                .to_glib_none()
74                .0))
75        }
76    }
77
78    fn parent_max_size(&self, input: &gst::BufferRef) -> usize {
79        unsafe {
80            let data = Self::type_data();
81            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPHeaderExtensionClass;
82            let f = (*parent_class)
83                .get_max_size
84                .expect("no parent \"get_max_size\" implementation");
85            f(
86                self.obj()
87                    .unsafe_cast_ref::<RTPHeaderExtension>()
88                    .to_glib_none()
89                    .0,
90                input.as_ptr(),
91            )
92        }
93    }
94
95    fn parent_write(
96        &self,
97        input: &gst::BufferRef,
98        write_flags: crate::RTPHeaderExtensionFlags,
99        output: &gst::BufferRef,
100        output_data: &mut [u8],
101    ) -> Result<usize, gst::LoggableError> {
102        unsafe {
103            let data = Self::type_data();
104            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPHeaderExtensionClass;
105            let f = (*parent_class)
106                .write
107                .expect("no parent \"write\" implementation");
108
109            let res = f(
110                self.obj()
111                    .unsafe_cast_ref::<RTPHeaderExtension>()
112                    .to_glib_none()
113                    .0,
114                input.as_ptr(),
115                write_flags.into_glib(),
116                mut_override(output.as_ptr()),
117                output_data.as_mut_ptr(),
118                output_data.len(),
119            );
120
121            if res < 0 {
122                Err(gst::loggable_error!(
123                    gst::CAT_RUST,
124                    "Failed to write extension data"
125                ))
126            } else {
127                Ok(res as usize)
128            }
129        }
130    }
131
132    fn parent_read(
133        &self,
134        read_flags: crate::RTPHeaderExtensionFlags,
135        input_data: &[u8],
136        output: &mut gst::BufferRef,
137    ) -> Result<(), gst::LoggableError> {
138        unsafe {
139            let data = Self::type_data();
140            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPHeaderExtensionClass;
141            let f = (*parent_class)
142                .read
143                .expect("no parent \"read\" implementation");
144
145            gst::result_from_gboolean!(
146                f(
147                    self.obj()
148                        .unsafe_cast_ref::<RTPHeaderExtension>()
149                        .to_glib_none()
150                        .0,
151                    read_flags.into_glib(),
152                    input_data.as_ptr(),
153                    input_data.len(),
154                    output.as_mut_ptr(),
155                ),
156                gst::CAT_RUST,
157                "Failed to read extension data",
158            )
159        }
160    }
161
162    fn parent_set_non_rtp_sink_caps(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
163        unsafe {
164            let data = Self::type_data();
165            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPHeaderExtensionClass;
166            if let Some(f) = (*parent_class).set_non_rtp_sink_caps {
167                gst::result_from_gboolean!(
168                    f(
169                        self.obj()
170                            .unsafe_cast_ref::<RTPHeaderExtension>()
171                            .to_glib_none()
172                            .0,
173                        caps.as_mut_ptr(),
174                    ),
175                    gst::CAT_RUST,
176                    "Failed to set non-RTP sink caps",
177                )
178            } else {
179                Ok(())
180            }
181        }
182    }
183
184    fn parent_update_non_rtp_src_caps(
185        &self,
186        caps: &mut gst::CapsRef,
187    ) -> Result<(), gst::LoggableError> {
188        unsafe {
189            let data = Self::type_data();
190            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPHeaderExtensionClass;
191            if let Some(f) = (*parent_class).update_non_rtp_src_caps {
192                gst::result_from_gboolean!(
193                    f(
194                        self.obj()
195                            .unsafe_cast_ref::<RTPHeaderExtension>()
196                            .to_glib_none()
197                            .0,
198                        caps.as_mut_ptr(),
199                    ),
200                    gst::CAT_RUST,
201                    "Failed to update non-RTP source caps",
202                )
203            } else {
204                Ok(())
205            }
206        }
207    }
208
209    fn parent_set_attributes(
210        &self,
211        direction: crate::RTPHeaderExtensionDirection,
212        attributes: &str,
213    ) -> Result<(), gst::LoggableError> {
214        unsafe {
215            let data = Self::type_data();
216            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPHeaderExtensionClass;
217            if let Some(f) = (*parent_class).set_attributes {
218                gst::result_from_gboolean!(
219                    f(
220                        self.obj()
221                            .unsafe_cast_ref::<RTPHeaderExtension>()
222                            .to_glib_none()
223                            .0,
224                        direction.into_glib(),
225                        attributes.to_glib_none().0,
226                    ),
227                    gst::CAT_RUST,
228                    "Failed to set attributes",
229                )
230            } else {
231                Ok(())
232            }
233        }
234    }
235
236    fn parent_set_caps_from_attributes(
237        &self,
238        caps: &mut gst::CapsRef,
239    ) -> Result<(), gst::LoggableError> {
240        unsafe {
241            let data = Self::type_data();
242            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPHeaderExtensionClass;
243            let f = (*parent_class)
244                .set_caps_from_attributes
245                .expect("no parent \"set_caps_from_attributes\" implementation");
246
247            gst::result_from_gboolean!(
248                f(
249                    self.obj()
250                        .unsafe_cast_ref::<RTPHeaderExtension>()
251                        .to_glib_none()
252                        .0,
253                    caps.as_mut_ptr(),
254                ),
255                gst::CAT_RUST,
256                "Failed to set caps from attributes",
257            )
258        }
259    }
260}
261
262impl<T: RTPHeaderExtensionImpl> RTPHeaderExtensionImplExt for T {}
263
264unsafe impl<T: RTPHeaderExtensionImpl> IsSubclassable<T> for RTPHeaderExtension {
265    fn class_init(klass: &mut glib::Class<Self>) {
266        Self::parent_class_init::<T>(klass);
267        let klass = klass.as_mut();
268        klass.get_supported_flags = Some(get_supported_flags::<T>);
269        klass.get_max_size = Some(get_max_size::<T>);
270        klass.write = Some(write::<T>);
271        klass.read = Some(read::<T>);
272        klass.set_non_rtp_sink_caps = Some(set_non_rtp_sink_caps::<T>);
273        klass.update_non_rtp_src_caps = Some(update_non_rtp_src_caps::<T>);
274        klass.set_attributes = Some(set_attributes::<T>);
275        klass.set_caps_from_attributes = Some(set_caps_from_attributes::<T>);
276
277        unsafe {
278            ffi::gst_rtp_header_extension_class_set_uri(&mut *klass, T::URI.to_glib_none().0);
279        }
280    }
281}
282
283unsafe extern "C" fn get_supported_flags<T: RTPHeaderExtensionImpl>(
284    ptr: *mut ffi::GstRTPHeaderExtension,
285) -> ffi::GstRTPHeaderExtensionFlags {
286    unsafe {
287        let instance = &*(ptr as *mut T::Instance);
288        let imp = instance.imp();
289
290        gst::panic_to_error!(imp, crate::RTPHeaderExtensionFlags::empty(), {
291            imp.supported_flags()
292        })
293        .into_glib()
294    }
295}
296
297unsafe extern "C" fn get_max_size<T: RTPHeaderExtensionImpl>(
298    ptr: *mut ffi::GstRTPHeaderExtension,
299    input: *const gst::ffi::GstBuffer,
300) -> usize {
301    unsafe {
302        let instance = &*(ptr as *mut T::Instance);
303        let imp = instance.imp();
304
305        gst::panic_to_error!(imp, 0, { imp.max_size(gst::BufferRef::from_ptr(input)) })
306    }
307}
308
309unsafe extern "C" fn write<T: RTPHeaderExtensionImpl>(
310    ptr: *mut ffi::GstRTPHeaderExtension,
311    input: *const gst::ffi::GstBuffer,
312    write_flags: ffi::GstRTPHeaderExtensionFlags,
313    output: *mut gst::ffi::GstBuffer,
314    output_data: *mut u8,
315    output_data_len: usize,
316) -> isize {
317    unsafe {
318        let instance = &*(ptr as *mut T::Instance);
319        let imp = instance.imp();
320
321        gst::panic_to_error!(imp, -1, {
322            match imp.write(
323                gst::BufferRef::from_ptr(input),
324                from_glib(write_flags),
325                gst::BufferRef::from_ptr(output),
326                if output_data_len == 0 {
327                    &mut []
328                } else {
329                    std::slice::from_raw_parts_mut(output_data, output_data_len)
330                },
331            ) {
332                Ok(len) => len as isize,
333                Err(err) => {
334                    err.log_with_imp(imp);
335                    -1
336                }
337            }
338        })
339    }
340}
341
342unsafe extern "C" fn read<T: RTPHeaderExtensionImpl>(
343    ptr: *mut ffi::GstRTPHeaderExtension,
344    read_flags: ffi::GstRTPHeaderExtensionFlags,
345    input_data: *const u8,
346    input_data_len: usize,
347    output: *mut gst::ffi::GstBuffer,
348) -> glib::ffi::gboolean {
349    unsafe {
350        let instance = &*(ptr as *mut T::Instance);
351        let imp = instance.imp();
352
353        gst::panic_to_error!(imp, false, {
354            match imp.read(
355                from_glib(read_flags),
356                if input_data_len == 0 {
357                    &[]
358                } else {
359                    std::slice::from_raw_parts(input_data, input_data_len)
360                },
361                gst::BufferRef::from_mut_ptr(output),
362            ) {
363                Ok(_) => true,
364                Err(err) => {
365                    err.log_with_imp(imp);
366                    false
367                }
368            }
369        })
370        .into_glib()
371    }
372}
373
374unsafe extern "C" fn set_non_rtp_sink_caps<T: RTPHeaderExtensionImpl>(
375    ptr: *mut ffi::GstRTPHeaderExtension,
376    caps: *mut gst::ffi::GstCaps,
377) -> glib::ffi::gboolean {
378    unsafe {
379        let instance = &*(ptr as *mut T::Instance);
380        let imp = instance.imp();
381
382        gst::panic_to_error!(imp, false, {
383            match imp.set_non_rtp_sink_caps(&from_glib_borrow(caps)) {
384                Ok(_) => true,
385                Err(err) => {
386                    err.log_with_imp(imp);
387                    false
388                }
389            }
390        })
391        .into_glib()
392    }
393}
394
395unsafe extern "C" fn update_non_rtp_src_caps<T: RTPHeaderExtensionImpl>(
396    ptr: *mut ffi::GstRTPHeaderExtension,
397    caps: *mut gst::ffi::GstCaps,
398) -> glib::ffi::gboolean {
399    unsafe {
400        let instance = &*(ptr as *mut T::Instance);
401        let imp = instance.imp();
402
403        gst::panic_to_error!(imp, false, {
404            match imp.update_non_rtp_src_caps(gst::CapsRef::from_mut_ptr(caps)) {
405                Ok(_) => true,
406                Err(err) => {
407                    err.log_with_imp(imp);
408                    false
409                }
410            }
411        })
412        .into_glib()
413    }
414}
415
416unsafe extern "C" fn set_attributes<T: RTPHeaderExtensionImpl>(
417    ptr: *mut ffi::GstRTPHeaderExtension,
418    direction: ffi::GstRTPHeaderExtensionDirection,
419    attributes: *const libc::c_char,
420) -> glib::ffi::gboolean {
421    unsafe {
422        let instance = &*(ptr as *mut T::Instance);
423        let imp = instance.imp();
424
425        gst::panic_to_error!(imp, false, {
426            match imp.set_attributes(
427                from_glib(direction),
428                &glib::GString::from_glib_borrow(attributes),
429            ) {
430                Ok(_) => true,
431                Err(err) => {
432                    err.log_with_imp(imp);
433                    false
434                }
435            }
436        })
437        .into_glib()
438    }
439}
440
441unsafe extern "C" fn set_caps_from_attributes<T: RTPHeaderExtensionImpl>(
442    ptr: *mut ffi::GstRTPHeaderExtension,
443    caps: *mut gst::ffi::GstCaps,
444) -> glib::ffi::gboolean {
445    unsafe {
446        let instance = &*(ptr as *mut T::Instance);
447        let imp = instance.imp();
448
449        gst::panic_to_error!(imp, false, {
450            match imp.set_caps_from_attributes(gst::CapsRef::from_mut_ptr(caps)) {
451                Ok(_) => true,
452                Err(err) => {
453                    err.log_with_imp(imp);
454                    false
455                }
456            }
457        })
458        .into_glib()
459    }
460}