gstreamer_analytics/
object_detection.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::translate::*;
4
5use crate::{ffi, relation_meta::*};
6
7#[derive(Debug)]
8pub enum AnalyticsODMtd {}
9
10mod sealed {
11    pub trait Sealed {}
12    impl<T: super::AnalyticsRelationMetaODExt> Sealed for T {}
13}
14
15pub trait AnalyticsRelationMetaODExt: sealed::Sealed {
16    fn add_od_mtd(
17        &mut self,
18        type_: glib::Quark,
19        x: i32,
20        y: i32,
21        w: i32,
22        h: i32,
23        loc_conf_lvl: f32,
24    ) -> Result<AnalyticsMtdRef<AnalyticsODMtd>, glib::BoolError>;
25
26    #[cfg(feature = "v1_26")]
27    #[allow(clippy::too_many_arguments)]
28    fn add_oriented_od_mtd(
29        &mut self,
30        type_: glib::Quark,
31        x: i32,
32        y: i32,
33        w: i32,
34        h: i32,
35        r: f32,
36        loc_conf_lvl: f32,
37    ) -> Result<AnalyticsMtdRef<AnalyticsODMtd>, glib::BoolError>;
38}
39
40impl AnalyticsRelationMetaODExt
41    for gst::MetaRefMut<'_, AnalyticsRelationMeta, gst::meta::Standalone>
42{
43    #[doc(alias = "gst_analytics_relation_meta_add_od_mtd")]
44    fn add_od_mtd(
45        &mut self,
46        type_: glib::Quark,
47        x: i32,
48        y: i32,
49        w: i32,
50        h: i32,
51        loc_conf_lvl: f32,
52    ) -> Result<AnalyticsMtdRef<AnalyticsODMtd>, glib::BoolError> {
53        unsafe {
54            let mut mtd = std::mem::MaybeUninit::uninit();
55            let ret = from_glib(ffi::gst_analytics_relation_meta_add_od_mtd(
56                self.as_mut_ptr(),
57                type_.into_glib(),
58                x,
59                y,
60                w,
61                h,
62                loc_conf_lvl,
63                mtd.as_mut_ptr(),
64            ));
65            let id = mtd.assume_init().id;
66
67            if ret {
68                Ok(AnalyticsMtdRef::from_meta(self.as_ref(), id))
69            } else {
70                Err(glib::bool_error!("Couldn't add more data"))
71            }
72        }
73    }
74
75    #[cfg(feature = "v1_26")]
76    #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
77    #[doc(alias = "gst_analytics_relation_meta_add_oriented_od_mtd")]
78    fn add_oriented_od_mtd(
79        &mut self,
80        type_: glib::Quark,
81        x: i32,
82        y: i32,
83        w: i32,
84        h: i32,
85        r: f32,
86        loc_conf_lvl: f32,
87    ) -> Result<AnalyticsMtdRef<AnalyticsODMtd>, glib::BoolError> {
88        unsafe {
89            let mut mtd = std::mem::MaybeUninit::uninit();
90            let ret = from_glib(ffi::gst_analytics_relation_meta_add_oriented_od_mtd(
91                self.as_mut_ptr(),
92                type_.into_glib(),
93                x,
94                y,
95                w,
96                h,
97                r,
98                loc_conf_lvl,
99                mtd.as_mut_ptr(),
100            ));
101            let id = mtd.assume_init().id;
102
103            if ret {
104                Ok(AnalyticsMtdRef::from_meta(self.as_ref(), id))
105            } else {
106                Err(glib::bool_error!("Couldn't add more data"))
107            }
108        }
109    }
110}
111
112#[derive(Clone, Copy, Default, Debug)]
113pub struct AnalyticsODLocation {
114    pub x: i32,
115    pub y: i32,
116    pub w: i32,
117    pub h: i32,
118    pub loc_conf_lvl: f32,
119}
120
121#[cfg(feature = "v1_26")]
122#[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
123#[derive(Clone, Copy, Default, Debug)]
124pub struct AnalyticsODOrientedLocation {
125    pub x: i32,
126    pub y: i32,
127    pub w: i32,
128    pub h: i32,
129    pub r: f32,
130    pub loc_conf_lvl: f32,
131}
132
133unsafe impl AnalyticsMtd for AnalyticsODMtd {
134    #[doc(alias = "gst_analytics_od_mtd_get_mtd_type")]
135    fn mtd_type() -> ffi::GstAnalyticsMtdType {
136        unsafe { ffi::gst_analytics_od_mtd_get_mtd_type() }
137    }
138}
139
140unsafe fn from(t: ffi::GstAnalyticsMtd) -> ffi::GstAnalyticsODMtd {
141    std::mem::transmute(t)
142}
143
144impl AnalyticsMtdRef<'_, AnalyticsODMtd> {
145    #[doc(alias = "gst_analytics_od_mtd_get_obj_type")]
146    pub fn obj_type(&self) -> Option<glib::Quark> {
147        unsafe {
148            let mtd = from(ffi::GstAnalyticsMtd::unsafe_from(self));
149            let type_ = ffi::gst_analytics_od_mtd_get_obj_type(&mtd);
150            if type_ == 0 {
151                None
152            } else {
153                Some(glib::Quark::from_glib(type_))
154            }
155        }
156    }
157
158    #[doc(alias = "gst_analytics_od_mtd_get_location")]
159    pub fn location(&self) -> Result<AnalyticsODLocation, glib::BoolError> {
160        let mut loc = AnalyticsODLocation::default();
161
162        let success = unsafe {
163            let mtd = from(ffi::GstAnalyticsMtd::unsafe_from(self));
164            ffi::gst_analytics_od_mtd_get_location(
165                &mtd,
166                &mut loc.x,
167                &mut loc.y,
168                &mut loc.w,
169                &mut loc.h,
170                &mut loc.loc_conf_lvl,
171            )
172        };
173
174        if success != 0 {
175            Ok(loc)
176        } else {
177            Err(glib::bool_error!("Could retrieve location"))
178        }
179    }
180
181    #[cfg(feature = "v1_26")]
182    #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
183    #[doc(alias = "gst_analytics_od_mtd_get_oriented_location")]
184    pub fn oriented_location(&self) -> Result<AnalyticsODOrientedLocation, glib::BoolError> {
185        let mut loc = AnalyticsODOrientedLocation::default();
186
187        let success = unsafe {
188            let mtd = from(ffi::GstAnalyticsMtd::unsafe_from(self));
189            ffi::gst_analytics_od_mtd_get_oriented_location(
190                &mtd,
191                &mut loc.x,
192                &mut loc.y,
193                &mut loc.w,
194                &mut loc.h,
195                &mut loc.r,
196                &mut loc.loc_conf_lvl,
197            )
198        };
199
200        if success != 0 {
201            Ok(loc)
202        } else {
203            Err(glib::bool_error!("Could retrieve location"))
204        }
205    }
206
207    #[doc(alias = "gst_analytics_od_mtd_get_confidence_lvl")]
208    pub fn confidence_level(&self) -> f32 {
209        unsafe {
210            let mtd = from(ffi::GstAnalyticsMtd::unsafe_from(self));
211            let mut lvl: f32 = 0.0;
212            ffi::gst_analytics_od_mtd_get_confidence_lvl(&mtd, &mut lvl);
213            lvl
214        }
215    }
216}
217
218#[cfg(test)]
219mod tests {
220    use crate::*;
221
222    #[test]
223    fn object_detection() {
224        gst::init().unwrap();
225
226        assert_eq!(AnalyticsODMtd::type_name(), "object-detection");
227
228        let mut buf = gst::Buffer::new();
229        let mut meta = AnalyticsRelationMeta::add(buf.make_mut());
230
231        assert!(meta.is_empty());
232
233        let od = meta
234            .add_od_mtd(glib::Quark::from_str("blb"), 0, 1, 10, 20, 0.8)
235            .unwrap();
236
237        assert_eq!(od.obj_type().unwrap(), glib::Quark::from_str("blb"));
238
239        let loc = od.location().unwrap();
240
241        assert_eq!(loc.x, 0);
242        assert_eq!(loc.y, 1);
243        assert_eq!(loc.w, 10);
244        assert_eq!(loc.h, 20);
245        assert_eq!(loc.loc_conf_lvl, 0.8);
246        let meta = buf.meta::<AnalyticsRelationMeta>().unwrap();
247
248        assert!(meta.mtd::<AnalyticsODMtd>(1).is_none());
249
250        let meta2 = buf.meta::<AnalyticsRelationMeta>().unwrap();
251        let od2 = meta2.mtd::<AnalyticsODMtd>(0).unwrap();
252
253        assert_eq!(od2.obj_type().unwrap(), glib::Quark::from_str("blb"));
254        let loc = od2.location().unwrap();
255
256        assert_eq!(loc.x, 0);
257        assert_eq!(loc.y, 1);
258        assert_eq!(loc.w, 10);
259        assert_eq!(loc.h, 20);
260        assert_eq!(loc.loc_conf_lvl, 0.8);
261    }
262
263    #[cfg(feature = "v1_26")]
264    #[test]
265    fn oriented_object_detection() {
266        gst::init().unwrap();
267
268        let mut buf = gst::Buffer::new();
269        let mut meta = AnalyticsRelationMeta::add(buf.make_mut());
270
271        assert!(meta.is_empty());
272
273        let od = meta
274            .add_oriented_od_mtd(
275                glib::Quark::from_str("blb"),
276                30,
277                40,
278                10,
279                20,
280                std::f32::consts::FRAC_PI_4,
281                1.0,
282            )
283            .unwrap();
284
285        assert_eq!(od.obj_type().unwrap(), glib::Quark::from_str("blb"));
286
287        let loc = od.oriented_location().unwrap();
288
289        assert_eq!(loc.x, 30);
290        assert_eq!(loc.y, 40);
291        assert_eq!(loc.w, 10);
292        assert_eq!(loc.h, 20);
293        assert_eq!(loc.r, std::f32::consts::FRAC_PI_4);
294        assert_eq!(loc.loc_conf_lvl, 1.0);
295        let meta = buf.meta::<AnalyticsRelationMeta>().unwrap();
296
297        assert!(meta.mtd::<AnalyticsODMtd>(1).is_none());
298
299        let meta2 = buf.meta::<AnalyticsRelationMeta>().unwrap();
300        let od2 = meta2.mtd::<AnalyticsODMtd>(0).unwrap();
301
302        assert_eq!(od2.obj_type().unwrap(), glib::Quark::from_str("blb"));
303        let loc = od2.location().unwrap();
304
305        assert_eq!(loc.x, 24);
306        assert_eq!(loc.y, 39);
307        assert_eq!(loc.w, 22);
308        assert_eq!(loc.h, 22);
309        assert_eq!(loc.loc_conf_lvl, 1.0);
310    }
311}