Adding Dalvik Virtual Machine routines and macros
authorYouness Alaoui <youness.alaoui@collabora.co.uk>
Wed, 17 Oct 2012 23:42:59 +0000 (19:42 -0400)
committerNicolas Dufresne <nicolas.dufresne@collabora.com>
Thu, 21 Jan 2016 17:11:14 +0000 (12:11 -0500)
sys/androidcamera/Makefile.am
sys/androidcamera/gst-dvm.c [new file with mode: 0644]
sys/androidcamera/gst-dvm.h [new file with mode: 0644]

index b10a327..daf9ca2 100644 (file)
@@ -19,7 +19,8 @@ libgstandroidmedia_la_SOURCES = \
        video/video.c \
        video/gstvideodecoder.c \
        video/gstvideoencoder.c \
-       video/gstvideoutils.c
+       video/gstvideoutils.c \
+       gst-dvm.c
 
 noinst_HEADERS = \
        gstamc.h \
@@ -29,7 +30,8 @@ noinst_HEADERS = \
        video/video.h \
        video/gstvideodecoder.h \
        video/gstvideoencoder.h \
-       video/gstvideoutils.h
+       video/gstvideoutils.h \
+       gst-dvm.h
 
 if !HAVE_GST_0_10_37
 libgstandroidmedia_la_SOURCES += $(VIDEO_BASE_CLASSES_C)
diff --git a/sys/androidcamera/gst-dvm.c b/sys/androidcamera/gst-dvm.c
new file mode 100644 (file)
index 0000000..df2209b
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2012, Collabora Ltd.
+ *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ * 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 Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gst-dvm.h"
+
+#include <pthread.h>
+
+GST_DEBUG_CATEGORY (gst_dvm_debug);
+#define GST_CAT_DEFAULT gst_dvm_debug
+
+static GModule *java_module;
+static jint (*get_created_java_vms) (JavaVM ** vmBuf, jsize bufLen,
+    jsize * nVMs);
+static jint (*create_java_vm) (JavaVM ** p_vm, JNIEnv ** p_env, void *vm_args);
+static JavaVM *java_vm = NULL;
+static gboolean started_java_vm = FALSE;
+
+static pthread_key_t current_jni_env;
+
+static JNIEnv *
+gst_dvm_attach_current_thread (void)
+{
+  JNIEnv *env;
+  JavaVMAttachArgs args;
+
+  GST_DEBUG ("Attaching thread %p", g_thread_self ());
+  args.version = JNI_VERSION_1_6;
+  args.name = NULL;
+  args.group = NULL;
+
+  if ((*java_vm)->AttachCurrentThread (java_vm, &env, &args) < 0) {
+    GST_ERROR ("Failed to attach current thread");
+    return NULL;
+  }
+
+  return env;
+}
+
+static void
+gst_dvm_detach_current_thread (void *env)
+{
+  GST_DEBUG ("Detaching thread %p", g_thread_self ());
+  (*java_vm)->DetachCurrentThread (java_vm);
+}
+
+JNIEnv *
+gst_dvm_get_env (void)
+{
+  JNIEnv *env;
+
+  if ((env = pthread_getspecific (current_jni_env)) == NULL) {
+    env = gst_dvm_attach_current_thread ();
+    pthread_setspecific (current_jni_env, env);
+  }
+
+  return env;
+}
+
+gboolean
+gst_dvm_init (void)
+{
+  jsize n_vms;
+
+  GST_DEBUG_CATEGORY_INIT (gst_dvm_debug, "dvm", 0, "DVM");
+
+  pthread_key_create (&current_jni_env, gst_dvm_detach_current_thread);
+
+  java_module = g_module_open ("libdvm", G_MODULE_BIND_LOCAL);
+  if (!java_module)
+    goto load_failed;
+
+  if (!g_module_symbol (java_module, "JNI_CreateJavaVM",
+          (gpointer *) & create_java_vm))
+    goto symbol_error;
+
+  if (!g_module_symbol (java_module, "JNI_GetCreatedJavaVMs",
+          (gpointer *) & get_created_java_vms))
+    goto symbol_error;
+
+  n_vms = 0;
+  if (get_created_java_vms (&java_vm, 1, &n_vms) < 0)
+    goto get_created_failed;
+
+  if (n_vms > 0) {
+    GST_DEBUG ("Successfully got existing Java VM %p", java_vm);
+  } else {
+    JNIEnv *env;
+    JavaVMInitArgs vm_args;
+    JavaVMOption options[4];
+
+    options[0].optionString = "-verbose:jni";
+    options[1].optionString = "-verbose:gc";
+    options[2].optionString = "-Xcheck:jni";
+    options[3].optionString = "-Xdebug";
+
+    vm_args.version = JNI_VERSION_1_4;
+    vm_args.options = options;
+    vm_args.nOptions = 4;
+    vm_args.ignoreUnrecognized = JNI_TRUE;
+    if (create_java_vm (&java_vm, &env, &vm_args) < 0)
+      goto create_failed;
+    GST_DEBUG ("Successfully created Java VM %p", java_vm);
+
+    started_java_vm = TRUE;
+  }
+
+  return java_vm != NULL;
+
+load_failed:
+  {
+    GST_ERROR ("Failed to load libdvm: %s", g_module_error ());
+    return FALSE;
+  }
+symbol_error:
+  {
+    GST_ERROR ("Failed to locate required JNI symbols in libdvm: %s",
+        g_module_error ());
+    g_module_close (java_module);
+    java_module = NULL;
+    return FALSE;
+  }
+get_created_failed:
+  {
+    GST_ERROR ("Failed to get already created VMs");
+    g_module_close (java_module);
+    java_module = NULL;
+    return FALSE;
+  }
+create_failed:
+  {
+    GST_ERROR ("Failed to create a Java VM");
+    g_module_close (java_module);
+    java_module = NULL;
+    return FALSE;
+  }
+}
diff --git a/sys/androidcamera/gst-dvm.h b/sys/androidcamera/gst-dvm.h
new file mode 100644 (file)
index 0000000..4cef357
--- /dev/null
@@ -0,0 +1,103 @@
+/* Dalvik Virtual Machine helper functions
+ *
+ * Copyright (C) 2012, Collabora Ltd.
+ *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ * 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 Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifndef __GST_DVM_H__
+#define __GST_DVM_H__
+
+#include <gst/gst.h>
+#include <jni.h>
+
+#define GST_DVM_GET_CLASS(k, name) {                                    \
+    jclass tmp;                                                         \
+                                                                        \
+    tmp = (*env)->FindClass (env, name);                                \
+    if (!tmp) {                                                         \
+      (*env)->ExceptionClear (env);                                     \
+      GST_ERROR ("Failed to get class %s", name);                       \
+      return FALSE;                                                     \
+    }                                                                   \
+                                                                        \
+    k.klass = (*env)->NewGlobalRef (env, tmp);                          \
+    if (!k.klass) {                                                     \
+      (*env)->ExceptionClear (env);                                     \
+      (*env)->DeleteLocalRef (env, tmp);                                \
+      GST_ERROR ("Failed to get %s class global reference", name);      \
+      return FALSE;                                                     \
+    }                                                                   \
+    (*env)->DeleteLocalRef (env, tmp);                                  \
+  }
+#define GST_DVM_GET_STATIC_METHOD(k, method, signature)                 \
+  k.method = (*env)->GetStaticMethodID (env, k.klass, #method,          \
+      signature);                                                       \
+  if (!k.method) {                                                      \
+    (*env)->ExceptionClear (env);                                       \
+    GST_ERROR ("Failed to get static method %s for %s", #method, #k);   \
+    return FALSE;                                                       \
+  }
+
+#define GST_DVM_GET_METHOD(k, method, signature)                        \
+  k.method = (*env)->GetMethodID (env, k.klass, #method, signature);    \
+  if (!k.method) {                                                      \
+    (*env)->ExceptionClear (env);                                       \
+    GST_ERROR ("Failed to get method %s for %s", #method, #k);          \
+    return FALSE;                                                       \
+  }
+
+#define GST_DVM_GET_CONSTRUCTOR(k, field, signature)                    \
+  k.field = (*env)->GetMethodID (env, k.klass, "<init>",  signature);   \
+  if (!k.field) {                                                       \
+    (*env)->ExceptionClear (env);                                       \
+    GST_ERROR ("Failed to get constructor %s for %s", #field, #k);      \
+    return FALSE;                                                       \
+  }
+
+#define GST_DVM_GET_FIELD(k, field, signature)                          \
+  k.field = (*env)->GetFieldID (env, k.klass, #field, signature);       \
+  if (!k.field) {                                                       \
+    (*env)->ExceptionClear (env);                                       \
+    GST_ERROR ("Failed to get field %s for %s", #field, #k);            \
+    return FALSE;                                                       \
+  }
+
+#define GST_DVM_GET_CONSTANT(k, field, type, signature) {               \
+    jfieldID id;                                                        \
+                                                                        \
+    id = (*env)->GetStaticFieldID (env, k.klass, #field, signature);    \
+    if (!id) {                                                          \
+      (*env)->ExceptionClear (env);                                     \
+      GST_ERROR ("Failed to get static field %s for %s", #field, #k);   \
+      return FALSE;                                                     \
+    }                                                                   \
+    k.field = (*env)->GetStatic##type##Field (env, k.klass, id);        \
+    if ((*env)->ExceptionCheck (env)) {                                 \
+      (*env)->ExceptionClear (env);                                     \
+      GST_ERROR ("Failed to get " #type " constant %s", #field);        \
+      return FALSE;                                                     \
+    }                                                                   \
+  }
+
+
+JNIEnv *gst_dvm_get_env (void);
+gboolean gst_dvm_init (void);
+
+#endif /* __GST_DVM_H__ */