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::ffi;
7use crate::RTPHeaderExtension;
8
9pub trait RTPHeaderExtensionImpl:
10    ElementImpl + ObjectSubclass<Type: IsA<RTPHeaderExtension>>
11{
12    const URI: &'static str;
13
14    /// retrieve the supported flags
15    ///
16    /// # Returns
17    ///
18    /// the flags supported by this instance of `self`
19    fn supported_flags(&self) -> crate::RTPHeaderExtensionFlags {
20        self.parent_supported_flags()
21    }
22
23    /// This is used to know how much data a certain header extension will need for
24    /// both allocating the resulting data, and deciding how much payload data can
25    /// be generated.
26    ///
27    /// Implementations should return as accurate a value as is possible using the
28    /// information given in the input `buffer`.
29    /// ## `input_meta`
30    /// a [`gst::Buffer`][crate::gst::Buffer]
31    ///
32    /// # Returns
33    ///
34    /// the maximum size of the data written by this extension
35    fn max_size(&self, input: &gst::BufferRef) -> usize {
36        self.parent_max_size(input)
37    }
38
39    /// Writes the RTP header extension to `data` using information available from
40    /// the `input_meta`. `data` will be sized to be at least the value returned
41    /// from [`RTPHeaderExtensionExt::max_size()`][crate::prelude::RTPHeaderExtensionExt::max_size()].
42    /// ## `input_meta`
43    /// the input [`gst::Buffer`][crate::gst::Buffer] to read information from if necessary
44    /// ## `write_flags`
45    /// [`RTPHeaderExtensionFlags`][crate::RTPHeaderExtensionFlags] for how the extension should
46    ///  be written
47    /// ## `output`
48    /// output RTP [`gst::Buffer`][crate::gst::Buffer]
49    /// ## `data`
50    /// location to write the rtp header extension into
51    ///
52    /// # Returns
53    ///
54    /// the size of the data written, < 0 on failure
55    fn write(
56        &self,
57        input: &gst::BufferRef,
58        write_flags: crate::RTPHeaderExtensionFlags,
59        output: &gst::BufferRef,
60        output_data: &mut [u8],
61    ) -> Result<usize, gst::LoggableError> {
62        self.parent_write(input, write_flags, output, output_data)
63    }
64
65    /// Read the RTP header extension from `data`.
66    /// ## `read_flags`
67    /// [`RTPHeaderExtensionFlags`][crate::RTPHeaderExtensionFlags] for how the extension should
68    ///  be written
69    /// ## `data`
70    /// location to read the rtp header extension from
71    /// ## `buffer`
72    /// a [`gst::Buffer`][crate::gst::Buffer] to modify if necessary
73    ///
74    /// # Returns
75    ///
76    /// whether the extension could be read from `data`
77    fn read(
78        &self,
79        read_flags: crate::RTPHeaderExtensionFlags,
80        input_data: &[u8],
81        output: &mut gst::BufferRef,
82    ) -> Result<(), gst::LoggableError> {
83        self.parent_read(read_flags, input_data, output)
84    }
85
86    /// Passes RTP payloader's sink (i.e. not payloaded) `caps` to the header
87    /// extension.
88    /// ## `caps`
89    /// sink [`gst::Caps`][crate::gst::Caps]
90    ///
91    /// # Returns
92    ///
93    /// Whether `caps` could be read successfully
94    fn set_non_rtp_sink_caps(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
95        self.parent_set_non_rtp_sink_caps(caps)
96    }
97
98    /// Updates depayloader src caps based on the information received in RTP header.
99    /// `caps` must be writable as this function may modify them.
100    /// ## `caps`
101    /// src [`gst::Caps`][crate::gst::Caps] to modify
102    ///
103    /// # Returns
104    ///
105    /// whether `caps` were modified successfully
106    fn update_non_rtp_src_caps(&self, caps: &mut gst::CapsRef) -> Result<(), gst::LoggableError> {
107        self.parent_update_non_rtp_src_caps(caps)
108    }
109
110    /// set the necessary attributes that may be signaled e.g. with
111    ///  an SDP.
112    fn set_attributes(
113        &self,
114        direction: crate::RTPHeaderExtensionDirection,
115        attributes: &str,
116    ) -> Result<(), gst::LoggableError> {
117        self.parent_set_attributes(direction, attributes)
118    }
119
120    /// [`RTPHeaderExtensionExt::set_id()`][crate::prelude::RTPHeaderExtensionExt::set_id()] must have been called with a valid
121    /// extension id that is contained in these caps.
122    ///
123    /// The only current known caps format is based on the SDP standard as produced
124    /// by `gst_sdp_media_attributes_to_caps()`.
125    /// ## `caps`
126    /// writable [`gst::Caps`][crate::gst::Caps] to modify
127    ///
128    /// # Returns
129    ///
130    /// whether the configured attributes on `self` can successfully be set on
131    ///     `caps`
132    fn set_caps_from_attributes(&self, caps: &mut gst::CapsRef) -> Result<(), gst::LoggableError> {
133        self.parent_set_caps_from_attributes(caps)
134    }
135}
136
137pub trait RTPHeaderExtensionImplExt: RTPHeaderExtensionImpl {
138    fn parent_supported_flags(&self) -> crate::RTPHeaderExtensionFlags {
139        unsafe {
140            let data = Self::type_data();
141            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPHeaderExtensionClass;
142            let f = (*parent_class)
143                .get_supported_flags
144                .expect("no parent \"get_supported_flags\" implementation");
145            from_glib(f(self
146                .obj()
147                .unsafe_cast_ref::<RTPHeaderExtension>()
148                .to_glib_none()
149                .0))
150        }
151    }
152
153    fn parent_max_size(&self, input: &gst::BufferRef) -> usize {
154        unsafe {
155            let data = Self::type_data();
156            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPHeaderExtensionClass;
157            let f = (*parent_class)
158                .get_max_size
159                .expect("no parent \"get_max_size\" implementation");
160            f(
161                self.obj()
162                    .unsafe_cast_ref::<RTPHeaderExtension>()
163                    .to_glib_none()
164                    .0,
165                input.as_ptr(),
166            )
167        }
168    }
169
170    fn parent_write(
171        &self,
172        input: &gst::BufferRef,
173        write_flags: crate::RTPHeaderExtensionFlags,
174        output: &gst::BufferRef,
175        output_data: &mut [u8],
176    ) -> Result<usize, gst::LoggableError> {
177        unsafe {
178            let data = Self::type_data();
179            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPHeaderExtensionClass;
180            let f = (*parent_class)
181                .write
182                .expect("no parent \"write\" implementation");
183
184            let res = f(
185                self.obj()
186                    .unsafe_cast_ref::<RTPHeaderExtension>()
187                    .to_glib_none()
188                    .0,
189                input.as_ptr(),
190                write_flags.into_glib(),
191                mut_override(output.as_ptr()),
192                output_data.as_mut_ptr(),
193                output_data.len(),
194            );
195
196            if res < 0 {
197                Err(gst::loggable_error!(
198                    gst::CAT_RUST,
199                    "Failed to write extension data"
200                ))
201            } else {
202                Ok(res as usize)
203            }
204        }
205    }
206
207    fn parent_read(
208        &self,
209        read_flags: crate::RTPHeaderExtensionFlags,
210        input_data: &[u8],
211        output: &mut gst::BufferRef,
212    ) -> Result<(), gst::LoggableError> {
213        unsafe {
214            let data = Self::type_data();
215            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPHeaderExtensionClass;
216            let f = (*parent_class)
217                .read
218                .expect("no parent \"read\" implementation");
219
220            gst::result_from_gboolean!(
221                f(
222                    self.obj()
223                        .unsafe_cast_ref::<RTPHeaderExtension>()
224                        .to_glib_none()
225                        .0,
226                    read_flags.into_glib(),
227                    input_data.as_ptr(),
228                    input_data.len(),
229                    output.as_mut_ptr(),
230                ),
231                gst::CAT_RUST,
232                "Failed to read extension data",
233            )
234        }
235    }
236
237    fn parent_set_non_rtp_sink_caps(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
238        unsafe {
239            let data = Self::type_data();
240            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPHeaderExtensionClass;
241            if let Some(f) = (*parent_class).set_non_rtp_sink_caps {
242                gst::result_from_gboolean!(
243                    f(
244                        self.obj()
245                            .unsafe_cast_ref::<RTPHeaderExtension>()
246                            .to_glib_none()
247                            .0,
248                        caps.as_mut_ptr(),
249                    ),
250                    gst::CAT_RUST,
251                    "Failed to set non-RTP sink caps",
252                )
253            } else {
254                Ok(())
255            }
256        }
257    }
258
259    fn parent_update_non_rtp_src_caps(
260        &self,
261        caps: &mut gst::CapsRef,
262    ) -> Result<(), gst::LoggableError> {
263        unsafe {
264            let data = Self::type_data();
265            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPHeaderExtensionClass;
266            if let Some(f) = (*parent_class).update_non_rtp_src_caps {
267                gst::result_from_gboolean!(
268                    f(
269                        self.obj()
270                            .unsafe_cast_ref::<RTPHeaderExtension>()
271                            .to_glib_none()
272                            .0,
273                        caps.as_mut_ptr(),
274                    ),
275                    gst::CAT_RUST,
276                    "Failed to update non-RTP source caps",
277                )
278            } else {
279                Ok(())
280            }
281        }
282    }
283
284    fn parent_set_attributes(
285        &self,
286        direction: crate::RTPHeaderExtensionDirection,
287        attributes: &str,
288    ) -> Result<(), gst::LoggableError> {
289        unsafe {
290            let data = Self::type_data();
291            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPHeaderExtensionClass;
292            if let Some(f) = (*parent_class).set_attributes {
293                gst::result_from_gboolean!(
294                    f(
295                        self.obj()
296                            .unsafe_cast_ref::<RTPHeaderExtension>()
297                            .to_glib_none()
298                            .0,
299                        direction.into_glib(),
300                        attributes.to_glib_none().0,
301                    ),
302                    gst::CAT_RUST,
303                    "Failed to set attributes",
304                )
305            } else {
306                Ok(())
307            }
308        }
309    }
310
311    fn parent_set_caps_from_attributes(
312        &self,
313        caps: &mut gst::CapsRef,
314    ) -> Result<(), gst::LoggableError> {
315        unsafe {
316            let data = Self::type_data();
317            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPHeaderExtensionClass;
318            let f = (*parent_class)
319                .set_caps_from_attributes
320                .expect("no parent \"set_caps_from_attributes\" implementation");
321
322            gst::result_from_gboolean!(
323                f(
324                    self.obj()
325                        .unsafe_cast_ref::<RTPHeaderExtension>()
326                        .to_glib_none()
327                        .0,
328                    caps.as_mut_ptr(),
329                ),
330                gst::CAT_RUST,
331                "Failed to set caps from attributes",
332            )
333        }
334    }
335}
336
337impl<T: RTPHeaderExtensionImpl> RTPHeaderExtensionImplExt for T {}
338
339unsafe impl<T: RTPHeaderExtensionImpl> IsSubclassable<T> for RTPHeaderExtension {
340    fn class_init(klass: &mut glib::Class<Self>) {
341        Self::parent_class_init::<T>(klass);
342        let klass = klass.as_mut();
343        klass.get_supported_flags = Some(get_supported_flags::<T>);
344        klass.get_max_size = Some(get_max_size::<T>);
345        klass.write = Some(write::<T>);
346        klass.read = Some(read::<T>);
347        klass.set_non_rtp_sink_caps = Some(set_non_rtp_sink_caps::<T>);
348        klass.update_non_rtp_src_caps = Some(update_non_rtp_src_caps::<T>);
349        klass.set_attributes = Some(set_attributes::<T>);
350        klass.set_caps_from_attributes = Some(set_caps_from_attributes::<T>);
351
352        unsafe {
353            ffi::gst_rtp_header_extension_class_set_uri(&mut *klass, T::URI.to_glib_none().0);
354        }
355    }
356}
357
358unsafe extern "C" fn get_supported_flags<T: RTPHeaderExtensionImpl>(
359    ptr: *mut ffi::GstRTPHeaderExtension,
360) -> ffi::GstRTPHeaderExtensionFlags {
361    let instance = &*(ptr as *mut T::Instance);
362    let imp = instance.imp();
363
364    gst::panic_to_error!(imp, crate::RTPHeaderExtensionFlags::empty(), {
365        imp.supported_flags()
366    })
367    .into_glib()
368}
369
370unsafe extern "C" fn get_max_size<T: RTPHeaderExtensionImpl>(
371    ptr: *mut ffi::GstRTPHeaderExtension,
372    input: *const gst::ffi::GstBuffer,
373) -> usize {
374    let instance = &*(ptr as *mut T::Instance);
375    let imp = instance.imp();
376
377    gst::panic_to_error!(imp, 0, { imp.max_size(gst::BufferRef::from_ptr(input)) })
378}
379
380unsafe extern "C" fn write<T: RTPHeaderExtensionImpl>(
381    ptr: *mut ffi::GstRTPHeaderExtension,
382    input: *const gst::ffi::GstBuffer,
383    write_flags: ffi::GstRTPHeaderExtensionFlags,
384    output: *mut gst::ffi::GstBuffer,
385    output_data: *mut u8,
386    output_data_len: usize,
387) -> isize {
388    let instance = &*(ptr as *mut T::Instance);
389    let imp = instance.imp();
390
391    gst::panic_to_error!(imp, -1, {
392        match imp.write(
393            gst::BufferRef::from_ptr(input),
394            from_glib(write_flags),
395            gst::BufferRef::from_ptr(output),
396            if output_data_len == 0 {
397                &mut []
398            } else {
399                std::slice::from_raw_parts_mut(output_data, output_data_len)
400            },
401        ) {
402            Ok(len) => len as isize,
403            Err(err) => {
404                err.log_with_imp(imp);
405                -1
406            }
407        }
408    })
409}
410
411unsafe extern "C" fn read<T: RTPHeaderExtensionImpl>(
412    ptr: *mut ffi::GstRTPHeaderExtension,
413    read_flags: ffi::GstRTPHeaderExtensionFlags,
414    input_data: *const u8,
415    input_data_len: usize,
416    output: *mut gst::ffi::GstBuffer,
417) -> glib::ffi::gboolean {
418    let instance = &*(ptr as *mut T::Instance);
419    let imp = instance.imp();
420
421    gst::panic_to_error!(imp, false, {
422        match imp.read(
423            from_glib(read_flags),
424            if input_data_len == 0 {
425                &[]
426            } else {
427                std::slice::from_raw_parts(input_data, input_data_len)
428            },
429            gst::BufferRef::from_mut_ptr(output),
430        ) {
431            Ok(_) => true,
432            Err(err) => {
433                err.log_with_imp(imp);
434                false
435            }
436        }
437    })
438    .into_glib()
439}
440
441unsafe extern "C" fn set_non_rtp_sink_caps<T: RTPHeaderExtensionImpl>(
442    ptr: *mut ffi::GstRTPHeaderExtension,
443    caps: *mut gst::ffi::GstCaps,
444) -> glib::ffi::gboolean {
445    let instance = &*(ptr as *mut T::Instance);
446    let imp = instance.imp();
447
448    gst::panic_to_error!(imp, false, {
449        match imp.set_non_rtp_sink_caps(&from_glib_borrow(caps)) {
450            Ok(_) => true,
451            Err(err) => {
452                err.log_with_imp(imp);
453                false
454            }
455        }
456    })
457    .into_glib()
458}
459
460unsafe extern "C" fn update_non_rtp_src_caps<T: RTPHeaderExtensionImpl>(
461    ptr: *mut ffi::GstRTPHeaderExtension,
462    caps: *mut gst::ffi::GstCaps,
463) -> glib::ffi::gboolean {
464    let instance = &*(ptr as *mut T::Instance);
465    let imp = instance.imp();
466
467    gst::panic_to_error!(imp, false, {
468        match imp.update_non_rtp_src_caps(gst::CapsRef::from_mut_ptr(caps)) {
469            Ok(_) => true,
470            Err(err) => {
471                err.log_with_imp(imp);
472                false
473            }
474        }
475    })
476    .into_glib()
477}
478
479unsafe extern "C" fn set_attributes<T: RTPHeaderExtensionImpl>(
480    ptr: *mut ffi::GstRTPHeaderExtension,
481    direction: ffi::GstRTPHeaderExtensionDirection,
482    attributes: *const libc::c_char,
483) -> glib::ffi::gboolean {
484    let instance = &*(ptr as *mut T::Instance);
485    let imp = instance.imp();
486
487    gst::panic_to_error!(imp, false, {
488        match imp.set_attributes(
489            from_glib(direction),
490            &glib::GString::from_glib_borrow(attributes),
491        ) {
492            Ok(_) => true,
493            Err(err) => {
494                err.log_with_imp(imp);
495                false
496            }
497        }
498    })
499    .into_glib()
500}
501
502unsafe extern "C" fn set_caps_from_attributes<T: RTPHeaderExtensionImpl>(
503    ptr: *mut ffi::GstRTPHeaderExtension,
504    caps: *mut gst::ffi::GstCaps,
505) -> glib::ffi::gboolean {
506    let instance = &*(ptr as *mut T::Instance);
507    let imp = instance.imp();
508
509    gst::panic_to_error!(imp, false, {
510        match imp.set_caps_from_attributes(gst::CapsRef::from_mut_ptr(caps)) {
511            Ok(_) => true,
512            Err(err) => {
513                err.log_with_imp(imp);
514                false
515            }
516        }
517    })
518    .into_glib()
519}