1#[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}