Skip to main content

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
140impl AnalyticsMtdRef<'_, AnalyticsODMtd> {
141    #[doc(alias = "gst_analytics_od_mtd_get_obj_type")]
142    pub fn obj_type(&self) -> Option<glib::Quark> {
143        unsafe {
144            let mtd = ffi::GstAnalyticsMtd::unsafe_from(self);
145            let type_ = ffi::gst_analytics_od_mtd_get_obj_type(
146                &mtd as *const _ as *const ffi::GstAnalyticsODMtd,
147            );
148            if type_ == 0 {
149                None
150            } else {
151                Some(glib::Quark::from_glib(type_))
152            }
153        }
154    }
155
156    #[doc(alias = "gst_analytics_od_mtd_get_location")]
157    pub fn location(&self) -> Result<AnalyticsODLocation, glib::BoolError> {
158        let mut loc = AnalyticsODLocation::default();
159
160        let success = unsafe {
161            let mtd = ffi::GstAnalyticsMtd::unsafe_from(self);
162            ffi::gst_analytics_od_mtd_get_location(
163                &mtd as *const _ as *const ffi::GstAnalyticsODMtd,
164                &mut loc.x,
165                &mut loc.y,
166                &mut loc.w,
167                &mut loc.h,
168                &mut loc.loc_conf_lvl,
169            )
170        };
171
172        if success != 0 {
173            Ok(loc)
174        } else {
175            Err(glib::bool_error!("Could retrieve location"))
176        }
177    }
178
179    #[cfg(feature = "v1_26")]
180    #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
181    #[doc(alias = "gst_analytics_od_mtd_get_oriented_location")]
182    pub fn oriented_location(&self) -> Result<AnalyticsODOrientedLocation, glib::BoolError> {
183        let mut loc = AnalyticsODOrientedLocation::default();
184
185        let success = unsafe {
186            let mtd = ffi::GstAnalyticsMtd::unsafe_from(self);
187            ffi::gst_analytics_od_mtd_get_oriented_location(
188                &mtd as *const _ as *const ffi::GstAnalyticsODMtd,
189                &mut loc.x,
190                &mut loc.y,
191                &mut loc.w,
192                &mut loc.h,
193                &mut loc.r,
194                &mut loc.loc_conf_lvl,
195            )
196        };
197
198        if success != 0 {
199            Ok(loc)
200        } else {
201            Err(glib::bool_error!("Could retrieve location"))
202        }
203    }
204
205    #[doc(alias = "gst_analytics_od_mtd_get_confidence_lvl")]
206    pub fn confidence_level(&self) -> f32 {
207        unsafe {
208            let mtd = ffi::GstAnalyticsMtd::unsafe_from(self);
209            let mut lvl: f32 = 0.0;
210            ffi::gst_analytics_od_mtd_get_confidence_lvl(
211                &mtd as *const _ as *const ffi::GstAnalyticsODMtd,
212                &mut lvl,
213            );
214            lvl
215        }
216    }
217}
218
219#[cfg(test)]
220mod tests {
221    use crate::*;
222
223    #[test]
224    fn object_detection() {
225        gst::init().unwrap();
226
227        assert_eq!(AnalyticsODMtd::type_name(), "object-detection");
228
229        let mut buf = gst::Buffer::new();
230        let mut meta = AnalyticsRelationMeta::add(buf.make_mut());
231
232        assert!(meta.is_empty());
233
234        let od = meta
235            .add_od_mtd(glib::Quark::from_str("blb"), 0, 1, 10, 20, 0.8)
236            .unwrap();
237
238        assert_eq!(od.obj_type().unwrap(), glib::Quark::from_str("blb"));
239
240        let loc = od.location().unwrap();
241
242        assert_eq!(loc.x, 0);
243        assert_eq!(loc.y, 1);
244        assert_eq!(loc.w, 10);
245        assert_eq!(loc.h, 20);
246        assert_eq!(loc.loc_conf_lvl, 0.8);
247        let meta = buf.meta::<AnalyticsRelationMeta>().unwrap();
248
249        assert!(meta.mtd::<AnalyticsODMtd>(1).is_none());
250
251        let meta2 = buf.meta::<AnalyticsRelationMeta>().unwrap();
252        let od2 = meta2.mtd::<AnalyticsODMtd>(0).unwrap();
253
254        assert_eq!(od2.obj_type().unwrap(), glib::Quark::from_str("blb"));
255        let loc = od2.location().unwrap();
256
257        assert_eq!(loc.x, 0);
258        assert_eq!(loc.y, 1);
259        assert_eq!(loc.w, 10);
260        assert_eq!(loc.h, 20);
261        assert_eq!(loc.loc_conf_lvl, 0.8);
262    }
263
264    #[cfg(feature = "v1_26")]
265    #[test]
266    fn oriented_object_detection() {
267        gst::init().unwrap();
268
269        let mut buf = gst::Buffer::new();
270        let mut meta = AnalyticsRelationMeta::add(buf.make_mut());
271
272        assert!(meta.is_empty());
273
274        let od = meta
275            .add_oriented_od_mtd(
276                glib::Quark::from_str("blb"),
277                30,
278                40,
279                10,
280                20,
281                std::f32::consts::FRAC_PI_4,
282                1.0,
283            )
284            .unwrap();
285
286        assert_eq!(od.obj_type().unwrap(), glib::Quark::from_str("blb"));
287
288        let loc = od.oriented_location().unwrap();
289
290        assert_eq!(loc.x, 30);
291        assert_eq!(loc.y, 40);
292        assert_eq!(loc.w, 10);
293        assert_eq!(loc.h, 20);
294        assert_eq!(loc.r, std::f32::consts::FRAC_PI_4);
295        assert_eq!(loc.loc_conf_lvl, 1.0);
296        let meta = buf.meta::<AnalyticsRelationMeta>().unwrap();
297
298        assert!(meta.mtd::<AnalyticsODMtd>(1).is_none());
299
300        let meta2 = buf.meta::<AnalyticsRelationMeta>().unwrap();
301        let od2 = meta2.mtd::<AnalyticsODMtd>(0).unwrap();
302
303        assert_eq!(od2.obj_type().unwrap(), glib::Quark::from_str("blb"));
304        let loc = od2.location().unwrap();
305
306        assert_eq!(loc.x, 24);
307        assert_eq!(loc.y, 39);
308        assert_eq!(loc.w, 22);
309        assert_eq!(loc.h, 22);
310        assert_eq!(loc.loc_conf_lvl, 1.0);
311    }
312}