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: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8459>
This commit is contained in:
Santosh Mahto 2025-02-11 11:39:43 +05:30 committed by Olivier Crête
parent e68eb7bb23
commit 7c7832fee1
3 changed files with 94 additions and 9 deletions

View File

@ -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')

View File

@ -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);

View File

@ -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