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::{ffi, RelTypes};
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        ffi::GstAnalyticsMtd {
195            id: 0,
196            meta: t.as_mut_ptr(),
197        }
198    }
199}
200
201impl AnalyticsRelationPath {
202    pub fn as_slice(&self) -> &[u32] {
203        unsafe {
204            std::slice::from_raw_parts(
205                (*self.garray).data as *const u32,
206                (*self.garray).len as usize,
207            )
208        }
209    }
210}
211
212impl Drop for AnalyticsRelationPath {
213    fn drop(&mut self) {
214        unsafe {
215            glib::ffi::g_array_free(self.garray, glib::ffi::GTRUE);
216        }
217    }
218}
219
220mod sealed {
221    pub trait Sealed {}
222    impl<T> Sealed for T {}
223}
224
225pub trait AnalyticsMetaRefExt<'a>: sealed::Sealed {
226    #[doc(alias = "gst_analytics_relation_meta_get_mtd")]
227    fn mtd<T: AnalyticsMtd>(&self, an_meta_id: u32) -> Option<AnalyticsMtdRef<'a, T>>;
228    fn iter<T: AnalyticsMtd>(&'a self) -> AnalyticsMtdIter<'a, T>;
229    fn iter_direct_related<T: AnalyticsMtd>(
230        &'a self,
231        an_meta_id: u32,
232        rel_type: RelTypes,
233    ) -> AnalyticsMtdIter<'a, T>;
234}
235
236impl<'a> AnalyticsMetaRefExt<'a> for gst::MetaRef<'a, AnalyticsRelationMeta> {
237    fn mtd<T: AnalyticsMtd>(&self, an_meta_id: u32) -> Option<AnalyticsMtdRef<'a, T>> {
238        unsafe {
239            let mut mtd = std::mem::MaybeUninit::uninit();
240            let ret = from_glib(ffi::gst_analytics_relation_meta_get_mtd(
241                self.as_mut_ptr(),
242                an_meta_id,
243                T::mtd_type(),
244                mtd.as_mut_ptr(),
245            ));
246            let id = mtd.assume_init().id;
247
248            if ret {
249                Some(AnalyticsMtdRef::from_meta(self, id))
250            } else {
251                None
252            }
253        }
254    }
255
256    fn iter<T: AnalyticsMtd>(&'a self) -> AnalyticsMtdIter<'a, T> {
257        AnalyticsMtdIter::new(self)
258    }
259    fn iter_direct_related<T: AnalyticsMtd>(
260        &'a self,
261        an_meta_id: u32,
262        rel_type: RelTypes,
263    ) -> AnalyticsMtdIter<'a, T> {
264        AnalyticsMtdIter::new_direct_related(self, an_meta_id, rel_type.into_glib())
265    }
266}
267
268impl<'a, T: AnalyticsMtd> AnalyticsMtdRef<'a, T> {
269    pub fn id(&self) -> u32 {
270        self.id
271    }
272
273    pub unsafe fn from_meta(meta: &gst::MetaRef<'a, AnalyticsRelationMeta>, id: u32) -> Self {
274        skip_assert_initialized!();
275        AnalyticsMtdRef {
276            meta: meta.clone(),
277            id,
278            mtd_type: PhantomData,
279        }
280    }
281
282    #[doc(alias = "gst_analytics_mtd_get_mtd_type")]
283    pub fn mtd_type(&self) -> ffi::GstAnalyticsMtdType {
284        unsafe {
285            let mtd = ffi::GstAnalyticsMtd::unsafe_from(self);
286            ffi::gst_analytics_mtd_get_mtd_type(&mtd)
287        }
288    }
289}
290impl<'a> AnalyticsMtdRef<'a, AnalyticsAnyMtd> {
291    pub fn downcast<T: AnalyticsMtd>(
292        self,
293    ) -> Result<AnalyticsMtdRef<'a, T>, AnalyticsMtdRef<'a, AnalyticsAnyMtd>> {
294        if self.mtd_type() == T::mtd_type() {
295            Ok(AnalyticsMtdRef {
296                id: self.id,
297                meta: self.meta,
298                mtd_type: PhantomData,
299            })
300        } else {
301            Err(self)
302        }
303    }
304
305    pub fn downcast_ref<T: AnalyticsMtd>(&self) -> Option<&AnalyticsMtdRef<'a, T>> {
306        unsafe {
307            if self.mtd_type() == T::mtd_type() {
308                Some(&*(self as *const _ as *const _))
309            } else {
310                None
311            }
312        }
313    }
314}
315
316impl<'a> AnalyticsMtdRefMut<'a, AnalyticsAnyMtd> {
317    pub fn downcast_mut<T: AnalyticsMtd>(&mut self) -> Option<&mut AnalyticsMtdRefMut<'a, T>> {
318        unsafe {
319            if self.as_ref().mtd_type() == T::mtd_type() {
320                Some(&mut *(self as *mut _ as *mut _))
321            } else {
322                None
323            }
324        }
325    }
326}
327
328impl<'a, T: AnalyticsMtd> UnsafeFrom<&AnalyticsMtdRef<'a, T>> for ffi::GstAnalyticsMtd {
329    unsafe fn unsafe_from(t: &AnalyticsMtdRef<'a, T>) -> Self {
330        ffi::GstAnalyticsMtd {
331            id: t.id,
332            meta: t.meta.as_mut_ptr(),
333        }
334    }
335}
336
337pub trait AnalyticsMetaRefMutExt<'a>: sealed::Sealed {
338    #[doc(alias = "gst_analytics_relation_meta_get_mtd")]
339    fn mtd_mut<T: AnalyticsMtd>(&'a mut self, an_meta_id: u32)
340        -> Option<AnalyticsMtdRefMut<'a, T>>;
341
342    fn iter_mut<T: AnalyticsMtd>(&'a mut self) -> AnalyticsMtdIterMut<'a, T>;
343    fn iter_direct_related_mut<T: AnalyticsMtd>(
344        &'a mut self,
345        an_meta_id: u32,
346        rel_type: RelTypes,
347    ) -> AnalyticsMtdIterMut<'a, T>;
348}
349
350impl<'a> AnalyticsMetaRefMutExt<'a>
351    for gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>
352{
353    fn mtd_mut<T: AnalyticsMtd>(
354        &'a mut self,
355        an_meta_id: u32,
356    ) -> Option<AnalyticsMtdRefMut<'a, T>> {
357        unsafe {
358            let mut mtd = std::mem::MaybeUninit::uninit();
359            let ret = from_glib(ffi::gst_analytics_relation_meta_get_mtd(
360                self.as_mut_ptr(),
361                an_meta_id,
362                T::mtd_type(),
363                mtd.as_mut_ptr(),
364            ));
365            let id = mtd.assume_init().id;
366
367            if ret {
368                Some(AnalyticsMtdRefMut::from_meta(self, id))
369            } else {
370                None
371            }
372        }
373    }
374
375    fn iter_mut<T: AnalyticsMtd>(&'a mut self) -> AnalyticsMtdIterMut<'a, T> {
376        AnalyticsMtdIterMut::new(self)
377    }
378    fn iter_direct_related_mut<T: AnalyticsMtd>(
379        &'a mut self,
380        an_meta_id: u32,
381        rel_type: RelTypes,
382    ) -> AnalyticsMtdIterMut<'a, T> {
383        AnalyticsMtdIterMut::new_direct_related(self, an_meta_id, rel_type.into_glib())
384    }
385}
386
387unsafe impl MetaAPI for AnalyticsRelationMeta {
388    type GstType = ffi::GstAnalyticsRelationMeta;
389
390    #[doc(alias = "gst_analytics_relation_meta_api_get_type")]
391    #[inline]
392    fn meta_api() -> glib::Type {
393        unsafe { from_glib(ffi::gst_analytics_relation_meta_api_get_type()) }
394    }
395}
396
397pub unsafe trait AnalyticsMtd {
398    fn mtd_type() -> ffi::GstAnalyticsMtdType;
399}
400
401pub trait AnalyticsMtdExt: AnalyticsMtd {
402    #[doc(alias = "gst_analytics_mtd_type_get_name")]
403    fn type_name() -> &'static str {
404        unsafe {
405            let ptr = ffi::gst_analytics_mtd_type_get_name(Self::mtd_type());
406            std::ffi::CStr::from_ptr(ptr).to_str().unwrap()
407        }
408    }
409}
410
411impl<T: AnalyticsMtd> AnalyticsMtdExt for T {}
412
413impl<'a, T: AnalyticsMtd> AnalyticsMtdRefMut<'a, T> {
414    pub fn id(&self) -> u32 {
415        self.id
416    }
417
418    pub unsafe fn from_meta(
419        meta: &'a mut gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>,
420        id: u32,
421    ) -> Self {
422        skip_assert_initialized!();
423        AnalyticsMtdRefMut {
424            meta,
425            id,
426            mtd_type: PhantomData,
427        }
428    }
429}
430
431impl<'a, T: AnalyticsMtd> UnsafeFrom<&mut AnalyticsMtdRefMut<'a, T>> for ffi::GstAnalyticsMtd {
432    unsafe fn unsafe_from(t: &mut AnalyticsMtdRefMut<'a, T>) -> Self {
433        ffi::GstAnalyticsMtd {
434            id: t.id,
435            meta: t.meta.as_mut_ptr(),
436        }
437    }
438}
439
440impl<'a, T: AnalyticsMtd> From<AnalyticsMtdRefMut<'a, T>> for AnalyticsMtdRef<'a, T> {
441    fn from(value: AnalyticsMtdRefMut<'a, T>) -> Self {
442        skip_assert_initialized!();
443        AnalyticsMtdRef {
444            meta: value.meta.as_ref().clone(),
445            id: value.id,
446            mtd_type: value.mtd_type,
447        }
448    }
449}
450
451impl<'a, T: AnalyticsMtd> From<&mut AnalyticsMtdRefMut<'a, T>> for AnalyticsMtdRef<'a, T> {
452    fn from(value: &mut AnalyticsMtdRefMut<'a, T>) -> Self {
453        skip_assert_initialized!();
454        AnalyticsMtdRef {
455            meta: value.meta.as_ref().clone(),
456            id: value.id,
457            mtd_type: value.mtd_type,
458        }
459    }
460}
461
462impl<'a, T: AnalyticsMtd> AsRef<AnalyticsMtdRef<'a, T>> for AnalyticsMtdRefMut<'a, T> {
463    #[inline]
464    fn as_ref(&self) -> &AnalyticsMtdRef<'a, T> {
465        unsafe { &*(self as *const AnalyticsMtdRefMut<'a, T> as *const AnalyticsMtdRef<'a, T>) }
466    }
467}
468
469macro_rules! define_mtd_iter {
470    ($name:ident, $metaref:ty, $itemref:ty, $copy_meta:expr) => {
471        pub struct $name<'a, T: AnalyticsMtd> {
472            meta: $metaref,
473            state: glib::ffi::gpointer,
474            mtd_type: ffi::GstAnalyticsMtdType,
475            an_meta_id: u32,
476            rel_type: ffi::GstAnalyticsRelTypes,
477            phantom: std::marker::PhantomData<T>,
478        }
479
480        impl<'a, T: AnalyticsMtd> $name<'a, T> {
481            fn new(meta: $metaref) -> Self {
482                skip_assert_initialized!();
483                $name {
484                    meta,
485                    state: std::ptr::null_mut(),
486                    mtd_type: T::mtd_type(),
487                    an_meta_id: u32::MAX,
488                    rel_type: RelTypes::ANY.into_glib(),
489                    phantom: PhantomData,
490                }
491            }
492            fn new_direct_related(
493                meta: $metaref,
494                an_meta_id: u32,
495                rel_type: ffi::GstAnalyticsRelTypes,
496            ) -> Self {
497                skip_assert_initialized!();
498                $name {
499                    meta,
500                    state: std::ptr::null_mut(),
501                    mtd_type: T::mtd_type(),
502                    an_meta_id,
503                    rel_type,
504                    phantom: PhantomData,
505                }
506            }
507        }
508
509        impl<'a, T: AnalyticsMtd + 'a> Iterator for $name<'a, T> {
510            type Item = $itemref;
511
512            fn next(&mut self) -> Option<Self::Item> {
513                unsafe {
514                    let mut mtd = ffi::GstAnalyticsMtd::unsafe_from(&**self.meta);
515                    let ret = {
516                        if self.an_meta_id == u32::MAX {
517                            ffi::gst_analytics_relation_meta_iterate(
518                                self.meta.as_mut_ptr(),
519                                &mut self.state,
520                                self.mtd_type,
521                                &mut mtd,
522                            )
523                        } else {
524                            ffi::gst_analytics_relation_meta_get_direct_related(
525                                self.meta.as_mut_ptr(),
526                                self.an_meta_id,
527                                self.rel_type,
528                                self.mtd_type,
529                                &mut self.state,
530                                &mut mtd,
531                            )
532                        }
533                    };
534                    if from_glib(ret) {
535                        // This is a known clippy limitation
536                        // https://github.com/rust-lang/rust-clippy/issues/1553
537                        #[allow(clippy::redundant_closure_call)]
538                        Some(Self::Item::from_meta($copy_meta(self.meta), mtd.id))
539                    } else {
540                        None
541                    }
542                }
543            }
544        }
545    };
546}
547
548define_mtd_iter!(
549    AnalyticsMtdIter,
550    &'a gst::MetaRef<'a, AnalyticsRelationMeta>,
551    AnalyticsMtdRef<'a, T>,
552    |meta| meta
553);
554
555define_mtd_iter!(
556    AnalyticsMtdIterMut,
557    &'a mut gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>,
558    AnalyticsMtdRefMut<'a, T>,
559    |meta: &mut _| &mut *(meta as *mut gst::MetaRefMut<
560        'a,
561        AnalyticsRelationMeta,
562        gst::meta::Standalone,
563    >)
564);
565
566#[derive(Debug)]
567pub enum AnalyticsAnyMtd {}
568
569unsafe impl AnalyticsMtd for AnalyticsAnyMtd {
570    fn mtd_type() -> ffi::GstAnalyticsMtdType {
571        ffi::GST_ANALYTICS_MTD_TYPE_ANY as ffi::GstAnalyticsMtdType
572    }
573}
574
575#[cfg(test)]
576mod tests {
577    use crate::*;
578
579    #[test]
580    fn build_relation_meta() {
581        gst::init().unwrap();
582
583        let mut buf = gst::Buffer::new();
584
585        let meta = AnalyticsRelationMeta::add(buf.make_mut());
586
587        assert!(meta.is_empty());
588    }
589
590    #[test]
591    fn build_relation_meta_full() {
592        gst::init().unwrap();
593
594        let mut buf = gst::Buffer::new();
595
596        let params = AnalyticsRelationMetaInitParams::new(10, 10);
597        let meta = AnalyticsRelationMeta::add_full(buf.make_mut(), &params);
598
599        assert!(meta.is_empty());
600    }
601
602    #[test]
603    fn relations() {
604        gst::init().unwrap();
605
606        let mut buf = gst::Buffer::new();
607        let _ = AnalyticsRelationMeta::add(buf.make_mut());
608
609        let mut meta = buf.make_mut().meta_mut::<AnalyticsRelationMeta>().unwrap();
610        let od = meta
611            .add_od_mtd(glib::Quark::from_str("blb"), 0, 1, 10, 20, 0.8)
612            .unwrap();
613        let od1_id = od.id();
614
615        let od = meta
616            .add_od_mtd(glib::Quark::from_str("blb"), 0, 1, 10, 20, 0.8)
617            .unwrap();
618        let od2_id = od.id();
619
620        let od: AnalyticsMtdRef<'_, AnalyticsODMtd> = meta
621            .add_od_mtd(glib::Quark::from_str("blb"), 0, 1, 10, 20, 0.8)
622            .unwrap();
623        let od3_id = od.id();
624
625        meta.set_relation(RelTypes::IS_PART_OF, od1_id, od2_id)
626            .unwrap();
627        meta.set_relation(RelTypes::IS_PART_OF, od2_id, od3_id)
628            .unwrap();
629
630        meta.set_relation(RelTypes::IS_PART_OF, 8888, 9999)
631            .expect_err("Invalid id");
632
633        let meta = buf.meta::<AnalyticsRelationMeta>().unwrap();
634        assert!(meta.relation(od1_id, od2_id) == crate::RelTypes::IS_PART_OF);
635        assert!(meta.relation(od2_id, od3_id) == crate::RelTypes::IS_PART_OF);
636
637        assert!(meta.exist(od1_id, od2_id, 1, crate::RelTypes::IS_PART_OF));
638        assert!(meta.exist(od1_id, od3_id, 2, crate::RelTypes::IS_PART_OF));
639        assert!(!meta.exist(od2_id, od1_id, 1, crate::RelTypes::IS_PART_OF));
640        assert!(!meta.exist(od1_id, od3_id, 1, crate::RelTypes::IS_PART_OF));
641        assert!(!meta.exist(od1_id, od2_id, 1, crate::RelTypes::CONTAIN));
642
643        let path = meta
644            .exist_path(od1_id, od3_id, 3, crate::RelTypes::ANY)
645            .unwrap();
646
647        assert_eq!(path.as_slice().len(), 3);
648        assert_eq!(path.as_slice()[0], od1_id);
649        assert_eq!(path.as_slice()[1], od2_id);
650        assert_eq!(path.as_slice()[2], od3_id);
651
652        assert_eq!(meta.len(), meta.iter::<AnalyticsAnyMtd>().count());
653        assert_eq!(meta.len(), meta.iter::<AnalyticsODMtd>().count());
654        for mtd in meta.iter::<AnalyticsODMtd>() {
655            assert_eq!(mtd.obj_type().unwrap(), glib::Quark::from_str("blb"))
656        }
657
658        assert_eq!(meta.len(), meta.iter::<AnalyticsAnyMtd>().count());
659        for mtd in meta.iter::<AnalyticsAnyMtd>() {
660            if let Ok(mtd) = mtd.downcast::<AnalyticsODMtd>() {
661                assert_eq!(mtd.obj_type().unwrap(), glib::Quark::from_str("blb"))
662            }
663        }
664
665        assert_eq!(
666            meta.iter_direct_related::<AnalyticsODMtd>(od1_id, crate::RelTypes::IS_PART_OF)
667                .count(),
668            1
669        );
670        assert_eq!(
671            meta.iter_direct_related::<AnalyticsODMtd>(od2_id, crate::RelTypes::IS_PART_OF)
672                .count(),
673            1
674        );
675        assert_eq!(
676            meta.iter_direct_related::<AnalyticsODMtd>(od3_id, crate::RelTypes::IS_PART_OF)
677                .count(),
678            0
679        );
680        assert_eq!(
681            meta.iter_direct_related::<AnalyticsODMtd>(od1_id, crate::RelTypes::CONTAIN)
682                .count(),
683            0
684        );
685
686        assert_eq!(
687            meta.iter_direct_related::<AnalyticsAnyMtd>(od1_id, crate::RelTypes::CONTAIN)
688                .count(),
689            0
690        );
691        for mtd in meta.iter_direct_related::<AnalyticsODMtd>(od1_id, crate::RelTypes::IS_PART_OF) {
692            assert_eq!(mtd.obj_type().unwrap(), glib::Quark::from_str("blb"))
693        }
694
695        let mut meta = buf.make_mut().meta_mut::<AnalyticsRelationMeta>().unwrap();
696        assert_eq!(meta.len(), meta.iter_mut::<AnalyticsAnyMtd>().count());
697
698        let mut meta = buf.make_mut().meta_mut::<AnalyticsRelationMeta>().unwrap();
699        let _ = meta.add_tracking_mtd(10, gst::ClockTime::from_seconds(10));
700        let _ = meta.add_tracking_mtd(10, gst::ClockTime::from_seconds(10));
701
702        for mut item in meta.iter_mut::<AnalyticsTrackingMtd>() {
703            item.set_lost().unwrap();
704        }
705    }
706}