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::{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}