Skip to main content

gstreamer_analytics/
relation_meta.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::translate::*;
4use gst::prelude::*;
5use std::marker::PhantomData;
6
7use crate::{RelTypes, ffi};
8
9#[repr(transparent)]
10#[doc(alias = "GstAnalyticsRelationMeta")]
11pub struct AnalyticsRelationMeta(ffi::GstAnalyticsRelationMeta);
12
13unsafe impl Send for AnalyticsRelationMeta {}
14unsafe impl Sync for AnalyticsRelationMeta {}
15
16#[derive(Debug, Copy, Clone)]
17#[doc(alias = "GstAnalyticsRelationMetaInitParams")]
18pub struct AnalyticsRelationMetaInitParams(ffi::GstAnalyticsRelationMetaInitParams);
19
20impl Default for AnalyticsRelationMetaInitParams {
21    fn default() -> Self {
22        Self(ffi::GstAnalyticsRelationMetaInitParams {
23            initial_relation_order: 0,
24            initial_buf_size: 0,
25        })
26    }
27}
28
29impl AnalyticsRelationMetaInitParams {
30    pub fn new(initial_relation_order: usize, initial_buf_size: usize) -> Self {
31        skip_assert_initialized!();
32        Self(ffi::GstAnalyticsRelationMetaInitParams {
33            initial_relation_order,
34            initial_buf_size,
35        })
36    }
37}
38
39#[derive(Debug, Clone)]
40pub struct AnalyticsMtdRef<'a, T: AnalyticsMtd> {
41    id: u32,
42    meta: gst::MetaRef<'a, AnalyticsRelationMeta>,
43    mtd_type: PhantomData<&'a T>,
44}
45
46#[derive(Debug)]
47pub struct AnalyticsMtdRefMut<'a, T: AnalyticsMtd> {
48    id: u32,
49    meta: &'a mut gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>,
50    mtd_type: PhantomData<&'a T>,
51}
52
53pub struct AnalyticsRelationPath {
54    garray: *mut glib::ffi::GArray,
55}
56
57impl std::fmt::Debug for AnalyticsRelationMeta {
58    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
59        f.debug_struct("AnalyticsRelationMeta")
60            .field("len", &self.len())
61            .finish()
62    }
63}
64
65impl AnalyticsRelationMeta {
66    #[doc(alias = "gst_buffer_add_analytics_relation_meta")]
67    pub fn add(buffer: &mut gst::BufferRef) -> gst::MetaRefMut<'_, Self, gst::meta::Standalone> {
68        skip_assert_initialized!();
69
70        unsafe {
71            let meta_ptr = ffi::gst_buffer_add_analytics_relation_meta(buffer.as_mut_ptr());
72            Self::from_mut_ptr(buffer, meta_ptr)
73        }
74    }
75
76    #[doc(alias = "gst_buffer_add_analytics_relation_meta_full")]
77    pub fn add_full<'a>(
78        buffer: &'a mut gst::BufferRef,
79        init_params: &AnalyticsRelationMetaInitParams,
80    ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> {
81        skip_assert_initialized!();
82
83        unsafe {
84            let meta_ptr = ffi::gst_buffer_add_analytics_relation_meta_full(
85                buffer.as_mut_ptr(),
86                mut_override(&init_params.0),
87            );
88            Self::from_mut_ptr(buffer, meta_ptr)
89        }
90    }
91
92    #[doc(alias = "gst_analytics_relation_get_length")]
93    pub fn len(&self) -> usize {
94        unsafe { ffi::gst_analytics_relation_get_length(self.as_mut_ptr()) }
95    }
96
97    pub fn is_empty(&self) -> bool {
98        self.len() == 0
99    }
100
101    #[doc(alias = "gst_analytics_relation_meta_set_relation")]
102    pub fn set_relation(
103        &mut self,
104        type_: crate::RelTypes,
105        an_meta_first_id: u32,
106        an_meta_second_id: u32,
107    ) -> Result<(), glib::BoolError> {
108        let ret = unsafe {
109            from_glib(ffi::gst_analytics_relation_meta_set_relation(
110                self.as_mut_ptr(),
111                type_.into_glib(),
112                an_meta_first_id,
113                an_meta_second_id,
114            ))
115        };
116
117        if ret {
118            Ok(())
119        } else {
120            Err(glib::bool_error!(
121                "Could not set relation {:}->{:} of type {:?}",
122                an_meta_first_id,
123                an_meta_second_id,
124                type_
125            ))
126        }
127    }
128
129    #[doc(alias = "gst_analytics_relation_meta_get_relation")]
130    pub fn relation(&self, an_meta_first_id: u32, an_meta_second_id: u32) -> crate::RelTypes {
131        unsafe {
132            from_glib(ffi::gst_analytics_relation_meta_get_relation(
133                self.as_mut_ptr(),
134                an_meta_first_id,
135                an_meta_second_id,
136            ))
137        }
138    }
139
140    #[doc(alias = "gst_analytics_relation_meta_exist")]
141    pub fn exist(
142        &self,
143        an_meta_first_id: u32,
144        an_meta_second_id: u32,
145        relation_span: i32,
146        cond_types: crate::RelTypes,
147    ) -> bool {
148        unsafe {
149            from_glib(ffi::gst_analytics_relation_meta_exist(
150                self.as_mut_ptr(),
151                an_meta_first_id,
152                an_meta_second_id,
153                relation_span,
154                cond_types.into_glib(),
155                std::ptr::null_mut(),
156            ))
157        }
158    }
159
160    #[doc(alias = "gst_analytics_relation_meta_exist")]
161    pub fn exist_path(
162        &self,
163        an_meta_first_id: u32,
164        an_meta_second_id: u32,
165        relation_span: i32,
166        cond_types: crate::RelTypes,
167    ) -> Result<AnalyticsRelationPath, glib::BoolError> {
168        let mut array = std::ptr::null_mut::<glib::ffi::GArray>();
169        let ret = unsafe {
170            from_glib(ffi::gst_analytics_relation_meta_exist(
171                self.as_mut_ptr(),
172                an_meta_first_id,
173                an_meta_second_id,
174                relation_span,
175                cond_types.into_glib(),
176                &mut array,
177            ))
178        };
179
180        if ret {
181            Ok(AnalyticsRelationPath { garray: array })
182        } else {
183            Err(glib::bool_error!("Such relation doesn't exist"))
184        }
185    }
186
187    pub unsafe fn as_mut_ptr(&self) -> *mut ffi::GstAnalyticsRelationMeta {
188        mut_override(&self.0)
189    }
190}
191
192impl UnsafeFrom<&AnalyticsRelationMeta> for ffi::GstAnalyticsMtd {
193    unsafe fn unsafe_from(t: &AnalyticsRelationMeta) -> Self {
194        unsafe {
195            ffi::GstAnalyticsMtd {
196                id: 0,
197                meta: t.as_mut_ptr(),
198            }
199        }
200    }
201}
202
203impl AnalyticsRelationPath {
204    pub fn as_slice(&self) -> &[u32] {
205        unsafe {
206            std::slice::from_raw_parts(
207                (*self.garray).data as *const u32,
208                (*self.garray).len as usize,
209            )
210        }
211    }
212}
213
214impl Drop for AnalyticsRelationPath {
215    fn drop(&mut self) {
216        unsafe {
217            glib::ffi::g_array_free(self.garray, glib::ffi::GTRUE);
218        }
219    }
220}
221
222mod sealed {
223    pub trait Sealed {}
224    impl<T> Sealed for T {}
225}
226
227pub trait AnalyticsMetaRefExt<'a>: sealed::Sealed {
228    #[doc(alias = "gst_analytics_relation_meta_get_mtd")]
229    fn mtd<T: AnalyticsMtd>(&self, an_meta_id: u32) -> Option<AnalyticsMtdRef<'a, T>>;
230    fn iter<T: AnalyticsMtd>(&'a self) -> AnalyticsMtdIter<'a, T>;
231    fn iter_direct_related<T: AnalyticsMtd>(
232        &'a self,
233        an_meta_id: u32,
234        rel_type: RelTypes,
235    ) -> AnalyticsMtdIter<'a, T>;
236}
237
238impl<'a> AnalyticsMetaRefExt<'a> for gst::MetaRef<'a, AnalyticsRelationMeta> {
239    fn mtd<T: AnalyticsMtd>(&self, an_meta_id: u32) -> Option<AnalyticsMtdRef<'a, T>> {
240        unsafe {
241            let mut mtd = std::mem::MaybeUninit::uninit();
242            let ret = from_glib(ffi::gst_analytics_relation_meta_get_mtd(
243                self.as_mut_ptr(),
244                an_meta_id,
245                T::mtd_type(),
246                mtd.as_mut_ptr(),
247            ));
248            let id = mtd.assume_init().id;
249
250            if ret {
251                Some(AnalyticsMtdRef::from_meta(self, id))
252            } else {
253                None
254            }
255        }
256    }
257
258    fn iter<T: AnalyticsMtd>(&'a self) -> AnalyticsMtdIter<'a, T> {
259        AnalyticsMtdIter::new(self)
260    }
261    fn iter_direct_related<T: AnalyticsMtd>(
262        &'a self,
263        an_meta_id: u32,
264        rel_type: RelTypes,
265    ) -> AnalyticsMtdIter<'a, T> {
266        AnalyticsMtdIter::new_direct_related(self, an_meta_id, rel_type.into_glib())
267    }
268}
269
270impl<'a, T: AnalyticsMtd> AnalyticsMtdRef<'a, T> {
271    pub fn id(&self) -> u32 {
272        self.id
273    }
274
275    #[cfg(feature = "v1_28")]
276    pub(crate) fn meta_ref(&self) -> &gst::MetaRef<'a, AnalyticsRelationMeta> {
277        &self.meta
278    }
279
280    pub unsafe fn from_meta(meta: &gst::MetaRef<'a, AnalyticsRelationMeta>, id: u32) -> Self {
281        skip_assert_initialized!();
282        AnalyticsMtdRef {
283            meta: meta.clone(),
284            id,
285            mtd_type: PhantomData,
286        }
287    }
288
289    #[doc(alias = "gst_analytics_mtd_get_mtd_type")]
290    pub fn mtd_type(&self) -> ffi::GstAnalyticsMtdType {
291        unsafe {
292            let mtd = ffi::GstAnalyticsMtd::unsafe_from(self);
293            ffi::gst_analytics_mtd_get_mtd_type(&mtd)
294        }
295    }
296}
297impl<'a> AnalyticsMtdRef<'a, AnalyticsAnyMtd> {
298    pub fn downcast<T: AnalyticsMtd>(
299        self,
300    ) -> Result<AnalyticsMtdRef<'a, T>, AnalyticsMtdRef<'a, AnalyticsAnyMtd>> {
301        if self.mtd_type() == T::mtd_type() {
302            Ok(AnalyticsMtdRef {
303                id: self.id,
304                meta: self.meta,
305                mtd_type: PhantomData,
306            })
307        } else {
308            Err(self)
309        }
310    }
311
312    pub fn downcast_ref<T: AnalyticsMtd>(&self) -> Option<&AnalyticsMtdRef<'a, T>> {
313        unsafe {
314            if self.mtd_type() == T::mtd_type() {
315                Some(&*(self as *const _ as *const _))
316            } else {
317                None
318            }
319        }
320    }
321}
322
323impl<'a> AnalyticsMtdRefMut<'a, AnalyticsAnyMtd> {
324    pub fn downcast_mut<T: AnalyticsMtd>(&mut self) -> Option<&mut AnalyticsMtdRefMut<'a, T>> {
325        unsafe {
326            if self.as_ref().mtd_type() == T::mtd_type() {
327                Some(&mut *(self as *mut _ as *mut _))
328            } else {
329                None
330            }
331        }
332    }
333}
334
335impl<'a, T: AnalyticsMtd> UnsafeFrom<&AnalyticsMtdRef<'a, T>> for ffi::GstAnalyticsMtd {
336    unsafe fn unsafe_from(t: &AnalyticsMtdRef<'a, T>) -> Self {
337        unsafe {
338            ffi::GstAnalyticsMtd {
339                id: t.id,
340                meta: t.meta.as_mut_ptr(),
341            }
342        }
343    }
344}
345
346pub trait AnalyticsMetaRefMutExt<'a>: sealed::Sealed {
347    #[doc(alias = "gst_analytics_relation_meta_get_mtd")]
348    fn mtd_mut<T: AnalyticsMtd>(&'a mut self, an_meta_id: u32)
349    -> Option<AnalyticsMtdRefMut<'a, T>>;
350
351    fn iter_mut<T: AnalyticsMtd>(&'a mut self) -> AnalyticsMtdIterMut<'a, T>;
352    fn iter_direct_related_mut<T: AnalyticsMtd>(
353        &'a mut self,
354        an_meta_id: u32,
355        rel_type: RelTypes,
356    ) -> AnalyticsMtdIterMut<'a, T>;
357}
358
359impl<'a> AnalyticsMetaRefMutExt<'a>
360    for gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>
361{
362    fn mtd_mut<T: AnalyticsMtd>(
363        &'a mut self,
364        an_meta_id: u32,
365    ) -> Option<AnalyticsMtdRefMut<'a, T>> {
366        unsafe {
367            let mut mtd = std::mem::MaybeUninit::uninit();
368            let ret = from_glib(ffi::gst_analytics_relation_meta_get_mtd(
369                self.as_mut_ptr(),
370                an_meta_id,
371                T::mtd_type(),
372                mtd.as_mut_ptr(),
373            ));
374            let id = mtd.assume_init().id;
375
376            if ret {
377                Some(AnalyticsMtdRefMut::from_meta(self, id))
378            } else {
379                None
380            }
381        }
382    }
383
384    fn iter_mut<T: AnalyticsMtd>(&'a mut self) -> AnalyticsMtdIterMut<'a, T> {
385        AnalyticsMtdIterMut::new(self)
386    }
387    fn iter_direct_related_mut<T: AnalyticsMtd>(
388        &'a mut self,
389        an_meta_id: u32,
390        rel_type: RelTypes,
391    ) -> AnalyticsMtdIterMut<'a, T> {
392        AnalyticsMtdIterMut::new_direct_related(self, an_meta_id, rel_type.into_glib())
393    }
394}
395
396unsafe impl MetaAPI for AnalyticsRelationMeta {
397    type GstType = ffi::GstAnalyticsRelationMeta;
398
399    #[doc(alias = "gst_analytics_relation_meta_api_get_type")]
400    #[inline]
401    fn meta_api() -> glib::Type {
402        unsafe { from_glib(ffi::gst_analytics_relation_meta_api_get_type()) }
403    }
404}
405
406pub unsafe trait AnalyticsMtd {
407    fn mtd_type() -> ffi::GstAnalyticsMtdType;
408}
409
410pub trait AnalyticsMtdExt: AnalyticsMtd {
411    #[doc(alias = "gst_analytics_mtd_type_get_name")]
412    fn type_name() -> &'static str {
413        unsafe {
414            let ptr = ffi::gst_analytics_mtd_type_get_name(Self::mtd_type());
415            std::ffi::CStr::from_ptr(ptr).to_str().unwrap()
416        }
417    }
418}
419
420impl<T: AnalyticsMtd> AnalyticsMtdExt for T {}
421
422impl<'a, T: AnalyticsMtd> AnalyticsMtdRefMut<'a, T> {
423    pub fn id(&self) -> u32 {
424        self.id
425    }
426
427    pub unsafe fn from_meta(
428        meta: &'a mut gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>,
429        id: u32,
430    ) -> Self {
431        skip_assert_initialized!();
432        AnalyticsMtdRefMut {
433            meta,
434            id,
435            mtd_type: PhantomData,
436        }
437    }
438}
439
440impl<'a, T: AnalyticsMtd> UnsafeFrom<&mut AnalyticsMtdRefMut<'a, T>> for ffi::GstAnalyticsMtd {
441    unsafe fn unsafe_from(t: &mut AnalyticsMtdRefMut<'a, T>) -> Self {
442        ffi::GstAnalyticsMtd {
443            id: t.id,
444            meta: t.meta.as_mut_ptr(),
445        }
446    }
447}
448
449impl<'a, T: AnalyticsMtd> From<AnalyticsMtdRefMut<'a, T>> for AnalyticsMtdRef<'a, T> {
450    fn from(value: AnalyticsMtdRefMut<'a, T>) -> Self {
451        skip_assert_initialized!();
452        AnalyticsMtdRef {
453            meta: value.meta.as_ref().clone(),
454            id: value.id,
455            mtd_type: value.mtd_type,
456        }
457    }
458}
459
460impl<'a, T: AnalyticsMtd> From<&mut AnalyticsMtdRefMut<'a, T>> for AnalyticsMtdRef<'a, T> {
461    fn from(value: &mut AnalyticsMtdRefMut<'a, T>) -> Self {
462        skip_assert_initialized!();
463        AnalyticsMtdRef {
464            meta: value.meta.as_ref().clone(),
465            id: value.id,
466            mtd_type: value.mtd_type,
467        }
468    }
469}
470
471impl<'a, T: AnalyticsMtd> AsRef<AnalyticsMtdRef<'a, T>> for AnalyticsMtdRefMut<'a, T> {
472    #[inline]
473    fn as_ref(&self) -> &AnalyticsMtdRef<'a, T> {
474        unsafe { &*(self as *const AnalyticsMtdRefMut<'a, T> as *const AnalyticsMtdRef<'a, T>) }
475    }
476}
477
478macro_rules! define_mtd_iter {
479    ($name:ident, $metaref:ty, $itemref:ty, $copy_meta:expr) => {
480        #[must_use = "iterators are lazy and do nothing unless consumed"]
481        pub struct $name<'a, T: AnalyticsMtd> {
482            meta: $metaref,
483            state: glib::ffi::gpointer,
484            mtd_type: ffi::GstAnalyticsMtdType,
485            an_meta_id: u32,
486            rel_type: ffi::GstAnalyticsRelTypes,
487            phantom: std::marker::PhantomData<T>,
488        }
489
490        impl<'a, T: AnalyticsMtd> $name<'a, T> {
491            fn new(meta: $metaref) -> Self {
492                skip_assert_initialized!();
493                $name {
494                    meta,
495                    state: std::ptr::null_mut(),
496                    mtd_type: T::mtd_type(),
497                    an_meta_id: u32::MAX,
498                    rel_type: RelTypes::ANY.into_glib(),
499                    phantom: PhantomData,
500                }
501            }
502            fn new_direct_related(
503                meta: $metaref,
504                an_meta_id: u32,
505                rel_type: ffi::GstAnalyticsRelTypes,
506            ) -> Self {
507                skip_assert_initialized!();
508                $name {
509                    meta,
510                    state: std::ptr::null_mut(),
511                    mtd_type: T::mtd_type(),
512                    an_meta_id,
513                    rel_type,
514                    phantom: PhantomData,
515                }
516            }
517        }
518
519        impl<'a, T: AnalyticsMtd + 'a> Iterator for $name<'a, T> {
520            type Item = $itemref;
521
522            fn next(&mut self) -> Option<Self::Item> {
523                unsafe {
524                    let mut mtd = ffi::GstAnalyticsMtd::unsafe_from(&**self.meta);
525                    let ret = {
526                        if self.an_meta_id == u32::MAX {
527                            ffi::gst_analytics_relation_meta_iterate(
528                                self.meta.as_mut_ptr(),
529                                &mut self.state,
530                                self.mtd_type,
531                                &mut mtd,
532                            )
533                        } else {
534                            ffi::gst_analytics_relation_meta_get_direct_related(
535                                self.meta.as_mut_ptr(),
536                                self.an_meta_id,
537                                self.rel_type,
538                                self.mtd_type,
539                                &mut self.state,
540                                &mut mtd,
541                            )
542                        }
543                    };
544                    if from_glib(ret) {
545                        // This is a known clippy limitation
546                        // https://github.com/rust-lang/rust-clippy/issues/1553
547                        #[allow(clippy::redundant_closure_call)]
548                        Some(Self::Item::from_meta($copy_meta(self.meta), mtd.id))
549                    } else {
550                        None
551                    }
552                }
553            }
554        }
555    };
556}
557
558define_mtd_iter!(
559    AnalyticsMtdIter,
560    &'a gst::MetaRef<'a, AnalyticsRelationMeta>,
561    AnalyticsMtdRef<'a, T>,
562    |meta| meta
563);
564
565define_mtd_iter!(
566    AnalyticsMtdIterMut,
567    &'a mut gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>,
568    AnalyticsMtdRefMut<'a, T>,
569    |meta: &mut _| &mut *(meta as *mut gst::MetaRefMut<
570        'a,
571        AnalyticsRelationMeta,
572        gst::meta::Standalone,
573    >)
574);
575
576#[derive(Debug)]
577pub enum AnalyticsAnyMtd {}
578
579unsafe impl AnalyticsMtd for AnalyticsAnyMtd {
580    fn mtd_type() -> ffi::GstAnalyticsMtdType {
581        ffi::GST_ANALYTICS_MTD_TYPE_ANY as ffi::GstAnalyticsMtdType
582    }
583}
584
585#[cfg(test)]
586mod tests {
587    use crate::*;
588
589    #[test]
590    fn build_relation_meta() {
591        gst::init().unwrap();
592
593        let mut buf = gst::Buffer::new();
594
595        let meta = AnalyticsRelationMeta::add(buf.make_mut());
596
597        assert!(meta.is_empty());
598    }
599
600    #[test]
601    fn build_relation_meta_full() {
602        gst::init().unwrap();
603
604        let mut buf = gst::Buffer::new();
605
606        let params = AnalyticsRelationMetaInitParams::new(10, 10);
607        let meta = AnalyticsRelationMeta::add_full(buf.make_mut(), &params);
608
609        assert!(meta.is_empty());
610    }
611
612    #[test]
613    fn relations() {
614        gst::init().unwrap();
615
616        let mut buf = gst::Buffer::new();
617        let _ = AnalyticsRelationMeta::add(buf.make_mut());
618
619        let mut meta = buf.make_mut().meta_mut::<AnalyticsRelationMeta>().unwrap();
620        let od = meta
621            .add_od_mtd(glib::Quark::from_str("blb"), 0, 1, 10, 20, 0.8)
622            .unwrap();
623        let od1_id = od.id();
624
625        let od = meta
626            .add_od_mtd(glib::Quark::from_str("blb"), 0, 1, 10, 20, 0.8)
627            .unwrap();
628        let od2_id = od.id();
629
630        let od: AnalyticsMtdRef<'_, AnalyticsODMtd> = meta
631            .add_od_mtd(glib::Quark::from_str("blb"), 0, 1, 10, 20, 0.8)
632            .unwrap();
633        let od3_id = od.id();
634
635        meta.set_relation(RelTypes::IS_PART_OF, od1_id, od2_id)
636            .unwrap();
637        meta.set_relation(RelTypes::IS_PART_OF, od2_id, od3_id)
638            .unwrap();
639
640        meta.set_relation(RelTypes::IS_PART_OF, 8888, 9999)
641            .expect_err("Invalid id");
642
643        let meta = buf.meta::<AnalyticsRelationMeta>().unwrap();
644        assert!(meta.relation(od1_id, od2_id) == crate::RelTypes::IS_PART_OF);
645        assert!(meta.relation(od2_id, od3_id) == crate::RelTypes::IS_PART_OF);
646
647        assert!(meta.exist(od1_id, od2_id, 1, crate::RelTypes::IS_PART_OF));
648        assert!(meta.exist(od1_id, od3_id, 2, crate::RelTypes::IS_PART_OF));
649        assert!(!meta.exist(od2_id, od1_id, 1, crate::RelTypes::IS_PART_OF));
650        assert!(!meta.exist(od1_id, od3_id, 1, crate::RelTypes::IS_PART_OF));
651        assert!(!meta.exist(od1_id, od2_id, 1, crate::RelTypes::CONTAIN));
652
653        let path = meta
654            .exist_path(od1_id, od3_id, 3, crate::RelTypes::ANY)
655            .unwrap();
656
657        assert_eq!(path.as_slice().len(), 3);
658        assert_eq!(path.as_slice()[0], od1_id);
659        assert_eq!(path.as_slice()[1], od2_id);
660        assert_eq!(path.as_slice()[2], od3_id);
661
662        assert_eq!(meta.len(), meta.iter::<AnalyticsAnyMtd>().count());
663        assert_eq!(meta.len(), meta.iter::<AnalyticsODMtd>().count());
664        for mtd in meta.iter::<AnalyticsODMtd>() {
665            assert_eq!(mtd.obj_type().unwrap(), glib::Quark::from_str("blb"))
666        }
667
668        assert_eq!(meta.len(), meta.iter::<AnalyticsAnyMtd>().count());
669        for mtd in meta.iter::<AnalyticsAnyMtd>() {
670            if let Ok(mtd) = mtd.downcast::<AnalyticsODMtd>() {
671                assert_eq!(mtd.obj_type().unwrap(), glib::Quark::from_str("blb"))
672            }
673        }
674
675        assert_eq!(
676            meta.iter_direct_related::<AnalyticsODMtd>(od1_id, crate::RelTypes::IS_PART_OF)
677                .count(),
678            1
679        );
680        assert_eq!(
681            meta.iter_direct_related::<AnalyticsODMtd>(od2_id, crate::RelTypes::IS_PART_OF)
682                .count(),
683            1
684        );
685        assert_eq!(
686            meta.iter_direct_related::<AnalyticsODMtd>(od3_id, crate::RelTypes::IS_PART_OF)
687                .count(),
688            0
689        );
690        assert_eq!(
691            meta.iter_direct_related::<AnalyticsODMtd>(od1_id, crate::RelTypes::CONTAIN)
692                .count(),
693            0
694        );
695
696        assert_eq!(
697            meta.iter_direct_related::<AnalyticsAnyMtd>(od1_id, crate::RelTypes::CONTAIN)
698                .count(),
699            0
700        );
701        for mtd in meta.iter_direct_related::<AnalyticsODMtd>(od1_id, crate::RelTypes::IS_PART_OF) {
702            assert_eq!(mtd.obj_type().unwrap(), glib::Quark::from_str("blb"))
703        }
704
705        let mut meta = buf.make_mut().meta_mut::<AnalyticsRelationMeta>().unwrap();
706        assert_eq!(meta.len(), meta.iter_mut::<AnalyticsAnyMtd>().count());
707
708        let mut meta = buf.make_mut().meta_mut::<AnalyticsRelationMeta>().unwrap();
709        let _ = meta.add_tracking_mtd(10, gst::ClockTime::from_seconds(10));
710        let _ = meta.add_tracking_mtd(10, gst::ClockTime::from_seconds(10));
711
712        for mut item in meta.iter_mut::<AnalyticsTrackingMtd>() {
713            item.set_lost().unwrap();
714        }
715    }
716}