androidcamera: Add support for using DexLoader with Embeded GstAhcCallback.jar
authorYouness Alaoui <youness.alaoui@collabora.co.uk>
Tue, 23 Oct 2012 13:01:50 +0000 (09:01 -0400)
committerNicolas Dufresne <nicolas.dufresne@collabora.com>
Thu, 21 Jan 2016 17:44:39 +0000 (12:44 -0500)
sys/androidcamera/Makefile.am
sys/androidcamera/com/gstreamer/GstAhcCallback.java [new file with mode: 0644]
sys/androidcamera/gst-android-hardware-camera.c
sys/androidcamera/gstahccallback.h [new file with mode: 0644]

index 9d446e8..bea49c1 100644 (file)
@@ -6,14 +6,18 @@ libgstandroidcamera_la_SOURCES = \
        gst-android-hardware-camera.c \
        gst-android-graphics-surfacetexture.c \
        gst-android-graphics-imageformat.c \
-       gstahcsrc.c
+       gstahcsrc.c \
+       gstahccallback.c
+
+JAVA_SOURCE = com/gstreamer/GstAhcCallback.java
 
 noinst_HEADERS = \
        gst-dvm.h \
+       gstahcsrc.h \
+       gstahccallback.h \
        gst-android-hardware-camera.h \
        gst-android-graphics-surfacetexture.h \
-       gst-android-graphics-imageformat.h \
-       gstahcsrc.h
+       gst-android-graphics-imageformat.h
 
 libgstandroidcamera_la_CFLAGS = \
        $(GST_PLUGINS_BASE_CFLAGS) \
@@ -27,7 +31,33 @@ libgstandroidcamera_la_LIBADD = \
 libgstandroidcamera_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 libgstandroidcamera_la_LIBTOOLFLAGS = --tag=disable-static
 
-EXTRA_DIST = $(VIDEO_BASE_CLASSES_C) $(VIDEO_BASE_CLASSES_H)
+EXTRA_DIST = $(JAVA_SOURCE)
+CLEANFILES = gstahccallback.c
+
+if HAVE_ANDROID_SDK
+gstahccallback.c: $(JAVA_SOURCE)
+       @echo "  JAVAC $(JAVA_SOURCE)"
+       @$(JAVAC) -target 1.6 -source 1.6 -nowarn -classpath $(ANDROID_SDK_DIR)/platforms/android-14/android.jar $(JAVA_SOURCE)
+       @echo "  DEX $(JAVA_SOURCE:.java=.class)"
+       @$(ANDROID_SDK_DIR)/platform-tools/dx --dex --output GstAhcCallback.jar $(JAVA_SOURCE:.java=.class)
+       @echo "  GEN $@"
+       @echo "#include \"gstahccallback.h\"" > $@
+       @echo "" >> $@
+       @echo "const static guint8 jar_file[] = {" >> $@
+       @hexdump -v -e '"  "' -e '8/1 "0x%02x, "' -e '"\n"'  GstAhcCallback.jar | sed 's/0x  ,//g' >> $@
+       @echo "};" >> $@
+       @echo "" >> $@
+       @echo "const guint8 *gst_ahc_callback_jar = jar_file;" >> $@
+       @echo "const gsize gst_ahc_callback_jar_size = sizeof(jar_file);" >> $@
+       @rm -f GstAhcCallback.jar
+else
+gstahccallback.c:
+       @echo "  GEN $@"
+       @echo "#include \"gstahccallback.h\"" > $@
+       @echo "" >> $@
+       @echo "const guint8 *gst_ahc_callback_jar = NULL;" >> $@
+       @echo "const gsize gst_ahc_callback_jar_size = 0;" >> $@
+endif
 
 Android.mk: Makefile.am $(BUILT_SOURCES)
        androgenizer \
diff --git a/sys/androidcamera/com/gstreamer/GstAhcCallback.java b/sys/androidcamera/com/gstreamer/GstAhcCallback.java
new file mode 100644 (file)
index 0000000..45ce0e8
--- /dev/null
@@ -0,0 +1,28 @@
+package com.gstreamer;
+
+import android.hardware.Camera;
+
+public class GstAhcCallback implements Camera.PreviewCallback, Camera.ErrorCallback {
+    public long mUserData;
+    public long mCallback;
+
+    public static native void gst_ah_camera_on_preview_frame(byte[] data, Camera camera,
+                                                             long callback, long user_data);
+    public static native void gst_ah_camera_on_error(int error, Camera camera,
+                                                     long callback, long user_data);
+
+    public GstAhcCallback(long callback, long user_data) {
+        mCallback = callback;
+        mUserData = user_data;
+    }
+
+    @Override
+    public void onPreviewFrame(byte[] data, Camera camera) {
+        gst_ah_camera_on_preview_frame(data, camera, mCallback, mUserData);
+    }
+
+    @Override
+    public void onError(int error, Camera camera) {
+        gst_ah_camera_on_error(error, camera, mCallback, mUserData);
+    }
+}
index 853504a..3e1f697 100644 (file)
@@ -24,7 +24,9 @@
 #endif
 
 #include "gst-dvm.h"
+#include "gstahccallback.h"
 #include "gst-android-hardware-camera.h"
+#include "stdio.h"
 
 static struct
 {
@@ -238,8 +240,102 @@ _init_classes (void)
   GST_DVM_GET_METHOD (java_lang_integer, intValue, "()I");
 
   /* com.gstreamer.GstAhcCallback */
-  GST_DVM_GET_CLASS (com_gstreamer_gstahccallback,
-      "com/gstreamer/GstAhcCallback");
+  if (gst_ahc_callback_jar) {
+    jclass dex_loader = NULL;
+    gchar *path = g_strdup_printf ("%s/GstAhcCallback.jar", g_getenv ("TMP"));
+    FILE *fd = fopen (path, "wb");
+
+    GST_WARNING ("Found embedded GstAhcCallback.jar, trying to load dynamically"
+        "from %s", path);
+    if (fd) {
+      if (fwrite (gst_ahc_callback_jar, gst_ahc_callback_jar_size, 1, fd) == 1) {
+        dex_loader = (*env)->FindClass (env, "dalvik/system/DexClassLoader");
+        (*env)->ExceptionClear (env);
+      }
+      fclose (fd);
+    }
+
+    if (dex_loader) {
+      jmethodID constructor;
+      jmethodID load_class;
+
+      constructor = (*env)->GetMethodID (env, dex_loader, "<init>",
+          "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;"
+          "Ljava/lang/ClassLoader;)V");
+      load_class = (*env)->GetMethodID (env, dex_loader, "loadClass",
+          "(Ljava/lang/String;)Ljava/lang/Class;");
+      (*env)->ExceptionClear (env);
+      if (constructor && load_class) {
+        jstring dex_path = NULL;
+        jstring optimized_directory = NULL;
+
+        dex_path = (*env)->NewStringUTF (env, path);
+        optimized_directory = (*env)->NewStringUTF (env, g_getenv ("TMP"));
+        (*env)->ExceptionClear (env);
+        if (dex_path && optimized_directory) {
+          jobject loader;
+          jobject parent = NULL;
+          jclass klass;
+
+          klass = (*env)->FindClass (env, "java/lang/Class");
+          (*env)->ExceptionClear (env);
+          if (klass) {
+            jmethodID get_class_loader;
+
+            get_class_loader = (*env)->GetMethodID (env, klass,
+                "getClassLoader", "()Ljava/lang/ClassLoader;");
+            (*env)->ExceptionClear (env);
+            if (get_class_loader) {
+              parent = (*env)->CallObjectMethod (env, klass, get_class_loader);
+              (*env)->ExceptionClear (env);
+            }
+            (*env)->DeleteLocalRef (env, klass);
+          }
+          loader = (*env)->NewObject (env, dex_loader, constructor, dex_path,
+              optimized_directory, NULL, parent);
+          (*env)->ExceptionClear (env);
+          if (loader) {
+            jstring class_name = NULL;
+
+            class_name = (*env)->NewStringUTF (env,
+                "com/gstreamer/GstAhcCallback");
+            (*env)->ExceptionClear (env);
+            if (class_name) {
+              jclass temp;
+
+              temp = (*env)->CallObjectMethod (env, loader, load_class,
+                  class_name);
+              (*env)->ExceptionClear (env);
+              if (temp) {
+
+                GST_WARNING ("Successfully loaded embedded GstAhcCallback");
+                com_gstreamer_gstahccallback.klass = (*env)->NewGlobalRef (env,
+                    temp);
+                (*env)->DeleteLocalRef (env, temp);
+              }
+              (*env)->DeleteLocalRef (env, class_name);
+            }
+            (*env)->DeleteLocalRef (env, loader);
+          }
+          if (parent)
+            (*env)->DeleteLocalRef (env, parent);
+        }
+        if (dex_path)
+          (*env)->DeleteLocalRef (env, dex_path);
+        if (optimized_directory)
+          (*env)->DeleteLocalRef (env, optimized_directory);
+      }
+      (*env)->DeleteLocalRef (env, dex_loader);
+      g_free (path);
+    }
+  } else {
+    GST_WARNING ("Did not find embedded GstAhcCallback.jar, fallback to"
+        " FindClass");
+  }
+  if (!com_gstreamer_gstahccallback.klass) {
+    GST_DVM_GET_CLASS (com_gstreamer_gstahccallback,
+        "com/gstreamer/GstAhcCallback");
+  }
   GST_DVM_GET_CONSTRUCTOR (com_gstreamer_gstahccallback, constructor, "(JJ)V");
 
   if ((*env)->RegisterNatives (env, com_gstreamer_gstahccallback.klass,
diff --git a/sys/androidcamera/gstahccallback.h b/sys/androidcamera/gstahccallback.h
new file mode 100644 (file)
index 0000000..df4d6d2
--- /dev/null
@@ -0,0 +1,33 @@
+/* com/gstreamer/GstAhcCallbac.java wrapper header
+ *
+ * Copyright (C) 2012, Cisco Systems, Inc.
+ *   Author: Youness Alaoui <youness.alaoui@collabora.co.uk>
+ *
+ * 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.
+ */
+
+#ifndef __GST_AHC_CALLBACK_H__
+#define __GST_AHC_CALLBACK_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+extern const guint8 *gst_ahc_callback_jar;
+extern const gsize gst_ahc_callback_jar_size;
+
+G_END_DECLS
+#endif /* __GST_AHC_CALLBACK_H__ */