gstreamer_analytics/
classification.rs1use glib::translate::*;
4
5use crate::{ffi, relation_meta::*};
6
7#[derive(Debug)]
8pub enum AnalyticsClassificationMtd {}
9
10mod sealed {
11 pub trait Sealed {}
12 impl<T: super::AnalyticsRelationMetaClassificationExt> Sealed for T {}
13}
14
15pub trait AnalyticsRelationMetaClassificationExt: sealed::Sealed {
16 fn add_one_cls_mtd(
17 &mut self,
18 confidence_level: f32,
19 class_quark: glib::Quark,
20 ) -> Result<AnalyticsMtdRef<'_, AnalyticsClassificationMtd>, glib::BoolError>;
21
22 fn add_cls_mtd(
23 &mut self,
24 confidence_levels: &[f32],
25 class_quarks: &[glib::Quark],
26 ) -> Result<AnalyticsMtdRef<'_, AnalyticsClassificationMtd>, glib::BoolError>;
27}
28
29impl<'a> AnalyticsRelationMetaClassificationExt
30 for gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>
31{
32 #[doc(alias = "gst_analytics_relation_meta_add_one_cls_mtd")]
33 fn add_one_cls_mtd(
34 &mut self,
35 confidence_level: f32,
36 class_quark: glib::Quark,
37 ) -> Result<AnalyticsMtdRef<'a, AnalyticsClassificationMtd>, glib::BoolError> {
38 unsafe {
39 let mut mtd = std::mem::MaybeUninit::uninit();
40 let ret = from_glib(ffi::gst_analytics_relation_meta_add_one_cls_mtd(
41 self.as_mut_ptr(),
42 confidence_level,
43 class_quark.into_glib(),
44 mtd.as_mut_ptr(),
45 ));
46 let id = mtd.assume_init().id;
47
48 if ret {
49 Ok(AnalyticsMtdRef::from_meta(self.as_ref(), id))
50 } else {
51 Err(glib::bool_error!("Couldn't add more data"))
52 }
53 }
54 }
55
56 #[doc(alias = "gst_analytics_relation_meta_add_cls_mtd")]
57 fn add_cls_mtd(
58 &mut self,
59 confidence_levels: &[f32],
60 class_quarks: &[glib::Quark],
61 ) -> Result<AnalyticsMtdRef<'a, AnalyticsClassificationMtd>, glib::BoolError> {
62 let length = std::cmp::min(confidence_levels.len(), class_quarks.len());
63 unsafe {
64 let mut mtd = std::mem::MaybeUninit::uninit();
65 let ret = from_glib(ffi::gst_analytics_relation_meta_add_cls_mtd(
66 self.as_mut_ptr(),
67 length,
68 mut_override(confidence_levels.as_ptr()),
69 class_quarks.as_ptr() as *mut _,
70 mtd.as_mut_ptr(),
71 ));
72 let id = mtd.assume_init().id;
73
74 if ret {
75 Ok(AnalyticsMtdRef::from_meta(self.as_ref(), id))
76 } else {
77 Err(glib::bool_error!("Couldn't add more data"))
78 }
79 }
80 }
81}
82
83unsafe impl AnalyticsMtd for AnalyticsClassificationMtd {
84 #[doc(alias = "gst_analytics_cls_mtd_get_mtd_type")]
85 fn mtd_type() -> ffi::GstAnalyticsMtdType {
86 unsafe { ffi::gst_analytics_cls_mtd_get_mtd_type() }
87 }
88}
89
90impl AnalyticsMtdRef<'_, AnalyticsClassificationMtd> {
91 #[doc(alias = "gst_analytics_cls_mtd_get_length")]
92 pub fn len(&self) -> usize {
93 unsafe {
94 let mtd = ffi::GstAnalyticsMtd::unsafe_from(self);
95 ffi::gst_analytics_cls_mtd_get_length(
96 &mtd as *const _ as *const ffi::GstAnalyticsClsMtd,
97 )
98 }
99 }
100
101 pub fn is_empty(&self) -> bool {
102 self.len() == 0
103 }
104
105 #[doc(alias = "gst_analytics_cls_mtd_get_level")]
106 pub fn level(&self, index: usize) -> f32 {
107 assert!(index < self.len());
108
109 unsafe {
110 let mtd = ffi::GstAnalyticsMtd::unsafe_from(self);
111 ffi::gst_analytics_cls_mtd_get_level(
112 &mtd as *const _ as *const ffi::GstAnalyticsClsMtd,
113 index,
114 )
115 }
116 }
117
118 #[doc(alias = "gst_analytics_cls_mtd_get_quark")]
119 pub fn quark(&self, index: usize) -> glib::Quark {
120 assert!(index < self.len());
121
122 unsafe {
123 let mtd = ffi::GstAnalyticsMtd::unsafe_from(self);
124 from_glib(ffi::gst_analytics_cls_mtd_get_quark(
125 &mtd as *const _ as *const ffi::GstAnalyticsClsMtd,
126 index,
127 ))
128 }
129 }
130
131 pub fn iterate(&self) -> AnalyticsClassificationIterator<'_> {
132 AnalyticsClassificationIterator {
133 mtd: self,
134 index: 0,
135 length: self.len(),
136 }
137 }
138}
139
140#[must_use = "iterators are lazy and do nothing unless consumed"]
141pub struct AnalyticsClassificationIterator<'a> {
142 mtd: &'a AnalyticsMtdRef<'a, AnalyticsClassificationMtd>,
143 index: usize,
144 length: usize,
145}
146
147impl Iterator for AnalyticsClassificationIterator<'_> {
148 type Item = (glib::Quark, f32);
149
150 fn next(&mut self) -> Option<Self::Item> {
151 if self.index == self.length {
152 None
153 } else {
154 let ret = Some((self.mtd.quark(self.index), self.mtd.level(self.index)));
155 self.index += 1;
156 ret
157 }
158 }
159}
160
161#[cfg(test)]
162mod tests {
163 use crate::*;
164
165 #[test]
166 fn one_class() {
167 gst::init().unwrap();
168
169 assert_eq!(AnalyticsClassificationMtd::type_name(), "classification");
170
171 let mut buf = gst::Buffer::new();
172 let mut meta = AnalyticsRelationMeta::add(buf.make_mut());
173
174 assert!(meta.is_empty());
175
176 let cls = meta
177 .add_one_cls_mtd(0.7, glib::Quark::from_str("class1"))
178 .unwrap();
179
180 assert_eq!(cls.len(), 1);
181 assert_eq!(cls.level(0), 0.7);
182 assert_eq!(cls.quark(0), glib::Quark::from_str("class1"));
183 }
184
185 #[test]
186 fn many_classes() {
187 gst::init().unwrap();
188
189 assert_eq!(AnalyticsClassificationMtd::type_name(), "classification");
190
191 let mut buf = gst::Buffer::new();
192 let mut meta = AnalyticsRelationMeta::add(buf.make_mut());
193
194 assert!(meta.is_empty());
195
196 let classes = [
197 glib::Quark::from_str("a"),
198 glib::Quark::from_str("b"),
199 glib::Quark::from_str("c"),
200 glib::Quark::from_str("d"),
201 ];
202 let levels = [0.1, 0.2, 0.3, 0.4];
203
204 let cls = meta.add_cls_mtd(&levels, &classes).unwrap();
205
206 assert_eq!(cls.len(), 4);
207 for i in 0..4usize {
208 assert_eq!(cls.level(i), levels[i]);
209 assert_eq!(cls.quark(i), classes[i]);
210 }
211
212 for (i, (q, l)) in cls.iterate().enumerate() {
213 assert_eq!(l, levels[i]);
214 assert_eq!(q, classes[i]);
215 }
216 }
217}