diff --git a/sys/androidcamera/Makefile.am b/sys/androidcamera/Makefile.am index 9d446e8e1b..bea49c16fd 100644 --- a/sys/androidcamera/Makefile.am +++ b/sys/androidcamera/Makefile.am @@ -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 index 0000000000..45ce0e8550 --- /dev/null +++ b/sys/androidcamera/com/gstreamer/GstAhcCallback.java @@ -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); + } +} diff --git a/sys/androidcamera/gst-android-hardware-camera.c b/sys/androidcamera/gst-android-hardware-camera.c index 853504a232..3e1f697ca0 100644 --- a/sys/androidcamera/gst-android-hardware-camera.c +++ b/sys/androidcamera/gst-android-hardware-camera.c @@ -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, "", + "(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 index 0000000000..df4d6d20bf --- /dev/null +++ b/sys/androidcamera/gstahccallback.h @@ -0,0 +1,33 @@ +/* com/gstreamer/GstAhcCallbac.java wrapper header + * + * Copyright (C) 2012, Cisco Systems, Inc. + * Author: Youness Alaoui + * + * 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 + +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__ */