SET(gtestInc /usr/src/gtest)
ENDIF(TIZEN OR GTEST_LIB)
+IF (NOT INCLUDE_INSTALL_DIR)
+ # We need to define includedir path
+ SET (INCLUDE_INSTALL_DIR /usr/include)
+ MESSAGE ("Warning: INCLUDE_INSTALL_DIR not defined. Using /usr/include")
+ENDIF (NOT INCLUDE_INSTALL_DIR)
+
pkg_check_modules(pkgs REQUIRED ${PKG_MODULES})
INCLUDE_DIRECTORIES(
ADD_SUBDIRECTORY(tensor_converter)
ADD_SUBDIRECTORY(tensor_filter)
+
+CONFIGURE_FILE(nnstreamer.pc.in nnstreamer.pc @ONLY)
+
+INSTALL(FILES include/tensor_typedef.h
+ DESTINATION ${INCLUDE_INSTALL_DIR}/nnstreamer
+ )
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/nnstreamer.pc
+ DESTINATION ${LIB_INSTALL_DIR}/pkgconfig
+ )
#include <glib.h>
#include <stdint.h>
+#include "tensor_typedef.h"
G_BEGIN_DECLS
-#define NNS_TENSOR_RANK_LIMIT (4)
-/**
- * @brief Possible data element types of other/tensor.
- *
- * The current version supports NNS_UINT8 only as video-input.
- * There is no restrictions for inter-NN or sink-to-app.
- */
-typedef enum _nns_tensor_type {
- _NNS_INT32 = 0,
- _NNS_UINT32,
- _NNS_INT16,
- _NNS_UINT16,
- _NNS_INT8,
- _NNS_UINT8,
- _NNS_FLOAT64,
- _NNS_FLOAT32,
-
- _NNS_END,
-} tensor_type;
-
/**
* @brief Possible input stream types for other/tensor.
*
--- /dev/null
+/*
+ * NNStreamer Common Header, Typedef part, for export as devel package.
+ * Copyright (C) 2018 MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * @file tensor_common_typedef.h
+ * @date 01 Jun 2018
+ * @brief Common header file for NNStreamer, the GStreamer plugin for neural networks
+ * @see http://github.com/TO-BE-DETERMINED-SOON
+ * @see https://github.sec.samsung.net/STAR/nnstreamer
+ * @author MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * To Packagers:
+ *
+ * This fils it to be packaged as "devel" package for NN developers.
+ */
+
+#ifndef __GST_TENSOR_TYPEDEF_H__
+#define __GST_TENSOR_TYPEDEF_H__
+
+#define NNS_TENSOR_RANK_LIMIT (4)
+/**
+ * @brief Possible data element types of other/tensor.
+ *
+ * The current version supports NNS_UINT8 only as video-input.
+ * There is no restrictions for inter-NN or sink-to-app.
+ */
+typedef enum _nns_tensor_type {
+ _NNS_INT32 = 0,
+ _NNS_UINT32,
+ _NNS_INT16,
+ _NNS_UINT16,
+ _NNS_INT8,
+ _NNS_UINT8,
+ _NNS_FLOAT64,
+ _NNS_FLOAT32,
+
+ _NNS_END,
+} tensor_type;
+
+#endif /*__GST_TENSOR_TYPEDEF_H__*/
--- /dev/null
+# Package Information for pkg-config
+
+prefix=@PREFIX@
+exec_prefix=@EXEC_PREFIX@
+libdir=@LIB_INSTALL_DIR@
+includedir=/usr/include/deviced
+
+Name: nnstreamer
+Description: Neural Network Suite for GStreamer
+Version: @VERSION@
+Requires:
+Libs:
+Cflags: -I${includedir}
NNStreamer is a set of gstreamer plugins to support general neural networks
and their plugins in a gstreamer stream.
+%package devel
+Summary: Development package for custom tensor operator developers (tensor_filter/custom)
+Requires: nnstreamer = %{version}-%{release}
+%description devel
+Development package for custom tensor operator developers (tensor_filter/custom).
+This contains corresponding header files and .pc pkgconfig file.
+
%prep
%setup -q
cp %{SOURCE1001} .
%defattr(-,root,root,-)
# The libraries are in LGPLv2.1 (testcases and non GST-plugin components are APL2)
%license LICENSE.LGPLv2.1
-%{_libdir}/*
+%{_libdir}/*.so
+%{_libdir}/*.so*
+# TODO generate .so files with version info. Migrate symbolic-link .so to devel.
+
+%files devel
+%{_includedir}/nnstreamer/*
+%{_libdir}/pkgconfig/nnstreamer.pc
%if 0%{?testcoverage}
%files unittest-coverage
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
-ADD_LIBRARY(tensor_filter SHARED tensor_filter.c tensor_filter_tensorflow_lite.c)
+ADD_LIBRARY(tensor_filter SHARED
+ tensor_filter.c
+ tensor_filter_tensorflow_lite.c
+ tensor_filter_custom.c
+ )
-TARGET_LINK_LIBRARIES(tensor_filter ${pkgs_LIBRARIES})
+TARGET_LINK_LIBRARIES(tensor_filter dl ${pkgs_LIBRARIES})
TARGET_INCLUDE_DIRECTORIES(tensor_filter PUBLIC ${pkgs_INCLUDE_DIRS})
TARGET_COMPILE_OPTIONS(tensor_filter PUBLIC ${pkgs_CFLAGS_OTHER})
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
)
+INSTALL(FILES tensor_filter_custom.h
+ DESTINATION ${INCLUDE_INSTALL_DIR}/nnstreamer
+ )
### Custom function support, ```tensor_filter_custom.c```
-This should fill in ```GstTensor_Filter_Framework``` supporting dlopen'ed custom shared objects, requiring such shared objects to provide its own defined functions.
+Neural network and streameline developers may define their own tensor postprocessing operations with tensor_filter_custom.
+
+With ```nnstreamer-devel``` package installed at build time (e.g., ```BuildRequires: pkgconfig(nnstreamer)``` in .spec file), develerops can implement their own functions and expose their functions via ```NNStreamer_custom_class``` defined in ```tensor_fitler_custom.h```. The resulting custom developer plugin should exist as a shared library (.so) with the symbol NNStreamer_custom exposed with all the func defined in NNStreamer_custom_class.
+
+@TODO Write an example custom filter for novice developers.
### We may add other NNFW as well (tensorflow, caffe, ...)
GstTensor_Filter_Framework *tensor_filter_supported[] = {
[_T_F_UNDEFINED] = NULL,
- [_T_F_CUSTOM] = NULL,
+ [_T_F_CUSTOM] = &NNS_support_custom,
[_T_F_TENSORFLOW_LITE] = &NNS_support_tensorflow_lite,
[_T_F_TENSORFLOW] = NULL,
[_T_F_CAFFE2] = NULL,
filter->outputDimension[2] = 1;
filter->outputDimension[3] = 1; // out
filter->outputType = _NNS_END; // not initialized
+
+ filter->privateData = NULL; // mark not initialized.
}
/**
static const gboolean nnfw_support_status[] = {
FALSE,
- FALSE,
- FALSE,
+ TRUE,
+ TRUE,
FALSE,
FALSE,
int (*invoke_NN)(GstTensor_Filter *filter, void *inputptr, void *outputptr); /**< Mandatory callback. Invoke the given network model. */
int (*getInputDimension)(GstTensor_Filter *filter, uint32_t *inputDimension, tensor_type *type); /**< Optional. Set NULL if not supported. Get dimension of input tensor */
int (*getOutputDimension)(GstTensor_Filter *filter, uint32_t *outputDimension, tensor_type *type); /**< Optional. Set NULL if not supported. Get dimension of output tensor */
+ void (*close)(GstTensor_Filter *filter); /**< Optional. Close this instance! */
};
extern GstTensor_Filter_Framework NNS_support_tensorflow_lite;
+extern GstTensor_Filter_Framework NNS_support_custom;
extern GstTensor_Filter_Framework *tensor_filter_supported[];
--- /dev/null
+/**
+ * GStreamer Tensor_Filter, Tensorflow-Lite Module
+ * Copyright (C) 2018 MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * @file tensor_filter_custom.c
+ * @date 01 Jun 2018
+ * @brief Custom tensor post-processing interface for NNStreamer suite between NN developer-plugins and NNstreamer.
+ * @see http://github.com/TO-BE-DETERMINED-SOON
+ * @see https://github.sec.samsung.net/STAR/nnstreamer
+ * @author MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * This is the per-NN-framework plugin (custom) for tensor_filter.
+ * Fill in "GstTensor_Filter_Framework" for tensor_filter.h/c
+ *
+ */
+
+#include "tensor_filter.h"
+#include "tensor_filter_custom.h"
+#include <glib.h>
+#include <dlfcn.h>
+
+struct _internal_data {
+ GstTensor_Filter *parent;
+
+ void *handle;
+ NNStreamer_custom_class *methods;
+
+ void* customFW_private_data;
+};
+typedef struct _internal_data internal_data;
+
+/**
+ * @brief Load the custom library. Will skip loading if it's already loaded.
+ * @return 0 if successfully loaded. 1 if skipped (already loaded). -1 if error
+ */
+static int custom_loadlib(GstTensor_Filter *filter) {
+ internal_data *ptr;
+ char *dlsym_error;
+
+ if (filter->privateData != NULL) {
+ /* @TODO : Check the integrity of filter->data and filter->modelFilename, nnfw */
+ return 1;
+ }
+
+ ptr = g_new0(internal_data, 0); /* Fill Zero! */
+ filter->privateData = ptr;
+ ptr->parent = filter;
+
+ /* Load .so if this is the first time for this instance. */
+ ptr->handle = dlopen(filter->modelFilename, RTLD_NOW);
+ if (!ptr->handle) {
+ g_free(ptr);
+ filter->privateData = NULL;
+ return -1;
+ }
+
+ dlerror();
+ ptr->methods = (NNStreamer_custom_class *) dlsym(ptr->handle, "NNStreamer_custom");
+ dlsym_error = dlerror();
+ if (dlsym_error) {
+ g_printerr("tensor_filter_custom:loadlib error: %s\n", dlsym_error);
+ dlclose(ptr->handle);
+ g_free(ptr);
+ filter->privateData = NULL;
+ return -1;
+ }
+
+ ptr->customFW_private_data = ptr->methods->initfunc();
+ return 0;
+}
+
+/**
+ * @brief The mandatory callback for GstTensor_Filter_Framework
+ * @param filter The parent object
+ * @param[in] inptr The input tensor
+ * @param[out] outptr The output tensor
+ */
+static int custom_invoke(GstTensor_Filter *filter, void *inptr, void *outptr) {
+ int retval = custom_loadlib(filter);
+ internal_data *ptr;
+
+ /* Actually, tensor_filter must have called getInput/OotputDim first. */
+ g_assert(retval != 0);
+
+ if (retval < 0)
+ return retval;
+
+ g_assert(filter->privateData);
+ ptr = filter->privateData;
+
+ return ptr->methods->invoke(ptr->customFW_private_data, inptr, outptr);
+}
+
+/**
+ * @brief The optional callback for GstTensor_Filter_Framework
+ */
+static int custom_getInputDim(GstTensor_Filter *filter, uint32_t *inputDimension, tensor_type *type) {
+ int retval = custom_loadlib(filter);
+ internal_data *ptr;
+
+ if (retval < 0)
+ return retval;
+
+ g_assert(filter->privateData);
+ ptr = filter->privateData;
+
+ return ptr->methods->getInputDim(ptr->customFW_private_data, inputDimension, type);
+}
+
+/**
+ * @brief The optional callback for GstTensor_Filter_Framework
+ */
+static int custom_getOutputDim(GstTensor_Filter *filter, uint32_t *outputDimension, tensor_type *type) {
+ int retval = custom_loadlib(filter);
+ internal_data *ptr;
+
+ if (retval < 0)
+ return retval;
+
+ g_assert(filter->privateData);
+ ptr = filter->privateData;
+
+ return ptr->methods->getOutputDim(ptr->customFW_private_data, outputDimension, type);
+}
+
+/**
+ * @brief Free privateData and move on.
+ */
+static void custom_close(GstTensor_Filter *filter) {
+ internal_data *ptr = filter->privateData;
+
+ ptr->methods->exitfunc(ptr->customFW_private_data);
+ g_free(ptr);
+ filter->privateData = NULL;
+}
+
+GstTensor_Filter_Framework NNS_support_custom = {
+ .name = "custom",
+ .allow_in_place = FALSE, // custom cannot support in-place (outptr == inptr).
+ .invoke_NN = custom_invoke,
+ .getInputDimension = custom_getInputDim,
+ .getOutputDimension = custom_getOutputDim,
+ .close = custom_close,
+};
--- /dev/null
+/**
+ * GStreamer Tensor_Filter, Tensorflow-Lite Module
+ * Copyright (C) 2018 MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * @file tensor_filter_custom.h
+ * @date 01 Jun 2018
+ * @brief Custom tensor post-processing interface for NNStreamer suite for post-processing code developers.
+ * @see http://github.com/TO-BE-DETERMINED-SOON
+ * @see https://github.sec.samsung.net/STAR/nnstreamer
+ * @author MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * How To for NNdevelopers:
+ *
+ * 1. Define struct, "NNStreamer_custom", with the functions defined.
+ * 2. Compile as a shared object. (.so in Linux)
+ * 3. Use NNStreamer (tensor_filter framework=custom, model=FILEPATH_OF_YOUR_SO.so, ...)
+ *
+ * To Packagers:
+ *
+ * This file is to be packaged as "devel" package for NN developers.
+ */
+#ifndef __NNS_TENSOR_FILTER_CUSTOM_H__
+#define __NNS_TENSOR_FILTER_CUSTOM_H__
+
+#include <stdint.h>
+
+/**
+ * @brief A function that is called before calling other functions.
+ * @return The returned pointer will be passed to other functions as "private_data".
+ */
+typedef void *(*NNS_custom_init_func)(void);
+
+/**
+ * @brief A function that is called after calling other functions, when it's ready to close.
+ * @param[in] private_data If you have allocated *private_data at init, free it here.
+ */
+typedef void (*NNS_custom_exit_func)(void *private_data);
+
+/**
+ * @brief Get input tensor type.
+ * @param[in] private_data The pointer returned by NNStreamer_custom_exit.
+ * @param[out] inputDimension uint32_t[NNS_TENSOR_RANK_LIMIT]
+ * @param[out] type Type of each element in the input tensor
+ */
+typedef int (*NNS_custom_get_input_dimension)(void *private_data,
+ uint32_t *inputDimension, tensor_type *type);
+
+/**
+ * @brief Get output tensor type.
+ * @param[in] private_data The pointer returned by NNStreamer_custom_exit.
+ * @param[out] outputDimension uint32_t[NNS_TENSOR_RANK_LIMIT]
+ * @param[out] type Type of each element in the output tensor
+ */
+typedef int (*NNS_custom_get_output_dimension)(void *private_data,
+ uint32_t *outputDimension, tensor_type *type);
+
+/**
+ * @brief Invoke the "main function".
+ * @param[in] private_data The pointer returned by NNStreamer_custom_exit.
+ * @param[in] inputPtr pointer to input tensor, size = dim1 x dim2 x dim3 x dim4 x typesize, allocated by caller
+ * @param[in] inputPtr pointer to output tensor, size = dim1 x dim2 x dim3 x dim4 x typesize, allocated by caller
+ */
+typedef int (*NNS_custom_invoke)(void *private_data,
+ void *inputPtr, void *outputPtr);
+
+/**
+ * @brief Custom Filter Class
+ *
+ * Note that exery function pointer is MANDATORY!
+ */
+struct _NNStreamer_custom_class {
+ NNS_custom_init_func initfunc;
+ NNS_custom_exit_func exitfunc;
+ NNS_custom_get_input_dimension getInputDim;
+ NNS_custom_get_output_dimension getOutputDim;
+ NNS_custom_invoke invoke;
+};
+typedef struct _NNStreamer_custom_class NNStreamer_custom_class;
+extern NNStreamer_custom_class *NNStreamer_custom;
+
+#endif /*__NNS_TENSOR_FILTER_CUSTOM_H__*/