From 7c7832fee1a1cb610fa36e0c982aab3cc41ad171 Mon Sep 17 00:00:00 2001 From: Santosh Mahto Date: Tue, 11 Feb 2025 11:39:43 +0530 Subject: [PATCH] python analytics: Add api iter_on_type to iterate over specific Mtd types This adds new Python api `iter_on_type()` to GstAnalyticsRelationMeta to iterate over mtd type specified by argument. usage: ``` for i in rmeta.iter_on_type(GstAnalytics.ODMtd): ``` Part-of: --- .../gst-python/gi/overrides/GstAnalytics.py | 10 ++++ .../gi/overrides/gstanalyticsmodule.c | 46 ++++++++++++++---- .../gst-python/testsuite/test_analytics.py | 47 +++++++++++++++++++ 3 files changed, 94 insertions(+), 9 deletions(-) diff --git a/subprojects/gst-python/gi/overrides/GstAnalytics.py b/subprojects/gst-python/gi/overrides/GstAnalytics.py index ceb0dfb5fb..0a6932f860 100644 --- a/subprojects/gst-python/gi/overrides/GstAnalytics.py +++ b/subprojects/gst-python/gi/overrides/GstAnalytics.py @@ -84,5 +84,15 @@ class RelationMeta(GstAnalytics.RelationMeta): def __iter__(self): return _gi_gst_analytics.AnalyticsRelationMetaIterator(sys.modules[__name__], self) + def iter_on_type(self, filter): + if filter == GstAnalytics.Mtd: + return self.__iter__(); + + mtdtype = filter.get_mtd_type() + if mtdtype in __mtd_types__: + return _gi_gst_analytics.AnalyticsRelationMetaIteratorWithMtdTypeFilter( + sys.modules[__name__], self, mtdtype) + else: + raise TypeError('Wrong filter type is used for iter_on_type method.') __all__.append('RelationMeta') diff --git a/subprojects/gst-python/gi/overrides/gstanalyticsmodule.c b/subprojects/gst-python/gi/overrides/gstanalyticsmodule.c index c9bc61cad3..e819fe83f1 100644 --- a/subprojects/gst-python/gi/overrides/gstanalyticsmodule.c +++ b/subprojects/gst-python/gi/overrides/gstanalyticsmodule.c @@ -56,6 +56,7 @@ typedef struct GstAnalyticsRelationMeta *rmeta; gpointer state; gboolean ended; + GstAnalyticsMtdType filter; } _GstAnalyticsRelationMetaIterator; typedef struct @@ -165,6 +166,7 @@ _gst_analytics_relation_meta_iterator_new (PyTypeObject * type, PyObject * args, self->py_module = py_module; self->py_rmeta = py_rmeta; self->state = NULL; + self->filter = GST_ANALYTICS_MTD_TYPE_ANY; Py_INCREF (py_module); Py_INCREF (py_rmeta); self->rmeta = (GstAnalyticsRelationMeta *) (pygobject_get (py_rmeta)); @@ -195,7 +197,7 @@ _gst_analytics_relation_meta_iterator_next (_GstAnalyticsRelationMetaIterator * PyObject *py_result = NULL; if (self->ended || !gst_analytics_relation_meta_iterate (self->rmeta, - &self->state, GST_ANALYTICS_MTD_TYPE_ANY, &mtd)) { + &self->state, self->filter, &mtd)) { self->ended = TRUE; return NULL; @@ -251,14 +253,6 @@ _gi_gst_analytics_mtd_relation_path (PyObject * self, PyObject * args) return pathList; } -static PyMethodDef _gi_gst_analytics_functions[] = { - {"AnalyticsMtdRelationPath", - (PyCFunction) _gi_gst_analytics_mtd_relation_path, - METH_VARARGS, - "Returns the relation path between two Mtd"}, - {NULL, NULL, 0, NULL} -}; - static PyTypeObject GstAnalyticsRelationMetaIteratorType = { PyVarObject_HEAD_INIT (NULL, 0) .tp_name = "_gi_gst_analytics.AnalyticsRelationMetaIterator", @@ -285,6 +279,40 @@ static PyTypeObject GstAnalyticsMtdDirectRelatedIteratorType = { .tp_dealloc = (destructor) _gst_analytics_mtd_direct_related_iterator_dtor }; +static PyObject * +_gi_gst_analytics_relation_meta_iterator_with_type_filter (PyObject * self, + PyObject * args) +{ + PyObject *iter; + PyObject *py_rmeta; + PyObject *py_module; + PyObject *py_args; + GstAnalyticsMtdType mtdtype; + if (!PyArg_ParseTuple (args, "OOk", &py_module, &py_rmeta, &mtdtype)) { + return Py_None; + } + + py_args = PyTuple_Pack (2, py_module, py_rmeta); + iter = + _gst_analytics_relation_meta_iterator_new + (&GstAnalyticsRelationMetaIteratorType, py_args, NULL); + if (iter) + ((_GstAnalyticsRelationMetaIterator *) iter)->filter = mtdtype; + return iter; +} + +static PyMethodDef _gi_gst_analytics_functions[] = { + {"AnalyticsMtdRelationPath", + (PyCFunction) _gi_gst_analytics_mtd_relation_path, + METH_VARARGS, + "Returns the relation path between two Mtd"}, + {"AnalyticsRelationMetaIteratorWithMtdTypeFilter", + (PyCFunction) _gi_gst_analytics_relation_meta_iterator_with_type_filter, + METH_VARARGS, + "Return an iterator to iterate over specific Mtd type"}, + {NULL, NULL, 0, NULL} +}; + PYGLIB_MODULE_START (_gi_gst_analytics, "_gi_gst_analytics") { pygobject_init (3, 0, 0); diff --git a/subprojects/gst-python/testsuite/test_analytics.py b/subprojects/gst-python/testsuite/test_analytics.py index f124ae04da..10da70c399 100644 --- a/subprojects/gst-python/testsuite/test_analytics.py +++ b/subprojects/gst-python/testsuite/test_analytics.py @@ -264,7 +264,9 @@ class TestAnalyticsRelationMetaIterator(TestCase): (_, od_mtd1) = rmeta.add_od_mtd(GLib.quark_from_string("od"), 1, 1, 2, 2, 0.1) (_, od_mtd2) = rmeta.add_od_mtd(GLib.quark_from_string("od"), 1, 1, 2, 2, 0.1) (_, cls_mtd) = rmeta.add_one_cls_mtd(0.1, GLib.quark_from_string("cls")) + (_, cls_mtd1) = rmeta.add_one_cls_mtd(0.4, GLib.quark_from_string("cls")) (_, trk_mtd) = rmeta.add_tracking_mtd(1, 10) + (_, trk_mtd1) = rmeta.add_tracking_mtd(1, 11) (_, seg_mtd) = rmeta.add_segmentation_mtd(mask_buf, GstAnalytics.SegmentationType.SEMANTIC, [7, 4, 2], 0, 0, 7, 13) @@ -274,14 +276,59 @@ class TestAnalyticsRelationMetaIterator(TestCase): (od_mtd1, GstAnalytics.ODMtd.get_mtd_type()), (od_mtd2, GstAnalytics.ODMtd.get_mtd_type()), (cls_mtd, GstAnalytics.ClsMtd.get_mtd_type()), + (cls_mtd1, GstAnalytics.ClsMtd.get_mtd_type()), (trk_mtd, GstAnalytics.TrackingMtd.get_mtd_type()), + (trk_mtd1, GstAnalytics.TrackingMtd.get_mtd_type()), (seg_mtd, GstAnalytics.SegmentationMtd.get_mtd_type()) ] + od_index_mtds = [0, 1, 2] + cls_index_mtds = [3, 4] + trk_index_mtds = [5, 6] + seg_index_mtds = [7] + mtds_from_iter = list(rmeta) self.assertEqual(len(mtds), len(mtds_from_iter)) + # Iterating on type GstAnalytics.ODMtd + for j, i in zip(od_index_mtds, rmeta.iter_on_type(GstAnalytics.ODMtd)): + assert mtds[j][0] == i + assert mtds[j][0].id == i.id + assert mtds[j][0].meta == i.meta + assert mtds[j][1] == i.get_mtd_type() + # call a method to ensure it's a ODMtd + loc = i.get_location() + + + # Iterating on type GstAnalytics.ClsMtd + for j, i in zip(cls_index_mtds, rmeta.iter_on_type(GstAnalytics.ClsMtd)): + assert mtds[j][0] == i + assert mtds[j][0].id == i.id + assert mtds[j][0].meta == i.meta + assert mtds[j][1] == i.get_mtd_type() + # call a method to ensure it's a ClsMtd + level = i.get_level(0) + + # Iterating on type GstAnalytics.TrackingMtd + for j, i in zip(trk_index_mtds, rmeta.iter_on_type(GstAnalytics.TrackingMtd)): + assert mtds[j][0] == i + assert mtds[j][0].id == i.id + assert mtds[j][0].meta == i.meta + assert mtds[j][1] == i.get_mtd_type() + # call a method to ensure it's a TrackingMtd + info = i.get_info() + + # Iterating on type GstAnalytics.SegmentationMtd + for j, i in zip(seg_index_mtds, rmeta.iter_on_type(GstAnalytics.SegmentationMtd)): + assert mtds[j][0] == i + assert mtds[j][0].id == i.id + assert mtds[j][0].meta == i.meta + assert mtds[j][1] == i.get_mtd_type() + # call a method to ensure it's a SegmentationMtd + mask = i.get_mask() + + # Iterating on all type for e, i in zip(mtds, rmeta): assert i == e[0] assert e[0].id == i.id