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