[Android] custom-filter and amcsrc for native build
authorJaeyun <jy1210.jung@samsung.com>
Tue, 14 Jan 2020 11:31:28 +0000 (20:31 +0900)
committerMyungJoo Ham <myungjoo.ham@samsung.com>
Thu, 23 Jan 2020 01:30:39 +0000 (10:30 +0900)
register custom-filter and amcsrc for native build.

Signed-off-by: Jaeyun Jung <jy1210.jung@samsung.com>
api/android/api/src/androidTest/java/org/nnsuite/nnstreamer/APITestPipeline.java
api/android/api/src/main/jni/Android-nnstreamer.mk
api/android/api/src/main/jni/Android.mk
api/android/api/src/main/jni/nnstreamer-native-api.c
api/android/build-android-lib.sh
ext/nnstreamer/tensor_filter/tensor_filter_cpp.cc
gst/nnstreamer/tensor_filter/tensor_filter_custom.c
gst/nnstreamer/tensor_filter/tensor_filter_custom_easy.c
jni/nnstreamer.mk

index 6c88d93..6eb9d4b 100644 (file)
@@ -1,5 +1,6 @@
 package org.nnsuite.nnstreamer;
 
+import android.os.Environment;
 import android.support.test.rule.GrantPermissionRule;
 import android.support.test.runner.AndroidJUnit4;
 
@@ -751,4 +752,72 @@ public class APITestPipeline {
             /* expected */
         }
     }
+
+    @Test
+    public void testAMCsrc() {
+        String root = Environment.getExternalStorageDirectory().getAbsolutePath();
+        String media = root + "/nnstreamer/test/test_video.mp4";
+
+        String desc = "amcsrc location=" + media + " ! " +
+                "videoconvert ! videoscale ! video/x-raw,format=RGB,width=320,height=240 ! " +
+                "tensor_converter ! tensor_sink name=sinkx";
+
+        try (Pipeline pipe = new Pipeline(desc)) {
+            /* register sink callback */
+            pipe.registerSinkCallback("sinkx", new Pipeline.NewDataCallback() {
+                @Override
+                public void onNewDataReceived(TensorsData data) {
+                    if (data == null || data.getTensorsCount() != 1) {
+                        mInvalidState = true;
+                        return;
+                    }
+
+                    TensorsInfo info = data.getTensorsInfo();
+
+                    if (info == null || info.getTensorsCount() != 1) {
+                        mInvalidState = true;
+                    } else {
+                        ByteBuffer output = data.getTensorData(0);
+
+                        if (!APITestCommon.isValidBuffer(output, 230400)) {
+                            mInvalidState = true;
+                        }
+                    }
+
+                    mReceived++;
+                }
+            });
+
+            /* start pipeline */
+            pipe.start();
+
+            /* sleep 2 seconds to invoke */
+            Thread.sleep(2000);
+
+            /* stop pipeline */
+            pipe.stop();
+
+            /* check received data from sink */
+            assertFalse(mInvalidState);
+            assertTrue(mReceived > 0);
+
+            /* sleep 1 second and restart */
+            Thread.sleep(1000);
+            mReceived = 0;
+
+            pipe.start();
+
+            /* sleep 2 seconds to invoke */
+            Thread.sleep(2000);
+
+            /* stop pipeline */
+            pipe.stop();
+
+            /* check received data from sink */
+            assertFalse(mInvalidState);
+            assertTrue(mReceived > 0);
+        } catch (Exception e) {
+            fail();
+        }
+    }
 }
index 30e0fa2..d2ee946 100644 (file)
@@ -17,6 +17,8 @@ NNSTREAMER_SRC_FILES := \
     $(NNSTREAMER_COMMON_SRCS) \
     $(NNSTREAMER_PLUGINS_SRCS) \
     $(NNSTREAMER_CAPI_SRCS) \
+    $(NNSTREAMER_SOURCE_AMC_SRCS) \
+    $(NNSTREAMER_FILTER_CPP_SRCS) \
     $(NNSTREAMER_FILTER_TFLITE_SRCS) \
     $(NNSTREAMER_DECODER_BB_SRCS) \
     $(NNSTREAMER_DECODER_DV_SRCS) \
index 5bbb2d9..5554b34 100644 (file)
@@ -52,7 +52,7 @@ LOCAL_CFLAGS += -O2 -DVERSION=\"$(NNSTREAMER_VERSION)\"
 LOCAL_C_INCLUDES := $(NNSTREAMER_INCLUDES) $(NNSTREAMER_CAPI_INCLUDES)
 LOCAL_STATIC_LIBRARIES := nnstreamer tensorflow-lite cpufeatures
 LOCAL_SHARED_LIBRARIES := gstreamer_android
-LOCAL_LDLIBS := -llog -landroid
+LOCAL_LDLIBS := -llog -landroid -lmediandk
 
 ifeq ($(ENABLE_SNAP), true)
 LOCAL_CFLAGS += -DENABLE_SNAP=1
index ffce950..5688d78 100644 (file)
 
 /* nnstreamer plugins and sub-plugins declaration */
 GST_PLUGIN_STATIC_DECLARE (nnstreamer);
+GST_PLUGIN_STATIC_DECLARE (amcsrc);
+extern void init_filter_cpp (void);
+extern void init_filter_custom (void);
+extern void init_filter_custom_easy (void);
 extern void init_filter_tflite (void);
 #if defined (ENABLE_SNAP)
 extern void init_filter_snap (void);
@@ -36,6 +40,11 @@ extern void init_pose (void);
 extern void init_is (void);
 
 /**
+ * @brief Global lock for native functions.
+ */
+G_LOCK_DEFINE_STATIC (nns_native_lock);
+
+/**
  * @brief Attach thread with Java VM.
  */
 static JNIEnv *
@@ -562,32 +571,49 @@ nns_get_nnfw_type (jint fw_type, ml_nnfw_type_e * nnfw)
 jboolean
 nnstreamer_native_initialize (void)
 {
+  jboolean result = JNI_FALSE;
+  static gboolean nns_is_initilaized = FALSE;
+
   nns_logi ("Called native initialize.");
 
+  G_LOCK (nns_native_lock);
+
   if (!gst_is_initialized ()) {
     nns_loge ("GStreamer is not initialized.");
-    return JNI_FALSE;
+    goto done;
   }
 
-  /* register nnstreamer plugins */
-  GST_PLUGIN_STATIC_REGISTER (nnstreamer);
+  if (nns_is_initilaized == FALSE) {
+    /* register nnstreamer plugins */
+    GST_PLUGIN_STATIC_REGISTER (nnstreamer);
 
-  /* tensor-filter sub-plugin for tensorflow-lite */
-  init_filter_tflite ();
+    /* Android MediaCodec */
+    GST_PLUGIN_STATIC_REGISTER (amcsrc);
 
+    /* tensor-filter sub-plugins */
+    init_filter_cpp ();
+    init_filter_custom ();
+    init_filter_custom_easy ();
+    init_filter_tflite ();
 #if defined (ENABLE_SNAP)
-  /* tensor-filter sub-plugin for snap */
-  init_filter_snap ();
+    init_filter_snap ();
 #endif
 
-  /* tensor-decoder sub-plugins */
-  init_dv ();
-  init_bb ();
-  init_il ();
-  init_pose ();
-  init_is ();
+    /* tensor-decoder sub-plugins */
+    init_dv ();
+    init_bb ();
+    init_il ();
+    init_pose ();
+    init_is ();
 
-  return JNI_TRUE;
+    nns_is_initilaized = TRUE;
+  }
+
+  result = JNI_TRUE;
+
+done:
+  G_UNLOCK (nns_native_lock);
+  return result;
 }
 
 /**
index 2129500..9c92edc 100644 (file)
@@ -227,7 +227,10 @@ if [[ -e $nnstreamer_android_api_lib ]]; then
     cp $NNSTREAMER_ROOT/gst/nnstreamer/nnstreamer_plugin_api_converter.h main/jni/nnstreamer/include
     cp $NNSTREAMER_ROOT/gst/nnstreamer/nnstreamer_plugin_api_decoder.h main/jni/nnstreamer/include
     cp $NNSTREAMER_ROOT/gst/nnstreamer/nnstreamer_plugin_api_filter.h main/jni/nnstreamer/include
+    cp $NNSTREAMER_ROOT/gst/nnstreamer/tensor_filter_custom.h main/jni/nnstreamer/include
+    cp $NNSTREAMER_ROOT/gst/nnstreamer/tensor_filter_custom_easy.h main/jni/nnstreamer/include
     cp $NNSTREAMER_ROOT/gst/nnstreamer/tensor_typedef.h main/jni/nnstreamer/include
+    cp $NNSTREAMER_ROOT/ext/nnstreamer/tensor_filter/tensor_filter_cpp.h main/jni/nnstreamer/include
 
     nnstreamer_native_files="$nnstreamer_lib_name-native-$today.zip"
     zip -r $nnstreamer_native_files main
index f49f8cc..e10f810 100644 (file)
@@ -38,9 +38,6 @@
 
 #include "tensor_filter_cpp.h"
 
-void init_filter_cpp (void) __attribute__ ((constructor));
-void fini_filter_cpp (void) __attribute__ ((destructor));
-
 std::unordered_map<std::string, tensor_filter_cpp*> tensor_filter_cpp::filters;
 
 static gchar filter_subplugin_cpp[] = "cpp";
@@ -236,6 +233,10 @@ void tensor_filter_cpp::close (const GstTensorFilterProperties *prop, void **pri
   cpp->ref_count--;
 }
 
+G_BEGIN_DECLS
+void init_filter_cpp (void) __attribute__ ((constructor));
+void fini_filter_cpp (void) __attribute__ ((destructor));
+
 /** @brief Initialize this object for tensor_filter subplugin runtime register */
 void
 init_filter_cpp (void)
@@ -249,3 +250,4 @@ fini_filter_cpp (void)
 {
   nnstreamer_filter_exit (NNS_support_cpp.name);
 }
+G_END_DECLS
index 9e868a9..98afa5b 100644 (file)
@@ -34,8 +34,8 @@
 #include "nnstreamer_plugin_api_filter.h"
 #include "nnstreamer_conf.h"
 
-static void init_filter_custom (void) __attribute__ ((constructor));
-static void fini_filter_custom (void) __attribute__ ((destructor));
+void init_filter_custom (void) __attribute__ ((constructor));
+void fini_filter_custom (void) __attribute__ ((destructor));
 
 static GstTensorFilterFramework NNS_support_custom;
 
@@ -261,14 +261,14 @@ static GstTensorFilterFramework NNS_support_custom = {
 };
 
 /** @brief Initialize this object for tensor_filter subplugin runtime register */
-static void
+void
 init_filter_custom (void)
 {
   nnstreamer_filter_probe (&NNS_support_custom);
 }
 
 /** @brief Destruct the subplugin */
-static void
+void
 fini_filter_custom (void)
 {
   nnstreamer_filter_exit (NNS_support_custom.name);
index ac853a3..e99676b 100644 (file)
@@ -28,8 +28,8 @@
 #include <nnstreamer_plugin_api.h>
 #include <nnstreamer_subplugin.h>
 
-static void init_filter_custom (void) __attribute__ ((constructor));
-static void fini_filter_custom (void) __attribute__ ((destructor));
+void init_filter_custom_easy (void) __attribute__ ((constructor));
+void fini_filter_custom_easy (void) __attribute__ ((destructor));
 
 /**
  * @brief internal_data
@@ -180,15 +180,15 @@ static GstTensorFilterFramework NNS_support_custom_easy = {
 };
 
 /** @brief Initialize this object for tensor_filter subplugin runtime register */
-static void
-init_filter_custom (void)
+void
+init_filter_custom_easy (void)
 {
   nnstreamer_filter_probe (&NNS_support_custom_easy);
 }
 
 /** @brief Destruct the subplugin */
-static void
-fini_filter_custom (void)
+void
+fini_filter_custom_easy (void)
 {
   nnstreamer_filter_exit (NNS_support_custom_easy.name);
 }
index bcbbc48..060e8d6 100644 (file)
@@ -34,6 +34,7 @@ NNSTREAMER_PLUGINS_SRCS := \
     $(NNSTREAMER_GST_HOME)/tensor_filter/tensor_filter.c \
     $(NNSTREAMER_GST_HOME)/tensor_filter/tensor_filter_common.c \
     $(NNSTREAMER_GST_HOME)/tensor_filter/tensor_filter_custom.c \
+    $(NNSTREAMER_GST_HOME)/tensor_filter/tensor_filter_custom_easy.c \
     $(NNSTREAMER_GST_HOME)/tensor_merge/gsttensormerge.c \
     $(NNSTREAMER_GST_HOME)/tensor_mux/gsttensormux.c \
     $(NNSTREAMER_GST_HOME)/tensor_repo/tensor_repo.c \
@@ -55,6 +56,15 @@ NNSTREAMER_CAPI_SRCS := \
     $(NNSTREAMER_CAPI_HOME)/src/nnstreamer-capi-util.c \
     $(NNSTREAMER_CAPI_HOME)/src/tensor_filter_single.c
 
+# source AMC (Android MediaCodec)
+NNSTREAMER_SOURCE_AMC_SRCS := \
+    $(NNSTREAMER_EXT_HOME)/android_source/gstamcsrc.c \
+    $(NNSTREAMER_EXT_HOME)/android_source/gstamcsrc_looper.cc
+
+# filter cpp
+NNSTREAMER_FILTER_CPP_SRCS := \
+    $(NNSTREAMER_EXT_HOME)/tensor_filter/tensor_filter_cpp.cc
+
 # filter tensorflow
 NNSTREAMER_FILTER_TF_SRCS := \
     $(NNSTREAMER_EXT_HOME)/tensor_filter/tensor_filter_tensorflow.cc