diff --git a/subprojects/gst-python/gi/overrides/GstAnalytics.py b/subprojects/gst-python/gi/overrides/GstAnalytics.py new file mode 100644 index 0000000000..7369c83278 --- /dev/null +++ b/subprojects/gst-python/gi/overrides/GstAnalytics.py @@ -0,0 +1,58 @@ +# -*- Mode: Python; py-indent-offset: 4 -*- +# vim: tabstop=4 shiftwidth=4 expandtab +# +# GstAnalytics.py +# +# Copyright (C) 2024 Daniel Morin <daniel.morin@dmohub.org> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the +# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# SPDX-License-Identifier: LGPL-2.0-or-later + +from ..overrides import override +from ..module import get_introspection_module +import sys + +GstAnalytics = get_introspection_module('GstAnalytics') +__all__ = [] + +from gi.overrides import _gi_gst_analytics +_gi_gst_analytics + +__mtd_types__ = {} + + +def init(): + __mtd_types__[GstAnalytics.ODMtd.get_mtd_type()] = GstAnalytics.RelationMeta.get_od_mtd + __mtd_types__[GstAnalytics.ClsMtd.get_mtd_type()] = GstAnalytics.RelationMeta.get_cls_mtd + __mtd_types__[GstAnalytics.TrackingMtd.get_mtd_type()] = GstAnalytics.RelationMeta.get_tracking_mtd + __mtd_types__[GstAnalytics.SegmentationMtd.get_mtd_type()] = GstAnalytics.RelationMeta.get_segmentation_mtd + + +def _get_mtd(mtd_type, rmeta, mtd_id): + res = __mtd_types__[mtd_type](rmeta, mtd_id) + if not res[0]: + raise AddError('Mtd with id={mtd_id} of rmeta={rmeta} is not known.') + return res[1] + + +class RelationMeta(GstAnalytics.RelationMeta): + def __iter__(self): + return _gi_gst_analytics.AnalyticsRelationMetaIterator(sys.modules[__name__], self) + + +__all__.append('RelationMeta') +__all__.append('init') diff --git a/subprojects/gst-python/gi/overrides/gstanalyticsmodule.c b/subprojects/gst-python/gi/overrides/gstanalyticsmodule.c new file mode 100644 index 0000000000..b655bdeb1e --- /dev/null +++ b/subprojects/gst-python/gi/overrides/gstanalyticsmodule.c @@ -0,0 +1,166 @@ +/* gst-python + * Copyright (C) 2024 Collabora Ltd + * Author: Daniel Morin <daniel.morin@dmohub.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* include this first, before NO_IMPORT_PYGOBJECT is defined */ +#include <Python.h> +#include <pygobject.h> +#include <gst/gst.h> +#include <gst/analytics/analytics.h> + +#include <locale.h> + +#define PYGLIB_MODULE_START(symbol, modname) \ + static struct PyModuleDef _##symbol##module = { \ + PyModuleDef_HEAD_INIT, \ + modname, \ + NULL, \ + -1, \ + symbol##_functions, \ + NULL, \ + NULL, \ + NULL, \ + NULL \ +}; \ +PyMODINIT_FUNC PyInit_##symbol(void); \ +PyMODINIT_FUNC PyInit_##symbol(void) \ +{ \ + PyObject *module; \ + module = PyModule_Create(&_##symbol##module); +#define PYGLIB_MODULE_END return module; } + +typedef struct +{ + PyObject_HEAD PyObject *py_module; + PyObject *py_rmeta; + GstAnalyticsRelationMeta *rmeta; + gpointer state; + gboolean ended; +} _GstAnalyticsRelationMetaIterator; + +static PyObject * +_gst_analytics_relation_meta_iterator_new (PyTypeObject * type, PyObject * args, + PyObject * kwds) +{ + PyObject *py_rmeta; + PyObject *py_module; + _GstAnalyticsRelationMetaIterator *self; + self = (_GstAnalyticsRelationMetaIterator *) type->tp_alloc (type, 0); + if (self != NULL) { + + if (!PyArg_ParseTuple (args, "OO", &py_module, &py_rmeta)) { + Py_DECREF (self); + return NULL; + } + + self->py_module = py_module; + self->py_rmeta = py_rmeta; + self->state = NULL; + Py_INCREF (py_module); + Py_INCREF (py_rmeta); + self->rmeta = (GstAnalyticsRelationMeta *) (pygobject_get (py_rmeta)); + self->ended = FALSE; + } + + return (PyObject *) self; +} + +static void +_gst_analytics_relation_meta_iterator_dtor (_GstAnalyticsRelationMetaIterator * + self) +{ + Py_DECREF (self->py_rmeta); + Py_DECREF (self->py_module); + Py_TYPE (self)->tp_free ((PyObject *) self); +} + +static PyObject * +_gst_analytics_relation_meta_iterator_next (_GstAnalyticsRelationMetaIterator * + self) +{ + GstAnalyticsMtd mtd; + PyObject *py_mtd_id; + PyObject *py_mtd_type; + PyObject *py_args; + PyObject *py_func; + PyObject *py_result = NULL; + + if (self->ended || !gst_analytics_relation_meta_iterate (self->rmeta, + &self->state, GST_ANALYTICS_MTD_TYPE_ANY, &mtd)) { + + self->ended = TRUE; + return NULL; + } + + py_mtd_type = PyLong_FromUnsignedLong (gst_analytics_mtd_get_mtd_type (&mtd)); + py_mtd_id = PyLong_FromUnsignedLong (mtd.id); + py_args = PyTuple_Pack (3, py_mtd_type, self->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_mtd_id); + Py_DECREF (py_mtd_type); + + return py_result; +} + +static PyMethodDef _gi_gst_analytics_functions[] = { + {NULL, NULL, 0, NULL} +}; + +static PyTypeObject GstAnalyticsRelationMetaIteratorType = { + PyVarObject_HEAD_INIT (NULL, 0) + .tp_name = "_gi_gst_analytics.AnalyticsRelationMetaIterator", + .tp_doc = "Iterator for Gst.AnalyticsRelationMeta", + .tp_basicsize = sizeof (_GstAnalyticsRelationMetaIterator), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = _gst_analytics_relation_meta_iterator_new, + .tp_iter = (getiterfunc) PyObject_SelfIter, + .tp_iternext = (iternextfunc) _gst_analytics_relation_meta_iterator_next, + .tp_dealloc = (destructor) _gst_analytics_relation_meta_iterator_dtor +}; + +PYGLIB_MODULE_START (_gi_gst_analytics, "_gi_gst_analytics") +{ + pygobject_init (3, 0, 0); + + if (PyType_Ready (&GstAnalyticsRelationMetaIteratorType) < 0) + return NULL; + + Py_INCREF (&GstAnalyticsRelationMetaIteratorType); + if (PyModule_AddObject (module, "AnalyticsRelationMetaIterator", (PyObject *) + & GstAnalyticsRelationMetaIteratorType) < 0) { + Py_DECREF (&GstAnalyticsRelationMetaIteratorType); + Py_DECREF (module); + return NULL; + } +} + +PYGLIB_MODULE_END; diff --git a/subprojects/gst-python/gi/overrides/meson.build b/subprojects/gst-python/gi/overrides/meson.build index 20aeb06ac9..5fdf0218d0 100644 --- a/subprojects/gst-python/gi/overrides/meson.build +++ b/subprojects/gst-python/gi/overrides/meson.build @@ -1,4 +1,4 @@ -pysources = ['Gst.py', 'GstPbutils.py', 'GstVideo.py', 'GstAudio.py'] +pysources = ['Gst.py', 'GstPbutils.py', 'GstVideo.py', 'GstAudio.py','GstAnalytics.py'] python.install_sources(pysources, pure : false, subdir: 'gi/overrides', @@ -9,6 +9,7 @@ if host_system == 'windows' gst_dep_for_gi = gst_dep else gst_dep_for_gi = gst_dep.partial_dependency(compile_args: true, includes: true, sources: true) + gstanalytics_dep_for_gi = gstbad_dep.partial_dependency(compile_args:true, includes:true, sources:true) endif gstpython = python.extension_module('_gi_gst', @@ -20,6 +21,15 @@ gstpython = python.extension_module('_gi_gst', dependencies : [gst_dep_for_gi, python_dep, pygobject_dep], ) +gstanalyticspython = python.extension_module ('_gi_gst_analytics', + sources: ['gstanalyticsmodule.c'], + install: true, + install_dir: pygi_override_dir, + install_tag: 'python-runtime', + include_directories : [configinc], + dependencies : [gst_dep_for_gi, python_dep, pygobject_dep, gstbad_dep], +) + env = environment() env.prepend('_GI_OVERRIDES_PATH', [ meson.current_source_dir(), diff --git a/subprojects/gst-python/meson.build b/subprojects/gst-python/meson.build index cf270075f0..4f10371327 100644 --- a/subprojects/gst-python/meson.build +++ b/subprojects/gst-python/meson.build @@ -20,6 +20,8 @@ gst_dep = dependency('gstreamer-1.0', version : gst_req, fallback : ['gstreamer', 'gst_dep']) gstbase_dep = dependency('gstreamer-base-1.0', version : gst_req, fallback : ['gstreamer', 'gst_base_dep']) +gstbad_dep = dependency('gstreamer-analytics-1.0', version :gst_req, + fallback : []) gmodule_dep = dependency('gmodule-no-export-2.0') libdl = cc.find_library('dl', required: false) pygobject_dep = dependency('pygobject-3.0', fallback: ['pygobject', 'pygobject_dep'], version : '>= 3.8')