From 326117fdb3d254da850045ab4e734bd1af75a21d Mon Sep 17 00:00:00 2001 From: Dongju Chae Date: Thu, 16 May 2019 15:52:23 +0900 Subject: [PATCH] [PythonFilter/Build] Update build files for Ubuntu/Tizen packaging Changed ubuntu/tizen build files to support Python subplugin/api Signed-off-by: Dongju Chae --- debian/control | 16 +++++- debian/nnstreamer-python2.install | 2 + debian/nnstreamer-python2.links | 1 + debian/nnstreamer-python3.install | 2 + debian/nnstreamer-python3.links | 1 + ext/nnstreamer/tensor_filter/meson.build | 66 ++++++++++++++++++++++ .../tensor_filter/tensor_filter_python.c | 17 +++++- .../tensor_filter/tensor_filter_python_api.c | 45 +++++++++++---- .../tensor_filter/tensor_filter_python_core.cc | 8 +-- .../tensor_filter/tensor_filter_python_core.h | 4 +- meson.build | 29 ++++++++++ meson_options.txt | 1 + packaging/nnstreamer.spec | 18 ++++++ 13 files changed, 190 insertions(+), 20 deletions(-) create mode 100644 debian/nnstreamer-python2.install create mode 100644 debian/nnstreamer-python2.links create mode 100644 debian/nnstreamer-python3.install create mode 100644 debian/nnstreamer-python3.links diff --git a/debian/control b/debian/control index 3291a1b..4c34d0f 100644 --- a/debian/control +++ b/debian/control @@ -7,7 +7,7 @@ Build-Depends: gcc (>=5), ninja-build, meson (>=0.40), libgstreamer1.0-dev, libgstreamer-plugins-base1.0-dev, libglib2.0-dev, gstreamer1.0-tools, gstreamer1.0-plugins-base, gstreamer1.0-plugins-good, libgtest-dev, ssat, libpng-dev, libopencv-dev, liborc-0.4-dev, - python, python-numpy, + python, python-numpy, python3, python3-dev, python3-numpy, tensorflow-lite-dev, tensorflow-dev [amd64 arm64], python2.7-dev, libprotobuf-dev [amd64 arm64] Standards-Version: 3.9.6 @@ -34,6 +34,20 @@ Depends: nnstreamer, ${shlibs:Depends}, ${misc:Depends} Description: NNStreamer TensorFlow Lite Support This package allows nnstreamer to support tensorflow-lite. +Package: nnstreamer-python2 +Architecture: any +Multi-Arch: same +Depends: nnstreamer, python, python-numpy, ${shlibs:Depends}, ${misc:Depends} +Description: NNStreamer Python Custom Filter Support (2.7) + This Package allows nnstreamer to support python custom filters + +Package: nnstreamer-python3 +Architecture: any +Multi-Arch: same +Depends: nnstreamer, python3, python3-numpy, ${shlibs:Depends}, ${misc:Depends} +Description: NNStreamer Python Custom Filter Support (3.x) + This Package allows nnstreamer to support python custom filters + Package: nnstreamer-dev Architecture: any Multi-Arch: same diff --git a/debian/nnstreamer-python2.install b/debian/nnstreamer-python2.install new file mode 100644 index 0000000..6ab4a72 --- /dev/null +++ b/debian/nnstreamer-python2.install @@ -0,0 +1,2 @@ +/usr/lib/nnstreamer/filters/libnnstreamer_filter_python2.so +/usr/lib/nnstreamer/filters/nnstreamer_python2.so diff --git a/debian/nnstreamer-python2.links b/debian/nnstreamer-python2.links new file mode 100644 index 0000000..220e273 --- /dev/null +++ b/debian/nnstreamer-python2.links @@ -0,0 +1 @@ +/usr/lib/nnstreamer/filters/nnstreamer_python2.so /usr/lib/python2.7/dist-packages/nnstreamer_python.so diff --git a/debian/nnstreamer-python3.install b/debian/nnstreamer-python3.install new file mode 100644 index 0000000..ce02cee --- /dev/null +++ b/debian/nnstreamer-python3.install @@ -0,0 +1,2 @@ +/usr/lib/nnstreamer/filters/libnnstreamer_filter_python3.so +/usr/lib/nnstreamer/filters/nnstreamer_python3.so diff --git a/debian/nnstreamer-python3.links b/debian/nnstreamer-python3.links new file mode 100644 index 0000000..c49efb9 --- /dev/null +++ b/debian/nnstreamer-python3.links @@ -0,0 +1 @@ +/usr/lib/nnstreamer/filters/nnstreamer_python3.so /usr/lib/python3/dist-packages/nnstreamer_python.so diff --git a/ext/nnstreamer/tensor_filter/meson.build b/ext/nnstreamer/tensor_filter/meson.build index ace79a7..6359290 100644 --- a/ext/nnstreamer/tensor_filter/meson.build +++ b/ext/nnstreamer/tensor_filter/meson.build @@ -58,6 +58,72 @@ if get_option('enable-tensorflow-lite') ) endif +filter_sub_python_sources = [ + 'tensor_filter_python.c', + 'tensor_filter_python_core.cc' +] + +nnstreamer_filter_python_sources = [] +foreach s : filter_sub_python_sources + nnstreamer_filter_python_sources += join_paths(meson.current_source_dir(), s) +endforeach + +if have_python2 + nnstreamer_filter_python_deps = [python2_dep, libdl_dep, glib_dep, gst_dep, nnstreamer_dep] + + shared_library('nnstreamer_filter_python2', + nnstreamer_filter_python_sources, + cpp_args: ['-Wno-sign-compare'], + dependencies: nnstreamer_filter_python_deps, + install: true, + install_dir: filter_subplugin_install_dir + ) + + static_library('nnstreamer_filter_python2', + nnstreamer_filter_python_sources, + cpp_args: ['-Wno-sign-compare'], + dependencies: nnstreamer_filter_python_deps, + install: true, + install_dir: nnstreamer_libdir + ) + + shared_library('nnstreamer_python2', + 'tensor_filter_python_api.c', + name_prefix: '', + dependencies: nnstreamer_filter_python_deps, + install: true, + install_dir: filter_subplugin_install_dir + ) +endif + +if have_python3 + nnstreamer_filter_python_deps = [python3_dep, libdl_dep, glib_dep, gst_dep, nnstreamer_dep] + + shared_library('nnstreamer_filter_python3', + nnstreamer_filter_python_sources, + cpp_args: ['-Wno-sign-compare'], + dependencies: nnstreamer_filter_python_deps, + install: true, + install_dir: filter_subplugin_install_dir + ) + + static_library('nnstreamer_filter_python3', + nnstreamer_filter_python_sources, + cpp_args: ['-Wno-sign-compare'], + dependencies: nnstreamer_filter_python_deps, + install: true, + install_dir: nnstreamer_libdir + ) + + shared_library('nnstreamer_python3', + 'tensor_filter_python_api.c', + name_prefix: '', + dependencies: nnstreamer_filter_python_deps, + install: true, + install_dir: filter_subplugin_install_dir + ) +endif + if get_option('enable-movidius-ncsdk2') # Explicitly checks mvnc.h in the ncsdk2 directory # check_header() requires meson >= 0.47 diff --git a/ext/nnstreamer/tensor_filter/tensor_filter_python.c b/ext/nnstreamer/tensor_filter/tensor_filter_python.c index 0128cd1..5c058fc 100644 --- a/ext/nnstreamer/tensor_filter/tensor_filter_python.c +++ b/ext/nnstreamer/tensor_filter/tensor_filter_python.c @@ -22,6 +22,20 @@ * @bug No known bugs except for NYI items */ +/** + * SECTION:element-tensor_filter_python + * + * A filter that loads and executes a python script implementing a custom filter. + * The python script should be provided. + * + * + * Example launch line + * |[ + * gst-launch-1.0 videotestsrc ! video/x-raw,format=RGB,width=640,height=480 ! tensor_converter ! tensor_filter framework="python2" model="${PATH_TO_SCRIPT}" ! tensor_sink + * ]| + * + */ + #define NO_IMPORT_ARRAY #include "tensor_filter_python_core.h" #include @@ -175,8 +189,7 @@ py_loadScriptFile (const GstTensorFilterProperties * prop, void **private_data) } /** check methods in python script */ - cb_type type = py_core_getCbType (py->py_private_data); - switch (type) { + switch (py_core_getCbType (py->py_private_data)) { case CB_SETDIM: NNS_support_python->getInputDimension = NULL; NNS_support_python->getOutputDimension = NULL; diff --git a/ext/nnstreamer/tensor_filter/tensor_filter_python_api.c b/ext/nnstreamer/tensor_filter/tensor_filter_python_api.c index d2826a1..b0bf146 100644 --- a/ext/nnstreamer/tensor_filter/tensor_filter_python_api.c +++ b/ext/nnstreamer/tensor_filter/tensor_filter_python_api.c @@ -22,6 +22,22 @@ * @bug No known bugs except for NYI items */ +/** + * SECTION:element-tensor_filter_python_api + * + * A python module that provides a wrapper for internal structures in tensor_filter_python. + * Users can import this module to access such a functionality + * + * + * Example python script + * |[ + * import numpy as np + * import nnstreamer_python as nns + * dim = nns.TensorShape([1,2,3], np.uint8) + * ]| + * + */ + #include "tensor_filter_python_core.h" /** @brief object structure for custom Python type: TensorShape */ @@ -31,6 +47,13 @@ typedef struct { PyArray_Descr* type; } TensorShapeObject; +/** @brief define a prototype for this python module */ +#if PY_VERSION_HEX >= 0x03000000 +PyMODINIT_FUNC PyInit_nnstreamer_python(void); +#else +PyMODINIT_FUNC initnnstreamer_python(void); +#endif + /** * @brief method impl. for setDims * @param self : Python type object @@ -112,7 +135,7 @@ TensorShape_new(PyTypeObject *type, PyObject *args, PyObject *kw) { */ static int TensorShape_init(TensorShapeObject *self, PyObject *args, PyObject *kw) { - char *keywords[] = {"dims", "type", NULL}; + char *keywords[] = {(char*) "dims", (char*) "type", NULL}; PyObject *dims = NULL; PyObject *type = NULL; @@ -120,7 +143,7 @@ TensorShape_init(TensorShapeObject *self, PyObject *args, PyObject *kw) { return -1; if (dims) { - PyObject *none = PyObject_CallMethod((PyObject*) self, (char*) "setDims", "O", dims); + PyObject *none = PyObject_CallMethod((PyObject*) self, (char*) "setDims", (char*) "O", dims); Py_XDECREF(none); } @@ -151,15 +174,15 @@ TensorShape_dealloc(TensorShapeObject *self) { /** @brief members for custom type object */ static PyMemberDef TensorShape_members[] = { - {"dims", T_OBJECT_EX, offsetof(TensorShapeObject, dims), 0, NULL}, - {"type", T_OBJECT_EX, offsetof(TensorShapeObject, type), 0, NULL} + {(char*) "dims", T_OBJECT_EX, offsetof(TensorShapeObject, dims), 0, NULL}, + {(char*) "type", T_OBJECT_EX, offsetof(TensorShapeObject, type), 0, NULL} }; /** @brief methods for custom type object */ static PyMethodDef TensorShape_methods[] = { - {"setDims", (PyCFunction)TensorShape_setDims, METH_VARARGS | METH_KEYWORDS, NULL}, - {"getDims", (PyCFunction)TensorShape_getDims, METH_VARARGS | METH_KEYWORDS, NULL}, - {"getType", (PyCFunction)TensorShape_getType, METH_VARARGS | METH_KEYWORDS, NULL}, + {(char*) "setDims", (PyCFunction)TensorShape_setDims, METH_VARARGS | METH_KEYWORDS, NULL}, + {(char*) "getDims", (PyCFunction)TensorShape_getDims, METH_VARARGS | METH_KEYWORDS, NULL}, + {(char*) "getType", (PyCFunction)TensorShape_getType, METH_VARARGS | METH_KEYWORDS, NULL}, {NULL, NULL, 0, NULL} }; @@ -181,11 +204,11 @@ static PyTypeObject TensorShapeType = { #if PY_VERSION_HEX >= 0x03000000 #define RETVAL(x) x static PyModuleDef nnstreamer_python_module = { - PyModuleDef_HEAD_INIT, "nnstreamer_python3", NULL, -1, NULL + PyModuleDef_HEAD_INIT, "nnstreamer_python", NULL, -1, NULL }; /** @brief module initialization (python 3.x) */ PyMODINIT_FUNC -PyInit_nnstreamer_python3(void) { +PyInit_nnstreamer_python(void) { #else #define RETVAL(x) static PyMethodDef nnstreamer_python_methods[] = { @@ -193,14 +216,14 @@ static PyMethodDef nnstreamer_python_methods[] = { }; /** @brief module initialization (python 2.x) */ PyMODINIT_FUNC -initnnstreamer_python2(void) { +initnnstreamer_python(void) { #endif PyObject *type_object = (PyObject*) &TensorShapeType; PyObject *module; #if PY_VERSION_HEX >= 0x03000000 module = PyModule_Create(&nnstreamer_python_module); #else - module = Py_InitModule("nnstreamer_python2", nnstreamer_python_methods); + module = Py_InitModule("nnstreamer_python", nnstreamer_python_methods); #endif if (module == NULL) return RETVAL(NULL); diff --git a/ext/nnstreamer/tensor_filter/tensor_filter_python_core.cc b/ext/nnstreamer/tensor_filter/tensor_filter_python_core.cc index c90f1bf..7a9f60c 100644 --- a/ext/nnstreamer/tensor_filter/tensor_filter_python_core.cc +++ b/ext/nnstreamer/tensor_filter/tensor_filter_python_core.cc @@ -46,13 +46,13 @@ PYCore::PYCore (const char* _script_path, const char* _custom) * To fix import error of python extension modules * (e.g., multiarray.x86_64-linux-gnu.so: undefined symbol: PyExc_SystemError) */ + gchar libname[32]; #if PY_VERSION_HEX >= 0x03000000 - handle = dlopen("libpython3.5m.so.1", RTLD_LAZY | RTLD_GLOBAL); - if (handle == NULL) /** try another version */ - handle = dlopen("libpython3.6m.so.1", RTLD_LAZY | RTLD_GLOBAL); + g_snprintf (libname, sizeof(libname), "libpython%fm.so.1", PYTHON3_VERSION); #else - handle = dlopen("libpython2.7.so.1", RTLD_LAZY | RTLD_GLOBAL); + g_snprintf (libname, sizeof(libname), "libpython%f.so.1", PYTHON2_VERSION); #endif + handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL); g_assert(handle); Py_Initialize(); diff --git a/ext/nnstreamer/tensor_filter/tensor_filter_python_core.h b/ext/nnstreamer/tensor_filter/tensor_filter_python_core.h index b670344..c4ef5de 100644 --- a/ext/nnstreamer/tensor_filter/tensor_filter_python_core.h +++ b/ext/nnstreamer/tensor_filter/tensor_filter_python_core.h @@ -28,15 +28,15 @@ #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION #include -#include #include #include #include - #include #include #include +#include "nnstreamer_plugin_api_filter.h" + #define Py_ERRMSG(...) do {PyErr_Print(); g_critical (__VA_ARGS__);} while (0); /** @brief Callback type for custom filter */ diff --git a/meson.build b/meson.build index b619e18..301896d 100644 --- a/meson.build +++ b/meson.build @@ -154,6 +154,35 @@ if get_option('enable-tensorflow-lite') endif endif +# Python +have_python2 = false +have_python3 = false + +if get_option('enable-python') + prog_pkgconfig = find_program('pkg-config') + + # Check python 2.7 + python2_dep = dependency('python-2.7', required: false) + if python2_dep.found() + python2_incs = run_command(prog_pkgconfig, ['python-2.7', '--cflags']).stdout().strip().split() + if cc.has_header('numpy/arrayobject.h', args: python2_incs) + add_project_arguments('-DPYTHON2_VERSION=2.7', language: ['c', 'cpp']) + have_python2 = true + endif + endif + + # Check python 3.x + python3_dep = dependency('python3', required: false) + if python3_dep.found() + python3_version = run_command(prog_pkgconfig, ['python3', '--modversion']).stdout().strip() + python3_incs = run_command(prog_pkgconfig, ['python3', '--cflags']).stdout().strip().split() + if cc.has_header('numpy/arrayobject.h', args: python3_incs) + add_project_arguments('-DPYTHON3_VERSION=' + python3_version, language: ['c', 'cpp']) + have_python3 = true + endif + endif +endif + # Build nnstreamer (common, plugins) subdir('gst') diff --git a/meson_options.txt b/meson_options.txt index 7608e83..020dada 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -9,3 +9,4 @@ option('install-example', type: 'boolean', value: false) option('disable-video-support', type: 'boolean', value: false) option('disable-audio-support', type: 'boolean', value: false) option('enable-tizen-capi', type: 'boolean', value: false) +option('enable-python', type: 'boolean', value: true) diff --git a/packaging/nnstreamer.spec b/packaging/nnstreamer.spec index 8c29c76..6364b3f 100644 --- a/packaging/nnstreamer.spec +++ b/packaging/nnstreamer.spec @@ -40,6 +40,9 @@ BuildRequires: gtest-devel # a few test cases uses python BuildRequires: python BuildRequires: python-numpy +# for python custom filters +BuildRequires: pkgconfig(python2) +BuildRequires: python-numpy-devel # Testcase requires bmp2png, which requires libpng BuildRequires: pkgconfig(libpng) # for tensorflow-lite @@ -111,6 +114,13 @@ Requires: nnstreamer = %{version}-%{release} %description tensorflow-lite NNStreamer's tensor_fliter subplugin of TensorFlow Lite. +%package -n nnstreamer-python2 +Summary: NNStreamer Python Custom Filter Support +Requires: nnstreamer = %{version}-%{release} +Requires: python +%description -n nnstreamer-python2 +NNStreamer's tensor_filter subplugin of Python (2.7). + %package devel Summary: Development package for custom tensor operator developers (tensor_filter/custom) Requires: nnstreamer = %{version}-%{release} @@ -244,6 +254,9 @@ ln -s %{gstlibdir}/libnnstreamer.so libnnstreamer.so popd /sbin/ldconfig +%post -n nnstreamer-python2 +ln -s %{_prefix}/lib/nnstreamer/filters/nnstreamer_python2.so %{python_sitelib}/nnstreamer_python.so + %postun -p /sbin/ldconfig pushd %{_libdir} rm libnnstreamer.so @@ -268,6 +281,11 @@ popd %defattr(-,root,root,-) %{_prefix}/lib/nnstreamer/filters/libnnstreamer_filter_tensorflow-lite.so +%files -n nnstreamer-python2 +%defattr(-,root,root,-) +%{_prefix}/lib/nnstreamer/filters/libnnstreamer_filter_python2.so +%{_prefix}/lib/nnstreamer/filters/nnstreamer_python2.so + %files devel %{_includedir}/nnstreamer/tensor_typedef.h %{_includedir}/nnstreamer/tensor_filter_custom.h -- 2.7.4