Decode tensors to octet stream.
If tensor format is flexible, remove the header.
Signed-off-by: gichan <gichan2.jang@samsung.com>
/usr/lib/nnstreamer/decoders/libnnstreamer_decoder_image_segment.so
/usr/lib/nnstreamer/decoders/libnnstreamer_decoder_image_labeling.so
/usr/lib/nnstreamer/decoders/libnnstreamer_decoder_direct_video.so
+/usr/lib/nnstreamer/decoders/libnnstreamer_decoder_octet_stream.so
/usr/lib/nnstreamer/filters/libnnstreamer_filter_cpp.so
/usr/lib/*/libnnstreamer.so
/usr/lib/*/gstreamer-1.0/libnnstreamer.so
install_dir: nnstreamer_libdir
)
endif
+
+# octet stream
+decoder_sub_octet_stream_sources = [
+ 'tensordec-octetstream.c',
+ 'tensordecutil.c'
+]
+
+nnstreamer_decoder_octet_stream_sources = []
+foreach s : decoder_sub_octet_stream_sources
+ nnstreamer_decoder_octet_stream_sources += join_paths(meson.current_source_dir(), s)
+endforeach
+
+shared_library('nnstreamer_decoder_octet_stream',
+ nnstreamer_decoder_octet_stream_sources,
+ dependencies: [nnstreamer_dep, glib_dep, gst_dep],
+ install: true,
+ install_dir: decoder_subplugin_install_dir
+)
+static_library('nnstreamer_decoder_octet_stream',
+ nnstreamer_decoder_octet_stream_sources,
+ dependencies: [nnstreamer_dep, glib_dep, gst_dep],
+ install: true,
+ install_dir: nnstreamer_libdir
+)
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/**
+ * GStreamer/NNStreamer Tensor-Decoder
+ * Copyright (C) 2021 Gichan Jang <gichan2.jang@samsung.com>
+ */
+/**
+ * @file tensordec-octetstream.c
+ * @date 04 Nov 2021
+ * @brief NNStreamer tensor-decoder subplugin, "octet stream",
+ * which converts tensors to octet stream.
+ * @see https://github.com/nnstreamer/nnstreamer
+ * @author Gichan Jang <gichan2.jang@samsung.com>
+ * @bug No known bugs except for NYI items
+ *
+ */
+
+#include <string.h>
+#include <glib.h>
+#include <nnstreamer_plugin_api_decoder.h>
+#include <nnstreamer_plugin_api.h>
+#include <nnstreamer_log.h>
+#include <nnstreamer_util.h>
+#include "tensordecutil.h"
+
+void init_os (void) __attribute__ ((constructor));
+void fini_os (void) __attribute__ ((destructor));
+
+#define OCTET_CAPS_STR "application/octet-stream"
+
+/** @brief tensordec-plugin's GstTensorDecoderDef callback */
+static int
+os_init (void **pdata)
+{
+ *pdata = NULL;
+ return TRUE;
+}
+
+/** @brief tensordec-plugin's GstTensorDecoderDef callback */
+static void
+os_exit (void **pdata)
+{
+ UNUSED (pdata);
+ return;
+}
+
+/** @brief tensordec-plugin's GstTensorDecoderDef callback */
+static int
+os_setOption (void **pdata, int opNum, const char *param)
+{
+ UNUSED (pdata);
+ UNUSED (opNum);
+ UNUSED (param);
+ return TRUE;
+}
+
+/** @brief tensordec-plugin's GstTensorDecoderDef callback */
+static GstCaps *
+os_getOutCaps (void **pdata, const GstTensorsConfig * config)
+{
+ GstCaps *caps;
+ UNUSED (pdata);
+
+ caps = gst_caps_from_string (OCTET_CAPS_STR);
+ setFramerateFromConfig (caps, config);
+ return caps;
+}
+
+/** @brief tensordec-plugin's GstTensorDecoderDef callback */
+static GstFlowReturn
+os_decode (void **pdata, const GstTensorsConfig * config,
+ const GstTensorMemory * input, GstBuffer * outbuf)
+{
+ guint i;
+ gboolean is_flexible;
+ GstTensorMetaInfo meta;
+ gpointer mem_data;
+ UNUSED (pdata);
+
+ if (!config || !input || !outbuf) {
+ ml_loge ("NULL parameter is passed to tensor_decoder::octet_stream");
+ return GST_FLOW_ERROR;
+ }
+ is_flexible = gst_tensors_config_is_flexible (config);
+
+ for (i = 0; i < config->info.num_tensors; i++) {
+ gsize offset = 0, data_size = 0;
+ GstMemory *mem = NULL;
+
+ if (is_flexible) {
+ gst_tensor_meta_info_parse_header (&meta, input[i].data);
+ offset = gst_tensor_meta_info_get_header_size (&meta);
+ data_size = gst_tensor_meta_info_get_data_size (&meta);
+ } else {
+ data_size = gst_tensors_info_get_size (&config->info, i);
+ }
+ mem_data = _g_memdup ((guint8 *) input[i].data + offset, data_size);
+ mem = gst_memory_new_wrapped ((GstMemoryFlags) 0, mem_data, data_size,
+ 0, data_size, NULL, g_free);
+ gst_buffer_append_memory (outbuf, mem);
+ }
+
+ return GST_FLOW_OK;
+}
+
+static gchar decoder_subplugin_octet_stream[] = "octet_stream";
+
+/** @brief octet stream tensordec-plugin GstTensorDecoderDef instance */
+static GstTensorDecoderDef octetSTream = {
+ .modename = decoder_subplugin_octet_stream,
+ .init = os_init,
+ .exit = os_exit,
+ .setOption = os_setOption,
+ .getOutCaps = os_getOutCaps,
+ .getTransformSize = NULL,
+ .decode = os_decode
+};
+
+/** @brief Initialize this object for tensordec-plugin */
+void
+init_os (void)
+{
+ nnstreamer_decoder_probe (&octetSTream);
+}
+
+/** @brief Destruct this object for tensordec-plugin */
+void
+fini_os (void)
+{
+ nnstreamer_decoder_exit (octetSTream.modename);
+}
include $(BUILD_SHARED_LIBRARY)
+include $(CLEAR_VARS)
+LOCAL_MODULE := nnstreamer_decoder_octet_stream
+LOCAL_SRC_FILES := $(NNSTREAMER_DECODER_OS_SRCS)
+LOCAL_C_INCLUDES := $(NNSTREAMER_INCLUDES)
+
+LOCAL_SHARED_LIBRARIES := $(GST_BUILDING_BLOCK_LIST) nnstreamer
+
+LOCAL_ARM_NEON := true
+LOCAL_CFLAGS += -O0 -DVERSION=\"$(NNSTREAMER_VERSION)\"
+LOCAL_CXXFLAGS += -std=c++11 -DVERSION=\"$(NNSTREAMER_VERSION)\"
+LOCAL_CFLAGS += -pthread -fopenmp
+
+LOCAL_C_INCLUDES += $(GST_HEADERS_COMMON)
+
+include $(BUILD_SHARED_LIBRARY)
+
$(call import-module, android/cpufeatures)
$(NNSTREAMER_EXT_HOME)/tensor_decoder/tensordec-imagesegment.c \
$(NNSTREAMER_EXT_HOME)/tensor_decoder/tensordecutil.c
+# decoder octet-stream
+NNSTREAMER_DECODER_OS_SRCS := \
+ $(NNSTREAMER_EXT_HOME)/tensor_decoder/tensordec-octetstream.c \
+ $(NNSTREAMER_EXT_HOME)/tensor_decoder/tensordecutil.c
+
# gstreamer join element
NNSTREAMER_JOIN_SRCS := \
$(NNSTREAMER_ROOT)/gst/join/gstjoin.c
%{_prefix}/lib/nnstreamer/decoders/libnnstreamer_decoder_image_segment.so
%{_prefix}/lib/nnstreamer/decoders/libnnstreamer_decoder_image_labeling.so
%{_prefix}/lib/nnstreamer/decoders/libnnstreamer_decoder_direct_video.so
+%{_prefix}/lib/nnstreamer/decoders/libnnstreamer_decoder_octet_stream.so
%{_prefix}/lib/nnstreamer/filters/libnnstreamer_filter_cpp.so
%{gstlibdir}/libnnstreamer.so
%{_libdir}/libnnstreamer.so
--- /dev/null
+#!/usr/bin/env bash
+##
+## SPDX-License-Identifier: LGPL-2.1-only
+##
+## @file runTest.sh
+## @author Gichan Jang <gichan2.jang@samsung.com>
+## @date Nov 08 2021
+## @brief SSAT Test Cases for octet stream subplugin of tensor decoder
+##
+if [[ "$SSATAPILOADED" != "1" ]]; then
+ SILENT=0
+ INDEPENDENT=1
+ search="ssat-api.sh"
+ source $search
+ printf "${Blue}Independent Mode${NC}"
+fi
+
+# This is compatible with SSAT (https://github.com/myungjoo/SSAT)
+testInit $1
+
+PATH_TO_PLUGIN="../../build"
+
+# Test static tensor
+gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} \
+ videotestsrc num-buffers=3 pattern=13 ! video/x-raw,format=RGB,width=640,height=480,framerate=5/1 ! \
+ tee name=t ! queue ! tensor_converter ! multifilesink location=octet_raw_1_%1d.log \
+ t. ! queue ! tensor_converter ! tensor_decoder mode=octet_stream ! application/octet-stream ! multifilesink location=octet_decoded_1_%1d.log" 1 0 0 $PERFORMANCE
+callCompareTest octet_raw_1_0.log octet_decoded_1_0.log 1-0 "tensor_decoder::octet_stream compare test 1-0" 0 0
+callCompareTest octet_raw_1_1.log octet_decoded_1_1.log 1-1 "tensor_decoder::octet_stream compare test 1-1" 0 0
+callCompareTest octet_raw_1_2.log octet_decoded_1_2.log 1-2 "tensor_decoder::octet_stream compare test 1-2" 0 0
+
+# Test flexible tensor
+gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} \
+ videotestsrc num-buffers=3 pattern=13 ! video/x-raw,format=RGB,width=640,height=480,framerate=5/1 ! \
+ tee name=t ! queue ! tensor_converter ! multifilesink location=octet_raw_2_%1d.log \
+ t. ! queue ! tensor_converter ! other/tensors,format=flexible ! tensor_decoder mode=octet_stream ! application/octet-stream,framerate=5/1 ! multifilesink location=octet_decoded_2_%1d.log" 2 0 0 $PERFORMANCE
+callCompareTest octet_raw_2_0.log octet_decoded_2_0.log 2-0 "tensor_decoder::octet_stream compare test 2-0" 0 0
+callCompareTest octet_raw_2_1.log octet_decoded_2_1.log 2-1 "tensor_decoder::octet_stream compare test 2-1" 0 0
+callCompareTest octet_raw_2_2.log octet_decoded_2_2.log 2-2 "tensor_decoder::octet_stream compare test 2-2" 0 0
+
+# Test static tensors
+gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} \
+ videotestsrc num-buffers=3 pattern=13 ! video/x-raw,format=RGB,width=640,height=480,framerate=5/1 ! tensor_converter ! raw_tensor.sink_0 \
+ videotestsrc num-buffers=3 pattern=18 ! video/x-raw,format=RGB,width=320,height=240,framerate=5/1 ! tensor_converter ! raw_tensor.sink_1 \
+ tensor_mux name=raw_tensor ! \
+ tee name=t ! queue ! multifilesink location=octet_raw_3_%1d.log \
+ t. ! queue ! tensor_decoder mode=octet_stream ! application/octet-stream ! multifilesink location=octet_decoded_3_%1d.log" 3 0 0 $PERFORMANCE
+callCompareTest octet_raw_3_0.log octet_decoded_3_0.log 3-0 "tensor_decoder::octet_stream compare test 3-0" 0 0
+callCompareTest octet_raw_3_1.log octet_decoded_3_1.log 3-1 "tensor_decoder::octet_stream compare test 3-1" 0 0
+callCompareTest octet_raw_3_2.log octet_decoded_3_2.log 3-2 "tensor_decoder::octet_stream compare test 3-2" 0 0
+
+# Test flexible tensors
+gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} \
+ videotestsrc num-buffers=3 pattern=13 ! video/x-raw,format=RGB,width=640,height=480,framerate=5/1 ! tensor_converter ! other/tensors,format=flexible ! raw_tensor.sink_0 \
+ videotestsrc num-buffers=3 pattern=18 ! video/x-raw,format=RGB,width=320,height=240,framerate=5/1 ! tensor_converter ! other/tensors,format=flexible ! raw_tensor.sink_1 \
+ tensor_mux name=raw_tensor ! \
+ tee name=t ! queue ! multifilesink location=octet_raw_4_%1d.log \
+ t. ! queue ! tensor_decoder mode=octet_stream ! application/octet-stream ! multifilesink location=octet_decoded_4_%1d.log" 4 0 0 $PERFORMANCE
+# Compare with the results of test 3 (static tensors)
+callCompareTest octet_raw_3_0.log octet_decoded_4_0.log 4-0 "tensor_decoder::octet_stream compare test 4-0" 0 0
+callCompareTest octet_raw_3_1.log octet_decoded_4_1.log 4-1 "tensor_decoder::octet_stream compare test 4-1" 0 0
+callCompareTest octet_raw_3_2.log octet_decoded_4_2.log 4-2 "tensor_decoder::octet_stream compare test 4-2" 0 0
+
+rm *.log
+
+report