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