gstanalytics: Add api iter_direct_related python to GstAnalyticsMeta

The API `iter_direct_related` allows to iterate over directly related
Mtd objects.
Usage:
```
for i in mtd.iter_direct_related(GstAnalytics.RELATE_TO,
                      GstAnalytics.ODMtd)
```

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8461>
This commit is contained in:
Santosh Mahto 2025-02-11 19:01:06 +05:30 committed by Olivier Crête
parent e649072584
commit 4c4e80d286
3 changed files with 157 additions and 0 deletions

View File

@ -41,6 +41,15 @@ class Mtd(GstAnalytics.Mtd):
return False
return self.meta == other.meta and self.id == other.id
def iter_direct_related(self, relation, mtd_type = GstAnalytics.Mtd):
if mtd_type != GstAnalytics.Mtd:
mtd_type = mtd_type.get_mtd_type();
else:
mtd_type = GstAnalytics.MTD_TYPE_ANY
return _gi_gst_analytics.AnalyticsMtdDirectRelatedIterator(
sys.modules[__name__], self, relation, mtd_type)
__all__.append('Mtd')

View File

@ -58,6 +58,95 @@ typedef struct
gboolean ended;
} _GstAnalyticsRelationMetaIterator;
typedef struct
{
PyObject_HEAD PyObject *py_module;
PyObject *py_mtd;
GstAnalyticsMtd *mtd;
gpointer state;
gboolean ended;
GstAnalyticsRelTypes relation;
GstAnalyticsMtdType mtdtype;
} _GstAnalyticsMtdDirectRelatedIterator;
static PyObject *
_gst_analytics_mtd_direct_related_iterator_new (PyTypeObject * type,
PyObject * args, PyObject * kwds)
{
PyObject *py_module;
PyObject *py_mtd;
GstAnalyticsRelTypes relation;
GstAnalyticsMtdType mtdtype;
_GstAnalyticsMtdDirectRelatedIterator *self;
self = (_GstAnalyticsMtdDirectRelatedIterator *) type->tp_alloc (type, 0);
if (self != NULL) {
if (!PyArg_ParseTuple (args, "OOik", &py_module, &py_mtd, &relation,
&mtdtype)) {
Py_DECREF (self);
return NULL;
}
self->py_module = py_module;
self->py_mtd = py_mtd;
self->state = NULL;
self->relation = relation;
self->mtdtype = mtdtype;
Py_INCREF (self->py_module);
Py_INCREF (self->py_mtd);
self->mtd = (GstAnalyticsMtd *) (pygobject_get (py_mtd));
self->ended = FALSE;
}
return (PyObject *) self;
}
static void
_gst_analytics_mtd_direct_related_iterator_dtor
(_GstAnalyticsMtdDirectRelatedIterator * self)
{
Py_DECREF (self->py_mtd);
Py_DECREF (self->py_module);
Py_TYPE (self)->tp_free ((PyObject *) self);
}
static PyObject *_gst_analytics_mtd_direct_related_iterator_next
(_GstAnalyticsMtdDirectRelatedIterator * self)
{
GstAnalyticsMtd mtd;
PyObject *py_args;
PyObject *py_func;
PyObject *py_rmeta;
PyObject *py_mtd_id;
PyObject *py_mtd_type;
PyObject *py_result = NULL;
if (self->ended
|| !gst_analytics_relation_meta_get_direct_related (self->mtd->meta,
self->mtd->id, self->relation, self->mtdtype, &self->state, &mtd)) {
self->ended = TRUE;
return NULL;
}
py_mtd_type = PyLong_FromUnsignedLong (gst_analytics_mtd_get_mtd_type (&mtd));
py_rmeta = PyObject_GetAttrString (self->py_mtd, "meta");
py_mtd_id = PyLong_FromUnsignedLong (mtd.id);
py_args = PyTuple_Pack (3, py_mtd_type, py_rmeta, py_mtd_id);
py_func = PyObject_GetAttrString (self->py_module, "_get_mtd");
if (py_func) {
py_result = PyObject_Call (py_func, py_args, NULL);
Py_DECREF (py_func);
}
Py_DECREF (py_args);
Py_DECREF (py_rmeta);
return py_result;
}
static PyObject *
_gst_analytics_relation_meta_iterator_new (PyTypeObject * type, PyObject * args,
PyObject * kwds)
@ -147,6 +236,19 @@ static PyTypeObject GstAnalyticsRelationMetaIteratorType = {
.tp_dealloc = (destructor) _gst_analytics_relation_meta_iterator_dtor
};
static PyTypeObject GstAnalyticsMtdDirectRelatedIteratorType = {
PyVarObject_HEAD_INIT (NULL, 0)
.tp_name = "_gi_gst_analytics.AnalyticsMtdDirectRelatedIterator",
.tp_doc = "Iterator for Related Gst.AnalyticsMtd",
.tp_basicsize = sizeof (_GstAnalyticsMtdDirectRelatedIterator),
.tp_itemsize = 0,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_new = _gst_analytics_mtd_direct_related_iterator_new,
.tp_iter = (getiterfunc) PyObject_SelfIter,
.tp_iternext = (iternextfunc) _gst_analytics_mtd_direct_related_iterator_next,
.tp_dealloc = (destructor) _gst_analytics_mtd_direct_related_iterator_dtor
};
PYGLIB_MODULE_START (_gi_gst_analytics, "_gi_gst_analytics")
{
pygobject_init (3, 0, 0);
@ -161,6 +263,18 @@ PYGLIB_MODULE_START (_gi_gst_analytics, "_gi_gst_analytics")
Py_DECREF (module);
return NULL;
}
if (PyType_Ready (&GstAnalyticsMtdDirectRelatedIteratorType) < 0)
return NULL;
Py_INCREF (&GstAnalyticsMtdDirectRelatedIteratorType);
if (PyModule_AddObject (module, "AnalyticsMtdDirectRelatedIterator",
(PyObject *)
& GstAnalyticsMtdDirectRelatedIteratorType) < 0) {
Py_DECREF (&GstAnalyticsMtdDirectRelatedIteratorType);
Py_DECREF (module);
return NULL;
}
}
PYGLIB_MODULE_END;

View File

@ -261,6 +261,8 @@ class TestAnalyticsRelationMetaIterator(TestCase):
GstVideo.VideoFormat.GRAY8, 10, 10)
(_, od_mtd) = rmeta.add_od_mtd(GLib.quark_from_string("od"), 1, 1, 2, 2, 0.1)
(_, 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"))
(_, trk_mtd) = rmeta.add_tracking_mtd(1, 10)
(_, seg_mtd) = rmeta.add_segmentation_mtd(mask_buf,
@ -269,6 +271,8 @@ class TestAnalyticsRelationMetaIterator(TestCase):
mtds = [
(od_mtd, GstAnalytics.ODMtd.get_mtd_type()),
(od_mtd1, GstAnalytics.ODMtd.get_mtd_type()),
(od_mtd2, GstAnalytics.ODMtd.get_mtd_type()),
(cls_mtd, GstAnalytics.ClsMtd.get_mtd_type()),
(trk_mtd, GstAnalytics.TrackingMtd.get_mtd_type()),
(seg_mtd, GstAnalytics.SegmentationMtd.get_mtd_type())
@ -291,3 +295,33 @@ class TestAnalyticsRelationMetaIterator(TestCase):
self.assertEqual(location[3], 2)
self.assertEqual(location[4], 2)
self.assertAlmostEqual(location[5], 0.1, 3)
# Test iteration over direct relation
rmeta.set_relation(GstAnalytics.RelTypes.RELATE_TO, od_mtd.id, od_mtd1.id)
rmeta.set_relation(GstAnalytics.RelTypes.IS_PART_OF, od_mtd.id, trk_mtd.id)
rmeta.set_relation(GstAnalytics.RelTypes.RELATE_TO, od_mtd.id, od_mtd2.id)
rmeta.set_relation(GstAnalytics.RelTypes.RELATE_TO, od_mtd.id, cls_mtd.id)
expected_mtd_ids = [od_mtd1.id, od_mtd2.id, cls_mtd.id]
expected_mtd_type = [GstAnalytics.ODMtd, GstAnalytics.ODMtd, GstAnalytics.ClsMtd]
count = 0
# Iterate over all type
for mtd in od_mtd.iter_direct_related(GstAnalytics.RelTypes.RELATE_TO):
assert mtd.id == expected_mtd_ids[count]
assert type(mtd) == expected_mtd_type[count]
if (type(mtd) == GstAnalytics.ODMtd):
assert mtd.get_obj_type() == GLib.quark_from_string("od")
elif (type(mtd) == GstAnalytics.ClsMtd):
assert mtd.get_quark(0) == GLib.quark_from_string("cls")
count = count + 1
assert(count == len(expected_mtd_ids))
# Iterate over only with type GstAnalytics.ODMtd
count = 0
for mtd in od_mtd.iter_direct_related(GstAnalytics.RelTypes.RELATE_TO, GstAnalytics.ODMtd):
assert mtd.id == expected_mtd_ids[count]
assert type(mtd) == GstAnalytics.ODMtd
count = count + 1
assert(count == 2)