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