gstreamer/
meta.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3#[cfg(feature = "v1_20")]
4#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
5use std::ptr;
6use std::{
7    fmt,
8    marker::PhantomData,
9    ops::{self, Bound, RangeBounds},
10};
11
12use glib::translate::*;
13
14use crate::{ffi, Buffer, BufferRef, Caps, CapsRef, ClockTime};
15
16pub unsafe trait MetaAPI: Sync + Send + Sized {
17    type GstType;
18
19    #[doc(alias = "get_meta_api")]
20    fn meta_api() -> glib::Type;
21}
22
23pub trait MetaAPIExt: MetaAPI {
24    #[inline]
25    unsafe fn from_ptr(buffer: &BufferRef, ptr: *const Self::GstType) -> MetaRef<Self> {
26        debug_assert!(!ptr.is_null());
27
28        let meta_api = Self::meta_api();
29        if meta_api != glib::Type::INVALID {
30            debug_assert_eq!(
31                meta_api,
32                from_glib((*(*(ptr as *const ffi::GstMeta)).info).api)
33            )
34        }
35
36        MetaRef {
37            meta: &*(ptr as *const Self),
38            buffer,
39        }
40    }
41
42    #[inline]
43    unsafe fn from_mut_ptr<T>(
44        buffer: &mut BufferRef,
45        ptr: *mut Self::GstType,
46    ) -> MetaRefMut<Self, T> {
47        debug_assert!(!ptr.is_null());
48
49        let meta_api = Self::meta_api();
50        if meta_api != glib::Type::INVALID {
51            debug_assert_eq!(
52                meta_api,
53                from_glib((*(*(ptr as *const ffi::GstMeta)).info).api)
54            )
55        }
56
57        MetaRefMut {
58            meta: &mut *(ptr as *mut Self),
59            buffer,
60            mode: PhantomData,
61        }
62    }
63}
64
65impl<A: MetaAPI> MetaAPIExt for A {}
66
67#[cfg(feature = "v1_16")]
68#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
69#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
70pub struct MetaSeqnum(u64);
71
72pub struct MetaRef<'a, T: 'a> {
73    meta: &'a T,
74    buffer: &'a BufferRef,
75}
76
77pub enum Standalone {}
78pub enum Iterated {}
79
80pub struct MetaRefMut<'a, T: 'a, U> {
81    meta: &'a mut T,
82    buffer: &'a mut BufferRef,
83    mode: PhantomData<U>,
84}
85
86impl<'a, T: fmt::Debug + 'a> fmt::Debug for MetaRef<'a, T> {
87    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
88        f.debug_struct("MetaRef")
89            .field("meta", &self.meta)
90            .field("buffer", &self.buffer)
91            .finish()
92    }
93}
94
95impl<'a, T: fmt::Debug + 'a, U> fmt::Debug for MetaRefMut<'a, T, U> {
96    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97        f.debug_struct("MetaRef")
98            .field("meta", &self.meta)
99            .field("buffer", &self.buffer)
100            .field("mode", &self.mode)
101            .finish()
102    }
103}
104
105impl<T> ops::Deref for MetaRef<'_, T> {
106    type Target = T;
107
108    #[inline]
109    fn deref(&self) -> &T {
110        self.meta
111    }
112}
113
114impl<'a, T> AsRef<MetaRef<'a, T>> for MetaRef<'a, T> {
115    #[inline]
116    fn as_ref(&self) -> &MetaRef<'a, T> {
117        self
118    }
119}
120
121impl<T> AsRef<T> for MetaRef<'_, T> {
122    #[inline]
123    fn as_ref(&self) -> &T {
124        self.meta
125    }
126}
127
128impl<'a, T: 'a> Clone for MetaRef<'a, T> {
129    fn clone(&self) -> Self {
130        MetaRef {
131            meta: self.meta,
132            buffer: self.buffer,
133        }
134    }
135}
136
137impl<T, U> ops::Deref for MetaRefMut<'_, T, U> {
138    type Target = T;
139
140    #[inline]
141    fn deref(&self) -> &T {
142        self.meta
143    }
144}
145
146impl<T, U> ops::DerefMut for MetaRefMut<'_, T, U> {
147    #[inline]
148    fn deref_mut(&mut self) -> &mut T {
149        self.meta
150    }
151}
152
153impl<'a, T, U> AsRef<MetaRef<'a, T>> for MetaRefMut<'a, T, U> {
154    #[inline]
155    fn as_ref(&self) -> &MetaRef<'a, T> {
156        unsafe { &*(self as *const MetaRefMut<'a, T, U> as *const MetaRef<'a, T>) }
157    }
158}
159
160impl<T, U> AsMut<T> for MetaRefMut<'_, T, U> {
161    #[inline]
162    fn as_mut(&mut self) -> &mut T {
163        self.meta
164    }
165}
166
167impl<'a, T> MetaRef<'a, T> {
168    #[doc(alias = "get_api")]
169    #[inline]
170    pub fn api(&self) -> glib::Type {
171        unsafe {
172            let meta = self.meta as *const _ as *const ffi::GstMeta;
173            let info = (*meta).info;
174            glib::Type::from_glib((*info).api)
175        }
176    }
177
178    #[inline]
179    pub fn flags(&self) -> crate::MetaFlags {
180        unsafe {
181            let meta = self.meta as *const _ as *const ffi::GstMeta;
182            from_glib((*meta).flags)
183        }
184    }
185
186    #[inline]
187    pub fn type_(&self) -> glib::Type {
188        unsafe {
189            let meta = self.meta as *const _ as *const ffi::GstMeta;
190            let info = (*meta).info;
191            glib::Type::from_glib((*info).type_)
192        }
193    }
194
195    #[cfg(feature = "v1_16")]
196    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
197    #[doc(alias = "get_seqnum")]
198    #[doc(alias = "gst_meta_get_seqnum")]
199    #[inline]
200    pub fn seqnum(&self) -> MetaSeqnum {
201        unsafe {
202            let meta = self.meta as *const _ as *const ffi::GstMeta;
203            MetaSeqnum(ffi::gst_meta_get_seqnum(meta))
204        }
205    }
206
207    #[inline]
208    #[doc(alias = "gst_meta_api_type_has_tag")]
209    pub fn has_tag<MT: MetaTag>(&self) -> bool {
210        self.has_tag_by_quark(MT::quark())
211    }
212
213    #[inline]
214    pub fn has_tag_by_quark(&self, tag: glib::Quark) -> bool {
215        meta_api_type_has_tag_by_quark(self.api(), tag)
216    }
217
218    #[inline]
219    #[doc(alias = "gst_meta_api_type_tags_contain_only")]
220    pub fn tags_contain_only(&self, tags: &[&str]) -> bool {
221        meta_api_type_tags_contain_only(self.api(), tags)
222    }
223
224    #[inline]
225    #[doc(alias = "gst_meta_api_type_get_tags")]
226    pub fn tags<'b>(&self) -> &'b [glib::GStringPtr] {
227        meta_api_type_get_tags(self.api())
228    }
229
230    #[inline]
231    pub fn upcast_ref(&self) -> &MetaRef<'a, Meta> {
232        unsafe { &*(self as *const MetaRef<'a, T> as *const MetaRef<'a, Meta>) }
233    }
234
235    pub fn transform<MT>(&self, buffer: &mut BufferRef, data: &'a MT) -> Result<(), glib::BoolError>
236    where
237        T: MetaAPI,
238        MT: MetaTransform<'a>,
239    {
240        unsafe {
241            let info = *(*self.upcast_ref().as_ptr()).info;
242            let Some(transform_func) = info.transform_func else {
243                return Err(glib::bool_error!(
244                    "Can't copy meta without transform function"
245                ));
246            };
247
248            let data = data.to_raw(self)?;
249
250            glib::result_from_gboolean!(
251                transform_func(
252                    buffer.as_mut_ptr(),
253                    mut_override(self.upcast_ref().as_ptr()),
254                    mut_override(self.buffer.as_ptr()),
255                    MT::quark().into_glib(),
256                    mut_override(&data) as *mut _,
257                ),
258                "Failed to transform meta"
259            )
260        }
261    }
262
263    #[inline]
264    pub fn as_ptr(&self) -> *const T::GstType
265    where
266        T: MetaAPI,
267    {
268        self.meta as *const _ as *const <T as MetaAPI>::GstType
269    }
270
271    #[cfg(feature = "v1_24")]
272    #[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
273    #[doc(alias = "gst_meta_serialize")]
274    pub fn serialize<B: ByteArrayInterface + ?Sized>(
275        &self,
276        writer: &mut B,
277    ) -> Result<usize, glib::BoolError> {
278        unsafe {
279            #[repr(C)]
280            struct Writer<'a, B: ?Sized> {
281                iface_: ffi::GstByteArrayInterface,
282                writer: &'a mut B,
283            }
284
285            unsafe extern "C" fn resize<B: ByteArrayInterface + ?Sized>(
286                iface_: *mut ffi::GstByteArrayInterface,
287                size: usize,
288            ) -> glib::ffi::gboolean {
289                let iface_ = &mut *(iface_ as *mut Writer<B>);
290
291                match iface_.writer.resize(size) {
292                    Some(new_data) => {
293                        iface_.iface_.data = new_data.as_mut_ptr();
294                        iface_.iface_.len = size;
295
296                        glib::ffi::GTRUE
297                    }
298                    None => glib::ffi::GFALSE,
299                }
300            }
301
302            let initial_len = writer.initial_len();
303
304            let mut iface_ = Writer {
305                iface_: ffi::GstByteArrayInterface {
306                    data: writer.as_mut().as_mut_ptr(),
307                    len: initial_len,
308                    resize: Some(resize::<B>),
309                    _gst_reserved: [ptr::null_mut(); 4],
310                },
311                writer: &mut *writer,
312            };
313
314            let res = bool::from_glib(ffi::gst_meta_serialize(
315                self.meta as *const T as *const ffi::GstMeta,
316                &mut iface_.iface_,
317            ));
318
319            if !res {
320                return Err(glib::bool_error!("Failed to serialize meta"));
321            }
322
323            assert!(iface_.iface_.len >= initial_len);
324
325            Ok(iface_.iface_.len - initial_len)
326        }
327    }
328}
329
330#[cfg(feature = "v1_24")]
331#[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
332pub trait ByteArrayInterface: AsMut<[u8]> {
333    fn initial_len(&self) -> usize;
334    fn resize(&mut self, size: usize) -> Option<&mut [u8]>;
335}
336
337#[cfg(feature = "v1_24")]
338#[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
339impl ByteArrayInterface for Vec<u8> {
340    fn initial_len(&self) -> usize {
341        self.len()
342    }
343
344    fn resize(&mut self, size: usize) -> Option<&mut [u8]> {
345        self.resize(size, 0);
346        Some(&mut self[0..size])
347    }
348}
349
350#[cfg(feature = "v1_24")]
351#[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
352impl<A: smallvec::Array<Item = u8>> ByteArrayInterface for smallvec::SmallVec<A> {
353    fn initial_len(&self) -> usize {
354        self.len()
355    }
356
357    fn resize(&mut self, size: usize) -> Option<&mut [u8]> {
358        self.resize(size, 0);
359        Some(&mut self[0..size])
360    }
361}
362
363#[cfg(feature = "v1_24")]
364#[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
365impl ByteArrayInterface for &mut [u8] {
366    fn initial_len(&self) -> usize {
367        0
368    }
369
370    fn resize(&mut self, size: usize) -> Option<&mut [u8]> {
371        if self.len() < size {
372            return None;
373        }
374
375        Some(&mut self[0..size])
376    }
377}
378
379#[cfg(feature = "v1_24")]
380#[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
381impl<const N: usize> ByteArrayInterface for [u8; N] {
382    fn initial_len(&self) -> usize {
383        0
384    }
385
386    fn resize(&mut self, size: usize) -> Option<&mut [u8]> {
387        if N < size {
388            return None;
389        }
390
391        Some(&mut self[0..size])
392    }
393}
394
395impl<'a> MetaRef<'a, Meta> {
396    #[inline]
397    pub fn downcast_ref<T: MetaAPI>(&self) -> Option<&MetaRef<'a, T>> {
398        let target_type = T::meta_api();
399        let type_ = self.api();
400
401        if type_ == glib::Type::INVALID || target_type == type_ {
402            Some(unsafe { &*(self as *const MetaRef<'a, Meta> as *const MetaRef<'a, T>) })
403        } else {
404            None
405        }
406    }
407
408    #[cfg(feature = "v1_20")]
409    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
410    #[inline]
411    pub fn try_as_custom_meta(&self) -> Option<&MetaRef<'a, CustomMeta>> {
412        unsafe {
413            if ffi::gst_meta_info_is_custom(&*self.0.info) == glib::ffi::GFALSE {
414                return None;
415            }
416
417            Some(&*(self as *const MetaRef<'a, Meta> as *const MetaRef<'a, CustomMeta>))
418        }
419    }
420}
421
422impl<'a, T, U> MetaRefMut<'a, T, U> {
423    #[doc(alias = "get_api")]
424    #[inline]
425    pub fn api(&self) -> glib::Type {
426        self.as_meta_ref().api()
427    }
428
429    #[inline]
430    pub fn flags(&self) -> crate::MetaFlags {
431        self.as_meta_ref().flags()
432    }
433
434    #[inline]
435    pub fn type_(&self) -> glib::Type {
436        self.as_meta_ref().type_()
437    }
438
439    #[cfg(feature = "v1_16")]
440    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
441    #[doc(alias = "get_seqnum")]
442    #[doc(alias = "gst_meta_get_seqnum")]
443    #[inline]
444    pub fn seqnum(&self) -> MetaSeqnum {
445        self.as_meta_ref().seqnum()
446    }
447
448    #[inline]
449    #[doc(alias = "gst_meta_api_type_has_tag")]
450    pub fn has_tag<MT: MetaTag>(&self) -> bool {
451        self.as_meta_ref().has_tag::<MT>()
452    }
453
454    #[inline]
455    pub fn has_tag_by_quark(&self, tag: glib::Quark) -> bool {
456        self.as_meta_ref().has_tag_by_quark(tag)
457    }
458
459    #[inline]
460    #[doc(alias = "gst_meta_api_type_tags_contain_only")]
461    pub fn tags_contain_only(&self, tags: &[&str]) -> bool {
462        self.as_meta_ref().tags_contain_only(tags)
463    }
464
465    #[inline]
466    #[doc(alias = "gst_meta_api_type_get_tags")]
467    pub fn tags<'b>(&self) -> &'b [glib::GStringPtr] {
468        self.as_meta_ref().tags()
469    }
470
471    #[inline]
472    pub fn upcast_ref(&self) -> &MetaRef<'a, Meta> {
473        unsafe { &*(self as *const MetaRefMut<'a, T, U> as *const MetaRef<'a, Meta>) }
474    }
475
476    #[inline]
477    pub fn upcast_mut(&mut self) -> &mut MetaRefMut<'a, Meta, U> {
478        unsafe { &mut *(self as *mut MetaRefMut<'a, T, U> as *mut MetaRefMut<'a, Meta, U>) }
479    }
480
481    #[inline]
482    pub fn as_meta_ref(&self) -> MetaRef<T> {
483        MetaRef {
484            meta: self.meta,
485            buffer: self.buffer,
486        }
487    }
488
489    pub fn transform<MT>(
490        &'a self,
491        buffer: &mut BufferRef,
492        data: &'a MT,
493    ) -> Result<(), glib::BoolError>
494    where
495        T: MetaAPI,
496        MT: MetaTransform<'a>,
497    {
498        self.as_meta_ref().transform(buffer, data)
499    }
500
501    #[inline]
502    pub fn as_ptr(&self) -> *const T::GstType
503    where
504        T: MetaAPI,
505    {
506        self.meta as *const _ as *const <T as MetaAPI>::GstType
507    }
508
509    #[inline]
510    pub fn as_mut_ptr(&mut self) -> *mut T::GstType
511    where
512        T: MetaAPI,
513    {
514        self.meta as *mut _ as *mut <T as MetaAPI>::GstType
515    }
516
517    #[cfg(feature = "v1_24")]
518    #[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
519    #[doc(alias = "gst_meta_serialize")]
520    pub fn serialize<B: ByteArrayInterface + ?Sized>(
521        &self,
522        writer: &mut B,
523    ) -> Result<usize, glib::BoolError> {
524        self.as_meta_ref().serialize(writer)
525    }
526
527    #[cfg(feature = "v1_24")]
528    #[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
529    pub fn clear(&mut self) -> Result<(), glib::BoolError>
530    where
531        T: MetaAPI,
532    {
533        unsafe {
534            let info = *(*self.upcast_ref().as_ptr()).info;
535
536            if let Some(clear_func) = info.clear_func {
537                clear_func(self.buffer.as_mut_ptr(), self.upcast_mut().as_mut_ptr());
538                Ok(())
539            } else {
540                Err(glib::bool_error!("Failed to clear meta"))
541            }
542        }
543    }
544}
545
546impl<T> MetaRefMut<'_, T, Standalone> {
547    #[doc(alias = "gst_buffer_remove_meta")]
548    pub fn remove(self) -> Result<(), glib::BoolError> {
549        if self.flags().contains(crate::MetaFlags::LOCKED) {
550            return Err(glib::bool_error!("Can't remove locked meta"));
551        }
552
553        unsafe {
554            let res = ffi::gst_buffer_remove_meta(
555                self.buffer.as_mut_ptr(),
556                self.meta as *mut T as *mut ffi::GstMeta,
557            );
558            debug_assert_ne!(res, glib::ffi::GFALSE);
559
560            Ok(())
561        }
562    }
563}
564
565impl<'a, U> MetaRefMut<'a, Meta, U> {
566    #[inline]
567    pub fn downcast_ref<T: MetaAPI>(&mut self) -> Option<&MetaRefMut<'a, T, U>> {
568        let target_type = T::meta_api();
569        let type_ = self.api();
570
571        if type_ == glib::Type::INVALID || target_type == type_ {
572            Some(unsafe { &*(self as *mut MetaRefMut<'a, Meta, U> as *const MetaRefMut<'a, T, U>) })
573        } else {
574            None
575        }
576    }
577
578    #[inline]
579    pub fn downcast_mut<T: MetaAPI>(&mut self) -> Option<&mut MetaRefMut<'a, T, U>> {
580        let target_type = T::meta_api();
581        let type_ = self.api();
582
583        if type_ == glib::Type::INVALID || target_type == type_ {
584            Some(unsafe {
585                &mut *(self as *mut MetaRefMut<'a, Meta, U> as *mut MetaRefMut<'a, T, U>)
586            })
587        } else {
588            None
589        }
590    }
591
592    #[cfg(feature = "v1_20")]
593    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
594    #[inline]
595    pub fn try_as_custom_meta(&self) -> Option<&MetaRefMut<'a, CustomMeta, U>> {
596        unsafe {
597            if ffi::gst_meta_info_is_custom(&*self.0.info) == glib::ffi::GFALSE {
598                return None;
599            }
600
601            Some(&*(self as *const MetaRefMut<'a, Meta, U> as *const MetaRefMut<'a, CustomMeta, U>))
602        }
603    }
604
605    #[cfg(feature = "v1_20")]
606    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
607    #[inline]
608    pub fn try_as_mut_custom_meta(&mut self) -> Option<&mut MetaRefMut<'a, CustomMeta, U>> {
609        unsafe {
610            if ffi::gst_meta_info_is_custom(&*self.0.info) == glib::ffi::GFALSE {
611                return None;
612            }
613
614            Some(&mut *(self as *mut MetaRefMut<'a, Meta, U> as *mut MetaRefMut<'a, CustomMeta, U>))
615        }
616    }
617}
618
619#[repr(transparent)]
620#[doc(alias = "GstMeta")]
621pub struct Meta(ffi::GstMeta);
622
623unsafe impl Send for Meta {}
624unsafe impl Sync for Meta {}
625
626unsafe impl MetaAPI for Meta {
627    type GstType = ffi::GstMeta;
628
629    #[inline]
630    fn meta_api() -> glib::Type {
631        glib::Type::INVALID
632    }
633}
634
635impl fmt::Debug for Meta {
636    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
637        f.debug_struct("Meta")
638            .field("api", &unsafe { glib::Type::from_glib((*self.0.info).api) })
639            .field("type", &unsafe {
640                glib::Type::from_glib((*self.0.info).type_)
641            })
642            .field("flags", &unsafe {
643                crate::MetaFlags::from_glib(self.0.flags)
644            })
645            .finish()
646    }
647}
648
649impl Meta {
650    #[cfg(feature = "v1_24")]
651    #[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
652    #[doc(alias = "gst_meta_deserialize")]
653    pub fn deserialize<'a>(
654        buffer: &'a mut BufferRef,
655        data: &[u8],
656        consumed: &mut usize,
657    ) -> Result<MetaRefMut<'a, Self, Standalone>, glib::BoolError> {
658        skip_assert_initialized!();
659
660        unsafe {
661            use std::mem;
662
663            let mut consumed_u32 = mem::MaybeUninit::uninit();
664
665            let res = ffi::gst_meta_deserialize(
666                buffer.as_mut_ptr(),
667                data.as_ptr(),
668                data.len(),
669                consumed_u32.as_mut_ptr(),
670            );
671
672            *consumed = consumed_u32.assume_init() as usize;
673
674            if res.is_null() {
675                return Err(glib::bool_error!("Failed to deserialize meta"));
676            }
677
678            Ok(MetaRefMut {
679                meta: &mut *(res as *mut Self),
680                buffer,
681                mode: PhantomData,
682            })
683        }
684    }
685}
686
687#[repr(transparent)]
688#[doc(alias = "GstParentBufferMeta")]
689pub struct ParentBufferMeta(ffi::GstParentBufferMeta);
690
691unsafe impl Send for ParentBufferMeta {}
692unsafe impl Sync for ParentBufferMeta {}
693
694impl ParentBufferMeta {
695    #[doc(alias = "gst_buffer_add_parent_buffer_meta")]
696    pub fn add<'a>(buffer: &'a mut BufferRef, parent: &Buffer) -> MetaRefMut<'a, Self, Standalone> {
697        skip_assert_initialized!();
698        unsafe {
699            let meta = ffi::gst_buffer_add_parent_buffer_meta(
700                buffer.as_mut_ptr(),
701                parent.to_glib_none().0,
702            );
703
704            Self::from_mut_ptr(buffer, meta)
705        }
706    }
707
708    #[doc(alias = "get_parent")]
709    #[inline]
710    pub fn parent(&self) -> &BufferRef {
711        unsafe { BufferRef::from_ptr(self.0.buffer) }
712    }
713
714    #[doc(alias = "get_parent_owned")]
715    #[inline]
716    pub fn parent_owned(&self) -> Buffer {
717        unsafe { from_glib_none(self.0.buffer) }
718    }
719}
720
721unsafe impl MetaAPI for ParentBufferMeta {
722    type GstType = ffi::GstParentBufferMeta;
723
724    #[doc(alias = "gst_parent_buffer_meta_api_get_type")]
725    #[inline]
726    fn meta_api() -> glib::Type {
727        unsafe { from_glib(ffi::gst_parent_buffer_meta_api_get_type()) }
728    }
729}
730
731impl fmt::Debug for ParentBufferMeta {
732    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
733        f.debug_struct("ParentBufferMeta")
734            .field("parent", &self.parent())
735            .finish()
736    }
737}
738
739#[repr(transparent)]
740#[doc(alias = "GstProtectionMeta")]
741pub struct ProtectionMeta(ffi::GstProtectionMeta);
742
743unsafe impl Send for ProtectionMeta {}
744unsafe impl Sync for ProtectionMeta {}
745
746impl ProtectionMeta {
747    #[doc(alias = "gst_buffer_add_protection_meta")]
748    pub fn add(buffer: &mut BufferRef, info: crate::Structure) -> MetaRefMut<Self, Standalone> {
749        skip_assert_initialized!();
750        unsafe {
751            let meta =
752                ffi::gst_buffer_add_protection_meta(buffer.as_mut_ptr(), info.into_glib_ptr());
753
754            Self::from_mut_ptr(buffer, meta)
755        }
756    }
757
758    #[doc(alias = "get_info")]
759    #[inline]
760    pub fn info(&self) -> &crate::StructureRef {
761        unsafe { crate::StructureRef::from_glib_borrow(self.0.info) }
762    }
763
764    #[doc(alias = "get_info_mut")]
765    #[inline]
766    pub fn info_mut(&mut self) -> &mut crate::StructureRef {
767        unsafe { crate::StructureRef::from_glib_borrow_mut(self.0.info) }
768    }
769}
770
771unsafe impl MetaAPI for ProtectionMeta {
772    type GstType = ffi::GstProtectionMeta;
773
774    #[doc(alias = "gst_protection_meta_api_get_type")]
775    #[inline]
776    fn meta_api() -> glib::Type {
777        unsafe { from_glib(ffi::gst_protection_meta_api_get_type()) }
778    }
779}
780
781impl fmt::Debug for ProtectionMeta {
782    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
783        f.debug_struct("ProtectionMeta")
784            .field("info", &self.info())
785            .finish()
786    }
787}
788
789#[repr(transparent)]
790#[doc(alias = "GstReferenceTimestampMeta")]
791pub struct ReferenceTimestampMeta(ffi::GstReferenceTimestampMeta);
792
793unsafe impl Send for ReferenceTimestampMeta {}
794unsafe impl Sync for ReferenceTimestampMeta {}
795
796impl ReferenceTimestampMeta {
797    #[doc(alias = "gst_buffer_add_reference_timestamp_meta")]
798    pub fn add<'a>(
799        buffer: &'a mut BufferRef,
800        reference: &Caps,
801        timestamp: ClockTime,
802        duration: impl Into<Option<ClockTime>>,
803    ) -> MetaRefMut<'a, Self, Standalone> {
804        skip_assert_initialized!();
805        unsafe {
806            let meta = ffi::gst_buffer_add_reference_timestamp_meta(
807                buffer.as_mut_ptr(),
808                reference.to_glib_none().0,
809                timestamp.into_glib(),
810                duration.into().into_glib(),
811            );
812
813            Self::from_mut_ptr(buffer, meta)
814        }
815    }
816
817    #[doc(alias = "get_reference")]
818    #[inline]
819    pub fn reference(&self) -> &CapsRef {
820        unsafe { CapsRef::from_ptr(self.0.reference) }
821    }
822
823    #[doc(alias = "get_reference_owned")]
824    #[inline]
825    pub fn reference_owned(&self) -> Caps {
826        unsafe { from_glib_none(self.0.reference) }
827    }
828
829    #[doc(alias = "get_timestamp")]
830    #[inline]
831    pub fn timestamp(&self) -> ClockTime {
832        unsafe { try_from_glib(self.0.timestamp).expect("undefined timestamp") }
833    }
834
835    #[doc(alias = "get_duration")]
836    #[inline]
837    pub fn duration(&self) -> Option<ClockTime> {
838        unsafe { from_glib(self.0.duration) }
839    }
840
841    #[cfg(feature = "v1_28")]
842    #[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
843    #[inline]
844    pub fn info(&self) -> Option<&crate::StructureRef> {
845        unsafe {
846            if self.0.info.is_null() {
847                None
848            } else {
849                Some(crate::StructureRef::from_glib_borrow(self.0.info))
850            }
851        }
852    }
853
854    #[cfg(feature = "v1_28")]
855    #[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
856    #[inline]
857    pub fn set_info(&mut self, structure: crate::Structure) {
858        unsafe {
859            if !self.0.info.is_null() {
860                ffi::gst_structure_free(self.0.info);
861            }
862            self.0.info = structure.into_glib_ptr();
863        }
864    }
865}
866
867unsafe impl MetaAPI for ReferenceTimestampMeta {
868    type GstType = ffi::GstReferenceTimestampMeta;
869
870    #[doc(alias = "gst_reference_timestamp_meta_api_get_type")]
871    #[inline]
872    fn meta_api() -> glib::Type {
873        unsafe { from_glib(ffi::gst_reference_timestamp_meta_api_get_type()) }
874    }
875}
876
877impl fmt::Debug for ReferenceTimestampMeta {
878    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
879        use crate::utils::Displayable;
880
881        f.debug_struct("ReferenceTimestampMeta")
882            .field("reference", &self.reference())
883            .field("timestamp", &self.timestamp().display())
884            .field("duration", &self.duration().display())
885            .finish()
886    }
887}
888
889#[cfg(feature = "v1_20")]
890#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
891#[repr(transparent)]
892#[doc(alias = "GstCustomMeta")]
893pub struct CustomMeta(ffi::GstCustomMeta);
894
895#[cfg(feature = "v1_20")]
896#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
897unsafe impl Send for CustomMeta {}
898#[cfg(feature = "v1_20")]
899#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
900unsafe impl Sync for CustomMeta {}
901
902#[cfg(feature = "v1_20")]
903#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
904impl CustomMeta {
905    #[doc(alias = "gst_meta_register_custom")]
906    pub fn register(name: &str, tags: &[&str]) {
907        assert_initialized_main_thread!();
908        unsafe {
909            ffi::gst_meta_register_custom(
910                name.to_glib_none().0,
911                tags.to_glib_none().0,
912                None,
913                ptr::null_mut(),
914                None,
915            );
916        }
917    }
918
919    #[doc(alias = "gst_meta_register_custom")]
920    pub fn register_with_transform<
921        F: Fn(&mut BufferRef, &CustomMeta, &BufferRef, glib::Quark) -> bool + Send + Sync + 'static,
922    >(
923        name: &str,
924        tags: &[&str],
925        transform_func: F,
926    ) {
927        assert_initialized_main_thread!();
928        unsafe extern "C" fn transform_func_trampoline<
929            F: Fn(&mut BufferRef, &CustomMeta, &BufferRef, glib::Quark) -> bool
930                + Send
931                + Sync
932                + 'static,
933        >(
934            dest: *mut ffi::GstBuffer,
935            meta: *mut ffi::GstCustomMeta,
936            src: *mut ffi::GstBuffer,
937            type_: glib::ffi::GQuark,
938            _data: glib::ffi::gpointer,
939            user_data: glib::ffi::gpointer,
940        ) -> glib::ffi::gboolean {
941            let func = &*(user_data as *const F);
942            let res = func(
943                BufferRef::from_mut_ptr(dest),
944                &*(meta as *const CustomMeta),
945                BufferRef::from_ptr(src),
946                from_glib(type_),
947            );
948            res.into_glib()
949        }
950
951        unsafe extern "C" fn transform_func_free<F>(ptr: glib::ffi::gpointer) {
952            let _ = Box::from_raw(ptr as *mut F);
953        }
954
955        unsafe {
956            ffi::gst_meta_register_custom(
957                name.to_glib_none().0,
958                tags.to_glib_none().0,
959                Some(transform_func_trampoline::<F>),
960                Box::into_raw(Box::new(transform_func)) as glib::ffi::gpointer,
961                Some(transform_func_free::<F>),
962            );
963        }
964    }
965
966    #[doc(alias = "gst_meta_register_simple")]
967    pub fn register_simple(name: &str) {
968        assert_initialized_main_thread!();
969        unsafe {
970            ffi::gst_meta_register_custom(
971                name.to_glib_none().0,
972                [ptr::null()].as_mut_ptr(),
973                None,
974                ptr::null_mut(),
975                None,
976            );
977        }
978    }
979
980    pub fn is_registered(name: &str) -> bool {
981        assert_initialized_main_thread!();
982        unsafe { name.run_with_gstr(|name| !ffi::gst_meta_get_info(name.as_ptr()).is_null()) }
983    }
984
985    #[doc(alias = "gst_buffer_add_custom_meta")]
986    pub fn add<'a>(
987        buffer: &'a mut BufferRef,
988        name: &str,
989    ) -> Result<MetaRefMut<'a, Self, Standalone>, glib::BoolError> {
990        skip_assert_initialized!();
991        unsafe {
992            let meta = ffi::gst_buffer_add_custom_meta(buffer.as_mut_ptr(), name.to_glib_none().0);
993
994            if meta.is_null() {
995                return Err(glib::bool_error!("Failed to add custom meta"));
996            }
997
998            Ok(MetaRefMut {
999                meta: &mut *(meta as *mut Self),
1000                buffer,
1001                mode: PhantomData,
1002            })
1003        }
1004    }
1005
1006    #[doc(alias = "gst_buffer_get_custom_meta")]
1007    pub fn from_buffer<'a>(
1008        buffer: &'a BufferRef,
1009        name: &str,
1010    ) -> Result<MetaRef<'a, Self>, glib::BoolError> {
1011        skip_assert_initialized!();
1012        unsafe {
1013            let meta = ffi::gst_buffer_get_custom_meta(buffer.as_mut_ptr(), name.to_glib_none().0);
1014
1015            if meta.is_null() {
1016                return Err(glib::bool_error!("Failed to get custom meta"));
1017            }
1018
1019            Ok(MetaRef {
1020                meta: &*(meta as *const Self),
1021                buffer,
1022            })
1023        }
1024    }
1025
1026    #[doc(alias = "gst_buffer_get_custom_meta")]
1027    pub fn from_mut_buffer<'a>(
1028        buffer: &'a mut BufferRef,
1029        name: &str,
1030    ) -> Result<MetaRefMut<'a, Self, Standalone>, glib::BoolError> {
1031        skip_assert_initialized!();
1032        unsafe {
1033            let meta = ffi::gst_buffer_get_custom_meta(buffer.as_mut_ptr(), name.to_glib_none().0);
1034
1035            if meta.is_null() {
1036                return Err(glib::bool_error!("Failed to get custom meta"));
1037            }
1038
1039            Ok(MetaRefMut {
1040                meta: &mut *(meta as *mut Self),
1041                buffer,
1042                mode: PhantomData,
1043            })
1044        }
1045    }
1046
1047    #[doc(alias = "gst_custom_meta_get_structure")]
1048    #[inline]
1049    pub fn structure(&self) -> &crate::StructureRef {
1050        unsafe {
1051            crate::StructureRef::from_glib_borrow(ffi::gst_custom_meta_get_structure(mut_override(
1052                &self.0,
1053            )))
1054        }
1055    }
1056
1057    #[doc(alias = "gst_custom_meta_get_structure")]
1058    #[inline]
1059    pub fn mut_structure(&mut self) -> &mut crate::StructureRef {
1060        unsafe {
1061            crate::StructureRef::from_glib_borrow_mut(ffi::gst_custom_meta_get_structure(
1062                &mut self.0,
1063            ))
1064        }
1065    }
1066
1067    #[doc(alias = "gst_custom_meta_has_name")]
1068    #[inline]
1069    pub fn has_name(&self, name: &str) -> bool {
1070        unsafe {
1071            from_glib(ffi::gst_custom_meta_has_name(
1072                mut_override(&self.0),
1073                name.to_glib_none().0,
1074            ))
1075        }
1076    }
1077}
1078
1079pub trait MetaTag {
1080    const TAG_NAME: &'static glib::GStr;
1081    fn quark() -> glib::Quark;
1082}
1083
1084#[macro_export]
1085macro_rules! impl_meta_tag(
1086    ($name:ident, $gst_tag:path) => {
1087        pub enum $name {}
1088        impl $crate::meta::MetaTag for $name {
1089            const TAG_NAME: &'static glib::GStr = unsafe { glib::GStr::from_utf8_with_nul_unchecked($gst_tag) };
1090	    fn quark() -> glib::Quark {
1091                static QUARK: std::sync::OnceLock<glib::Quark> = std::sync::OnceLock::new();
1092                *QUARK.get_or_init(|| glib::Quark::from_static_str(Self::TAG_NAME))
1093            }
1094        }
1095    };
1096);
1097
1098pub mod tags {
1099    impl_meta_tag!(Memory, crate::ffi::GST_META_TAG_MEMORY_STR);
1100    impl_meta_tag!(
1101        MemoryReference,
1102        crate::ffi::GST_META_TAG_MEMORY_REFERENCE_STR
1103    );
1104}
1105
1106pub unsafe trait MetaTransform<'a> {
1107    type GLibType;
1108    fn quark() -> glib::Quark;
1109    fn to_raw<T: MetaAPI>(&self, meta: &MetaRef<T>) -> Result<Self::GLibType, glib::BoolError>;
1110}
1111
1112#[derive(Debug, Clone, PartialEq, Eq)]
1113pub struct MetaTransformCopy {
1114    range: (Bound<usize>, Bound<usize>),
1115    region: bool,
1116}
1117
1118impl MetaTransformCopy {
1119    pub fn new(region: bool, range: impl RangeBounds<usize>) -> Self {
1120        skip_assert_initialized!();
1121        MetaTransformCopy {
1122            range: (range.start_bound().cloned(), range.end_bound().cloned()),
1123            region,
1124        }
1125    }
1126}
1127
1128unsafe impl MetaTransform<'_> for MetaTransformCopy {
1129    type GLibType = ffi::GstMetaTransformCopy;
1130
1131    fn quark() -> glib::Quark {
1132        static QUARK: std::sync::OnceLock<glib::Quark> = std::sync::OnceLock::new();
1133        *QUARK.get_or_init(|| glib::Quark::from_static_str(glib::gstr!("gst-copy")))
1134    }
1135    fn to_raw<T: MetaAPI>(
1136        &self,
1137        meta: &MetaRef<T>,
1138    ) -> Result<ffi::GstMetaTransformCopy, glib::BoolError> {
1139        let (offset, size) = meta.buffer.byte_range_into_offset_len(self.range)?;
1140
1141        Ok(ffi::GstMetaTransformCopy {
1142            region: self.region.into_glib(),
1143            offset,
1144            size,
1145        })
1146    }
1147}
1148
1149#[inline]
1150#[doc(alias = "gst_meta_api_type_has_tag")]
1151pub fn meta_api_type_has_tag<MT: MetaTag>(type_: glib::Type) -> bool {
1152    skip_assert_initialized!();
1153    meta_api_type_has_tag_by_quark(type_, MT::quark())
1154}
1155
1156#[inline]
1157#[doc(alias = "gst_meta_api_type_has_tag")]
1158pub fn meta_api_type_has_tag_by_quark(type_: glib::Type, tag: glib::Quark) -> bool {
1159    skip_assert_initialized!();
1160    unsafe {
1161        from_glib(ffi::gst_meta_api_type_has_tag(
1162            type_.into_glib(),
1163            tag.into_glib(),
1164        ))
1165    }
1166}
1167
1168#[inline]
1169#[doc(alias = "gst_meta_api_type_tags_contain_only")]
1170pub fn meta_api_type_tags_contain_only(type_: glib::Type, tags: &[&str]) -> bool {
1171    skip_assert_initialized!();
1172    let meta_tags = meta_api_type_get_tags(type_);
1173
1174    meta_tags
1175        .iter()
1176        .all(|tag| tags.iter().any(|t| *t == tag.as_str()))
1177}
1178
1179#[inline]
1180#[doc(alias = "gst_meta_api_type_get_tags")]
1181pub fn meta_api_type_get_tags<'b>(type_: glib::Type) -> &'b [glib::GStringPtr] {
1182    skip_assert_initialized!();
1183    unsafe { glib::StrV::from_glib_borrow(ffi::gst_meta_api_type_get_tags(type_.into_glib())) }
1184}
1185
1186#[cfg(feature = "v1_26")]
1187#[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
1188#[doc(alias = "gst_meta_api_type_aggregate_params")]
1189pub fn meta_api_type_aggregate_params(
1190    type_: glib::Type,
1191    params1: &crate::StructureRef,
1192    params2: &crate::StructureRef,
1193) -> Result<Option<crate::Structure>, glib::BoolError> {
1194    skip_assert_initialized!();
1195    unsafe {
1196        let mut new_params = ptr::null_mut();
1197        let res = bool::from_glib(ffi::gst_meta_api_type_aggregate_params(
1198            type_.into_glib(),
1199            &mut new_params,
1200            params1.as_ptr(),
1201            params2.as_ptr(),
1202        ));
1203
1204        if res {
1205            Ok(from_glib_full(new_params))
1206        } else {
1207            Err(glib::bool_error!("Failed to aggregate meta type params"))
1208        }
1209    }
1210}
1211
1212#[cfg(test)]
1213mod tests {
1214    use super::*;
1215
1216    #[test]
1217    fn test_add_get_iterate_meta() {
1218        crate::init().unwrap();
1219
1220        let mut buffer = crate::Buffer::new();
1221        let parent = crate::Buffer::new();
1222        {
1223            let meta = ParentBufferMeta::add(buffer.get_mut().unwrap(), &parent);
1224            assert_eq!(meta.parent().as_ptr(), parent.as_ptr());
1225        }
1226
1227        {
1228            let metas = buffer.iter_meta::<Meta>();
1229            assert_eq!(metas.count(), 1);
1230        }
1231        {
1232            let metas = buffer.get_mut().unwrap().iter_meta_mut::<Meta>();
1233            assert_eq!(metas.count(), 1);
1234        }
1235        {
1236            let metas = buffer.iter_meta::<ParentBufferMeta>().collect::<Vec<_>>();
1237            assert_eq!(metas.len(), 1);
1238            assert_eq!(metas[0].parent().as_ptr(), parent.as_ptr());
1239        }
1240        {
1241            let metas = buffer
1242                .get_mut()
1243                .unwrap()
1244                .iter_meta_mut::<ParentBufferMeta>()
1245                .collect::<Vec<_>>();
1246            assert_eq!(metas.len(), 1);
1247            assert_eq!(metas[0].parent().as_ptr(), parent.as_ptr());
1248            assert!(!metas[0].has_tag_by_quark(glib::Quark::from_str("video")));
1249            assert!(metas[0].has_tag::<tags::MemoryReference>());
1250            assert_eq!(metas[0].tags().len(), 1);
1251
1252            assert_eq!(metas[0].tags(), metas[0].upcast_ref().tags());
1253        }
1254
1255        {
1256            let meta = buffer
1257                .get_mut()
1258                .unwrap()
1259                .meta_mut::<ParentBufferMeta>()
1260                .unwrap();
1261            assert_eq!(meta.parent().as_ptr(), parent.as_ptr());
1262            meta.remove().unwrap();
1263        }
1264
1265        {
1266            let metas = buffer.iter_meta::<Meta>();
1267            assert_eq!(metas.count(), 0);
1268        }
1269        {
1270            let metas = buffer.get_mut().unwrap().iter_meta_mut::<Meta>();
1271            assert_eq!(metas.count(), 0);
1272        }
1273        {
1274            let metas = buffer.iter_meta::<ParentBufferMeta>();
1275            assert_eq!(metas.count(), 0);
1276        }
1277        {
1278            let metas = buffer
1279                .get_mut()
1280                .unwrap()
1281                .iter_meta_mut::<ParentBufferMeta>();
1282            assert_eq!(metas.count(), 0);
1283        }
1284
1285        assert!(buffer.meta::<ParentBufferMeta>().is_none());
1286    }
1287
1288    #[test]
1289    fn test_copy_reference_timestamp_meta() {
1290        crate::init().unwrap();
1291
1292        let caps = crate::Caps::new_empty_simple("timestamp/x-ntp");
1293        let mut buffer = crate::Buffer::new();
1294        {
1295            ReferenceTimestampMeta::add(
1296                buffer.get_mut().unwrap(),
1297                &caps,
1298                crate::ClockTime::from_seconds(1),
1299                crate::ClockTime::NONE,
1300            );
1301        }
1302
1303        let mut buffer_dest = crate::Buffer::new();
1304        {
1305            let meta = buffer.meta::<ReferenceTimestampMeta>().unwrap();
1306            let buffer_dest = buffer_dest.get_mut().unwrap();
1307            meta.transform(buffer_dest, &MetaTransformCopy::new(false, ..))
1308                .unwrap();
1309        }
1310
1311        let meta = buffer_dest.meta::<ReferenceTimestampMeta>().unwrap();
1312        assert_eq!(meta.reference(), &caps);
1313        assert_eq!(meta.timestamp(), crate::ClockTime::from_seconds(1));
1314        assert_eq!(meta.duration(), crate::ClockTime::NONE);
1315    }
1316
1317    #[cfg(feature = "v1_24")]
1318    #[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
1319    #[test]
1320    fn test_meta_serialize() {
1321        use smallvec::SmallVec;
1322
1323        crate::init().unwrap();
1324
1325        let caps = crate::Caps::new_empty_simple("timestamp/x-ntp");
1326        let mut buffer = crate::Buffer::new();
1327
1328        let meta = ReferenceTimestampMeta::add(
1329            buffer.get_mut().unwrap(),
1330            &caps,
1331            crate::ClockTime::from_seconds(1),
1332            crate::ClockTime::NONE,
1333        );
1334
1335        let mut data_1 = Vec::new();
1336        let mut data_2 = [0u8; 128];
1337        let mut data_3 = SmallVec::<[u8; 128]>::new();
1338
1339        let len_1 = meta.serialize(&mut data_1).unwrap();
1340        let len_2 = meta.serialize(&mut data_2).unwrap();
1341        let len_3 = meta.serialize(&mut data_3).unwrap();
1342        assert_eq!(&data_1[..len_1], &data_2[..len_2]);
1343        assert_eq!(&data_1[..len_1], &data_3[..len_3]);
1344
1345        assert!(meta.serialize(&mut [0]).is_err());
1346
1347        let mut buffer_dest = crate::Buffer::new();
1348        let mut consumed = 0;
1349        let mut meta =
1350            Meta::deserialize(buffer_dest.get_mut().unwrap(), &data_1, &mut consumed).unwrap();
1351        assert_eq!(consumed, len_1);
1352
1353        let meta = meta.downcast_ref::<ReferenceTimestampMeta>().unwrap();
1354        assert_eq!(meta.reference(), &caps);
1355        assert_eq!(meta.timestamp(), crate::ClockTime::from_seconds(1));
1356        assert_eq!(meta.duration(), crate::ClockTime::NONE);
1357
1358        let mut consumed = 0;
1359        assert!(
1360            Meta::deserialize(buffer_dest.get_mut().unwrap(), &[0, 1, 2], &mut consumed).is_err()
1361        );
1362        assert_eq!(consumed, 0);
1363    }
1364}