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