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