FOREACH(flag ${pkgs_CFALGS})
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
ENDFOREACH(flag)
-SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall -Werror -fPIC")
-SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS} -Wall -Werror -fPIC")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall -Werror -fPIC -g")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS} -Wall -Werror -fPIC -g")
# Provide common data
ADD_LIBRARY(common STATIC common/tensor_common.c)
ADD_SUBDIRECTORY(tensor_converter)
ADD_SUBDIRECTORY(tensor_filter)
ADD_SUBDIRECTORY(tensor_decoder)
+ADD_SUBDIRECTORY(nnstreamer_example)
CONFIGURE_FILE(nnstreamer.pc.in nnstreamer.pc @ONLY)
+# For nnstreamer users (gst app developers using via gstreamer API)
INSTALL(FILES include/tensor_typedef.h
DESTINATION ${INCLUDE_INSTALL_DIR}/nnstreamer
)
+
+# For nnstreamer custom filter developers
+INSTALL(FILES include/tensor_common.h include/tensor_filter_custom.h
+ DESTINATION ${INCLUDE_INSTALL_DIR}/nnstreamer
+ )
+
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/nnstreamer.pc
DESTINATION ${LIB_INSTALL_DIR}/pkgconfig
)
#define __NNS_TENSOR_FILTER_CUSTOM_H__
#include <stdint.h>
+#include <tensor_common.h>
/**
* @brief A function that is called before calling other functions.
Version: @VERSION@
Requires:
Libs:
-Cflags: -I${includedir}
+Cflags: -I${includedir}/nnstreamer
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+ADD_SUBDIRECTORY(custom_example_passthrough)
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+ADD_LIBRARY(nnstreamer_customfilter_passthrough SHARED nnstreamer_customfilter_example_passthrough.c)
+
+TARGET_LINK_LIBRARIES(nnstreamer_customfilter_passthrough ${pkgs_LIBRARIES})
+TARGET_INCLUDE_DIRECTORIES(nnstreamer_customfilter_passthrough PUBLIC ${pkgs_INCLUDE_DIRS})
+TARGET_COMPILE_OPTIONS(nnstreamer_customfilter_passthrough PUBLIC ${pkgs_CFLAGS_OTHER})
+
+INSTALL(TARGETS nnstreamer_customfilter_passthrough
+ RUNTIME DESTINATION ${EXEC_PREFIX}
+ LIBRARY DESTINATION ${LIB_INSTALL_DIR}
+ ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
+ )
--- /dev/null
+/**
+ * NNStreamer Custom Filter Example 1. Pass-Through
+ * Copyright (C) 2018 MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * LICENSE: Apache-2.0
+ *
+ * @file nnstreamer_customfilter_example_passthrough.c
+ * @date 11 Jun 2018
+ * @brief Custom NNStreamer Filter Example 1. "Pass-Through"
+ * @author MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * As a test, before #71 is resolved, this will support "3x280x40" uint8 tensors.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <tensor_filter_custom.h>
+
+#define D1 (3)
+#define D2 (280)
+#define D3 (40)
+
+typedef struct _pt_data {
+ uint32_t id; /***< Just for testing */
+ uint32_t dim[NNS_TENSOR_RANK_LIMIT];
+ tensor_type type;
+} pt_data;
+
+static void *pt_init() {
+ pt_data *data = (pt_data *)malloc(sizeof (pt_data));
+ int i;
+
+ data->id = 0;
+ data->dim[0] = D1;
+ data->dim[1] = D2;
+ data->dim[2] = D3;
+ for (i = 3; i < NNS_TENSOR_RANK_LIMIT; i++)
+ data->dim[i] = 1;
+ data->type = _NNS_UINT8;
+
+ return data;
+}
+
+static void pt_exit(void *private_data) {
+ pt_data *data = private_data;
+ g_assert(data);
+ free(data);
+}
+
+static int get_inputDim(void *private_data, uint32_t inputDimension[NNS_TENSOR_RANK_LIMIT], tensor_type *type) {
+ pt_data *data = private_data;
+ int i;
+
+ g_assert(data);
+ g_assert(NNS_TENSOR_RANK_LIMIT >= 3);
+ inputDimension[0] = D1;
+ inputDimension[1] = D2;
+ inputDimension[2] = D3;
+ for (i = 3; i < NNS_TENSOR_RANK_LIMIT; i++)
+ inputDimension[i] = 1;
+ *type = _NNS_UINT8;
+ return 0;
+ return 0;
+}
+
+static int get_outputDim(void *private_data, uint32_t outputDimension[NNS_TENSOR_RANK_LIMIT], tensor_type *type) {
+ pt_data *data = private_data;
+ int i;
+
+ g_assert(data);
+ g_assert(NNS_TENSOR_RANK_LIMIT >= 3);
+ outputDimension[0] = D1;
+ outputDimension[1] = D2;
+ outputDimension[2] = D3;
+ for (i = 3; i < NNS_TENSOR_RANK_LIMIT; i++)
+ outputDimension[i] = 1;
+ *type = _NNS_UINT8;
+ return 0;
+}
+
+static int pt_invoke(void *private_data, uint8_t *inptr, uint8_t *outptr) {
+ pt_data *data = private_data;
+ size_t size;
+
+ g_assert(data);
+ g_assert(inptr);
+ g_assert(outptr);
+
+ size = get_tensor_element_count(data->dim) * tensor_element_size[data->type];
+
+ g_assert(inptr != outptr);
+ memcpy(outptr, inptr, size);
+
+ return 0;
+}
+
+static NNStreamer_custom_class NNStreamer_custom_body = {
+ .initfunc = pt_init,
+ .exitfunc = pt_exit,
+ .getInputDim = get_inputDim,
+ .getOutputDim = get_outputDim,
+ .invoke = pt_invoke,
+};
+
+/* The dyn-loaded object */
+NNStreamer_custom_class *NNStreamer_custom = &NNStreamer_custom_body;
+
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
)
-INSTALL(FILES tensor_filter_custom.h
- DESTINATION ${INCLUDE_INSTALL_DIR}/nnstreamer
- )
return 1;
}
- ptr = g_new0(internal_data, 0); /* Fill Zero! */
+ ptr = g_new0(internal_data, 1); /* Fill Zero! */
filter->privateData = ptr;
ptr->parent = filter;
}
dlerror();
- ptr->methods = (NNStreamer_custom_class *) dlsym(ptr->handle, "NNStreamer_custom");
+ 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);
return -1;
}
+ g_assert(ptr->methods->initfunc);
ptr->customFW_private_data = ptr->methods->initfunc();
return 0;
}
--- /dev/null
+#!/usr/bin/env bash
+
+failed=0
+sopath=""
+
+./testcase01.sh $sopath || failed=1
+
+echo ""
+echo ""
+echo "=================================================="
+echo " Test for tensor_filter_custom"
+echo "=================================================="
+if [ "$failed" -eq "0" ]
+then
+ echo SUCCESS
+ echo ""
+ exit 0
+else
+ echo FAILED
+ echo ""
+ exit -1
+fi
--- /dev/null
+#!/usr/bin/env bash
+
+##
+# Copyright (C) 2018 Samsung Electronics
+# License: Apache-2.0
+#
+# @file testcase01.sh
+# @brief Test tensor_converter for testcase 01
+# @author MyungJoo Ham <myungjoo.ham@samsung.com>
+# @dependency cmp
+
+if [ $# -eq 0 ]
+then
+ PATH_TO_PLUGIN="$PWD/../../build/tensor_converter:$PWD/../../build/tensor_filter"
+else
+ PATH_TO_PLUGIN="$1"
+fi
+
+PATH_TO_MODEL="../../build/nnstreamer_example/custom_example_passthrough/libnnstreamer_customfilter_passthrough.so"
+
+failed=0
+
+# Generate one frame only (num-buffers=1)
+
+gst-launch-1.0 -v --gst-debug=GST_CAPS:4 --gst-plugin-path=${PATH_TO_PLUGIN} videotestsrc num-buffers=1 ! video/x-raw,format=RGB,width=280,height=40,framerate=0/1 ! videoconvert ! video/x-raw, format=RGB ! tensor_converter silent=FALSE ! tee name=t ! queue ! tensor_filter debug=TRUE framework='custom' model="${PATH_TO_MODEL}" input='3:280:40' inputtype='uint8' output='3:280:40' outputtype='uint8' ! filesink location="testcase01.passthrough.log" sync=true t. ! queue ! filesink location="testcase01.direct.log" sync=true || failed=1
+
+# Check the results (test.rgb.log, test.bgrx.log)
+cmp testcase01.passthrough.log testcase01.direct.log || failed=1
+
+if [ "$failed" -eq "0" ]
+then
+ echo Testcase 01: SUCCESS
+ exit 0
+else
+ echo Testcase 01: FAILED
+ exit -1
+fi