Skip to main content

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