diff --git a/docs/plugins/inspect/plugin-androidcamera.xml b/docs/plugins/inspect/plugin-androidcamera.xml new file mode 100644 index 0000000000..c9417ca974 --- /dev/null +++ b/docs/plugins/inspect/plugin-androidcamera.xml @@ -0,0 +1,28 @@ + + androidcamera + Capture from Android cameras + ../../sys/androidcamera/.libs/libgstandroidcamera.so + libgstandroidcamera.so + 0.10.22.1 + LGPL + gst-plugins-bad + GStreamer Bad Plug-ins git + Unknown package origin + + + ahcsrc + Android Camera Source + Source/Video + Reads frames from android.hardware.Camera class into buffers + Youness Alaoui <youness.alaoui@collabora.co.uk> + + + src + source + always +
video/x-raw-yuv, format=(fourcc) { YV12 , YUY2 , NV21 , NV16 }, width=(int) [ 1, 2147483647 ], height=(int) [ 1, 2147483647 ], framerate=(fraction) [ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)16, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, width=(int) [ 1, 2147483647 ], height=(int) [ 1, 2147483647 ], framerate=(fraction) [ 0/1, 2147483647/1 ]
+
+
+
+
+
diff --git a/sys/androidmedia/Makefile.am b/sys/androidmedia/Makefile.am index a04b0ade57..7ad9b6e936 100644 --- a/sys/androidmedia/Makefile.am +++ b/sys/androidmedia/Makefile.am @@ -1,22 +1,30 @@ plugin_LTLIBRARIES = libgstandroidmedia.la libgstandroidmedia_la_SOURCES = \ - gstamc.c \ + gstahcsrc.c \ gstamcaudiodec.c \ - gstamcvideodec.c \ - gstamcvideoenc.c \ + gstamc.c \ gstamcsurface.c \ gstamcsurfacetexture.c \ + gstamcvideodec.c \ + gstamcvideoenc.c \ + gst-android-graphics-imageformat.c \ + gst-android-graphics-surfacetexture.c \ + gst-android-hardware-camera.c \ gstjniutils.c noinst_HEADERS = \ - gstamc.h \ - gstamc-constants.h \ + gstahcsrc.h \ gstamcaudiodec.h \ - gstamcvideodec.h \ - gstamcvideoenc.h \ + gstamc-constants.h \ + gstamc.h \ gstamcsurface.h \ gstamcsurfacetexture.h \ + gstamcvideodec.h \ + gstamcvideoenc.h \ + gst-android-graphics-imageformat.h \ + gst-android-graphics-surfacetexture.h \ + gst-android-hardware-camera.h \ gstjniutils.h libgstandroidmedia_la_CFLAGS = \ @@ -25,8 +33,11 @@ libgstandroidmedia_la_CFLAGS = \ $(GST_PLUGINS_BASE_CFLAGS) \ $(GST_BASE_CFLAGS) \ $(GST_CFLAGS) \ - $(ORC_CFLAGS) + $(ORC_CFLAGS) \ + -DGST_USE_UNSTABLE_API + libgstandroidmedia_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-$(GST_API_VERSION).la \ $(top_builddir)/gst-libs/gst/gl/libgstgl-$(GST_API_VERSION).la \ $(GST_PLUGINS_BASE_LIBS) \ -lgstaudio-@GST_API_VERSION@ \ @@ -39,4 +50,6 @@ libgstandroidmedia_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstandroidmedia_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS) androidmedia_java_classesdir = $(datadir)/gst-android/ndk-build/androidmedia/ -androidmedia_java_classes_DATA = org/freedesktop/gstreamer/androidmedia/GstAmcOnFrameAvailableListener.java +androidmedia_java_classes_DATA = \ + org/freedesktop/gstreamer/androidmedia/GstAhcCallback.java \ + org/freedesktop/gstreamer/androidmedia/GstAmcOnFrameAvailableListener.java diff --git a/sys/androidmedia/gst-android-graphics-imageformat.c b/sys/androidmedia/gst-android-graphics-imageformat.c new file mode 100644 index 0000000000..a382e5827b --- /dev/null +++ b/sys/androidmedia/gst-android-graphics-imageformat.c @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2012, Collabora Ltd. + * Copyright (C) 2012, Cisco Systems, Inc. + * Author: Youness Alaoui + * + * Copyright (C) 2015, Collabora Ltd. + * Author: Justin Kim + * + * 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 "gstjniutils.h" + +#include "gst-android-graphics-imageformat.h" + + +static struct +{ + jclass klass; + jmethodID get_bits_per_pixel; + jint JPEG; + jint NV16; + jint NV21; + jint RGB_565; + jint UNKNOWN; + jint YUY2; + jint YV12; +} android_graphics_imageformat = { +0}; + +gint ImageFormat_JPEG; +gint ImageFormat_NV16; +gint ImageFormat_NV21; +gint ImageFormat_RGB_565; +gint ImageFormat_UNKNOWN; +gint ImageFormat_YUY2; +gint ImageFormat_YV12; + +static gboolean +_init_classes (void) +{ + JNIEnv *env; + + jfieldID fieldID; + jclass klass; + + GError *err = NULL; + + env = gst_amc_jni_get_env (); + + /* android.graphics.ImageFormat */ + klass = android_graphics_imageformat.klass = + gst_amc_jni_get_class (env, &err, "android/graphics/ImageFormat"); + + if (err) + goto failed; + + android_graphics_imageformat.get_bits_per_pixel = + gst_amc_jni_get_static_method_id (env, &err, klass, + "getBitsPerPixel", "(I)I"); + + if (err) + goto failed; + + fieldID = gst_amc_jni_get_static_field_id (env, &err, klass, "JPEG", "I"); + if (err) + goto failed; + if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, + &android_graphics_imageformat.JPEG)) + goto failed; + ImageFormat_JPEG = android_graphics_imageformat.JPEG; + + fieldID = gst_amc_jni_get_static_field_id (env, &err, klass, "NV16", "I"); + if (err) + goto failed; + if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, + &android_graphics_imageformat.NV16)) + goto failed; + ImageFormat_NV16 = android_graphics_imageformat.NV16; + + fieldID = gst_amc_jni_get_static_field_id (env, &err, klass, "NV21", "I"); + if (err) + goto failed; + if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, + &android_graphics_imageformat.NV21)) + goto failed; + ImageFormat_NV21 = android_graphics_imageformat.NV21; + + fieldID = gst_amc_jni_get_static_field_id (env, &err, klass, "RGB_565", "I"); + if (err) + goto failed; + if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, + &android_graphics_imageformat.RGB_565)) + goto failed; + ImageFormat_RGB_565 = android_graphics_imageformat.RGB_565; + + fieldID = gst_amc_jni_get_static_field_id (env, &err, klass, "UNKNOWN", "I"); + if (err) + goto failed; + if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, + &android_graphics_imageformat.UNKNOWN)) + goto failed; + ImageFormat_UNKNOWN = android_graphics_imageformat.UNKNOWN; + + fieldID = gst_amc_jni_get_static_field_id (env, &err, klass, "YUY2", "I"); + if (err) + goto failed; + if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, + &android_graphics_imageformat.YUY2)) + goto failed; + ImageFormat_YUY2 = android_graphics_imageformat.YUY2; + + fieldID = gst_amc_jni_get_static_field_id (env, &err, klass, "YV12", "I"); + if (err) + goto failed; + if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, + &android_graphics_imageformat.YV12)) + goto failed; + ImageFormat_YV12 = android_graphics_imageformat.YV12; + + return TRUE; + +failed: + if (err) { + GST_ERROR ("Failed to get android.graphics.ImageFormat class: %s", + err->message); + g_clear_error (&err); + } + + return FALSE; +} + +gboolean +gst_android_graphics_imageformat_init (void) +{ + if (!_init_classes ()) { + gst_android_graphics_imageformat_deinit (); + return FALSE; + } + + return TRUE; +} + +void +gst_android_graphics_imageformat_deinit (void) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + if (android_graphics_imageformat.klass) + (*env)->DeleteGlobalRef (env, android_graphics_imageformat.klass); + android_graphics_imageformat.klass = NULL; +} + +/* android.graphics.ImageFormat */ +gint +gst_ag_imageformat_get_bits_per_pixel (gint format) +{ + JNIEnv *env; + GError *err = NULL; + + jclass klass = android_graphics_imageformat.klass; + + jint bpp = 0; + + env = gst_amc_jni_get_env (); + + if (!gst_amc_jni_call_static_int_method (env, &err, + klass, android_graphics_imageformat.get_bits_per_pixel, &bpp, format)) { + GST_ERROR ("Failed to get android.graphics.ImageFormat class: %s", + err->message); + g_clear_error (&err); + } + + return bpp; +} diff --git a/sys/androidmedia/gst-android-graphics-imageformat.h b/sys/androidmedia/gst-android-graphics-imageformat.h new file mode 100644 index 0000000000..aff218b955 --- /dev/null +++ b/sys/androidmedia/gst-android-graphics-imageformat.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2012, Collabora Ltd. + * Copyright (C) 2012, Cisco Systems, Inc. + * Author: Youness Alaoui + * + * Copyright (C) 2015, Collabora Ltd. + * Author: Justin Kim + * + * 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_ANDROID_GRAPHICS_IMAGEFORMAT_H__ +#define __GST_ANDROID_GRAPHICS_IMAGEFORMAT_H__ + +#include + +G_BEGIN_DECLS + +/* android.graphics.ImageFormat */ +extern gint ImageFormat_JPEG; +extern gint ImageFormat_NV16; +extern gint ImageFormat_NV21; +extern gint ImageFormat_RGB_565; +extern gint ImageFormat_UNKNOWN; +extern gint ImageFormat_YUY2; +extern gint ImageFormat_YV12; + +gboolean gst_android_graphics_imageformat_init (void); +void gst_android_graphics_imageformat_deinit (void); + +gint gst_ag_imageformat_get_bits_per_pixel (gint format); + +G_END_DECLS + +#endif /* __GST_ANDROID_GRAPHICS_IMAGEFORMAT_H__ */ + diff --git a/sys/androidmedia/gst-android-graphics-surfacetexture.c b/sys/androidmedia/gst-android-graphics-surfacetexture.c new file mode 100644 index 0000000000..84993a8c87 --- /dev/null +++ b/sys/androidmedia/gst-android-graphics-surfacetexture.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2012, Collabora Ltd. + * Copyright (C) 2012, Cisco Systems, Inc. + * Author: Youness Alaoui + * + * Copyright (C) 2015, Collabora Ltd. + * Author: Justin Kim + * + * 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 "gstjniutils.h" + +#include "gst-android-graphics-surfacetexture.h" + +static struct +{ + jclass klass; + jmethodID constructor; + jmethodID release; +} android_graphics_surfacetexture = { +0}; + +static gboolean +_init_classes (void) +{ + JNIEnv *env; + GError *err = NULL; + + env = gst_amc_jni_get_env (); + + /* android.graphics.SurfaceTexture */ + android_graphics_surfacetexture.klass = + gst_amc_jni_get_class (env, &err, "android/graphics/SurfaceTexture"); + + if (!android_graphics_surfacetexture.klass) { + GST_ERROR ("Failed to get android.graphics.SurfaceTexture class: %s", + err->message); + g_clear_error (&err); + return FALSE; + } + + android_graphics_surfacetexture.constructor = + gst_amc_jni_get_method_id (env, &err, + android_graphics_surfacetexture.klass, "", "(I)V"); + android_graphics_surfacetexture.release = + gst_amc_jni_get_method_id (env, &err, + android_graphics_surfacetexture.klass, "release", "()V"); + + return TRUE; +} + +gboolean +gst_android_graphics_surfacetexture_init (void) +{ + if (!_init_classes ()) { + gst_android_graphics_surfacetexture_deinit (); + return FALSE; + } + + return TRUE; +} + +void +gst_android_graphics_surfacetexture_deinit (void) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + if (android_graphics_surfacetexture.klass) + (*env)->DeleteGlobalRef (env, android_graphics_surfacetexture.klass); + android_graphics_surfacetexture.klass = NULL; +} + +/* android.graphics.SurfaceTexture */ +GstAGSurfaceTexture * +gst_ag_surfacetexture_new (gint texture_id) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jobject object = NULL; + GstAGSurfaceTexture *tex = NULL; + + object = (*env)->NewObject (env, + android_graphics_surfacetexture.klass, + android_graphics_surfacetexture.constructor, texture_id); + if ((*env)->ExceptionCheck (env) || !object) { + GST_ERROR ("Failed to call Java method"); + (*env)->ExceptionClear (env); + return NULL; + } + + tex = g_slice_new0 (GstAGSurfaceTexture); + tex->object = (*env)->NewGlobalRef (env, object); + if (!tex->object) { + GST_ERROR ("Failed to create global reference"); + (*env)->ExceptionClear (env); + g_slice_free (GstAGSurfaceTexture, tex); + tex = NULL; + } + (*env)->DeleteLocalRef (env, object); + + return tex; +} + +void +gst_ag_surfacetexture_release (GstAGSurfaceTexture * self) +{ + JNIEnv *env; + GError *err = NULL; + + env = gst_amc_jni_get_env (); + + if (!gst_amc_jni_call_void_method (env, &err, self->object, + android_graphics_surfacetexture.release)) { + GST_ERROR ("Failed to call release: %s", err->message); + g_clear_error (&err); + } + +} + +void +gst_ag_surfacetexture_free (GstAGSurfaceTexture * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + (*env)->DeleteGlobalRef (env, self->object); + g_slice_free (GstAGSurfaceTexture, self); +} diff --git a/sys/androidmedia/gst-android-graphics-surfacetexture.h b/sys/androidmedia/gst-android-graphics-surfacetexture.h new file mode 100644 index 0000000000..3bb80ca5d4 --- /dev/null +++ b/sys/androidmedia/gst-android-graphics-surfacetexture.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2012, Collabora Ltd. + * Copyright (C) 2012, Cisco Systems, Inc. + * Author: Youness Alaoui + * + * Copyright (C) 2015, Collabora Ltd. + * Author: Justin Kim + * + * 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_ANDROID_GRAPHICS_SURFACETEXTURE_H__ +#define __GST_ANDROID_GRAPHICS_SURFACETEXTURE_H__ + +#include +#include + + +G_BEGIN_DECLS + +typedef struct _GstAGSurfaceTexture GstAGSurfaceTexture; + +/* android.graphics.SurfaceTexture */ +struct _GstAGSurfaceTexture { + /* < private > */ + jobject object; /* global reference */ +}; + + +gboolean gst_android_graphics_surfacetexture_init (void); +void gst_android_graphics_surfacetexture_deinit (void); + +/* android.graphics.SurfaceTexture */ +GstAGSurfaceTexture *gst_ag_surfacetexture_new (gint texture_id); +void gst_ag_surfacetexture_release (GstAGSurfaceTexture *self); +void gst_ag_surfacetexture_free (GstAGSurfaceTexture *self); + +G_END_DECLS + +#endif /* __GST_ANDROID_GRAPHICS_SURFACETEXTURE_H__ */ + diff --git a/sys/androidmedia/gst-android-hardware-camera.c b/sys/androidmedia/gst-android-hardware-camera.c new file mode 100644 index 0000000000..f28fe03252 --- /dev/null +++ b/sys/androidmedia/gst-android-hardware-camera.c @@ -0,0 +1,3875 @@ +/* + * Copyright (C) 2012, Collabora Ltd. + * Copyright (C) 2012, Cisco Systems, Inc. + * Author: Youness Alaoui + * + * Copyright (C) 2015, Collabora Ltd. + * Author: Justin Kim + * + * 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 "gstjniutils.h" + +#include "gst-android-hardware-camera.h" +#include "stdio.h" + +GST_DEBUG_CATEGORY_STATIC (ahc_debug); +#define GST_CAT_DEFAULT ahc_debug + +#define GST_DVM_STATIC_CALL(error_statement, type, k, method, ...) \ + (*env)->CallStatic##type##Method (env, k.klass, k.method, ## __VA_ARGS__); \ + if ((*env)->ExceptionCheck (env)) { \ + GST_ERROR ("Failed to call Java method"); \ + (*env)->ExceptionDescribe (env); \ + (*env)->ExceptionClear (env); \ + error_statement; \ + } + +#define GST_DVM_CALL(error_statement, obj, type, k, method, ...) \ + (*env)->Call##type##Method (env, obj, k.method, ## __VA_ARGS__); \ + if ((*env)->ExceptionCheck (env)) { \ + GST_ERROR ("Failed to call Java method"); \ + (*env)->ExceptionDescribe (env); \ + (*env)->ExceptionClear (env); \ + error_statement; \ + } + + + +static struct +{ + jclass klass; + jmethodID addCallbackBuffer; + jmethodID autoFocus; + jmethodID cancelAutoFocus; + jmethodID getCameraInfo; + jmethodID getNumberOfCameras; + jmethodID getParameters; + jmethodID lock; + jmethodID open; + jmethodID reconnect; + jmethodID release; + jmethodID setErrorCallback; + jmethodID setParameters; + jmethodID setPreviewCallbackWithBuffer; + jmethodID setPreviewTexture; + jmethodID startPreview; + jmethodID startSmoothZoom; + jmethodID stopPreview; + jmethodID stopSmoothZoom; + jmethodID unlock; +} android_hardware_camera = { +0}; + +static struct +{ + jclass klass; + jmethodID constructor; + jfieldID facing; + jfieldID orientation; + jint CAMERA_FACING_BACK; + jint CAMERA_FACING_FRONT; +} android_hardware_camera_camerainfo = { +0}; + +gint CameraInfo_CAMERA_FACING_BACK; +gint CameraInfo_CAMERA_FACING_FRONT; + +static struct +{ + jclass klass; + jfieldID width; + jfieldID height; +} android_hardware_camera_size = { +0}; + +static struct +{ + jclass klass; + jmethodID flatten; + jmethodID getAntibanding; + jmethodID getColorEffect; + jmethodID getExposureCompensation; + jmethodID getExposureCompensationStep; + jmethodID getFlashMode; + jmethodID getFocalLength; + jmethodID getFocusMode; + jmethodID getHorizontalViewAngle; + jmethodID getMaxExposureCompensation; + jmethodID getMaxZoom; + jmethodID getMinExposureCompensation; + jmethodID getPreviewFormat; + jmethodID getPreviewFpsRange; + jmethodID getPreviewSize; + jmethodID getSceneMode; + jmethodID getSupportedAntibanding; + jmethodID getSupportedColorEffects; + jmethodID getSupportedFlashModes; + jmethodID getSupportedFocusModes; + jmethodID getSupportedPreviewFormats; + jmethodID getSupportedPreviewFpsRange; + jmethodID getSupportedPreviewSizes; + jmethodID getSupportedSceneModes; + jmethodID getSupportedWhiteBalance; + jmethodID getVerticalViewAngle; + jmethodID getVideoStabilization; + jmethodID getWhiteBalance; + jmethodID getZoom; + jmethodID getZoomRatios; + jmethodID isSmoothZoomSupported; + jmethodID isVideoStabilizationSupported; + jmethodID isZoomSupported; + jmethodID setAntibanding; + jmethodID setColorEffect; + jmethodID setExposureCompensation; + jmethodID setFlashMode; + jmethodID setFocusMode; + jmethodID setPreviewFormat; + jmethodID setPreviewFpsRange; + jmethodID setPreviewSize; + jmethodID setSceneMode; + jmethodID setVideoStabilization; + jmethodID setWhiteBalance; + jmethodID setZoom; + jmethodID unflatten; + jstring WHITE_BALANCE_AUTO; + jstring WHITE_BALANCE_INCANDESCENT; + jstring WHITE_BALANCE_FLUORESCENT; + jstring WHITE_BALANCE_WARM_FLUORESCENT; + jstring WHITE_BALANCE_DAYLIGHT; + jstring WHITE_BALANCE_CLOUDY_DAYLIGHT; + jstring WHITE_BALANCE_TWILIGHT; + jstring WHITE_BALANCE_SHADE; + jstring EFFECT_NONE; + jstring EFFECT_MONO; + jstring EFFECT_NEGATIVE; + jstring EFFECT_SOLARIZE; + jstring EFFECT_SEPIA; + jstring EFFECT_POSTERIZE; + jstring EFFECT_WHITEBOARD; + jstring EFFECT_BLACKBOARD; + jstring EFFECT_AQUA; + jstring ANTIBANDING_AUTO; + jstring ANTIBANDING_50HZ; + jstring ANTIBANDING_60HZ; + jstring ANTIBANDING_OFF; + jstring FLASH_MODE_OFF; + jstring FLASH_MODE_AUTO; + jstring FLASH_MODE_ON; + jstring FLASH_MODE_RED_EYE; + jstring FLASH_MODE_TORCH; + jstring SCENE_MODE_AUTO; + jstring SCENE_MODE_ACTION; + jstring SCENE_MODE_PORTRAIT; + jstring SCENE_MODE_LANDSCAPE; + jstring SCENE_MODE_NIGHT; + jstring SCENE_MODE_NIGHT_PORTRAIT; + jstring SCENE_MODE_THEATRE; + jstring SCENE_MODE_BEACH; + jstring SCENE_MODE_SNOW; + jstring SCENE_MODE_SUNSET; + jstring SCENE_MODE_STEADYPHOTO; + jstring SCENE_MODE_FIREWORKS; + jstring SCENE_MODE_SPORTS; + jstring SCENE_MODE_PARTY; + jstring SCENE_MODE_CANDLELIGHT; + jstring SCENE_MODE_BARCODE; + jstring FOCUS_MODE_AUTO; + jstring FOCUS_MODE_INFINITY; + jstring FOCUS_MODE_MACRO; + jstring FOCUS_MODE_FIXED; + jstring FOCUS_MODE_EDOF; + jstring FOCUS_MODE_CONTINUOUS_VIDEO; + jstring FOCUS_MODE_CONTINUOUS_PICTURE; +} android_hardware_camera_parameters = { +0}; + +const gchar *Parameters_WHITE_BALANCE_AUTO; +const gchar *Parameters_WHITE_BALANCE_INCANDESCENT; +const gchar *Parameters_WHITE_BALANCE_FLUORESCENT; +const gchar *Parameters_WHITE_BALANCE_WARM_FLUORESCENT; +const gchar *Parameters_WHITE_BALANCE_DAYLIGHT; +const gchar *Parameters_WHITE_BALANCE_CLOUDY_DAYLIGHT; +const gchar *Parameters_WHITE_BALANCE_TWILIGHT; +const gchar *Parameters_WHITE_BALANCE_SHADE; +const gchar *Parameters_EFFECT_NONE; +const gchar *Parameters_EFFECT_MONO; +const gchar *Parameters_EFFECT_NEGATIVE; +const gchar *Parameters_EFFECT_SOLARIZE; +const gchar *Parameters_EFFECT_SEPIA; +const gchar *Parameters_EFFECT_POSTERIZE; +const gchar *Parameters_EFFECT_WHITEBOARD; +const gchar *Parameters_EFFECT_BLACKBOARD; +const gchar *Parameters_EFFECT_AQUA; +const gchar *Parameters_ANTIBANDING_AUTO; +const gchar *Parameters_ANTIBANDING_50HZ; +const gchar *Parameters_ANTIBANDING_60HZ; +const gchar *Parameters_ANTIBANDING_OFF; +const gchar *Parameters_FLASH_MODE_OFF; +const gchar *Parameters_FLASH_MODE_AUTO; +const gchar *Parameters_FLASH_MODE_ON; +const gchar *Parameters_FLASH_MODE_RED_EYE; +const gchar *Parameters_FLASH_MODE_TORCH; +const gchar *Parameters_SCENE_MODE_AUTO; +const gchar *Parameters_SCENE_MODE_ACTION; +const gchar *Parameters_SCENE_MODE_PORTRAIT; +const gchar *Parameters_SCENE_MODE_LANDSCAPE; +const gchar *Parameters_SCENE_MODE_NIGHT; +const gchar *Parameters_SCENE_MODE_NIGHT_PORTRAIT; +const gchar *Parameters_SCENE_MODE_THEATRE; +const gchar *Parameters_SCENE_MODE_BEACH; +const gchar *Parameters_SCENE_MODE_SNOW; +const gchar *Parameters_SCENE_MODE_SUNSET; +const gchar *Parameters_SCENE_MODE_STEADYPHOTO; +const gchar *Parameters_SCENE_MODE_FIREWORKS; +const gchar *Parameters_SCENE_MODE_SPORTS; +const gchar *Parameters_SCENE_MODE_PARTY; +const gchar *Parameters_SCENE_MODE_CANDLELIGHT; +const gchar *Parameters_SCENE_MODE_BARCODE; +const gchar *Parameters_FOCUS_MODE_AUTO; +const gchar *Parameters_FOCUS_MODE_INFINITY; +const gchar *Parameters_FOCUS_MODE_MACRO; +const gchar *Parameters_FOCUS_MODE_FIXED; +const gchar *Parameters_FOCUS_MODE_EDOF; +const gchar *Parameters_FOCUS_MODE_CONTINUOUS_VIDEO; +const gchar *Parameters_FOCUS_MODE_CONTINUOUS_PICTURE; + +static struct +{ + jclass klass; + jmethodID iterator; +} java_util_list = { +0}; + +static struct +{ + jclass klass; + jmethodID hasNext; + jmethodID next; +} java_util_iterator = { +0}; + +static struct +{ + jclass klass; + jmethodID intValue; +} java_lang_integer = { +0}; + +static struct +{ + jclass klass; + jmethodID equals; +} java_lang_string = { +0}; + +static struct +{ + jclass klass; + jmethodID constructor; +} org_freedesktop_gstreamer_androidmedia_gstahccallback = { +0}; + +static void +gst_ah_camera_on_preview_frame (JNIEnv * env, jclass klass, jbyteArray data, + jobject camera, jlong callback, jlong user_data) +{ + GstAHCPreviewCallback cb = (GstAHCPreviewCallback) (gsize) callback; + + if (cb) + cb (data, (gpointer) (gsize) user_data); +} + +static void +gst_ah_camera_on_error (JNIEnv * env, jclass klass, jint error, + jobject camera, jlong callback, jlong user_data) +{ + GstAHCErrorCallback cb = (GstAHCErrorCallback) (gsize) callback; + + if (cb) + cb (error, (gpointer) (gsize) user_data); +} + +static void +gst_ah_camera_on_auto_focus (JNIEnv * env, jclass klass, jboolean success, + jobject camera, jlong callback, jlong user_data) +{ + GstAHCAutoFocusCallback cb = (GstAHCAutoFocusCallback) (gsize) callback; + + if (cb) + cb (success, (gpointer) (gsize) user_data); +} + +static JNINativeMethod native_methods[] = { + {(gchar *) "gst_ah_camera_on_preview_frame", + (gchar *) "([BLandroid/hardware/Camera;JJ)V", + (void *) gst_ah_camera_on_preview_frame}, + {(gchar *) "gst_ah_camera_on_error", + (gchar *) "(ILandroid/hardware/Camera;JJ)V", + (void *) gst_ah_camera_on_error}, +// {(gchar *) "gst_ah_camera_on_auto_focus", +// (gchar *) "(ZLandroid/hardware/Camera;JJ)V", +// (void *) gst_ah_camera_on_auto_focus} +}; + +static gboolean +_init_classes (void) +{ + JNIEnv *env; + GError *err; + + jclass klass; + jfieldID fieldID; + + env = gst_amc_jni_get_env (); + + /* android.hardware.Camera */ + klass = android_hardware_camera.klass = + gst_amc_jni_get_class (env, &err, "android/hardware/Camera"); + if (!klass) + goto failed; + + android_hardware_camera.addCallbackBuffer = + gst_amc_jni_get_method_id (env, &err, klass, + "addCallbackBuffer", "([B)V"); + + android_hardware_camera.autoFocus = + gst_amc_jni_get_method_id (env, &err, klass, + "autoFocus", "(Landroid/hardware/Camera$AutoFocusCallback;)V"); + + android_hardware_camera.cancelAutoFocus = + gst_amc_jni_get_method_id (env, &err, klass, "cancelAutoFocus", "()V"); + + android_hardware_camera.getCameraInfo = + gst_amc_jni_get_static_method_id (env, &err, klass, + "getCameraInfo", "(ILandroid/hardware/Camera$CameraInfo;)V"); + + android_hardware_camera.getNumberOfCameras = + gst_amc_jni_get_static_method_id (env, &err, klass, + "getNumberOfCameras", "()I"); + + android_hardware_camera.getParameters = + gst_amc_jni_get_method_id (env, &err, klass, + "getParameters", "()Landroid/hardware/Camera$Parameters;"); + + android_hardware_camera.lock = + gst_amc_jni_get_method_id (env, &err, klass, "lock", "()V"); + + android_hardware_camera.open = + gst_amc_jni_get_static_method_id (env, &err, klass, + "open", "(I)Landroid/hardware/Camera;"); + + android_hardware_camera.reconnect = + gst_amc_jni_get_method_id (env, &err, klass, "reconnect", "()V"); + + android_hardware_camera.release = + gst_amc_jni_get_method_id (env, &err, klass, "release", "()V"); + + android_hardware_camera.setErrorCallback = + gst_amc_jni_get_method_id (env, &err, klass, "setErrorCallback", + "(Landroid/hardware/Camera$ErrorCallback;)V"); + + android_hardware_camera.setParameters = + gst_amc_jni_get_method_id (env, &err, klass, "setParameters", + "(Landroid/hardware/Camera$Parameters;)V"); + + android_hardware_camera.setPreviewCallbackWithBuffer = + gst_amc_jni_get_method_id (env, &err, klass, + "setPreviewCallbackWithBuffer", + "(Landroid/hardware/Camera$PreviewCallback;)V"); + + android_hardware_camera.setPreviewTexture = + gst_amc_jni_get_method_id (env, &err, klass, + "setPreviewTexture", "(Landroid/graphics/SurfaceTexture;)V"); + + android_hardware_camera.startPreview = + gst_amc_jni_get_method_id (env, &err, klass, "startPreview", "()V"); + + android_hardware_camera.startSmoothZoom = + gst_amc_jni_get_method_id (env, &err, klass, "startSmoothZoom", "(I)V"); + + android_hardware_camera.stopPreview = + gst_amc_jni_get_method_id (env, &err, klass, "stopPreview", "()V"); + + android_hardware_camera.stopPreview = + gst_amc_jni_get_method_id (env, &err, klass, "stopPreview", "()V"); + + android_hardware_camera.unlock = + gst_amc_jni_get_method_id (env, &err, klass, "unlock", "()V"); + + /* android.hardware.Camera.CameraInfo */ + klass = android_hardware_camera_camerainfo.klass = + gst_amc_jni_get_class (env, &err, "android/hardware/Camera$CameraInfo"); + if (!klass) + goto failed; + + android_hardware_camera_camerainfo.constructor = + gst_amc_jni_get_method_id (env, &err, klass, "", "()V"); + + android_hardware_camera_camerainfo.facing = + gst_amc_jni_get_field_id (env, &err, klass, "facing", "I"); + + android_hardware_camera_camerainfo.orientation = + gst_amc_jni_get_field_id (env, &err, klass, "orientation", "I"); + + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "CAMERA_FACING_BACK", + "I"); + if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, + &android_hardware_camera_camerainfo.CAMERA_FACING_BACK)) + goto failed; + CameraInfo_CAMERA_FACING_BACK = + android_hardware_camera_camerainfo.CAMERA_FACING_BACK; + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "CAMERA_FACING_FRONT", + "I"); + if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, + &android_hardware_camera_camerainfo.CAMERA_FACING_FRONT)) + goto failed; + CameraInfo_CAMERA_FACING_FRONT = + android_hardware_camera_camerainfo.CAMERA_FACING_FRONT; + + /* android.hardware.Camera.Size */ + klass = android_hardware_camera_size.klass = + gst_amc_jni_get_class (env, &err, "android/hardware/Camera$Size"); + if (!klass) + goto failed; + + android_hardware_camera_size.width = + gst_amc_jni_get_field_id (env, &err, klass, "width", "I"); + android_hardware_camera_size.height = + gst_amc_jni_get_field_id (env, &err, klass, "height", "I"); + + /* android.hardware.Camera.Parameters */ + klass = android_hardware_camera_parameters.klass = + gst_amc_jni_get_class (env, &err, "android/hardware/Camera$Parameters"); + if (!klass) + goto failed; + + android_hardware_camera_parameters.flatten = + gst_amc_jni_get_method_id (env, &err, klass, "flatten", + "()Ljava/lang/String;"); + + android_hardware_camera_parameters.getAntibanding = + gst_amc_jni_get_method_id (env, &err, klass, "getAntibanding", + "()Ljava/lang/String;"); + + android_hardware_camera_parameters.getColorEffect = + gst_amc_jni_get_method_id (env, &err, klass, "getColorEffect", + "()Ljava/lang/String;"); + + android_hardware_camera_parameters.getExposureCompensation = + gst_amc_jni_get_method_id (env, &err, klass, "getExposureCompensation", + "()I"); + + android_hardware_camera_parameters.getExposureCompensationStep = + gst_amc_jni_get_method_id (env, &err, klass, + "getExposureCompensationStep", "()F"); + + android_hardware_camera_parameters.getFlashMode = + gst_amc_jni_get_method_id (env, &err, klass, "getFlashMode", + "()Ljava/lang/String;"); + + android_hardware_camera_parameters.getFocalLength = + gst_amc_jni_get_method_id (env, &err, klass, "getFocalLength", "()F"); + + android_hardware_camera_parameters.getFocusMode = + gst_amc_jni_get_method_id (env, &err, klass, "getFocusMode", + "()Ljava/lang/String;"); + + android_hardware_camera_parameters.getHorizontalViewAngle = + gst_amc_jni_get_method_id (env, &err, klass, "getHorizontalViewAngle", + "()F"); + + android_hardware_camera_parameters.getMaxExposureCompensation = + gst_amc_jni_get_method_id (env, &err, klass, "getMaxExposureCompensation", + "()I"); + + android_hardware_camera_parameters.getMaxZoom = + gst_amc_jni_get_method_id (env, &err, klass, "getMaxZoom", "()I"); + + android_hardware_camera_parameters.getMinExposureCompensation = + gst_amc_jni_get_method_id (env, &err, klass, "getMinExposureCompensation", + "()I"); + + android_hardware_camera_parameters.getPreviewFormat = + gst_amc_jni_get_method_id (env, &err, klass, "getPreviewFormat", "()I"); + + android_hardware_camera_parameters.getPreviewFpsRange = + gst_amc_jni_get_method_id (env, &err, klass, "getPreviewFpsRange", + "([I)V"); + + android_hardware_camera_parameters.getPreviewSize = + gst_amc_jni_get_method_id (env, &err, klass, "getPreviewSize", + "()Landroid/hardware/Camera$Size;"); + + android_hardware_camera_parameters.getSceneMode = + gst_amc_jni_get_method_id (env, &err, klass, "getSceneMode", + "()Ljava/lang/String;"); + + android_hardware_camera_parameters.getSupportedAntibanding = + gst_amc_jni_get_method_id (env, &err, klass, "getSupportedAntibanding", + "()Ljava/util/List;"); + + android_hardware_camera_parameters.getSupportedColorEffects = + gst_amc_jni_get_method_id (env, &err, klass, "getSupportedColorEffects", + "()Ljava/util/List;"); + + android_hardware_camera_parameters.getSupportedFlashModes = + gst_amc_jni_get_method_id (env, &err, klass, "getSupportedFlashModes", + "()Ljava/util/List;"); + + android_hardware_camera_parameters.getSupportedFocusModes = + gst_amc_jni_get_method_id (env, &err, klass, "getSupportedFocusModes", + "()Ljava/util/List;"); + + android_hardware_camera_parameters.getSupportedPreviewFormats = + gst_amc_jni_get_method_id (env, &err, klass, "getSupportedPreviewFormats", + "()Ljava/util/List;"); + + android_hardware_camera_parameters.getSupportedPreviewFpsRange = + gst_amc_jni_get_method_id (env, &err, klass, + "getSupportedPreviewFpsRange", "()Ljava/util/List;"); + + android_hardware_camera_parameters.getSupportedPreviewSizes = + gst_amc_jni_get_method_id (env, &err, klass, "getSupportedPreviewSizes", + "()Ljava/util/List;"); + + android_hardware_camera_parameters.getSupportedSceneModes = + gst_amc_jni_get_method_id (env, &err, klass, "getSupportedSceneModes", + "()Ljava/util/List;"); + + android_hardware_camera_parameters.getSupportedWhiteBalance = + gst_amc_jni_get_method_id (env, &err, klass, "getSupportedWhiteBalance", + "()Ljava/util/List;"); + + android_hardware_camera_parameters.getVerticalViewAngle = + gst_amc_jni_get_method_id (env, &err, klass, "getVerticalViewAngle", + "()F"); + + android_hardware_camera_parameters.getVideoStabilization = + gst_amc_jni_get_method_id (env, &err, klass, "getVideoStabilization", + "()Z"); + + android_hardware_camera_parameters.getWhiteBalance = + gst_amc_jni_get_method_id (env, &err, klass, "getWhiteBalance", + "()Ljava/lang/String;"); + + android_hardware_camera_parameters.getZoom = + gst_amc_jni_get_method_id (env, &err, klass, "getZoom", "()I"); + + android_hardware_camera_parameters.getZoomRatios = + gst_amc_jni_get_method_id (env, &err, klass, "getZoomRatios", + "()Ljava/util/List;"); + + android_hardware_camera_parameters.isSmoothZoomSupported = + gst_amc_jni_get_method_id (env, &err, klass, "isSmoothZoomSupported", + "()Z"); + + android_hardware_camera_parameters.isVideoStabilizationSupported = + gst_amc_jni_get_method_id (env, &err, klass, + "isVideoStabilizationSupported", "()Z"); + + android_hardware_camera_parameters.isZoomSupported = + gst_amc_jni_get_method_id (env, &err, klass, "isZoomSupported", "()Z"); + + android_hardware_camera_parameters.setAntibanding = + gst_amc_jni_get_method_id (env, &err, klass, "setAntibanding", + "(Ljava/lang/String;)V"); + + android_hardware_camera_parameters.setColorEffect = + gst_amc_jni_get_method_id (env, &err, klass, "setColorEffect", + "(Ljava/lang/String;)V"); + + android_hardware_camera_parameters.setExposureCompensation = + gst_amc_jni_get_method_id (env, &err, klass, "setExposureCompensation", + "(I)V"); + + android_hardware_camera_parameters.setFlashMode = + gst_amc_jni_get_method_id (env, &err, klass, "setFlashMode", + "(Ljava/lang/String;)V"); + + android_hardware_camera_parameters.setFocusMode = + gst_amc_jni_get_method_id (env, &err, klass, "setFocusMode", + "(Ljava/lang/String;)V"); + + android_hardware_camera_parameters.setPreviewFormat = + gst_amc_jni_get_method_id (env, &err, klass, "setPreviewFormat", "(I)V"); + + android_hardware_camera_parameters.setPreviewFpsRange = + gst_amc_jni_get_method_id (env, &err, klass, "setPreviewFpsRange", + "(II)V"); + + android_hardware_camera_parameters.setPreviewSize = + gst_amc_jni_get_method_id (env, &err, klass, "setPreviewSize", "(II)V"); + + android_hardware_camera_parameters.setSceneMode = + gst_amc_jni_get_method_id (env, &err, klass, "setSceneMode", + "(Ljava/lang/String;)V"); + + android_hardware_camera_parameters.setWhiteBalance = + gst_amc_jni_get_method_id (env, &err, klass, "setWhiteBalance", + "(Ljava/lang/String;)V"); + + android_hardware_camera_parameters.setVideoStabilization = + gst_amc_jni_get_method_id (env, &err, klass, "setVideoStabilization", + "(Z)V"); + + android_hardware_camera_parameters.setZoom = + gst_amc_jni_get_method_id (env, &err, klass, "setZoom", "(I)V"); + + android_hardware_camera_parameters.unflatten = + gst_amc_jni_get_method_id (env, &err, klass, "unflatten", + "(Ljava/lang/String;)V"); + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "WHITE_BALANCE_AUTO", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.WHITE_BALANCE_AUTO)) + goto failed; + + Parameters_WHITE_BALANCE_AUTO = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.WHITE_BALANCE_AUTO, NULL); + { + jobject local = android_hardware_camera_parameters.WHITE_BALANCE_AUTO; + + android_hardware_camera_parameters.WHITE_BALANCE_AUTO = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, + "WHITE_BALANCE_INCANDESCENT", "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.WHITE_BALANCE_INCANDESCENT)) + goto failed; + + Parameters_WHITE_BALANCE_INCANDESCENT = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.WHITE_BALANCE_INCANDESCENT, NULL); + { + jobject local = + android_hardware_camera_parameters.WHITE_BALANCE_INCANDESCENT; + + android_hardware_camera_parameters.WHITE_BALANCE_INCANDESCENT = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, + "WHITE_BALANCE_FLUORESCENT", "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.WHITE_BALANCE_FLUORESCENT)) + goto failed; + + Parameters_WHITE_BALANCE_FLUORESCENT = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.WHITE_BALANCE_FLUORESCENT, NULL); + { + jobject local = + android_hardware_camera_parameters.WHITE_BALANCE_FLUORESCENT; + + android_hardware_camera_parameters.WHITE_BALANCE_FLUORESCENT = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, + "WHITE_BALANCE_WARM_FLUORESCENT", "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.WHITE_BALANCE_WARM_FLUORESCENT)) + goto failed; + + Parameters_WHITE_BALANCE_WARM_FLUORESCENT = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.WHITE_BALANCE_WARM_FLUORESCENT, NULL); + { + jobject local = + android_hardware_camera_parameters.WHITE_BALANCE_WARM_FLUORESCENT; + + android_hardware_camera_parameters.WHITE_BALANCE_WARM_FLUORESCENT = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, + "WHITE_BALANCE_DAYLIGHT", "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.WHITE_BALANCE_DAYLIGHT)) + goto failed; + + Parameters_WHITE_BALANCE_DAYLIGHT = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.WHITE_BALANCE_DAYLIGHT, NULL); + { + jobject local = android_hardware_camera_parameters.WHITE_BALANCE_DAYLIGHT; + + android_hardware_camera_parameters.WHITE_BALANCE_DAYLIGHT = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, + "WHITE_BALANCE_CLOUDY_DAYLIGHT", "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT)) + goto failed; + Parameters_WHITE_BALANCE_CLOUDY_DAYLIGHT = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT, NULL); + { + jobject local = + android_hardware_camera_parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT; + + android_hardware_camera_parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, + "WHITE_BALANCE_TWILIGHT", "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.WHITE_BALANCE_TWILIGHT)) + goto failed; + Parameters_WHITE_BALANCE_TWILIGHT = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.WHITE_BALANCE_TWILIGHT, NULL); + { + jobject local = android_hardware_camera_parameters.WHITE_BALANCE_TWILIGHT; + + android_hardware_camera_parameters.WHITE_BALANCE_TWILIGHT = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "WHITE_BALANCE_SHADE", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.WHITE_BALANCE_SHADE)) + goto failed; + + Parameters_WHITE_BALANCE_SHADE = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.WHITE_BALANCE_SHADE, NULL); + { + jobject local = android_hardware_camera_parameters.WHITE_BALANCE_SHADE; + + android_hardware_camera_parameters.WHITE_BALANCE_SHADE = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "EFFECT_NONE", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.EFFECT_NONE)) + goto failed; + + Parameters_EFFECT_NONE = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.EFFECT_NONE, NULL); + { + jobject local = android_hardware_camera_parameters.EFFECT_NONE; + + android_hardware_camera_parameters.EFFECT_NONE = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "EFFECT_MONO", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.EFFECT_MONO)) + goto failed; + + Parameters_EFFECT_MONO = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.EFFECT_MONO, NULL); + { + jobject local = android_hardware_camera_parameters.EFFECT_MONO; + + android_hardware_camera_parameters.EFFECT_MONO = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "EFFECT_NEGATIVE", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.EFFECT_NEGATIVE)) + goto failed; + + Parameters_EFFECT_NEGATIVE = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.EFFECT_NEGATIVE, NULL); + { + jobject local = android_hardware_camera_parameters.EFFECT_NEGATIVE; + + android_hardware_camera_parameters.EFFECT_NEGATIVE = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "EFFECT_SOLARIZE", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.EFFECT_SOLARIZE)) + goto failed; + + Parameters_EFFECT_SOLARIZE = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.EFFECT_SOLARIZE, NULL); + { + jobject local = android_hardware_camera_parameters.EFFECT_SOLARIZE; + + android_hardware_camera_parameters.EFFECT_SOLARIZE = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "EFFECT_SEPIA", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.EFFECT_SEPIA)) + goto failed; + + Parameters_EFFECT_SEPIA = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.EFFECT_SEPIA, NULL); + { + jobject local = android_hardware_camera_parameters.EFFECT_SEPIA; + + android_hardware_camera_parameters.EFFECT_SEPIA = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "EFFECT_POSTERIZE", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.EFFECT_POSTERIZE)) + goto failed; + + Parameters_EFFECT_POSTERIZE = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.EFFECT_POSTERIZE, NULL); + { + jobject local = android_hardware_camera_parameters.EFFECT_POSTERIZE; + + android_hardware_camera_parameters.EFFECT_POSTERIZE = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "EFFECT_WHITEBOARD", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.EFFECT_WHITEBOARD)) + goto failed; + + Parameters_EFFECT_WHITEBOARD = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.EFFECT_WHITEBOARD, NULL); + { + jobject local = android_hardware_camera_parameters.EFFECT_WHITEBOARD; + + android_hardware_camera_parameters.EFFECT_WHITEBOARD = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "EFFECT_BLACKBOARD", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.EFFECT_BLACKBOARD)) + goto failed; + + Parameters_EFFECT_BLACKBOARD = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.EFFECT_BLACKBOARD, NULL); + { + jobject local = android_hardware_camera_parameters.EFFECT_BLACKBOARD; + + android_hardware_camera_parameters.EFFECT_BLACKBOARD = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "EFFECT_AQUA", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.EFFECT_AQUA)) + goto failed; + + Parameters_EFFECT_AQUA = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.EFFECT_AQUA, NULL); + { + jobject local = android_hardware_camera_parameters.EFFECT_AQUA; + + android_hardware_camera_parameters.EFFECT_AQUA = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "ANTIBANDING_AUTO", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.ANTIBANDING_AUTO)) + goto failed; + + Parameters_ANTIBANDING_AUTO = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.ANTIBANDING_AUTO, NULL); + { + jobject local = android_hardware_camera_parameters.ANTIBANDING_AUTO; + + android_hardware_camera_parameters.ANTIBANDING_AUTO = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "ANTIBANDING_50HZ", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.ANTIBANDING_50HZ)) + goto failed; + + Parameters_ANTIBANDING_50HZ = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.ANTIBANDING_50HZ, NULL); + { + jobject local = android_hardware_camera_parameters.ANTIBANDING_50HZ; + + android_hardware_camera_parameters.ANTIBANDING_50HZ = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "ANTIBANDING_60HZ", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.ANTIBANDING_60HZ)) + goto failed; + + Parameters_ANTIBANDING_60HZ = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.ANTIBANDING_60HZ, NULL); + { + jobject local = android_hardware_camera_parameters.ANTIBANDING_60HZ; + + android_hardware_camera_parameters.ANTIBANDING_60HZ = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "ANTIBANDING_OFF", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.ANTIBANDING_OFF)) + goto failed; + + Parameters_ANTIBANDING_OFF = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.ANTIBANDING_OFF, NULL); + { + jobject local = android_hardware_camera_parameters.ANTIBANDING_OFF; + + android_hardware_camera_parameters.ANTIBANDING_OFF = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "FLASH_MODE_OFF", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.FLASH_MODE_OFF)) + goto failed; + + Parameters_FLASH_MODE_OFF = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.FLASH_MODE_OFF, NULL); + { + jobject local = android_hardware_camera_parameters.FLASH_MODE_OFF; + + android_hardware_camera_parameters.FLASH_MODE_OFF = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "FLASH_MODE_AUTO", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.FLASH_MODE_AUTO)) + goto failed; + + Parameters_FLASH_MODE_AUTO = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.FLASH_MODE_AUTO, NULL); + { + jobject local = android_hardware_camera_parameters.FLASH_MODE_AUTO; + + android_hardware_camera_parameters.FLASH_MODE_AUTO = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "FLASH_MODE_ON", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.FLASH_MODE_ON)) + goto failed; + + Parameters_FLASH_MODE_ON = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.FLASH_MODE_ON, NULL); + { + jobject local = android_hardware_camera_parameters.FLASH_MODE_ON; + + android_hardware_camera_parameters.FLASH_MODE_ON = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "FLASH_MODE_RED_EYE", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.FLASH_MODE_RED_EYE)) + goto failed; + + Parameters_FLASH_MODE_RED_EYE = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.FLASH_MODE_RED_EYE, NULL); + { + jobject local = android_hardware_camera_parameters.FLASH_MODE_RED_EYE; + + android_hardware_camera_parameters.FLASH_MODE_RED_EYE = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "FLASH_MODE_TORCH", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.FLASH_MODE_TORCH)) + goto failed; + + Parameters_FLASH_MODE_TORCH = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.FLASH_MODE_TORCH, NULL); + { + jobject local = android_hardware_camera_parameters.FLASH_MODE_TORCH; + + android_hardware_camera_parameters.FLASH_MODE_TORCH = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "SCENE_MODE_AUTO", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.SCENE_MODE_AUTO)) + goto failed; + + Parameters_SCENE_MODE_AUTO = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_AUTO, NULL); + { + jobject local = android_hardware_camera_parameters.SCENE_MODE_AUTO; + + android_hardware_camera_parameters.SCENE_MODE_AUTO = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "SCENE_MODE_ACTION", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.SCENE_MODE_ACTION)) + goto failed; + + Parameters_SCENE_MODE_ACTION = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_ACTION, NULL); + { + jobject local = android_hardware_camera_parameters.SCENE_MODE_ACTION; + + android_hardware_camera_parameters.SCENE_MODE_ACTION = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "SCENE_MODE_PORTRAIT", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.SCENE_MODE_PORTRAIT)) + goto failed; + + Parameters_SCENE_MODE_PORTRAIT = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_PORTRAIT, NULL); + { + jobject local = android_hardware_camera_parameters.SCENE_MODE_PORTRAIT; + + android_hardware_camera_parameters.SCENE_MODE_PORTRAIT = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "SCENE_MODE_LANDSCAPE", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.SCENE_MODE_LANDSCAPE)) + goto failed; + Parameters_SCENE_MODE_LANDSCAPE = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_LANDSCAPE, NULL); + { + jobject local = android_hardware_camera_parameters.SCENE_MODE_LANDSCAPE; + + android_hardware_camera_parameters.SCENE_MODE_LANDSCAPE = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "SCENE_MODE_NIGHT", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.SCENE_MODE_NIGHT)) + goto failed; + + Parameters_SCENE_MODE_NIGHT = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_NIGHT, NULL); + { + jobject local = android_hardware_camera_parameters.SCENE_MODE_NIGHT; + + android_hardware_camera_parameters.SCENE_MODE_NIGHT = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, + "SCENE_MODE_NIGHT_PORTRAIT", "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.SCENE_MODE_NIGHT_PORTRAIT)) + goto failed; + Parameters_SCENE_MODE_NIGHT_PORTRAIT = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_NIGHT_PORTRAIT, NULL); + { + jobject local = + android_hardware_camera_parameters.SCENE_MODE_NIGHT_PORTRAIT; + + android_hardware_camera_parameters.SCENE_MODE_NIGHT_PORTRAIT = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "SCENE_MODE_THEATRE", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.SCENE_MODE_THEATRE)) + goto failed; + + Parameters_SCENE_MODE_THEATRE = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_THEATRE, NULL); + { + jobject local = android_hardware_camera_parameters.SCENE_MODE_THEATRE; + + android_hardware_camera_parameters.SCENE_MODE_THEATRE = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "SCENE_MODE_BEACH", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.SCENE_MODE_BEACH)) + goto failed; + + Parameters_SCENE_MODE_BEACH = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_BEACH, NULL); + { + jobject local = android_hardware_camera_parameters.SCENE_MODE_BEACH; + + android_hardware_camera_parameters.SCENE_MODE_BEACH = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "SCENE_MODE_SNOW", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.SCENE_MODE_SNOW)) + goto failed; + + Parameters_SCENE_MODE_SNOW = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_SNOW, NULL); + { + jobject local = android_hardware_camera_parameters.SCENE_MODE_SNOW; + + android_hardware_camera_parameters.SCENE_MODE_SNOW = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "SCENE_MODE_SUNSET", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.SCENE_MODE_SUNSET)) + goto failed; + + + Parameters_SCENE_MODE_SUNSET = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_SUNSET, NULL); + { + jobject local = android_hardware_camera_parameters.SCENE_MODE_SUNSET; + + android_hardware_camera_parameters.SCENE_MODE_SUNSET = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, + "SCENE_MODE_STEADYPHOTO", "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.SCENE_MODE_STEADYPHOTO)) + goto failed; + + + Parameters_SCENE_MODE_STEADYPHOTO = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_STEADYPHOTO, NULL); + { + jobject local = android_hardware_camera_parameters.SCENE_MODE_STEADYPHOTO; + + android_hardware_camera_parameters.SCENE_MODE_STEADYPHOTO = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "SCENE_MODE_FIREWORKS", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.SCENE_MODE_FIREWORKS)) + goto failed; + + Parameters_SCENE_MODE_FIREWORKS = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_FIREWORKS, NULL); + { + jobject local = android_hardware_camera_parameters.SCENE_MODE_FIREWORKS; + + android_hardware_camera_parameters.SCENE_MODE_FIREWORKS = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "SCENE_MODE_SPORTS", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.SCENE_MODE_SPORTS)) + goto failed; + + + Parameters_SCENE_MODE_SPORTS = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_SPORTS, NULL); + { + jobject local = android_hardware_camera_parameters.SCENE_MODE_SPORTS; + + android_hardware_camera_parameters.SCENE_MODE_SPORTS = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "SCENE_MODE_PARTY", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.SCENE_MODE_PARTY)) + goto failed; + + Parameters_SCENE_MODE_PARTY = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_PARTY, NULL); + { + jobject local = android_hardware_camera_parameters.SCENE_MODE_PARTY; + + android_hardware_camera_parameters.SCENE_MODE_PARTY = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, + "SCENE_MODE_CANDLELIGHT", "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.SCENE_MODE_CANDLELIGHT)) + goto failed; + + Parameters_SCENE_MODE_CANDLELIGHT = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_CANDLELIGHT, NULL); + { + jobject local = android_hardware_camera_parameters.SCENE_MODE_CANDLELIGHT; + + android_hardware_camera_parameters.SCENE_MODE_CANDLELIGHT = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "SCENE_MODE_BARCODE", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.SCENE_MODE_BARCODE)) + goto failed; + + Parameters_SCENE_MODE_BARCODE = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_BARCODE, NULL); + { + jobject local = android_hardware_camera_parameters.SCENE_MODE_BARCODE; + + android_hardware_camera_parameters.SCENE_MODE_BARCODE = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "FOCUS_MODE_AUTO", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.FOCUS_MODE_AUTO)) + goto failed; + + Parameters_FOCUS_MODE_AUTO = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.FOCUS_MODE_AUTO, NULL); + { + jobject local = android_hardware_camera_parameters.FOCUS_MODE_AUTO; + + android_hardware_camera_parameters.FOCUS_MODE_AUTO = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "FOCUS_MODE_INFINITY", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.FOCUS_MODE_INFINITY)) + goto failed; + + Parameters_FOCUS_MODE_INFINITY = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.FOCUS_MODE_INFINITY, NULL); + { + jobject local = android_hardware_camera_parameters.FOCUS_MODE_INFINITY; + + android_hardware_camera_parameters.FOCUS_MODE_INFINITY = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "FOCUS_MODE_MACRO", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.FOCUS_MODE_MACRO)) + goto failed; + + Parameters_FOCUS_MODE_MACRO = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.FOCUS_MODE_MACRO, NULL); + { + jobject local = android_hardware_camera_parameters.FOCUS_MODE_MACRO; + + android_hardware_camera_parameters.FOCUS_MODE_MACRO = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "FOCUS_MODE_FIXED", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.FOCUS_MODE_FIXED)) + goto failed; + + Parameters_FOCUS_MODE_FIXED = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.FOCUS_MODE_FIXED, NULL); + { + jobject local = android_hardware_camera_parameters.FOCUS_MODE_FIXED; + + android_hardware_camera_parameters.FOCUS_MODE_FIXED = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, "FOCUS_MODE_EDOF", + "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.FOCUS_MODE_EDOF)) + goto failed; + + Parameters_FOCUS_MODE_EDOF = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.FOCUS_MODE_EDOF, NULL); + { + jobject local = android_hardware_camera_parameters.FOCUS_MODE_EDOF; + + android_hardware_camera_parameters.FOCUS_MODE_EDOF = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, + "FOCUS_MODE_CONTINUOUS_VIDEO", "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) + goto failed; + + Parameters_FOCUS_MODE_CONTINUOUS_VIDEO = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.FOCUS_MODE_CONTINUOUS_VIDEO, NULL); + { + jobject local = + android_hardware_camera_parameters.FOCUS_MODE_CONTINUOUS_VIDEO; + + android_hardware_camera_parameters.FOCUS_MODE_CONTINUOUS_VIDEO = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + fieldID = + gst_amc_jni_get_static_field_id (env, &err, klass, + "FOCUS_MODE_CONTINUOUS_PICTURE", "Ljava/lang/String;"); + if (!fieldID) + goto failed; + if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID, + &android_hardware_camera_parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) + goto failed; + + + Parameters_FOCUS_MODE_CONTINUOUS_PICTURE = + (*env)->GetStringUTFChars (env, + android_hardware_camera_parameters.FOCUS_MODE_CONTINUOUS_PICTURE, NULL); + { + jobject local = + android_hardware_camera_parameters.FOCUS_MODE_CONTINUOUS_PICTURE; + + android_hardware_camera_parameters.FOCUS_MODE_CONTINUOUS_PICTURE = + (*env)->NewGlobalRef (env, local); + (*env)->DeleteLocalRef (env, local); + } + + /* java.lang.String */ + klass = java_lang_string.klass = + gst_amc_jni_get_class (env, &err, "java/lang/String"); + java_lang_string.equals = + gst_amc_jni_get_method_id (env, &err, klass, "equals", + "(Ljava/lang/Object;)Z"); + + /* java.util.List */ + klass = java_util_list.klass = + gst_amc_jni_get_class (env, &err, "java/util/List"); + java_util_list.iterator = + gst_amc_jni_get_method_id (env, &err, klass, "iterator", + "()Ljava/util/Iterator;"); + + /* java.util.Iterator */ + klass = java_util_iterator.klass = + gst_amc_jni_get_class (env, &err, "java/util/Iterator"); + java_util_iterator.hasNext = + gst_amc_jni_get_method_id (env, &err, klass, "hasNext", "()Z"); + java_util_iterator.next = + gst_amc_jni_get_method_id (env, &err, klass, "next", + "()Ljava/lang/Object;"); + + /* java.lang.Integer */ + klass = java_lang_integer.klass = + gst_amc_jni_get_class (env, &err, "java/lang/Integer"); + java_lang_integer.intValue = + gst_amc_jni_get_method_id (env, &err, klass, "intValue", "()I"); + + if (!org_freedesktop_gstreamer_androidmedia_gstahccallback.klass) { + org_freedesktop_gstreamer_androidmedia_gstahccallback.klass = + gst_amc_jni_get_class (env, &err, "org/freedesktop/gstreamer/androidmedia/GstAhcCallback"); + } + org_freedesktop_gstreamer_androidmedia_gstahccallback.constructor = + gst_amc_jni_get_method_id (env, &err, org_freedesktop_gstreamer_androidmedia_gstahccallback.klass, + "", "(JJ)V"); + + if ((*env)->RegisterNatives (env, org_freedesktop_gstreamer_androidmedia_gstahccallback.klass, + native_methods, G_N_ELEMENTS (native_methods))) { + GST_ERROR ("Failed to register native methods for GstAhcCallback"); + return FALSE; + } + + return TRUE; + +failed: + if (err) { + GST_ERROR ("Failed to get android.hardware.Camera class: %s", err->message); + g_clear_error (&err); + } + + return FALSE; + +} + + +gboolean +gst_android_hardware_camera_init (void) +{ + GST_DEBUG_CATEGORY_INIT (ahc_debug, "ahc", 0, "Android Gstreamer Hardware Camera"); + if (!_init_classes ()) { + gst_android_hardware_camera_deinit (); + return FALSE; + } + + return TRUE; +} + +void +gst_android_hardware_camera_deinit (void) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + if (android_hardware_camera.klass) + (*env)->DeleteGlobalRef (env, android_hardware_camera.klass); + android_hardware_camera.klass = NULL; + + if (android_hardware_camera_camerainfo.klass) + (*env)->DeleteGlobalRef (env, android_hardware_camera_camerainfo.klass); + android_hardware_camera_camerainfo.klass = NULL; + + if (android_hardware_camera_size.klass) + (*env)->DeleteGlobalRef (env, android_hardware_camera_size.klass); + android_hardware_camera_size.klass = NULL; + + if (android_hardware_camera_parameters.klass) + (*env)->DeleteGlobalRef (env, android_hardware_camera_parameters.klass); + android_hardware_camera_parameters.klass = NULL; + if (Parameters_WHITE_BALANCE_AUTO) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.WHITE_BALANCE_AUTO, + Parameters_WHITE_BALANCE_AUTO); + Parameters_WHITE_BALANCE_AUTO = NULL; + if (android_hardware_camera_parameters.WHITE_BALANCE_AUTO) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.WHITE_BALANCE_AUTO); + android_hardware_camera_parameters.WHITE_BALANCE_AUTO = NULL; + if (Parameters_WHITE_BALANCE_INCANDESCENT) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.WHITE_BALANCE_INCANDESCENT, + Parameters_WHITE_BALANCE_INCANDESCENT); + Parameters_WHITE_BALANCE_INCANDESCENT = NULL; + if (android_hardware_camera_parameters.WHITE_BALANCE_INCANDESCENT) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.WHITE_BALANCE_INCANDESCENT); + android_hardware_camera_parameters.WHITE_BALANCE_INCANDESCENT = NULL; + if (Parameters_WHITE_BALANCE_FLUORESCENT) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.WHITE_BALANCE_FLUORESCENT, + Parameters_WHITE_BALANCE_FLUORESCENT); + Parameters_WHITE_BALANCE_FLUORESCENT = NULL; + if (android_hardware_camera_parameters.WHITE_BALANCE_FLUORESCENT) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.WHITE_BALANCE_FLUORESCENT); + android_hardware_camera_parameters.WHITE_BALANCE_FLUORESCENT = NULL; + if (Parameters_WHITE_BALANCE_WARM_FLUORESCENT) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.WHITE_BALANCE_WARM_FLUORESCENT, + Parameters_WHITE_BALANCE_WARM_FLUORESCENT); + Parameters_WHITE_BALANCE_WARM_FLUORESCENT = NULL; + if (android_hardware_camera_parameters.WHITE_BALANCE_WARM_FLUORESCENT) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.WHITE_BALANCE_WARM_FLUORESCENT); + android_hardware_camera_parameters.WHITE_BALANCE_WARM_FLUORESCENT = NULL; + if (Parameters_WHITE_BALANCE_DAYLIGHT) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.WHITE_BALANCE_DAYLIGHT, + Parameters_WHITE_BALANCE_DAYLIGHT); + Parameters_WHITE_BALANCE_DAYLIGHT = NULL; + if (android_hardware_camera_parameters.WHITE_BALANCE_DAYLIGHT) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.WHITE_BALANCE_DAYLIGHT); + android_hardware_camera_parameters.WHITE_BALANCE_DAYLIGHT = NULL; + if (Parameters_WHITE_BALANCE_CLOUDY_DAYLIGHT) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT, + Parameters_WHITE_BALANCE_CLOUDY_DAYLIGHT); + Parameters_WHITE_BALANCE_CLOUDY_DAYLIGHT = NULL; + if (android_hardware_camera_parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT); + android_hardware_camera_parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT = NULL; + if (Parameters_WHITE_BALANCE_TWILIGHT) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.WHITE_BALANCE_TWILIGHT, + Parameters_WHITE_BALANCE_TWILIGHT); + Parameters_WHITE_BALANCE_TWILIGHT = NULL; + if (android_hardware_camera_parameters.WHITE_BALANCE_TWILIGHT) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.WHITE_BALANCE_TWILIGHT); + android_hardware_camera_parameters.WHITE_BALANCE_TWILIGHT = NULL; + if (Parameters_WHITE_BALANCE_SHADE) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.WHITE_BALANCE_SHADE, + Parameters_WHITE_BALANCE_SHADE); + Parameters_WHITE_BALANCE_SHADE = NULL; + if (android_hardware_camera_parameters.WHITE_BALANCE_SHADE) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.WHITE_BALANCE_SHADE); + android_hardware_camera_parameters.WHITE_BALANCE_SHADE = NULL; + if (Parameters_EFFECT_NONE) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.EFFECT_NONE, Parameters_EFFECT_NONE); + Parameters_EFFECT_NONE = NULL; + if (android_hardware_camera_parameters.EFFECT_NONE) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.EFFECT_NONE); + android_hardware_camera_parameters.EFFECT_NONE = NULL; + if (Parameters_EFFECT_MONO) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.EFFECT_MONO, Parameters_EFFECT_MONO); + Parameters_EFFECT_MONO = NULL; + if (android_hardware_camera_parameters.EFFECT_MONO) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.EFFECT_MONO); + android_hardware_camera_parameters.EFFECT_MONO = NULL; + if (Parameters_EFFECT_NEGATIVE) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.EFFECT_NEGATIVE, + Parameters_EFFECT_NEGATIVE); + Parameters_EFFECT_NEGATIVE = NULL; + if (android_hardware_camera_parameters.EFFECT_NEGATIVE) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.EFFECT_NEGATIVE); + android_hardware_camera_parameters.EFFECT_NEGATIVE = NULL; + if (Parameters_EFFECT_SOLARIZE) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.EFFECT_SOLARIZE, + Parameters_EFFECT_SOLARIZE); + Parameters_EFFECT_SOLARIZE = NULL; + if (android_hardware_camera_parameters.EFFECT_SOLARIZE) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.EFFECT_SOLARIZE); + android_hardware_camera_parameters.EFFECT_SOLARIZE = NULL; + if (Parameters_EFFECT_SEPIA) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.EFFECT_SEPIA, + Parameters_EFFECT_SEPIA); + Parameters_EFFECT_SEPIA = NULL; + if (android_hardware_camera_parameters.EFFECT_SEPIA) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.EFFECT_SEPIA); + android_hardware_camera_parameters.EFFECT_SEPIA = NULL; + if (Parameters_EFFECT_POSTERIZE) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.EFFECT_POSTERIZE, + Parameters_EFFECT_POSTERIZE); + Parameters_EFFECT_POSTERIZE = NULL; + if (android_hardware_camera_parameters.EFFECT_POSTERIZE) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.EFFECT_POSTERIZE); + android_hardware_camera_parameters.EFFECT_POSTERIZE = NULL; + if (Parameters_EFFECT_WHITEBOARD) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.EFFECT_WHITEBOARD, + Parameters_EFFECT_WHITEBOARD); + Parameters_EFFECT_WHITEBOARD = NULL; + if (android_hardware_camera_parameters.EFFECT_WHITEBOARD) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.EFFECT_WHITEBOARD); + android_hardware_camera_parameters.EFFECT_WHITEBOARD = NULL; + if (Parameters_EFFECT_BLACKBOARD) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.EFFECT_BLACKBOARD, + Parameters_EFFECT_BLACKBOARD); + Parameters_EFFECT_BLACKBOARD = NULL; + if (android_hardware_camera_parameters.EFFECT_BLACKBOARD) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.EFFECT_BLACKBOARD); + android_hardware_camera_parameters.EFFECT_BLACKBOARD = NULL; + if (Parameters_EFFECT_AQUA) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.EFFECT_AQUA, Parameters_EFFECT_AQUA); + Parameters_EFFECT_AQUA = NULL; + if (android_hardware_camera_parameters.EFFECT_AQUA) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.EFFECT_AQUA); + android_hardware_camera_parameters.EFFECT_AQUA = NULL; + if (Parameters_ANTIBANDING_AUTO) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.ANTIBANDING_AUTO, + Parameters_ANTIBANDING_AUTO); + Parameters_ANTIBANDING_AUTO = NULL; + if (android_hardware_camera_parameters.ANTIBANDING_AUTO) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.ANTIBANDING_AUTO); + android_hardware_camera_parameters.ANTIBANDING_AUTO = NULL; + if (Parameters_ANTIBANDING_50HZ) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.ANTIBANDING_50HZ, + Parameters_ANTIBANDING_50HZ); + Parameters_ANTIBANDING_50HZ = NULL; + if (android_hardware_camera_parameters.ANTIBANDING_50HZ) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.ANTIBANDING_50HZ); + android_hardware_camera_parameters.ANTIBANDING_50HZ = NULL; + if (Parameters_ANTIBANDING_60HZ) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.ANTIBANDING_60HZ, + Parameters_ANTIBANDING_60HZ); + Parameters_ANTIBANDING_60HZ = NULL; + if (android_hardware_camera_parameters.ANTIBANDING_60HZ) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.ANTIBANDING_60HZ); + android_hardware_camera_parameters.ANTIBANDING_60HZ = NULL; + if (Parameters_ANTIBANDING_OFF) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.ANTIBANDING_OFF, + Parameters_ANTIBANDING_OFF); + Parameters_ANTIBANDING_OFF = NULL; + if (android_hardware_camera_parameters.ANTIBANDING_OFF) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.ANTIBANDING_OFF); + android_hardware_camera_parameters.ANTIBANDING_OFF = NULL; + if (Parameters_FLASH_MODE_OFF) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.FLASH_MODE_OFF, + Parameters_FLASH_MODE_OFF); + Parameters_FLASH_MODE_OFF = NULL; + if (android_hardware_camera_parameters.FLASH_MODE_OFF) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.FLASH_MODE_OFF); + android_hardware_camera_parameters.FLASH_MODE_OFF = NULL; + if (Parameters_FLASH_MODE_AUTO) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.FLASH_MODE_AUTO, + Parameters_FLASH_MODE_AUTO); + Parameters_FLASH_MODE_AUTO = NULL; + if (android_hardware_camera_parameters.FLASH_MODE_AUTO) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.FLASH_MODE_AUTO); + android_hardware_camera_parameters.FLASH_MODE_AUTO = NULL; + if (Parameters_FLASH_MODE_ON) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.FLASH_MODE_ON, + Parameters_FLASH_MODE_ON); + Parameters_FLASH_MODE_ON = NULL; + if (android_hardware_camera_parameters.FLASH_MODE_ON) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.FLASH_MODE_ON); + android_hardware_camera_parameters.FLASH_MODE_ON = NULL; + if (Parameters_FLASH_MODE_RED_EYE) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.FLASH_MODE_RED_EYE, + Parameters_FLASH_MODE_RED_EYE); + Parameters_FLASH_MODE_RED_EYE = NULL; + if (android_hardware_camera_parameters.FLASH_MODE_RED_EYE) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.FLASH_MODE_RED_EYE); + android_hardware_camera_parameters.FLASH_MODE_RED_EYE = NULL; + if (Parameters_FLASH_MODE_TORCH) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.FLASH_MODE_TORCH, + Parameters_FLASH_MODE_TORCH); + Parameters_FLASH_MODE_TORCH = NULL; + if (android_hardware_camera_parameters.FLASH_MODE_TORCH) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.FLASH_MODE_TORCH); + android_hardware_camera_parameters.FLASH_MODE_TORCH = NULL; + if (Parameters_SCENE_MODE_AUTO) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_AUTO, + Parameters_SCENE_MODE_AUTO); + Parameters_SCENE_MODE_AUTO = NULL; + if (android_hardware_camera_parameters.SCENE_MODE_AUTO) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.SCENE_MODE_AUTO); + android_hardware_camera_parameters.SCENE_MODE_AUTO = NULL; + if (Parameters_SCENE_MODE_ACTION) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_ACTION, + Parameters_SCENE_MODE_ACTION); + Parameters_SCENE_MODE_ACTION = NULL; + if (android_hardware_camera_parameters.SCENE_MODE_ACTION) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.SCENE_MODE_ACTION); + android_hardware_camera_parameters.SCENE_MODE_ACTION = NULL; + if (Parameters_SCENE_MODE_PORTRAIT) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_PORTRAIT, + Parameters_SCENE_MODE_PORTRAIT); + Parameters_SCENE_MODE_PORTRAIT = NULL; + if (android_hardware_camera_parameters.SCENE_MODE_PORTRAIT) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.SCENE_MODE_PORTRAIT); + android_hardware_camera_parameters.SCENE_MODE_PORTRAIT = NULL; + if (Parameters_SCENE_MODE_LANDSCAPE) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_LANDSCAPE, + Parameters_SCENE_MODE_LANDSCAPE); + Parameters_SCENE_MODE_LANDSCAPE = NULL; + if (android_hardware_camera_parameters.SCENE_MODE_LANDSCAPE) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.SCENE_MODE_LANDSCAPE); + android_hardware_camera_parameters.SCENE_MODE_LANDSCAPE = NULL; + if (Parameters_SCENE_MODE_NIGHT) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_NIGHT, + Parameters_SCENE_MODE_NIGHT); + Parameters_SCENE_MODE_NIGHT = NULL; + if (android_hardware_camera_parameters.SCENE_MODE_NIGHT) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.SCENE_MODE_NIGHT); + android_hardware_camera_parameters.SCENE_MODE_NIGHT = NULL; + if (Parameters_SCENE_MODE_NIGHT_PORTRAIT) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_NIGHT_PORTRAIT, + Parameters_SCENE_MODE_NIGHT_PORTRAIT); + Parameters_SCENE_MODE_NIGHT_PORTRAIT = NULL; + if (android_hardware_camera_parameters.SCENE_MODE_NIGHT_PORTRAIT) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.SCENE_MODE_NIGHT_PORTRAIT); + android_hardware_camera_parameters.SCENE_MODE_NIGHT_PORTRAIT = NULL; + if (Parameters_SCENE_MODE_THEATRE) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_THEATRE, + Parameters_SCENE_MODE_THEATRE); + Parameters_SCENE_MODE_THEATRE = NULL; + if (android_hardware_camera_parameters.SCENE_MODE_THEATRE) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.SCENE_MODE_THEATRE); + android_hardware_camera_parameters.SCENE_MODE_THEATRE = NULL; + if (Parameters_SCENE_MODE_BEACH) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_BEACH, + Parameters_SCENE_MODE_BEACH); + Parameters_SCENE_MODE_BEACH = NULL; + if (android_hardware_camera_parameters.SCENE_MODE_BEACH) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.SCENE_MODE_BEACH); + android_hardware_camera_parameters.SCENE_MODE_BEACH = NULL; + if (Parameters_SCENE_MODE_SNOW) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_SNOW, + Parameters_SCENE_MODE_SNOW); + Parameters_SCENE_MODE_SNOW = NULL; + if (android_hardware_camera_parameters.SCENE_MODE_SNOW) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.SCENE_MODE_SNOW); + android_hardware_camera_parameters.SCENE_MODE_SNOW = NULL; + if (Parameters_SCENE_MODE_SUNSET) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_SUNSET, + Parameters_SCENE_MODE_SUNSET); + Parameters_SCENE_MODE_SUNSET = NULL; + if (android_hardware_camera_parameters.SCENE_MODE_SUNSET) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.SCENE_MODE_SUNSET); + android_hardware_camera_parameters.SCENE_MODE_SUNSET = NULL; + if (Parameters_SCENE_MODE_STEADYPHOTO) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_STEADYPHOTO, + Parameters_SCENE_MODE_STEADYPHOTO); + Parameters_SCENE_MODE_STEADYPHOTO = NULL; + if (android_hardware_camera_parameters.SCENE_MODE_STEADYPHOTO) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.SCENE_MODE_STEADYPHOTO); + android_hardware_camera_parameters.SCENE_MODE_STEADYPHOTO = NULL; + if (Parameters_SCENE_MODE_FIREWORKS) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_FIREWORKS, + Parameters_SCENE_MODE_FIREWORKS); + Parameters_SCENE_MODE_FIREWORKS = NULL; + if (android_hardware_camera_parameters.SCENE_MODE_FIREWORKS) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.SCENE_MODE_FIREWORKS); + android_hardware_camera_parameters.SCENE_MODE_FIREWORKS = NULL; + if (Parameters_SCENE_MODE_SPORTS) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_SPORTS, + Parameters_SCENE_MODE_SPORTS); + Parameters_SCENE_MODE_SPORTS = NULL; + if (android_hardware_camera_parameters.SCENE_MODE_SPORTS) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.SCENE_MODE_SPORTS); + android_hardware_camera_parameters.SCENE_MODE_SPORTS = NULL; + if (Parameters_SCENE_MODE_PARTY) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_PARTY, + Parameters_SCENE_MODE_PARTY); + Parameters_SCENE_MODE_PARTY = NULL; + if (android_hardware_camera_parameters.SCENE_MODE_PARTY) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.SCENE_MODE_PARTY); + android_hardware_camera_parameters.SCENE_MODE_PARTY = NULL; + if (Parameters_SCENE_MODE_CANDLELIGHT) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_CANDLELIGHT, + Parameters_SCENE_MODE_CANDLELIGHT); + Parameters_SCENE_MODE_CANDLELIGHT = NULL; + if (android_hardware_camera_parameters.SCENE_MODE_CANDLELIGHT) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.SCENE_MODE_CANDLELIGHT); + android_hardware_camera_parameters.SCENE_MODE_CANDLELIGHT = NULL; + if (Parameters_SCENE_MODE_BARCODE) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.SCENE_MODE_BARCODE, + Parameters_SCENE_MODE_BARCODE); + Parameters_SCENE_MODE_BARCODE = NULL; + if (android_hardware_camera_parameters.SCENE_MODE_BARCODE) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.SCENE_MODE_BARCODE); + android_hardware_camera_parameters.SCENE_MODE_BARCODE = NULL; + if (Parameters_FOCUS_MODE_AUTO) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.FOCUS_MODE_AUTO, + Parameters_FOCUS_MODE_AUTO); + Parameters_FOCUS_MODE_AUTO = NULL; + if (android_hardware_camera_parameters.FOCUS_MODE_AUTO) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.FOCUS_MODE_AUTO); + android_hardware_camera_parameters.FOCUS_MODE_AUTO = NULL; + if (Parameters_FOCUS_MODE_INFINITY) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.FOCUS_MODE_INFINITY, + Parameters_FOCUS_MODE_INFINITY); + Parameters_FOCUS_MODE_INFINITY = NULL; + if (android_hardware_camera_parameters.FOCUS_MODE_INFINITY) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.FOCUS_MODE_INFINITY); + android_hardware_camera_parameters.FOCUS_MODE_INFINITY = NULL; + if (Parameters_FOCUS_MODE_MACRO) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.FOCUS_MODE_MACRO, + Parameters_FOCUS_MODE_MACRO); + Parameters_FOCUS_MODE_MACRO = NULL; + if (android_hardware_camera_parameters.FOCUS_MODE_MACRO) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.FOCUS_MODE_MACRO); + android_hardware_camera_parameters.FOCUS_MODE_MACRO = NULL; + if (Parameters_FOCUS_MODE_FIXED) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.FOCUS_MODE_FIXED, + Parameters_FOCUS_MODE_FIXED); + Parameters_FOCUS_MODE_FIXED = NULL; + if (android_hardware_camera_parameters.FOCUS_MODE_FIXED) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.FOCUS_MODE_FIXED); + android_hardware_camera_parameters.FOCUS_MODE_FIXED = NULL; + if (Parameters_FOCUS_MODE_EDOF) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.FOCUS_MODE_EDOF, + Parameters_FOCUS_MODE_EDOF); + Parameters_FOCUS_MODE_EDOF = NULL; + if (android_hardware_camera_parameters.FOCUS_MODE_EDOF) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.FOCUS_MODE_EDOF); + android_hardware_camera_parameters.FOCUS_MODE_EDOF = NULL; + if (Parameters_FOCUS_MODE_CONTINUOUS_VIDEO) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.FOCUS_MODE_CONTINUOUS_VIDEO, + Parameters_FOCUS_MODE_CONTINUOUS_VIDEO); + Parameters_FOCUS_MODE_CONTINUOUS_VIDEO = NULL; + if (android_hardware_camera_parameters.FOCUS_MODE_CONTINUOUS_VIDEO) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.FOCUS_MODE_CONTINUOUS_VIDEO); + android_hardware_camera_parameters.FOCUS_MODE_CONTINUOUS_VIDEO = NULL; + if (Parameters_FOCUS_MODE_CONTINUOUS_PICTURE) + (*env)->ReleaseStringUTFChars (env, + android_hardware_camera_parameters.FOCUS_MODE_CONTINUOUS_PICTURE, + Parameters_FOCUS_MODE_CONTINUOUS_PICTURE); + Parameters_FOCUS_MODE_CONTINUOUS_PICTURE = NULL; + if (android_hardware_camera_parameters.FOCUS_MODE_CONTINUOUS_PICTURE) + (*env)->DeleteGlobalRef (env, + android_hardware_camera_parameters.FOCUS_MODE_CONTINUOUS_PICTURE); + android_hardware_camera_parameters.FOCUS_MODE_CONTINUOUS_PICTURE = NULL; + + if (java_lang_string.klass) + (*env)->DeleteGlobalRef (env, java_lang_string.klass); + java_lang_string.klass = NULL; + + if (java_util_list.klass) + (*env)->DeleteGlobalRef (env, java_util_list.klass); + java_util_list.klass = NULL; + + if (java_util_iterator.klass) + (*env)->DeleteGlobalRef (env, java_util_iterator.klass); + java_util_iterator.klass = NULL; + + if (java_lang_integer.klass) + (*env)->DeleteGlobalRef (env, java_lang_integer.klass); + java_lang_integer.klass = NULL; + + if (org_freedesktop_gstreamer_androidmedia_gstahccallback.klass) { + (*env)->UnregisterNatives (env, org_freedesktop_gstreamer_androidmedia_gstahccallback.klass); + (*env)->DeleteGlobalRef (env, org_freedesktop_gstreamer_androidmedia_gstahccallback.klass); + } + org_freedesktop_gstreamer_androidmedia_gstahccallback.klass = NULL; +} + +/* android.hardware.Camera */ +#define AHC_CALL(error_statement, type, method, ...) \ + GST_DVM_CALL (error_statement, self->object, type, android_hardware_camera, \ + method, ## __VA_ARGS__); +#define AHC_STATIC_CALL(error_statement, type, method, ...) \ + GST_DVM_STATIC_CALL (error_statement, type, android_hardware_camera, \ + method, ## __VA_ARGS__); + +void +gst_ah_camera_add_callback_buffer (GstAHCamera * self, jbyteArray buffer) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + GST_DEBUG ("add callback_buffer %p", buffer); + + AHC_CALL (, Void, addCallbackBuffer, buffer); +} + +gboolean +gst_ah_camera_auto_focus (GstAHCamera * self, + GstAHCAutoFocusCallback cb, gpointer user_data) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jobject object = NULL; + gboolean ret = FALSE; + + if (cb) { + object = (*env)->NewObject (env, + org_freedesktop_gstreamer_androidmedia_gstahccallback.klass, + org_freedesktop_gstreamer_androidmedia_gstahccallback.constructor, + *((jlong *) & cb), *((jlong *) & user_data)); + if (!object) { + GST_ERROR ("Failed to create callback object"); + (*env)->ExceptionClear (env); + goto done; + } + } + + AHC_CALL (goto done, Void, autoFocus, object); + + ret = TRUE; +done: + if (object) + (*env)->DeleteLocalRef (env, object); + + return ret; +} + +gboolean +gst_ah_camera_cancel_auto_focus (GstAHCamera * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + AHC_CALL (return FALSE, Void, cancelAutoFocus); + + return TRUE; +} + +gboolean +gst_ah_camera_get_camera_info (gint camera_id, GstAHCCameraInfo * camera_info) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jobject jcamera_info = NULL; + gboolean ret = FALSE; + + jcamera_info = (*env)->NewObject (env, + android_hardware_camera_camerainfo.klass, + android_hardware_camera_camerainfo.constructor); + if (!jcamera_info) { + GST_ERROR ("Failed to call Java method"); + (*env)->ExceptionClear (env); + goto done; + } + + AHC_STATIC_CALL (goto done, Void, getCameraInfo, camera_id, jcamera_info); + + camera_info->facing = (*env)->GetIntField (env, jcamera_info, + android_hardware_camera_camerainfo.facing); + if ((*env)->ExceptionCheck (env)) { + GST_ERROR ("Failed to get CameraInfo.facing field"); + (*env)->ExceptionClear (env); + goto done; + } + + camera_info->orientation = (*env)->GetIntField (env, jcamera_info, + android_hardware_camera_camerainfo.orientation); + if ((*env)->ExceptionCheck (env)) { + GST_ERROR ("Failed to get CameraInfo.orientation field"); + (*env)->ExceptionClear (env); + goto done; + } + + ret = TRUE; +done: + if (jcamera_info) + (*env)->DeleteLocalRef (env, jcamera_info); + + return ret; +} + +gint +gst_ah_camera_get_number_of_cameras (void) +{ + JNIEnv *env = gst_amc_jni_get_env (); + gint num_cameras; + + num_cameras = AHC_STATIC_CALL (return -1, Int, getNumberOfCameras); + + return num_cameras; +} + +GstAHCParameters * +gst_ah_camera_get_parameters (GstAHCamera * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jobject object = NULL; + GstAHCParameters *params = NULL; + + object = AHC_CALL (return NULL, Object, getParameters); + if (object) { + params = g_slice_new0 (GstAHCParameters); + params->object = (*env)->NewGlobalRef (env, object); + (*env)->DeleteLocalRef (env, object); + if (!params->object) { + GST_ERROR ("Failed to create global reference"); + (*env)->ExceptionClear (env); + g_slice_free (GstAHCParameters, params); + return NULL; + } + } + + GST_DEBUG ("return parameters %p", params->object); + + return params; +} + +gboolean +gst_ah_camera_lock (GstAHCamera * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + AHC_CALL (return FALSE, Void, lock); + + return TRUE; +} + +GstAHCamera * +gst_ah_camera_open (gint camera_id) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jobject object = NULL; + GstAHCamera *camera = NULL; + + object = AHC_STATIC_CALL (goto done, Object, open, camera_id); + if (object) { + camera = g_slice_new0 (GstAHCamera); + camera->object = (*env)->NewGlobalRef (env, object); + (*env)->DeleteLocalRef (env, object); + if (!camera->object) { + GST_ERROR ("Failed to create global reference"); + (*env)->ExceptionClear (env); + g_slice_free (GstAHCamera, camera); + camera = NULL; + } + } + +done: + return camera; +} + +gboolean +gst_ah_camera_reconnect (GstAHCamera * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + AHC_CALL (return FALSE, Void, reconnect); + + return TRUE; +} + +void +gst_ah_camera_release (GstAHCamera * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + AHC_CALL (, Void, release); +} + +void +gst_ah_camera_free (GstAHCamera * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + (*env)->DeleteGlobalRef (env, self->object); + g_slice_free (GstAHCamera, self); +} + + +gboolean +gst_ah_camera_set_parameters (GstAHCamera * self, GstAHCParameters * params) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + AHC_CALL (return FALSE, Void, setParameters, params->object); + + return TRUE; +} + +gboolean +gst_ah_camera_set_error_callback (GstAHCamera * self, GstAHCErrorCallback cb, + gpointer user_data) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jobject object = NULL; + gboolean ret = FALSE; + + if (cb) { + object = (*env)->NewObject (env, + org_freedesktop_gstreamer_androidmedia_gstahccallback.klass, + org_freedesktop_gstreamer_androidmedia_gstahccallback.constructor, + *((jlong *) & cb), *((jlong *) & user_data)); + if (!object) { + GST_ERROR ("Failed to create callback object"); + (*env)->ExceptionClear (env); + goto done; + } + } + + AHC_CALL (goto done, Void, setErrorCallback, object); + + ret = TRUE; +done: + if (object) + (*env)->DeleteLocalRef (env, object); + + return ret; +} + +gboolean +gst_ah_camera_set_preview_callback_with_buffer (GstAHCamera * self, + GstAHCPreviewCallback cb, gpointer user_data) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jobject object = NULL; + gboolean ret = FALSE; + + if (cb) { + object = (*env)->NewObject (env, + org_freedesktop_gstreamer_androidmedia_gstahccallback.klass, + org_freedesktop_gstreamer_androidmedia_gstahccallback.constructor, + *((jlong *) & cb), *((jlong *) & user_data)); + if (!object) { + GST_ERROR ("Failed to create callback object"); + (*env)->ExceptionClear (env); + goto done; + } + } + + AHC_CALL (goto done, Void, setPreviewCallbackWithBuffer, object); + + ret = TRUE; +done: + if (object) + (*env)->DeleteLocalRef (env, object); + + return ret; +} + +void +gst_ah_camera_set_preview_texture (GstAHCamera * self, + GstAGSurfaceTexture * surfaceTexture) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + AHC_CALL (, Void, setPreviewTexture, surfaceTexture->object); +} + +gboolean +gst_ah_camera_start_preview (GstAHCamera * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + AHC_CALL (return FALSE, Void, startPreview); + + return TRUE; +} + +gboolean +gst_ah_camera_start_smooth_zoom (GstAHCamera * self, gint value) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + AHC_CALL (return FALSE, Void, startSmoothZoom, value); + + return TRUE; +} + +gboolean +gst_ah_camera_stop_preview (GstAHCamera * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + AHC_CALL (return FALSE, Void, stopPreview); + + return TRUE; +} + +gboolean +gst_ah_camera_stop_smooth_zoom (GstAHCamera * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + AHC_CALL (return FALSE, Void, stopSmoothZoom); + + return TRUE; +} + +gboolean +gst_ah_camera_unlock (GstAHCamera * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + AHC_CALL (return FALSE, Void, unlock); + + return TRUE; +} + +#undef AHC_CALL +#undef AHC_STATIC_CALL + +/* android.hardware.Camera.Size */ +GstAHCSize * +gst_ahc_size_new (gint width, gint height) +{ + GstAHCSize *self = g_slice_new0 (GstAHCSize); + + self->width = width; + self->height = height; + + return self; +} + +void +gst_ahc_size_free (GstAHCSize * self) +{ + g_slice_free (GstAHCSize, self); +} + +/* java.lang.String */ +static jboolean +java_lang_string_equals (JNIEnv * env, jstring str, jstring obj) +{ + return (*env)->CallBooleanMethod (env, str, java_lang_string.equals, obj); +} + +/* java.util.List */ +static jobject +java_util_list_iterator (JNIEnv * env, jobject obj) +{ + return (*env)->CallObjectMethod (env, obj, java_util_list.iterator); +} + +/* java.util.Iterator */ +static jobject +java_util_iterator_next (JNIEnv * env, jobject obj) +{ + return (*env)->CallObjectMethod (env, obj, java_util_iterator.next); +} + +static jboolean +java_util_iterator_has_next (JNIEnv * env, jobject obj) +{ + return (*env)->CallBooleanMethod (env, obj, java_util_iterator.hasNext); +} + +/* java.lang.Integer */ +static jint +java_lang_integer_int_value (JNIEnv * env, jobject obj) +{ + return (*env)->CallIntMethod (env, obj, java_lang_integer.intValue); +} + + +/* android.hardware.Camera.Parameters */ +#define AHCP_CALL(error_statement, type, method, ...) \ + GST_DVM_CALL (error_statement, self->object, type, \ + android_hardware_camera_parameters, method, ## __VA_ARGS__); + +#define AHCP_STATIC_CALL(error_statement, type, method, ...) \ + GST_DVM_STATIC_CALL (error_statement, type, \ + android_hardware_camera_parameters, method, ## __VA_ARGS__); + +static const gchar * +_white_balance_to_gchar (JNIEnv * env, jstring white_balance) +{ + if (!white_balance) + return NULL; + + if (java_lang_string_equals (env, white_balance, + android_hardware_camera_parameters.WHITE_BALANCE_AUTO)) + return Parameters_WHITE_BALANCE_AUTO; + else if (java_lang_string_equals (env, white_balance, + android_hardware_camera_parameters.WHITE_BALANCE_INCANDESCENT)) + return Parameters_WHITE_BALANCE_INCANDESCENT; + else if (java_lang_string_equals (env, white_balance, + android_hardware_camera_parameters.WHITE_BALANCE_FLUORESCENT)) + return Parameters_WHITE_BALANCE_FLUORESCENT; + else if (java_lang_string_equals (env, white_balance, + android_hardware_camera_parameters.WHITE_BALANCE_WARM_FLUORESCENT)) + return Parameters_WHITE_BALANCE_WARM_FLUORESCENT; + else if (java_lang_string_equals (env, white_balance, + android_hardware_camera_parameters.WHITE_BALANCE_DAYLIGHT)) + return Parameters_WHITE_BALANCE_DAYLIGHT; + else if (java_lang_string_equals (env, white_balance, + android_hardware_camera_parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT)) + return Parameters_WHITE_BALANCE_CLOUDY_DAYLIGHT; + else if (java_lang_string_equals (env, white_balance, + android_hardware_camera_parameters.WHITE_BALANCE_TWILIGHT)) + return Parameters_WHITE_BALANCE_TWILIGHT; + else if (java_lang_string_equals (env, white_balance, + android_hardware_camera_parameters.WHITE_BALANCE_SHADE)) + return Parameters_WHITE_BALANCE_SHADE; + + return NULL; +} + +static jstring +_white_balance_to_jstring (const gchar * white_balance) +{ + if (!white_balance) + return NULL; + + if (!g_strcmp0 (white_balance, Parameters_WHITE_BALANCE_AUTO)) + return android_hardware_camera_parameters.WHITE_BALANCE_AUTO; + else if (!g_strcmp0 (white_balance, Parameters_WHITE_BALANCE_INCANDESCENT)) + return android_hardware_camera_parameters.WHITE_BALANCE_INCANDESCENT; + else if (!g_strcmp0 (white_balance, Parameters_WHITE_BALANCE_FLUORESCENT)) + return android_hardware_camera_parameters.WHITE_BALANCE_FLUORESCENT; + else if (!g_strcmp0 (white_balance, + Parameters_WHITE_BALANCE_WARM_FLUORESCENT)) + return android_hardware_camera_parameters.WHITE_BALANCE_WARM_FLUORESCENT; + else if (!g_strcmp0 (white_balance, Parameters_WHITE_BALANCE_DAYLIGHT)) + return android_hardware_camera_parameters.WHITE_BALANCE_DAYLIGHT; + else if (!g_strcmp0 (white_balance, Parameters_WHITE_BALANCE_CLOUDY_DAYLIGHT)) + return android_hardware_camera_parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT; + else if (!g_strcmp0 (white_balance, Parameters_WHITE_BALANCE_TWILIGHT)) + return android_hardware_camera_parameters.WHITE_BALANCE_TWILIGHT; + else if (!g_strcmp0 (white_balance, Parameters_WHITE_BALANCE_SHADE)) + return android_hardware_camera_parameters.WHITE_BALANCE_SHADE; + + return NULL; +} + +static const gchar * +_color_effect_to_gchar (JNIEnv * env, jstring color_effect) +{ + if (!color_effect) + return NULL; + + if (java_lang_string_equals (env, color_effect, + android_hardware_camera_parameters.EFFECT_NONE)) + return Parameters_EFFECT_NONE; + else if (java_lang_string_equals (env, color_effect, + android_hardware_camera_parameters.EFFECT_MONO)) + return Parameters_EFFECT_MONO; + else if (java_lang_string_equals (env, color_effect, + android_hardware_camera_parameters.EFFECT_NEGATIVE)) + return Parameters_EFFECT_NEGATIVE; + else if (java_lang_string_equals (env, color_effect, + android_hardware_camera_parameters.EFFECT_SOLARIZE)) + return Parameters_EFFECT_SOLARIZE; + else if (java_lang_string_equals (env, color_effect, + android_hardware_camera_parameters.EFFECT_SEPIA)) + return Parameters_EFFECT_SEPIA; + else if (java_lang_string_equals (env, color_effect, + android_hardware_camera_parameters.EFFECT_POSTERIZE)) + return Parameters_EFFECT_POSTERIZE; + else if (java_lang_string_equals (env, color_effect, + android_hardware_camera_parameters.EFFECT_WHITEBOARD)) + return Parameters_EFFECT_WHITEBOARD; + else if (java_lang_string_equals (env, color_effect, + android_hardware_camera_parameters.EFFECT_BLACKBOARD)) + return Parameters_EFFECT_BLACKBOARD; + else if (java_lang_string_equals (env, color_effect, + android_hardware_camera_parameters.EFFECT_AQUA)) + return Parameters_EFFECT_AQUA; + + return NULL; +} + +static jstring +_color_effect_to_jstring (const gchar * color_effect) +{ + if (!color_effect) + return NULL; + + if (!g_strcmp0 (color_effect, Parameters_EFFECT_NONE)) + return android_hardware_camera_parameters.EFFECT_NONE; + else if (!g_strcmp0 (color_effect, Parameters_EFFECT_MONO)) + return android_hardware_camera_parameters.EFFECT_MONO; + else if (!g_strcmp0 (color_effect, Parameters_EFFECT_NEGATIVE)) + return android_hardware_camera_parameters.EFFECT_NEGATIVE; + else if (!g_strcmp0 (color_effect, Parameters_EFFECT_SOLARIZE)) + return android_hardware_camera_parameters.EFFECT_SOLARIZE; + else if (!g_strcmp0 (color_effect, Parameters_EFFECT_SEPIA)) + return android_hardware_camera_parameters.EFFECT_SEPIA; + else if (!g_strcmp0 (color_effect, Parameters_EFFECT_POSTERIZE)) + return android_hardware_camera_parameters.EFFECT_POSTERIZE; + else if (!g_strcmp0 (color_effect, Parameters_EFFECT_WHITEBOARD)) + return android_hardware_camera_parameters.EFFECT_WHITEBOARD; + else if (!g_strcmp0 (color_effect, Parameters_EFFECT_BLACKBOARD)) + return android_hardware_camera_parameters.EFFECT_BLACKBOARD; + else if (!g_strcmp0 (color_effect, Parameters_EFFECT_AQUA)) + return android_hardware_camera_parameters.EFFECT_AQUA; + + return NULL; +} + +static const gchar * +_antibanding_to_gchar (JNIEnv * env, jstring antibanding) +{ + if (!antibanding) + return NULL; + + if (java_lang_string_equals (env, antibanding, + android_hardware_camera_parameters.ANTIBANDING_AUTO)) + return Parameters_ANTIBANDING_AUTO; + else if (java_lang_string_equals (env, antibanding, + android_hardware_camera_parameters.ANTIBANDING_50HZ)) + return Parameters_ANTIBANDING_50HZ; + else if (java_lang_string_equals (env, antibanding, + android_hardware_camera_parameters.ANTIBANDING_60HZ)) + return Parameters_ANTIBANDING_60HZ; + else if (java_lang_string_equals (env, antibanding, + android_hardware_camera_parameters.ANTIBANDING_OFF)) + return Parameters_ANTIBANDING_OFF; + + return NULL; +} + +static jstring +_antibanding_to_jstring (const gchar * antibanding) +{ + if (!antibanding) + return NULL; + + if (!g_strcmp0 (antibanding, Parameters_ANTIBANDING_AUTO)) + return android_hardware_camera_parameters.ANTIBANDING_AUTO; + else if (!g_strcmp0 (antibanding, Parameters_ANTIBANDING_50HZ)) + return android_hardware_camera_parameters.ANTIBANDING_50HZ; + else if (!g_strcmp0 (antibanding, Parameters_ANTIBANDING_60HZ)) + return android_hardware_camera_parameters.ANTIBANDING_60HZ; + else if (!g_strcmp0 (antibanding, Parameters_ANTIBANDING_OFF)) + return android_hardware_camera_parameters.ANTIBANDING_OFF; + + return NULL; +} + +static const gchar * +_flash_mode_to_gchar (JNIEnv * env, jstring flash_mode) +{ + if (!flash_mode) + return NULL; + + if (java_lang_string_equals (env, flash_mode, + android_hardware_camera_parameters.FLASH_MODE_OFF)) + return Parameters_FLASH_MODE_OFF; + else if (java_lang_string_equals (env, flash_mode, + android_hardware_camera_parameters.FLASH_MODE_AUTO)) + return Parameters_FLASH_MODE_AUTO; + else if (java_lang_string_equals (env, flash_mode, + android_hardware_camera_parameters.FLASH_MODE_ON)) + return Parameters_FLASH_MODE_ON; + else if (java_lang_string_equals (env, flash_mode, + android_hardware_camera_parameters.FLASH_MODE_RED_EYE)) + return Parameters_FLASH_MODE_RED_EYE; + else if (java_lang_string_equals (env, flash_mode, + android_hardware_camera_parameters.FLASH_MODE_TORCH)) + return Parameters_FLASH_MODE_TORCH; + + return NULL; +} + +static jstring +_flash_mode_to_jstring (const gchar * flash_mode) +{ + if (!flash_mode) + return NULL; + + if (!g_strcmp0 (flash_mode, Parameters_FLASH_MODE_OFF)) + return android_hardware_camera_parameters.FLASH_MODE_OFF; + else if (!g_strcmp0 (flash_mode, Parameters_FLASH_MODE_AUTO)) + return android_hardware_camera_parameters.FLASH_MODE_AUTO; + else if (!g_strcmp0 (flash_mode, Parameters_FLASH_MODE_ON)) + return android_hardware_camera_parameters.FLASH_MODE_ON; + else if (!g_strcmp0 (flash_mode, Parameters_FLASH_MODE_RED_EYE)) + return android_hardware_camera_parameters.FLASH_MODE_RED_EYE; + else if (!g_strcmp0 (flash_mode, Parameters_FLASH_MODE_TORCH)) + return android_hardware_camera_parameters.FLASH_MODE_TORCH; + + return NULL; +} + +static const gchar * +_scene_mode_to_gchar (JNIEnv * env, jstring scene_mode) +{ + if (!scene_mode) + return NULL; + + if (java_lang_string_equals (env, scene_mode, + android_hardware_camera_parameters.SCENE_MODE_AUTO)) + return Parameters_SCENE_MODE_AUTO; + else if (java_lang_string_equals (env, scene_mode, + android_hardware_camera_parameters.SCENE_MODE_ACTION)) + return Parameters_SCENE_MODE_ACTION; + else if (java_lang_string_equals (env, scene_mode, + android_hardware_camera_parameters.SCENE_MODE_PORTRAIT)) + return Parameters_SCENE_MODE_PORTRAIT; + else if (java_lang_string_equals (env, scene_mode, + android_hardware_camera_parameters.SCENE_MODE_LANDSCAPE)) + return Parameters_SCENE_MODE_LANDSCAPE; + else if (java_lang_string_equals (env, scene_mode, + android_hardware_camera_parameters.SCENE_MODE_NIGHT)) + return Parameters_SCENE_MODE_NIGHT; + else if (java_lang_string_equals (env, scene_mode, + android_hardware_camera_parameters.SCENE_MODE_NIGHT_PORTRAIT)) + return Parameters_SCENE_MODE_NIGHT_PORTRAIT; + else if (java_lang_string_equals (env, scene_mode, + android_hardware_camera_parameters.SCENE_MODE_THEATRE)) + return Parameters_SCENE_MODE_THEATRE; + else if (java_lang_string_equals (env, scene_mode, + android_hardware_camera_parameters.SCENE_MODE_BEACH)) + return Parameters_SCENE_MODE_BEACH; + else if (java_lang_string_equals (env, scene_mode, + android_hardware_camera_parameters.SCENE_MODE_SNOW)) + return Parameters_SCENE_MODE_SNOW; + else if (java_lang_string_equals (env, scene_mode, + android_hardware_camera_parameters.SCENE_MODE_SUNSET)) + return Parameters_SCENE_MODE_SUNSET; + else if (java_lang_string_equals (env, scene_mode, + android_hardware_camera_parameters.SCENE_MODE_STEADYPHOTO)) + return Parameters_SCENE_MODE_STEADYPHOTO; + else if (java_lang_string_equals (env, scene_mode, + android_hardware_camera_parameters.SCENE_MODE_FIREWORKS)) + return Parameters_SCENE_MODE_FIREWORKS; + else if (java_lang_string_equals (env, scene_mode, + android_hardware_camera_parameters.SCENE_MODE_SPORTS)) + return Parameters_SCENE_MODE_SPORTS; + else if (java_lang_string_equals (env, scene_mode, + android_hardware_camera_parameters.SCENE_MODE_PARTY)) + return Parameters_SCENE_MODE_PARTY; + else if (java_lang_string_equals (env, scene_mode, + android_hardware_camera_parameters.SCENE_MODE_CANDLELIGHT)) + return Parameters_SCENE_MODE_CANDLELIGHT; + else if (java_lang_string_equals (env, scene_mode, + android_hardware_camera_parameters.SCENE_MODE_BARCODE)) + return Parameters_SCENE_MODE_BARCODE; + + return NULL; +} + +static const jstring +_scene_mode_to_jstring (const gchar * scene_mode) +{ + if (!scene_mode) + return NULL; + + if (!g_strcmp0 (scene_mode, Parameters_SCENE_MODE_AUTO)) + return android_hardware_camera_parameters.SCENE_MODE_AUTO; + else if (!g_strcmp0 (scene_mode, Parameters_SCENE_MODE_ACTION)) + return android_hardware_camera_parameters.SCENE_MODE_ACTION; + else if (!g_strcmp0 (scene_mode, Parameters_SCENE_MODE_PORTRAIT)) + return android_hardware_camera_parameters.SCENE_MODE_PORTRAIT; + else if (!g_strcmp0 (scene_mode, Parameters_SCENE_MODE_LANDSCAPE)) + return android_hardware_camera_parameters.SCENE_MODE_LANDSCAPE; + else if (!g_strcmp0 (scene_mode, Parameters_SCENE_MODE_NIGHT)) + return android_hardware_camera_parameters.SCENE_MODE_NIGHT; + else if (!g_strcmp0 (scene_mode, Parameters_SCENE_MODE_NIGHT_PORTRAIT)) + return android_hardware_camera_parameters.SCENE_MODE_NIGHT_PORTRAIT; + else if (!g_strcmp0 (scene_mode, Parameters_SCENE_MODE_THEATRE)) + return android_hardware_camera_parameters.SCENE_MODE_THEATRE; + else if (!g_strcmp0 (scene_mode, Parameters_SCENE_MODE_BEACH)) + return android_hardware_camera_parameters.SCENE_MODE_BEACH; + else if (!g_strcmp0 (scene_mode, Parameters_SCENE_MODE_SNOW)) + return android_hardware_camera_parameters.SCENE_MODE_SNOW; + else if (!g_strcmp0 (scene_mode, Parameters_SCENE_MODE_SUNSET)) + return android_hardware_camera_parameters.SCENE_MODE_SUNSET; + else if (!g_strcmp0 (scene_mode, Parameters_SCENE_MODE_STEADYPHOTO)) + return android_hardware_camera_parameters.SCENE_MODE_STEADYPHOTO; + else if (!g_strcmp0 (scene_mode, Parameters_SCENE_MODE_FIREWORKS)) + return android_hardware_camera_parameters.SCENE_MODE_FIREWORKS; + else if (!g_strcmp0 (scene_mode, Parameters_SCENE_MODE_SPORTS)) + return android_hardware_camera_parameters.SCENE_MODE_SPORTS; + else if (!g_strcmp0 (scene_mode, Parameters_SCENE_MODE_PARTY)) + return android_hardware_camera_parameters.SCENE_MODE_PARTY; + else if (!g_strcmp0 (scene_mode, Parameters_SCENE_MODE_CANDLELIGHT)) + return android_hardware_camera_parameters.SCENE_MODE_CANDLELIGHT; + else if (!g_strcmp0 (scene_mode, Parameters_SCENE_MODE_BARCODE)) + return android_hardware_camera_parameters.SCENE_MODE_BARCODE; + + return NULL; +} + +static const gchar * +_focus_mode_to_gchar (JNIEnv * env, jstring focus_mode) +{ + if (!focus_mode) + return NULL; + + if (java_lang_string_equals (env, focus_mode, + android_hardware_camera_parameters.FOCUS_MODE_AUTO)) + return Parameters_FOCUS_MODE_AUTO; + else if (java_lang_string_equals (env, focus_mode, + android_hardware_camera_parameters.FOCUS_MODE_INFINITY)) + return Parameters_FOCUS_MODE_INFINITY; + else if (java_lang_string_equals (env, focus_mode, + android_hardware_camera_parameters.FOCUS_MODE_MACRO)) + return Parameters_FOCUS_MODE_MACRO; + else if (java_lang_string_equals (env, focus_mode, + android_hardware_camera_parameters.FOCUS_MODE_FIXED)) + return Parameters_FOCUS_MODE_FIXED; + else if (java_lang_string_equals (env, focus_mode, + android_hardware_camera_parameters.FOCUS_MODE_EDOF)) + return Parameters_FOCUS_MODE_EDOF; + else if (java_lang_string_equals (env, focus_mode, + android_hardware_camera_parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) + return Parameters_FOCUS_MODE_CONTINUOUS_VIDEO; + else if (java_lang_string_equals (env, focus_mode, + android_hardware_camera_parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) + return Parameters_FOCUS_MODE_CONTINUOUS_PICTURE; + + return NULL; +} + +static jstring +_focus_mode_to_jstring (const gchar * focus_mode) +{ + if (!focus_mode) + return NULL; + + if (!g_strcmp0 (focus_mode, Parameters_FOCUS_MODE_AUTO)) + return android_hardware_camera_parameters.FOCUS_MODE_AUTO; + else if (!g_strcmp0 (focus_mode, Parameters_FOCUS_MODE_INFINITY)) + return android_hardware_camera_parameters.FOCUS_MODE_INFINITY; + else if (!g_strcmp0 (focus_mode, Parameters_FOCUS_MODE_MACRO)) + return android_hardware_camera_parameters.FOCUS_MODE_MACRO; + else if (!g_strcmp0 (focus_mode, Parameters_FOCUS_MODE_FIXED)) + return android_hardware_camera_parameters.FOCUS_MODE_FIXED; + else if (!g_strcmp0 (focus_mode, Parameters_FOCUS_MODE_EDOF)) + return android_hardware_camera_parameters.FOCUS_MODE_EDOF; + else if (!g_strcmp0 (focus_mode, Parameters_FOCUS_MODE_CONTINUOUS_VIDEO)) + return android_hardware_camera_parameters.FOCUS_MODE_CONTINUOUS_VIDEO; + else if (!g_strcmp0 (focus_mode, Parameters_FOCUS_MODE_CONTINUOUS_PICTURE)) + return android_hardware_camera_parameters.FOCUS_MODE_CONTINUOUS_PICTURE; + + return NULL; +} + +gchar * +gst_ahc_parameters_flatten (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jstring v_str = NULL; + const gchar *v = NULL; + gchar *ret = NULL; + + v_str = AHCP_CALL (goto done, Object, flatten); + v = (*env)->GetStringUTFChars (env, v_str, NULL); + if (!v) { + GST_ERROR ("Failed to convert string to UTF8"); + (*env)->ExceptionClear (env); + goto done; + } + + ret = g_strdup (v); +done: + if (v) + (*env)->ReleaseStringUTFChars (env, v_str, v); + if (v_str) + (*env)->DeleteLocalRef (env, v_str); + + return ret; +} + +const gchar * +gst_ahc_parameters_get_antibanding (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + const gchar *ret = NULL; + jstring antibanding; + + antibanding = AHCP_CALL (return NULL, Object, getAntibanding); + + ret = _antibanding_to_gchar (env, antibanding); + + if (antibanding) + (*env)->DeleteLocalRef (env, antibanding); + + return ret; +} + +const gchar * +gst_ahc_parameters_get_color_effect (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + const gchar *ret = NULL; + jstring color_effect; + + color_effect = AHCP_CALL (return NULL, Object, getColorEffect); + + ret = _color_effect_to_gchar (env, color_effect); + + if (color_effect) + (*env)->DeleteLocalRef (env, color_effect); + + return ret; +} + +gint +gst_ahc_parameters_get_exposure_compensation (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + gint ev; + + ev = AHCP_CALL (return -1, Int, getExposureCompensation); + + return ev; +} + +gfloat +gst_ahc_parameters_get_exposure_compensation_step (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + gfloat step; + + step = AHCP_CALL (return 0.0, Float, getExposureCompensationStep); + + return step; +} + +const gchar * +gst_ahc_parameters_get_flash_mode (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + const gchar *ret = NULL; + jstring flash_mode; + + flash_mode = AHCP_CALL (return NULL, Object, getFlashMode); + + ret = _flash_mode_to_gchar (env, flash_mode); + + if (flash_mode) + (*env)->DeleteLocalRef (env, flash_mode); + + return ret; +} + +gfloat +gst_ahc_parameters_get_focal_length (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + gfloat length; + + length = AHCP_CALL (return 0.0, Float, getFocalLength); + + return length; +} + +const gchar * +gst_ahc_parameters_get_focus_mode (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + const gchar *ret = NULL; + jstring focus_mode; + + focus_mode = AHCP_CALL (return NULL, Object, getFocusMode); + + ret = _focus_mode_to_gchar (env, focus_mode); + + if (focus_mode) + (*env)->DeleteLocalRef (env, focus_mode); + + return ret; +} + +gfloat +gst_ahc_parameters_get_horizontal_view_angle (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + gfloat angle; + + angle = AHCP_CALL (return 0.0, Float, getHorizontalViewAngle); + + return angle; +} + +gint +gst_ahc_parameters_get_max_exposure_compensation (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + gint max; + + max = AHCP_CALL (return 0, Int, getMaxExposureCompensation); + + return max; +} + +gint +gst_ahc_parameters_get_max_zoom (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + gint max; + + max = AHCP_CALL (return -1, Int, getMaxZoom); + + return max; +} + +gint +gst_ahc_parameters_get_min_exposure_compensation (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + gint min; + + min = AHCP_CALL (return 0, Int, getMinExposureCompensation); + + return min; +} + +gint +gst_ahc_parameters_get_preview_format (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + gint format; + + format = AHCP_CALL (return 0, Int, getPreviewFormat); + + return format; +} + +gboolean +gst_ahc_parameters_get_preview_fps_range (GstAHCParameters * self, + gint * min, gint * max) +{ + JNIEnv *env = gst_amc_jni_get_env (); + gboolean ret = FALSE; + jintArray range = NULL; + jint *fps = NULL; + + range = (*env)->NewIntArray (env, 2); + if (!fps) { + (*env)->ExceptionClear (env); + GST_ERROR ("Failed to create array"); + goto done; + } + + AHCP_CALL (goto done, Void, getPreviewFpsRange, range); + + fps = (*env)->GetIntArrayElements (env, range, NULL); + if ((*env)->ExceptionCheck (env) || !fps) { + (*env)->ExceptionClear (env); + GST_ERROR ("Failed to get array elements"); + goto done; + } + if (min) + *min = fps[0]; + if (max) + *max = fps[1]; + + ret = TRUE; +done: + if (fps) + (*env)->ReleaseIntArrayElements (env, range, fps, JNI_ABORT); + if (range) + (*env)->DeleteLocalRef (env, range); + + return ret; +} + +GstAHCSize * +gst_ahc_parameters_get_preview_size (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jobject jsize = NULL; + GstAHCSize *size = NULL; + + jsize = AHCP_CALL (goto done, Object, getPreviewSize); + + size = g_slice_new0 (GstAHCSize); + + size->width = (*env)->GetIntField (env, jsize, + android_hardware_camera_size.width); + if ((*env)->ExceptionCheck (env)) { + GST_ERROR ("Failed to get Camera.Size.width field"); + (*env)->ExceptionClear (env); + g_slice_free (GstAHCSize, size); + size = NULL; + goto done; + } + + size->height = (*env)->GetIntField (env, jsize, + android_hardware_camera_size.height); + if ((*env)->ExceptionCheck (env)) { + GST_ERROR ("Failed to get Camera.Size.height field"); + (*env)->ExceptionClear (env); + g_slice_free (GstAHCSize, size); + size = NULL; + goto done; + } + +done: + if (jsize) + (*env)->DeleteLocalRef (env, jsize); + + return size; +} + +const gchar * +gst_ahc_parameters_get_scene_mode (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + const gchar *ret = NULL; + jstring scene_mode; + + scene_mode = AHCP_CALL (return NULL, Object, getSceneMode); + + ret = _scene_mode_to_gchar (env, scene_mode); + + if (scene_mode) + (*env)->DeleteLocalRef (env, scene_mode); + + return ret; +} + +GList * +gst_ahc_parameters_get_supported_antibanding (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jobject list = NULL; + GList *ret = NULL; + + list = AHCP_CALL (return NULL, Object, getSupportedAntibanding); + + if (list) { + jobject iterator = NULL; + + iterator = java_util_list_iterator (env, list); + if (iterator) { + while (java_util_iterator_has_next (env, iterator)) { + jobject str = java_util_iterator_next (env, iterator); + + if (str) { + const gchar *value = _antibanding_to_gchar (env, str); + + ret = g_list_append (ret, (gchar *) value); + (*env)->DeleteLocalRef (env, str); + } + } + (*env)->DeleteLocalRef (env, iterator); + } + (*env)->DeleteLocalRef (env, list); + } + + return ret; +} + +void +gst_ahc_parameters_supported_antibanding_free (GList * list) +{ + g_list_free (list); +} + +GList * +gst_ahc_parameters_get_supported_color_effects (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jobject list = NULL; + GList *ret = NULL; + + list = AHCP_CALL (return NULL, Object, getSupportedColorEffects); + + if (list) { + jobject iterator = NULL; + + iterator = java_util_list_iterator (env, list); + if (iterator) { + while (java_util_iterator_has_next (env, iterator)) { + jobject str = java_util_iterator_next (env, iterator); + + if (str) { + const gchar *value = _color_effect_to_gchar (env, str); + + ret = g_list_append (ret, (gchar *) value); + (*env)->DeleteLocalRef (env, str); + } + } + (*env)->DeleteLocalRef (env, iterator); + } + (*env)->DeleteLocalRef (env, list); + } + + return ret; +} + +void +gst_ahc_parameters_supported_color_effects_free (GList * list) +{ + g_list_free (list); +} + +GList * +gst_ahc_parameters_get_supported_flash_modes (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jobject list = NULL; + GList *ret = NULL; + + list = AHCP_CALL (return NULL, Object, getSupportedFlashModes); + + if (list) { + jobject iterator = NULL; + + iterator = java_util_list_iterator (env, list); + if (iterator) { + while (java_util_iterator_has_next (env, iterator)) { + jobject str = java_util_iterator_next (env, iterator); + + if (str) { + const gchar *value = _flash_mode_to_gchar (env, str); + + ret = g_list_append (ret, (gchar *) value); + (*env)->DeleteLocalRef (env, str); + } + } + (*env)->DeleteLocalRef (env, iterator); + } + (*env)->DeleteLocalRef (env, list); + } + + return ret; +} + +void +gst_ahc_parameters_supported_flash_modes_free (GList * list) +{ + g_list_free (list); +} + +GList * +gst_ahc_parameters_get_supported_focus_modes (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jobject list = NULL; + GList *ret = NULL; + + list = AHCP_CALL (return NULL, Object, getSupportedFocusModes); + + if (list) { + jobject iterator = NULL; + + iterator = java_util_list_iterator (env, list); + if (iterator) { + while (java_util_iterator_has_next (env, iterator)) { + jobject str = java_util_iterator_next (env, iterator); + + if (str) { + const gchar *value = _focus_mode_to_gchar (env, str); + + ret = g_list_append (ret, (gchar *) value); + (*env)->DeleteLocalRef (env, str); + } + } + (*env)->DeleteLocalRef (env, iterator); + } + (*env)->DeleteLocalRef (env, list); + } + + return ret; +} + +void +gst_ahc_parameters_supported_focus_modes_free (GList * list) +{ + g_list_free (list); +} + +GList * +gst_ahc_parameters_get_supported_preview_formats (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jobject list = NULL; + GList *ret = NULL; + + list = AHCP_CALL (return NULL, Object, getSupportedPreviewFormats); + + if (list) { + jobject iterator = NULL; + + iterator = java_util_list_iterator (env, list); + if (iterator) { + while (java_util_iterator_has_next (env, iterator)) { + jobject integer = java_util_iterator_next (env, iterator); + + if (integer) { + jint value = java_lang_integer_int_value (env, integer); + + ret = g_list_append (ret, GINT_TO_POINTER (value)); + (*env)->DeleteLocalRef (env, integer); + } + } + (*env)->DeleteLocalRef (env, iterator); + } + (*env)->DeleteLocalRef (env, list); + } + + return ret; +} + +void +gst_ahc_parameters_supported_preview_formats_free (GList * list) +{ + g_list_free (list); +} + +GList * +gst_ahc_parameters_get_supported_preview_fps_range (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jobject list = NULL; + GList *ret = NULL; + + list = AHCP_CALL (return NULL, Object, getSupportedPreviewFpsRange); + + if (list) { + jobject iterator = NULL; + + iterator = java_util_list_iterator (env, list); + if (iterator) { + while (java_util_iterator_has_next (env, iterator)) { + jintArray range = java_util_iterator_next (env, iterator); + + if (range) { + jint *fps = g_new (jint, 2); + + (*env)->GetIntArrayRegion (env, range, 0, 2, fps); + ret = g_list_append (ret, fps); + (*env)->DeleteLocalRef (env, range); + } + } + (*env)->DeleteLocalRef (env, iterator); + } + (*env)->DeleteLocalRef (env, list); + } + + return ret; +} + +void +gst_ahc_parameters_supported_preview_fps_range_free (GList * list) +{ + g_list_foreach (list, (GFunc) g_free, NULL); + g_list_free (list); +} + +GList * +gst_ahc_parameters_get_supported_preview_sizes (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jobject list = NULL; + GList *ret = NULL; + + list = AHCP_CALL (return NULL, Object, getSupportedPreviewSizes); + + if (list) { + jobject iterator = NULL; + + iterator = java_util_list_iterator (env, list); + if (iterator) { + while (java_util_iterator_has_next (env, iterator)) { + jobject jsize = java_util_iterator_next (env, iterator); + + if (jsize) { + jint width, height; + + width = (*env)->GetIntField (env, jsize, + android_hardware_camera_size.width); + height = (*env)->GetIntField (env, jsize, + android_hardware_camera_size.height); + + ret = g_list_append (ret, gst_ahc_size_new (width, height)); + (*env)->DeleteLocalRef (env, jsize); + } + } + (*env)->DeleteLocalRef (env, iterator); + } + (*env)->DeleteLocalRef (env, list); + } + + return ret; +} + +void +gst_ahc_parameters_supported_preview_sizes_free (GList * list) +{ + g_list_foreach (list, (GFunc) gst_ahc_size_free, NULL); + g_list_free (list); +} + +GList * +gst_ahc_parameters_get_supported_scene_modes (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jobject list = NULL; + GList *ret = NULL; + + list = AHCP_CALL (return NULL, Object, getSupportedSceneModes); + + if (list) { + jobject iterator = NULL; + + iterator = java_util_list_iterator (env, list); + if (iterator) { + while (java_util_iterator_has_next (env, iterator)) { + jobject str = java_util_iterator_next (env, iterator); + + if (str) { + const gchar *value = _scene_mode_to_gchar (env, str); + + ret = g_list_append (ret, (gchar *) value); + (*env)->DeleteLocalRef (env, str); + } + } + (*env)->DeleteLocalRef (env, iterator); + } + (*env)->DeleteLocalRef (env, list); + } + + return ret; +} + +void +gst_ahc_parameters_supported_scene_modes_free (GList * list) +{ + g_list_free (list); +} + +GList * +gst_ahc_parameters_get_supported_white_balance (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jobject list = NULL; + GList *ret = NULL; + + list = AHCP_CALL (return NULL, Object, getSupportedWhiteBalance); + + if (list) { + jobject iterator = NULL; + + iterator = java_util_list_iterator (env, list); + if (iterator) { + while (java_util_iterator_has_next (env, iterator)) { + jobject str = java_util_iterator_next (env, iterator); + + if (str) { + const gchar *value = _white_balance_to_gchar (env, str); + + ret = g_list_append (ret, (gchar *) value); + (*env)->DeleteLocalRef (env, str); + } + } + (*env)->DeleteLocalRef (env, iterator); + } + (*env)->DeleteLocalRef (env, list); + } + + return ret; +} + +void +gst_ahc_parameters_supported_white_balance_free (GList * list) +{ + g_list_free (list); +} + +gfloat +gst_ahc_parameters_get_vertical_view_angle (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + gfloat angle; + + angle = AHCP_CALL (return 0.0, Float, getVerticalViewAngle); + + return angle; +} + +gboolean +gst_ahc_parameters_get_video_stabilization (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + gboolean ret; + + ret = AHCP_CALL (return FALSE, Boolean, getVideoStabilization); + + return ret; +} + +const gchar * +gst_ahc_parameters_get_white_balance (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + const gchar *ret = NULL; + jstring white_balance; + + white_balance = AHCP_CALL (return NULL, Object, getWhiteBalance); + + ret = _white_balance_to_gchar (env, white_balance); + + if (white_balance) + (*env)->DeleteLocalRef (env, white_balance); + + return ret; +} + +gint +gst_ahc_parameters_get_zoom (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + gint zoom; + + zoom = AHCP_CALL (return -1, Int, getZoom); + + return zoom; +} + +GList * +gst_ahc_parameters_get_zoom_ratios (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jobject list = NULL; + GList *ret = NULL; + + list = AHCP_CALL (return NULL, Object, getZoomRatios); + + if (list) { + jobject iterator = NULL; + + iterator = java_util_list_iterator (env, list); + if (iterator) { + while (java_util_iterator_has_next (env, iterator)) { + jobject integer = java_util_iterator_next (env, iterator); + + if (integer) { + jint value = java_lang_integer_int_value (env, integer); + + ret = g_list_append (ret, GINT_TO_POINTER (value)); + (*env)->DeleteLocalRef (env, integer); + } + } + (*env)->DeleteLocalRef (env, iterator); + } + (*env)->DeleteLocalRef (env, list); + } + + return ret; +} + +void +gst_ahc_parameters_zoom_ratios_free (GList * list) +{ + g_list_free (list); +} + +gboolean +gst_ahc_parameters_is_smooth_zoom_supported (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + gboolean supported; + + supported = AHCP_CALL (return FALSE, Boolean, isSmoothZoomSupported); + + return supported; +} + +gboolean +gst_ahc_parameters_is_video_stabilization_supported (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + gboolean supported; + + supported = AHCP_CALL (return FALSE, Boolean, isVideoStabilizationSupported); + + return supported; +} + +gboolean +gst_ahc_parameters_is_zoom_supported (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + gboolean supported; + + supported = AHCP_CALL (return FALSE, Boolean, isZoomSupported); + + return supported; +} + +gboolean +gst_ahc_parameters_set_antibanding (GstAHCParameters * self, + const gchar * value) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jstring antibanding; + + antibanding = _antibanding_to_jstring (value); + if (!antibanding) + return FALSE; + + AHCP_CALL (return FALSE, Void, setAntibanding, antibanding); + + return TRUE; +} + +gboolean +gst_ahc_parameters_set_color_effect (GstAHCParameters * self, + const gchar * value) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jstring color_effect; + + color_effect = _color_effect_to_jstring (value); + if (!color_effect) + return FALSE; + + AHCP_CALL (return FALSE, Void, setColorEffect, color_effect); + + return TRUE; +} + +gboolean +gst_ahc_parameters_set_exposure_compensation (GstAHCParameters * self, + gint value) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + AHCP_CALL (return FALSE, Void, setExposureCompensation, value); + + return TRUE; +} + +gboolean +gst_ahc_parameters_set_flash_mode (GstAHCParameters * self, const gchar * value) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jstring flash_mode; + + flash_mode = _flash_mode_to_jstring (value); + if (!flash_mode) + return FALSE; + + AHCP_CALL (return FALSE, Void, setFlashMode, flash_mode); + + return TRUE; +} + +gboolean +gst_ahc_parameters_set_focus_mode (GstAHCParameters * self, const gchar * value) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jstring focus_mode; + + focus_mode = _focus_mode_to_jstring (value); + if (!focus_mode) + return FALSE; + + AHCP_CALL (return FALSE, Void, setFocusMode, focus_mode); + + return TRUE; +} + +gboolean +gst_ahc_parameters_set_preview_format (GstAHCParameters * self, gint format) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + AHCP_CALL (return FALSE, Void, setPreviewFormat, format); + + return TRUE; +} + +gboolean +gst_ahc_parameters_set_preview_fps_range (GstAHCParameters * self, + gint min, gint max) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + AHCP_CALL (return FALSE, Void, setPreviewFpsRange, min, max); + + return TRUE; +} + +gboolean +gst_ahc_parameters_set_preview_size (GstAHCParameters * self, + gint width, gint height) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + AHCP_CALL (return FALSE, Void, setPreviewSize, width, height); + + return TRUE; +} + +gboolean +gst_ahc_parameters_set_scene_mode (GstAHCParameters * self, const gchar * value) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jstring scene_mode; + + scene_mode = _scene_mode_to_jstring (value); + if (!scene_mode) + return FALSE; + + AHCP_CALL (return FALSE, Void, setSceneMode, scene_mode); + + return TRUE; +} + + +gboolean +gst_ahc_parameters_set_video_stabilization (GstAHCParameters * self, + gboolean toggle) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + AHCP_CALL (return FALSE, Void, setVideoStabilization, toggle); + + return TRUE; +} + +gboolean +gst_ahc_parameters_set_white_balance (GstAHCParameters * self, + const gchar * value) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jstring white_balance; + + white_balance = _white_balance_to_jstring (value); + if (!white_balance) + return FALSE; + + AHCP_CALL (return FALSE, Void, setWhiteBalance, white_balance); + + return TRUE; +} + +gboolean +gst_ahc_parameters_set_zoom (GstAHCParameters * self, gint value) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + AHCP_CALL (return FALSE, Void, setZoom, value); + + return TRUE; +} + +gboolean +gst_ahc_parameters_unflatten (GstAHCParameters * self, const gchar * flattened) +{ + JNIEnv *env = gst_amc_jni_get_env (); + jstring v_str = NULL; + gboolean ret = TRUE; + + v_str = (*env)->NewStringUTF (env, flattened); + if (v_str == NULL) + return FALSE; + + AHCP_CALL (ret = FALSE, Void, unflatten, v_str); + + (*env)->DeleteLocalRef (env, v_str); + + return ret; +} + +void +gst_ahc_parameters_free (GstAHCParameters * self) +{ + JNIEnv *env = gst_amc_jni_get_env (); + + g_return_if_fail (self != NULL); + g_return_if_fail (self->object != NULL); + + GST_DEBUG ("freeing parameters %p", self->object); + + (*env)->DeleteGlobalRef (env, self->object); + g_slice_free (GstAHCParameters, self); +} diff --git a/sys/androidmedia/gst-android-hardware-camera.h b/sys/androidmedia/gst-android-hardware-camera.h new file mode 100644 index 0000000000..44e7842657 --- /dev/null +++ b/sys/androidmedia/gst-android-hardware-camera.h @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2012, Collabora Ltd. + * Copyright (C) 2012, Cisco Systems, Inc. + * Author: Youness Alaoui + * + * Copyright (C) 2015, Collabora Ltd. + * Author: Justin Kim + * + * 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_ANDROID_HARDWARE_CAMERA_H__ +#define __GST_ANDROID_HARDWARE_CAMERA_H__ + +#include +#include + +#include "gst-android-graphics-surfacetexture.h" +#include "gst-android-graphics-imageformat.h" + +G_BEGIN_DECLS + +typedef struct _GstAHCamera GstAHCamera; +typedef struct _GstAHCCameraInfo GstAHCCameraInfo; +typedef struct _GstAHCSize GstAHCSize; +typedef struct _GstAHCParameters GstAHCParameters; + +/* android.hardware.Camera */ +struct _GstAHCamera +{ + /* < private > */ + jobject object; /* global reference */ +}; + +/* android.hardware.Camera.CameraInfo */ +struct _GstAHCCameraInfo +{ + gint facing; + gint orientation; +}; +extern gint CameraInfo_CAMERA_FACING_BACK; +extern gint CameraInfo_CAMERA_FACING_FRONT; + +/* android.hardware.Camera.Size */ +struct _GstAHCSize +{ + gint width; + gint height; +}; + +/* android.hardware.Camera.Parameters */ +struct _GstAHCParameters +{ + /* < private > */ + jobject object; /* global reference */ +}; +extern const gchar *Parameters_WHITE_BALANCE_AUTO; +extern const gchar *Parameters_WHITE_BALANCE_INCANDESCENT; +extern const gchar *Parameters_WHITE_BALANCE_FLUORESCENT; +extern const gchar *Parameters_WHITE_BALANCE_WARM_FLUORESCENT; +extern const gchar *Parameters_WHITE_BALANCE_DAYLIGHT; +extern const gchar *Parameters_WHITE_BALANCE_CLOUDY_DAYLIGHT; +extern const gchar *Parameters_WHITE_BALANCE_TWILIGHT; +extern const gchar *Parameters_WHITE_BALANCE_SHADE; +extern const gchar *Parameters_EFFECT_NONE; +extern const gchar *Parameters_EFFECT_MONO; +extern const gchar *Parameters_EFFECT_NEGATIVE; +extern const gchar *Parameters_EFFECT_SOLARIZE; +extern const gchar *Parameters_EFFECT_SEPIA; +extern const gchar *Parameters_EFFECT_POSTERIZE; +extern const gchar *Parameters_EFFECT_WHITEBOARD; +extern const gchar *Parameters_EFFECT_BLACKBOARD; +extern const gchar *Parameters_EFFECT_AQUA; +extern const gchar *Parameters_ANTIBANDING_AUTO; +extern const gchar *Parameters_ANTIBANDING_50HZ; +extern const gchar *Parameters_ANTIBANDING_60HZ; +extern const gchar *Parameters_ANTIBANDING_OFF; +extern const gchar *Parameters_FLASH_MODE_OFF; +extern const gchar *Parameters_FLASH_MODE_AUTO; +extern const gchar *Parameters_FLASH_MODE_ON; +extern const gchar *Parameters_FLASH_MODE_RED_EYE; +extern const gchar *Parameters_FLASH_MODE_TORCH; +extern const gchar *Parameters_SCENE_MODE_AUTO; +extern const gchar *Parameters_SCENE_MODE_ACTION; +extern const gchar *Parameters_SCENE_MODE_PORTRAIT; +extern const gchar *Parameters_SCENE_MODE_LANDSCAPE; +extern const gchar *Parameters_SCENE_MODE_NIGHT; +extern const gchar *Parameters_SCENE_MODE_NIGHT_PORTRAIT; +extern const gchar *Parameters_SCENE_MODE_THEATRE; +extern const gchar *Parameters_SCENE_MODE_BEACH; +extern const gchar *Parameters_SCENE_MODE_SNOW; +extern const gchar *Parameters_SCENE_MODE_SUNSET; +extern const gchar *Parameters_SCENE_MODE_STEADYPHOTO; +extern const gchar *Parameters_SCENE_MODE_FIREWORKS; +extern const gchar *Parameters_SCENE_MODE_SPORTS; +extern const gchar *Parameters_SCENE_MODE_PARTY; +extern const gchar *Parameters_SCENE_MODE_CANDLELIGHT; +extern const gchar *Parameters_SCENE_MODE_BARCODE; +extern const gchar *Parameters_FOCUS_MODE_AUTO; +extern const gchar *Parameters_FOCUS_MODE_INFINITY; +extern const gchar *Parameters_FOCUS_MODE_MACRO; +extern const gchar *Parameters_FOCUS_MODE_FIXED; +extern const gchar *Parameters_FOCUS_MODE_EDOF; +extern const gchar *Parameters_FOCUS_MODE_CONTINUOUS_VIDEO; +extern const gchar *Parameters_FOCUS_MODE_CONTINUOUS_PICTURE; + +/* android.hardware.Camera.ErrorCallback */ +typedef void (*GstAHCErrorCallback) (gint error, gpointer user_data); + +/* android.hardware.Camera.PreviewCallback */ +typedef void (*GstAHCPreviewCallback) (jbyteArray data, gpointer user_data); + +/* android.hardware.Camera.AutoFocusCallback */ +typedef void (*GstAHCAutoFocusCallback) (gboolean success, gpointer user_data); + +gboolean gst_android_hardware_camera_init (void); +void gst_android_hardware_camera_deinit (void); + +/* android.hardware.Camera */ +void gst_ah_camera_add_callback_buffer (GstAHCamera * self, jbyteArray buffer); +gboolean gst_ah_camera_auto_focus (GstAHCamera * self, + GstAHCAutoFocusCallback cb, gpointer user_data); +gboolean gst_ah_camera_cancel_auto_focus (GstAHCamera * self); +gboolean gst_ah_camera_get_camera_info (gint camera_id, + GstAHCCameraInfo * camera_info); +gint gst_ah_camera_get_number_of_cameras (void); +GstAHCParameters *gst_ah_camera_get_parameters (GstAHCamera * self); +gboolean gst_ah_camera_lock (GstAHCamera * self); +GstAHCamera *gst_ah_camera_open (gint camera_id); +gboolean gst_ah_camera_reconnect (GstAHCamera * self); +void gst_ah_camera_release (GstAHCamera * self); +void gst_ah_camera_free (GstAHCamera * self); +gboolean gst_ah_camera_set_parameters (GstAHCamera * self, + GstAHCParameters * params); +gboolean gst_ah_camera_set_error_callback (GstAHCamera * self, + GstAHCErrorCallback cb, gpointer user_data); +gboolean gst_ah_camera_set_preview_callback_with_buffer (GstAHCamera * self, + GstAHCPreviewCallback cb, gpointer user_data); +void gst_ah_camera_set_preview_texture (GstAHCamera * self, + GstAGSurfaceTexture * surfaceTexture); +gboolean gst_ah_camera_start_preview (GstAHCamera * self); +gboolean gst_ah_camera_start_smooth_zoom (GstAHCamera * self, gint value); +gboolean gst_ah_camera_stop_preview (GstAHCamera * self); +gboolean gst_ah_camera_stop_smooth_zoom (GstAHCamera * self); +gboolean gst_ah_camera_unlock (GstAHCamera * self); + +/* android.hardware.Camera.Size */ +GstAHCSize *gst_ahc_size_new (gint width, gint height); +void gst_ahc_size_free (GstAHCSize * self); + +/* android.hardware.Camera.Parameters */ +gchar *gst_ahc_parameters_flatten (GstAHCParameters * self); +const gchar *gst_ahc_parameters_get_antibanding (GstAHCParameters * self); +const gchar *gst_ahc_parameters_get_color_effect (GstAHCParameters * self); +gint gst_ahc_parameters_get_exposure_compensation (GstAHCParameters * self); +gfloat gst_ahc_parameters_get_exposure_compensation_step (GstAHCParameters + * self); +const gchar *gst_ahc_parameters_get_flash_mode (GstAHCParameters * self); +gfloat gst_ahc_parameters_get_focal_length (GstAHCParameters * self); +const gchar *gst_ahc_parameters_get_focus_mode (GstAHCParameters * self); +gfloat gst_ahc_parameters_get_horizontal_view_angle (GstAHCParameters * self); +gint gst_ahc_parameters_get_max_exposure_compensation (GstAHCParameters * self); +gint gst_ahc_parameters_get_max_zoom (GstAHCParameters * self); +gint gst_ahc_parameters_get_min_exposure_compensation (GstAHCParameters * self); +gint gst_ahc_parameters_get_preview_format (GstAHCParameters * self); +gboolean gst_ahc_parameters_get_preview_fps_range (GstAHCParameters * self, + gint * min, gint * max); +GstAHCSize *gst_ahc_parameters_get_preview_size (GstAHCParameters * self); +const gchar *gst_ahc_parameters_get_scene_mode (GstAHCParameters * self); +/* GList */ +GList *gst_ahc_parameters_get_supported_antibanding (GstAHCParameters * self); +void gst_ahc_parameters_supported_antibanding_free (GList * list); +/* GList */ +GList *gst_ahc_parameters_get_supported_color_effects (GstAHCParameters * self); +void gst_ahc_parameters_supported_color_effects_free (GList * list); +/* GList */ +GList *gst_ahc_parameters_get_supported_flash_modes (GstAHCParameters * self); +void gst_ahc_parameters_supported_flash_modes_free (GList * list); +/* GList */ +GList *gst_ahc_parameters_get_supported_focus_modes (GstAHCParameters * self); +void gst_ahc_parameters_supported_focus_modes_free (GList * list); +/* GList */ +GList *gst_ahc_parameters_get_supported_preview_formats (GstAHCParameters + * self); +void gst_ahc_parameters_supported_preview_formats_free (GList * list); +/* GList */ +GList *gst_ahc_parameters_get_supported_preview_fps_range (GstAHCParameters + * self); +void gst_ahc_parameters_supported_preview_fps_range_free (GList * list); +/* GList */ +GList *gst_ahc_parameters_get_supported_preview_sizes (GstAHCParameters * self); +void gst_ahc_parameters_supported_preview_sizes_free (GList * list); +/* GList */ +GList *gst_ahc_parameters_get_supported_scene_modes (GstAHCParameters * self); +void gst_ahc_parameters_supported_scene_modes_free (GList * list); +/* GList */ +GList *gst_ahc_parameters_get_supported_white_balance (GstAHCParameters * self); +void gst_ahc_parameters_supported_white_balance_free (GList * list); +gfloat gst_ahc_parameters_get_vertical_view_angle (GstAHCParameters * self); +gboolean gst_ahc_parameters_get_video_stabilization (GstAHCParameters * self); +const gchar *gst_ahc_parameters_get_white_balance (GstAHCParameters * self); +gint gst_ahc_parameters_get_zoom (GstAHCParameters * self); +/* GList */ +GList *gst_ahc_parameters_get_zoom_ratios (GstAHCParameters * self); +void gst_ahc_parameters_zoom_ratios_free (GList * list); +gboolean gst_ahc_parameters_is_smooth_zoom_supported (GstAHCParameters * self); +gboolean gst_ahc_parameters_is_video_stabilization_supported ( + GstAHCParameters * self); +gboolean gst_ahc_parameters_is_zoom_supported (GstAHCParameters * self); +gboolean gst_ahc_parameters_set_antibanding (GstAHCParameters * self, + const gchar * antibanding); +gboolean gst_ahc_parameters_set_color_effect (GstAHCParameters * self, + const gchar * value); +gboolean gst_ahc_parameters_set_exposure_compensation (GstAHCParameters * self, + gint value); +gboolean gst_ahc_parameters_set_flash_mode (GstAHCParameters * self, + const gchar * value); +gboolean gst_ahc_parameters_set_focus_mode (GstAHCParameters * self, + const gchar * value); +gboolean gst_ahc_parameters_set_preview_format (GstAHCParameters * self, + gint format); +gboolean gst_ahc_parameters_set_preview_fps_range (GstAHCParameters * self, + gint min, gint max); +gboolean gst_ahc_parameters_set_preview_size (GstAHCParameters * self, + gint width, gint height); +gboolean gst_ahc_parameters_set_scene_mode (GstAHCParameters * self, + const gchar * value); +gboolean gst_ahc_parameters_set_white_balance (GstAHCParameters * self, + const gchar * value); +gboolean gst_ahc_parameters_set_video_stabilization (GstAHCParameters * self, + gboolean toggle); +gboolean gst_ahc_parameters_set_zoom (GstAHCParameters * self, gint value); +gboolean gst_ahc_parameters_unflatten (GstAHCParameters * self, + const gchar * flattened); +void gst_ahc_parameters_free (GstAHCParameters * self); + +G_END_DECLS + +#endif /* __GST_ANDROID_HARDWARE_CAMERA_H__ */ diff --git a/sys/androidmedia/gst-androidcamera.c b/sys/androidmedia/gst-androidcamera.c new file mode 100644 index 0000000000..d836add3ed --- /dev/null +++ b/sys/androidmedia/gst-androidcamera.c @@ -0,0 +1,68 @@ +/* + * 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 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 +#include + +#include "gst-android-hardware-camera.h" +#include "gstahcsrc.h" + +static gboolean +plugin_init (GstPlugin * plugin) +{ + if (!gst_dvm_init ()) + return FALSE; + + if (!gst_android_graphics_surfacetexture_init ()) + return FALSE; + + if (!gst_android_graphics_imageformat_init ()) { + gst_android_graphics_surfacetexture_deinit (); + return FALSE; + } + if (!gst_android_hardware_camera_init ()) { + gst_android_graphics_surfacetexture_deinit (); + gst_android_graphics_imageformat_deinit (); + return FALSE; + } + + return gst_element_register (plugin, "ahcsrc", GST_RANK_NONE, + GST_TYPE_AHC_SRC); +} + +#ifdef GST_PLUGIN_DEFINE2 +GST_PLUGIN_DEFINE2 (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + androidcamera, + "Android Camera plugin", + plugin_init, + PACKAGE_VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) +#else +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "androidcamera", + "Android Camera plugin", + plugin_init, + PACKAGE_VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) +#endif diff --git a/sys/androidmedia/gstahcsrc.c b/sys/androidmedia/gstahcsrc.c new file mode 100644 index 0000000000..bb87289819 --- /dev/null +++ b/sys/androidmedia/gstahcsrc.c @@ -0,0 +1,2513 @@ +/* GStreamer android.hardware.Camera Source + * + * 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. + */ + +/** + * SECTION:element-ahcsrc + * + * ahcsrc can be used to capture video from android devices. It uses the + * android.hardware.Camera Java API to capture from the system's cameras. + * + * In order for the plugin to get registered, it must be able to find its + * Java callbacks class. That class is embedded as a jar file inside the source + * element (if properly compiled) and will be written to a temporary directory + * so it can be loaded into the virtual machine. + * In order for it to work, an environment variable must be set to a writable + * directory. + * The source will look for the environment variable “TMP” which must contain + * the absolute path to a writable directory. + * It can be retreived using the following Java code : + * |[ + * context.getCacheDir().getAbsolutePath(); + * ]| + * Where the @context variable is an object of type android.content.Context + * (including its subclasses android.app.Activity or android.app.Application). + * Another optional environment variable can be set for pointing to the + * optimized dex classes directory. If the environment variable “DEX” is + * available, it will be used, otherwise, the directory in the “TMP” environment + * variable will be used for the optimized dex directory. + * The system dex directory can be obtained using the following Java code : + * |[ + * context.getDir(“dex”, 0).getAbsolutePath(); + * ]| + * + * + * Those environment variable must be set before gst_init is called from + * the native code. + * + * + * + * If the “TMP” environment variable is not available or the directory is not + * writable or any other issue happens while trying to load the embedded jar + * file, then the source will fallback on trying to load the class directly + * from the running application. + * The file com/gstreamer/GstAhcCallback.java in the source's directory can be + * copied into the Android application so it can be loaded at runtime + * as a fallback mechanism. + * + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "gstjniutils.h" + +#include "gstahcsrc.h" + +/* GObject */ +static void gst_ahc_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_ahc_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_ahc_src_dispose (GObject * object); + +/* GstElement */ +static GstStateChangeReturn gst_ahc_src_change_state (GstElement * element, + GstStateChange transition); + +/* GstBaseSrc */ +static GstCaps *gst_ahc_src_getcaps (GstBaseSrc * src, GstCaps * filter); +static gboolean gst_ahc_src_setcaps (GstBaseSrc * src, GstCaps * caps); +static GstCaps *gst_ahc_src_fixate (GstBaseSrc * basesrc, GstCaps * caps); +static gboolean gst_ahc_src_start (GstBaseSrc * bsrc); +static gboolean gst_ahc_src_stop (GstBaseSrc * bsrc); +static gboolean gst_ahc_src_unlock (GstBaseSrc * bsrc); +static gboolean gst_ahc_src_unlock_stop (GstBaseSrc * bsrc); +static GstFlowReturn gst_ahc_src_create (GstPushSrc * src, GstBuffer ** buffer); +static gboolean gst_ahc_src_query (GstBaseSrc * bsrc, GstQuery * query); + +/* GstPhotography */ +static void gst_ahc_src_photography_init (gpointer g_iface, + gpointer iface_data); +static gboolean gst_ahc_src_get_ev_compensation (GstPhotography * photo, + gfloat * ev_comp); +static gboolean _white_balance_to_enum (const gchar * white_balance, + GstPhotographyWhiteBalanceMode * mode); +static gboolean gst_ahc_src_get_white_balance_mode (GstPhotography * photo, + GstPhotographyWhiteBalanceMode * wb_mode); +static gboolean _color_effects_to_enum (const gchar * color_effect, + GstPhotographyColorToneMode * mode); +static gboolean gst_ahc_src_get_colour_tone_mode (GstPhotography * photo, + GstPhotographyColorToneMode * tone_mode); +static gboolean _scene_modes_to_enum (const gchar * scene, + GstPhotographySceneMode * mode); +static gboolean gst_ahc_src_get_scene_mode (GstPhotography * photo, + GstPhotographySceneMode * scene_mode); +static gboolean _flash_modes_to_enum (const gchar * flash, + GstPhotographyFlashMode * mode); +static gboolean gst_ahc_src_get_flash_mode (GstPhotography * photo, + GstPhotographyFlashMode * flash_mode); +static gboolean gst_ahc_src_get_zoom (GstPhotography * photo, gfloat * zoom); +static gboolean _antibanding_to_enum (const gchar * antibanding, + GstPhotographyFlickerReductionMode * mode); +static gboolean gst_ahc_src_get_flicker_mode (GstPhotography * photo, + GstPhotographyFlickerReductionMode * flicker_mode); +static gboolean _focus_modes_to_enum (const gchar * focus, + GstPhotographyFocusMode * mode); +static gboolean gst_ahc_src_get_focus_mode (GstPhotography * photo, + GstPhotographyFocusMode * focus_mode); + +static gboolean gst_ahc_src_set_ev_compensation (GstPhotography * photo, + gfloat ev_comp); +static gboolean gst_ahc_src_set_white_balance_mode (GstPhotography * photo, + GstPhotographyWhiteBalanceMode wb_mode); +static gboolean gst_ahc_src_set_colour_tone_mode (GstPhotography * photo, + GstPhotographyColorToneMode tone_mode); +static gboolean gst_ahc_src_set_scene_mode (GstPhotography * photo, + GstPhotographySceneMode scene_mode); +static gboolean gst_ahc_src_set_flash_mode (GstPhotography * photo, + GstPhotographyFlashMode flash_mode); +static gboolean gst_ahc_src_set_zoom (GstPhotography * photo, gfloat zoom); +static gboolean gst_ahc_src_set_flicker_mode (GstPhotography * photo, + GstPhotographyFlickerReductionMode flicker_mode); +static gboolean gst_ahc_src_set_focus_mode (GstPhotography * photo, + GstPhotographyFocusMode focus_mode); + +static GstPhotographyCaps gst_ahc_src_get_capabilities (GstPhotography * photo); +static void gst_ahc_src_set_autofocus (GstPhotography * photo, gboolean on); + +/* GstAHCSrc */ +static void gst_ahc_src_close (GstAHCSrc * self); +static void gst_ahc_src_on_preview_frame (jbyteArray data, gpointer user_data); +static void gst_ahc_src_on_error (gint error, gpointer user_data); +static void gst_ahc_src_on_auto_focus (gboolean success, gpointer user_data); + +#define NUM_CALLBACK_BUFFERS 5 + +#define GST_AHC_SRC_CAPS_STR \ + GST_VIDEO_CAPS_MAKE_WITH_FEATURES("ANY", " { YV12, YUY2, NV21, NV16, RGB16 }") + +static GstStaticPadTemplate gst_ahc_src_pad_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_AHC_SRC_CAPS_STR)); + +GST_DEBUG_CATEGORY_STATIC (gst_ahc_src_debug); +#define GST_CAT_DEFAULT gst_ahc_src_debug + +#define parent_class gst_ahc_src_parent_class + +enum +{ + PROP_0, + PROP_DEVICE, + PROP_DEVICE_NAME, + PROP_DEVICE_FACING, + PROP_DEVICE_ORIENTATION, + PROP_FOCAL_LENGTH, + PROP_HORIZONTAL_VIEW_ANGLE, + PROP_VERTICAL_VIEW_ANGLE, + PROP_VIDEO_STABILIZATION, + PROP_WB_MODE, + PROP_COLOUR_TONE, + PROP_SCENE_MODE, + PROP_FLASH_MODE, + PROP_NOISE_REDUCTION, + PROP_CAPABILITIES, + PROP_EV_COMP, + PROP_ISO_SPEED, + PROP_APERTURE, + PROP_EXPOSURE_MODE, + PROP_IMAGE_CAPTURE_SUPPORTED_CAPS, + PROP_IMAGE_PREVIEW_SUPPORTED_CAPS, + PROP_FLICKER_MODE, + PROP_FOCUS_MODE, + PROP_ZOOM, + PROP_SMOOTH_ZOOM, + PROP_WHITE_POINT, + PROP_MIN_EXPOSURE_TIME, + PROP_MAX_EXPOSURE_TIME, + PROP_LENS_FOCUS, + PROP_EXPOSURE_TIME, + PROP_COLOR_TEMPERATURE, + PROP_ANALOG_GAIN, + PROP_LAST +}; + +static GParamSpec *properties[PROP_LAST]; + +#define DEFAULT_DEVICE "0" + +G_DEFINE_TYPE_WITH_CODE (GstAHCSrc, gst_ahc_src, GST_TYPE_PUSH_SRC, + G_IMPLEMENT_INTERFACE (GST_TYPE_PHOTOGRAPHY, gst_ahc_src_photography_init)); + +#define CAMERA_FACING_BACK 0 +#define CAMERA_FACING_FRONT 1 + +static GType +gst_ahc_src_facing_get_type (void) +{ + static GType type = 0; + static const GEnumValue types[] = { + {CAMERA_FACING_BACK, "Back", "back"}, + {CAMERA_FACING_FRONT, "Front", "front"}, + {0, NULL, NULL} + }; + + if (!type) { + type = g_enum_register_static ("GstAHCSrcFacing", types); + } + return type; +} + +#define GST_AHC_SRC_FACING_TYPE (gst_ahc_src_facing_get_type()) + +static void +gst_ahc_src_photography_init (gpointer g_iface, gpointer iface_data) +{ + GstPhotographyInterface *iface = g_iface; + + iface->get_ev_compensation = gst_ahc_src_get_ev_compensation; + iface->get_white_balance_mode = gst_ahc_src_get_white_balance_mode; + iface->get_color_tone_mode = gst_ahc_src_get_colour_tone_mode; + iface->get_scene_mode = gst_ahc_src_get_scene_mode; + iface->get_flash_mode = gst_ahc_src_get_flash_mode; + iface->get_zoom = gst_ahc_src_get_zoom; + iface->get_flicker_mode = gst_ahc_src_get_flicker_mode; + iface->get_focus_mode = gst_ahc_src_get_focus_mode; + + iface->set_ev_compensation = gst_ahc_src_set_ev_compensation; + iface->set_white_balance_mode = gst_ahc_src_set_white_balance_mode; + iface->set_color_tone_mode = gst_ahc_src_set_colour_tone_mode; + iface->set_scene_mode = gst_ahc_src_set_scene_mode; + iface->set_flash_mode = gst_ahc_src_set_flash_mode; + iface->set_zoom = gst_ahc_src_set_zoom; + iface->set_flicker_mode = gst_ahc_src_set_flicker_mode; + iface->set_focus_mode = gst_ahc_src_set_focus_mode; + + iface->get_capabilities = gst_ahc_src_get_capabilities; + iface->set_autofocus = gst_ahc_src_set_autofocus; +} + +static void +gst_ahc_src_class_init (GstAHCSrcClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstPushSrcClass *gstpushsrc_class = GST_PUSH_SRC_CLASS (klass); + GstBaseSrcClass *gstbasesrc_class = GST_BASE_SRC_CLASS (klass); + + gobject_class->set_property = gst_ahc_src_set_property; + gobject_class->get_property = gst_ahc_src_get_property; + gobject_class->dispose = gst_ahc_src_dispose; + + element_class->change_state = gst_ahc_src_change_state; + + gstbasesrc_class->get_caps = gst_ahc_src_getcaps; + gstbasesrc_class->set_caps = gst_ahc_src_setcaps; + gstbasesrc_class->fixate = gst_ahc_src_fixate; + gstbasesrc_class->start = gst_ahc_src_start; + gstbasesrc_class->stop = gst_ahc_src_stop; + gstbasesrc_class->unlock = gst_ahc_src_unlock; + gstbasesrc_class->unlock_stop = gst_ahc_src_unlock_stop; + gstbasesrc_class->query = gst_ahc_src_query; + + gstpushsrc_class->create = gst_ahc_src_create; + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_ahc_src_pad_template)); + + /** + * GstAHCSrc:device: + * + * The Device ID of the camera to capture from + */ + properties[PROP_DEVICE] = g_param_spec_string ("device", + "Device", "Device ID", DEFAULT_DEVICE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (gobject_class, PROP_DEVICE, + properties[PROP_DEVICE]); + + /** + * GstAHCSrc:device-name: + * + * A user-friendly name for the camera device + */ + properties[PROP_DEVICE_NAME] = g_param_spec_string ("device-name", + "Device name", "Device name", NULL, + G_PARAM_READABLE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (gobject_class, PROP_DEVICE_NAME, + properties[PROP_DEVICE_NAME]); + + /** + * GstAHCSrc:device-orientation: + * + * The orientation of the currently set camera @device. + * The value is the angle that the camera image needs to be rotated clockwise + * so it shows correctly on the display in its natural orientation. + * It should be 0, 90, 180, or 270. + */ + properties[PROP_DEVICE_ORIENTATION] = g_param_spec_int ("device-orientation", + "Device orientation", "The orientation of the camera image", + 0, 360, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (gobject_class, PROP_DEVICE_ORIENTATION, + properties[PROP_DEVICE_ORIENTATION]); + + /** + * GstAHCSrc:device-facing: + * + * The direction that the currently select camera @device faces. + * + * A value of 0 means the camera is facing the opposite direction as the + * screen while a value of 1 means the camera is facing the same direction + * as the screen. + */ + properties[PROP_DEVICE_FACING] = g_param_spec_enum ("device-facing", + "Device facing", "The direction that the camera faces", + GST_AHC_SRC_FACING_TYPE, CAMERA_FACING_BACK, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (gobject_class, PROP_DEVICE_FACING, + properties[PROP_DEVICE_FACING]); + + /** + * GstAHCSrc:focal-length: + * + * Gets the focal length (in millimeter) of the camera. + */ + properties[PROP_FOCAL_LENGTH] = g_param_spec_float ("focal-length", + "Focal length", "Gets the focal length (in millimeter) of the camera", + -G_MAXFLOAT, G_MAXFLOAT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (gobject_class, PROP_FOCAL_LENGTH, + properties[PROP_FOCAL_LENGTH]); + + /** + * GstAHCSrc:horizontal-view-angle: + * + * Gets the horizontal angle of view in degrees. + */ + properties[PROP_HORIZONTAL_VIEW_ANGLE] = + g_param_spec_float ("horizontal-view-angle", "Horizontal view angle", + "Gets the horizontal angle of view in degrees", + -G_MAXFLOAT, G_MAXFLOAT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (gobject_class, PROP_HORIZONTAL_VIEW_ANGLE, + properties[PROP_HORIZONTAL_VIEW_ANGLE]); + + /** + * GstAHCSrc:vertical-view-angle: + * + * Gets the vertical angle of view in degrees. + */ + properties[PROP_VERTICAL_VIEW_ANGLE] = + g_param_spec_float ("vertical-view-angle", "Vertical view angle", + "Gets the vertical angle of view in degrees", + -G_MAXFLOAT, G_MAXFLOAT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (gobject_class, PROP_VERTICAL_VIEW_ANGLE, + properties[PROP_VERTICAL_VIEW_ANGLE]); + + /** + * GstAHCSrc:video-stabilizatio: + * + * Video stabilization reduces the shaking due to the motion of the camera. + */ + properties[PROP_VIDEO_STABILIZATION] = + g_param_spec_boolean ("video-stabilization", "Video stabilization", + "Video stabilization reduces the shaking due to the motion of the camera", + FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (gobject_class, PROP_VIDEO_STABILIZATION, + properties[PROP_VIDEO_STABILIZATION]); + + /** + * GstAHCSrc:smooth-zoom: + * + * If enabled, then smooth zooming will be used when the @zoom property is + * changed. In that case, the @zoom property can be queried to know the + * current zoom level while the smooth zoom is in progress. + */ + properties[PROP_SMOOTH_ZOOM] = g_param_spec_boolean ("smooth-zoom", + "Smooth Zoom", "Use smooth zoom when available", + FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (gobject_class, PROP_SMOOTH_ZOOM, + properties[PROP_SMOOTH_ZOOM]); + + /* Override GstPhotography properties */ + g_object_class_override_property (gobject_class, PROP_WB_MODE, + GST_PHOTOGRAPHY_PROP_WB_MODE); + properties[PROP_WB_MODE] = g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_WB_MODE); + + g_object_class_override_property (gobject_class, PROP_COLOUR_TONE, + GST_PHOTOGRAPHY_PROP_COLOR_TONE); + properties[PROP_COLOUR_TONE] = g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_COLOR_TONE); + + g_object_class_override_property (gobject_class, PROP_SCENE_MODE, + GST_PHOTOGRAPHY_PROP_SCENE_MODE); + properties[PROP_SCENE_MODE] = g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_SCENE_MODE); + + g_object_class_override_property (gobject_class, PROP_FLASH_MODE, + GST_PHOTOGRAPHY_PROP_FLASH_MODE); + properties[PROP_FLASH_MODE] = g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_FLASH_MODE); + + g_object_class_override_property (gobject_class, PROP_NOISE_REDUCTION, + GST_PHOTOGRAPHY_PROP_NOISE_REDUCTION); + properties[PROP_NOISE_REDUCTION] = + g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_NOISE_REDUCTION); + + g_object_class_override_property (gobject_class, PROP_CAPABILITIES, + GST_PHOTOGRAPHY_PROP_CAPABILITIES); + properties[PROP_CAPABILITIES] = g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_CAPABILITIES); + + g_object_class_override_property (gobject_class, PROP_EV_COMP, + GST_PHOTOGRAPHY_PROP_EV_COMP); + properties[PROP_EV_COMP] = g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_EV_COMP); + + g_object_class_override_property (gobject_class, PROP_ISO_SPEED, + GST_PHOTOGRAPHY_PROP_ISO_SPEED); + properties[PROP_ISO_SPEED] = g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_ISO_SPEED); + + g_object_class_override_property (gobject_class, PROP_APERTURE, + GST_PHOTOGRAPHY_PROP_APERTURE); + properties[PROP_APERTURE] = g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_APERTURE); + +#if 0 + g_object_class_override_property (gobject_class, PROP_EXPOSURE_MODE, + GST_PHOTOGRAPHY_PROP_EXPOSURE_MODE); + properties[PROP_EXPOSURE] = g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_EXPOSURE_MODE); +#endif + + g_object_class_override_property (gobject_class, + PROP_IMAGE_CAPTURE_SUPPORTED_CAPS, + GST_PHOTOGRAPHY_PROP_IMAGE_CAPTURE_SUPPORTED_CAPS); + properties[PROP_IMAGE_CAPTURE_SUPPORTED_CAPS] = + g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_IMAGE_CAPTURE_SUPPORTED_CAPS); + + g_object_class_override_property (gobject_class, + PROP_IMAGE_PREVIEW_SUPPORTED_CAPS, + GST_PHOTOGRAPHY_PROP_IMAGE_PREVIEW_SUPPORTED_CAPS); + properties[PROP_IMAGE_PREVIEW_SUPPORTED_CAPS] = + g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_IMAGE_PREVIEW_SUPPORTED_CAPS); + + g_object_class_override_property (gobject_class, PROP_FLICKER_MODE, + GST_PHOTOGRAPHY_PROP_FLICKER_MODE); + properties[PROP_FLICKER_MODE] = g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_FLICKER_MODE); + + g_object_class_override_property (gobject_class, PROP_FOCUS_MODE, + GST_PHOTOGRAPHY_PROP_FOCUS_MODE); + properties[PROP_FOCUS_MODE] = g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_FOCUS_MODE); + + g_object_class_override_property (gobject_class, PROP_ZOOM, + GST_PHOTOGRAPHY_PROP_ZOOM); + properties[PROP_ZOOM] = g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_ZOOM); + + g_object_class_override_property (gobject_class, PROP_WHITE_POINT, + GST_PHOTOGRAPHY_PROP_WHITE_POINT); + properties[PROP_WHITE_POINT] = g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_WHITE_POINT); + + g_object_class_override_property (gobject_class, PROP_MIN_EXPOSURE_TIME, + GST_PHOTOGRAPHY_PROP_MIN_EXPOSURE_TIME); + properties[PROP_MIN_EXPOSURE_TIME] = + g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_MIN_EXPOSURE_TIME); + + g_object_class_override_property (gobject_class, PROP_MAX_EXPOSURE_TIME, + GST_PHOTOGRAPHY_PROP_MAX_EXPOSURE_TIME); + properties[PROP_MAX_EXPOSURE_TIME] = + g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_MAX_EXPOSURE_TIME); + + g_object_class_override_property (gobject_class, PROP_LENS_FOCUS, + GST_PHOTOGRAPHY_PROP_LENS_FOCUS); + properties[PROP_LENS_FOCUS] = g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_LENS_FOCUS); + + g_object_class_override_property (gobject_class, PROP_EXPOSURE_TIME, + GST_PHOTOGRAPHY_PROP_EXPOSURE_TIME); + properties[PROP_EXPOSURE_TIME] = g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_EXPOSURE_TIME); + + g_object_class_override_property (gobject_class, PROP_COLOR_TEMPERATURE, + GST_PHOTOGRAPHY_PROP_COLOR_TEMPERATURE); + properties[PROP_COLOR_TEMPERATURE] = + g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_COLOR_TEMPERATURE); + + g_object_class_override_property (gobject_class, PROP_ANALOG_GAIN, + GST_PHOTOGRAPHY_PROP_ANALOG_GAIN); + properties[PROP_ANALOG_GAIN] = g_object_class_find_property (gobject_class, + GST_PHOTOGRAPHY_PROP_ANALOG_GAIN); + + + + klass->probe_properties = NULL; + + gst_element_class_set_static_metadata (element_class, + "Android Camera Source", + "Source/Video", + "Reads frames from android.hardware.Camera class into buffers", + "Youness Alaoui "); + + GST_DEBUG_CATEGORY_INIT (gst_ahc_src_debug, "ahcsrc", 0, + "android.hardware.Camera source element"); +} + +static gboolean +_data_queue_check_full (GstDataQueue * queue, guint visible, + guint bytes, guint64 time, gpointer checkdata) +{ + return FALSE; +} + +static void +gst_ahc_src_init (GstAHCSrc * self) +{ + gst_base_src_set_live (GST_BASE_SRC (self), TRUE); + gst_base_src_set_format (GST_BASE_SRC (self), GST_FORMAT_TIME); + gst_base_src_set_do_timestamp (GST_BASE_SRC (self), FALSE); + + self->camera = NULL; + self->texture = NULL; + self->data = NULL; + self->queue = gst_data_queue_new (_data_queue_check_full, NULL, NULL, NULL); + self->start = FALSE; + self->previous_ts = GST_CLOCK_TIME_NONE; + + g_mutex_init (&self->mutex); +} + +static void +gst_ahc_src_dispose (GObject * object) +{ + GstAHCSrc *self = GST_AHC_SRC (object); + + if (self->queue) + g_object_unref (self->queue); + self->queue = NULL; + + g_mutex_clear (&self->mutex); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_ahc_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstAHCSrc *self = GST_AHC_SRC (object); + + GST_DEBUG_OBJECT (self, "set props %d", prop_id); + + switch (prop_id) { + case PROP_DEVICE:{ + const gchar *dev = g_value_get_string (value); + gchar *endptr = NULL; + guint64 device; + + device = g_ascii_strtoll (dev, &endptr, 10); + if (endptr != dev && endptr[0] == 0 && device < G_MAXINT) + self->device = (gint) device; + } + break; + case PROP_VIDEO_STABILIZATION: + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + gst_ahc_parameters_set_video_stabilization (params, + g_value_get_boolean (value)); + gst_ah_camera_set_parameters (self->camera, params); + gst_ahc_parameters_free (params); + } + } + break; + case PROP_SMOOTH_ZOOM: + self->smooth_zoom = g_value_get_boolean (value); + break; + case PROP_WB_MODE:{ + GstPhotographyWhiteBalanceMode wb = g_value_get_enum (value); + + gst_ahc_src_set_white_balance_mode (GST_PHOTOGRAPHY (self), wb); + } + break; + case PROP_COLOUR_TONE:{ + GstPhotographyColorToneMode tone = g_value_get_enum (value); + + gst_ahc_src_set_colour_tone_mode (GST_PHOTOGRAPHY (self), tone); + } + break; + case PROP_SCENE_MODE:{ + GstPhotographySceneMode scene = g_value_get_enum (value); + + gst_ahc_src_set_scene_mode (GST_PHOTOGRAPHY (self), scene); + } + break; + case PROP_FLASH_MODE:{ + GstPhotographyFlashMode flash = g_value_get_enum (value); + + gst_ahc_src_set_flash_mode (GST_PHOTOGRAPHY (self), flash); + } + break; + case PROP_EV_COMP:{ + gfloat ev = g_value_get_float (value); + + gst_ahc_src_set_ev_compensation (GST_PHOTOGRAPHY (self), ev); + } + break; + case PROP_FLICKER_MODE:{ + GstPhotographyFlickerReductionMode flicker = g_value_get_enum (value); + + gst_ahc_src_set_flicker_mode (GST_PHOTOGRAPHY (self), flicker); + } + break; + case PROP_FOCUS_MODE:{ + GstPhotographyFocusMode focus = g_value_get_enum (value); + + gst_ahc_src_set_focus_mode (GST_PHOTOGRAPHY (self), focus); + } + break; + case PROP_ZOOM:{ + gfloat zoom = g_value_get_float (value); + + gst_ahc_src_set_zoom (GST_PHOTOGRAPHY (self), zoom); + } + break; + case PROP_NOISE_REDUCTION: + case PROP_ISO_SPEED: + case PROP_APERTURE: + case PROP_EXPOSURE_MODE: + case PROP_IMAGE_CAPTURE_SUPPORTED_CAPS: + case PROP_IMAGE_PREVIEW_SUPPORTED_CAPS: + case PROP_WHITE_POINT: + case PROP_MIN_EXPOSURE_TIME: + case PROP_MAX_EXPOSURE_TIME: + case PROP_LENS_FOCUS: + case PROP_EXPOSURE_TIME: + case PROP_COLOR_TEMPERATURE: + case PROP_ANALOG_GAIN: + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_ahc_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstAHCSrc *self = GST_AHC_SRC (object); + (void) self; + + switch (prop_id) { + case PROP_DEVICE:{ + gchar *dev = g_strdup_printf ("%d", self->device); + + g_value_take_string (value, dev); + } + break; + case PROP_DEVICE_NAME:{ + GstAHCCameraInfo info; + gchar *dev; + + if (gst_ah_camera_get_camera_info (self->device, &info)) + dev = g_strdup_printf ("#%d %s", self->device, + info.facing == CameraInfo_CAMERA_FACING_BACK ? "Back" : "Front"); + else + dev = g_strdup_printf ("#%d", self->device); + + g_value_take_string (value, dev); + } + break; + case PROP_DEVICE_FACING:{ + GstAHCCameraInfo info; + + if (gst_ah_camera_get_camera_info (self->device, &info)) + g_value_set_enum (value, info.facing == CameraInfo_CAMERA_FACING_BACK ? + CAMERA_FACING_BACK : CAMERA_FACING_FRONT); + else + g_value_set_enum (value, CAMERA_FACING_BACK); + } + break; + case PROP_DEVICE_ORIENTATION:{ + GstAHCCameraInfo info; + + if (gst_ah_camera_get_camera_info (self->device, &info)) + g_value_set_int (value, info.orientation); + else + g_value_set_int (value, 0); + } + break; + case PROP_FOCAL_LENGTH: + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + g_value_set_float (value, + gst_ahc_parameters_get_focal_length (params)); + gst_ahc_parameters_free (params); + } + } + break; + case PROP_HORIZONTAL_VIEW_ANGLE: + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + g_value_set_float (value, + gst_ahc_parameters_get_horizontal_view_angle (params)); + gst_ahc_parameters_free (params); + } + } + break; + case PROP_VERTICAL_VIEW_ANGLE: + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + g_value_set_float (value, + gst_ahc_parameters_get_vertical_view_angle (params)); + gst_ahc_parameters_free (params); + } + } + break; + case PROP_VIDEO_STABILIZATION: + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + g_value_set_boolean (value, + gst_ahc_parameters_get_video_stabilization (params)); + gst_ahc_parameters_free (params); + } + } + break; + case PROP_SMOOTH_ZOOM: + g_value_set_boolean (value, self->smooth_zoom); + break; + case PROP_WB_MODE:{ + GstPhotographyWhiteBalanceMode wb; + + if (gst_ahc_src_get_white_balance_mode (GST_PHOTOGRAPHY (self), &wb)) + g_value_set_enum (value, wb); + } + break; + case PROP_COLOUR_TONE:{ + GstPhotographyColorToneMode tone; + + if (gst_ahc_src_get_colour_tone_mode (GST_PHOTOGRAPHY (self), &tone)) + g_value_set_enum (value, tone); + } + break; + case PROP_SCENE_MODE:{ + GstPhotographySceneMode scene; + + if (gst_ahc_src_get_scene_mode (GST_PHOTOGRAPHY (self), &scene)) + g_value_set_enum (value, scene); + } + break; + case PROP_FLASH_MODE:{ + GstPhotographyFlashMode flash; + + if (gst_ahc_src_get_flash_mode (GST_PHOTOGRAPHY (self), &flash)) + g_value_set_enum (value, flash); + } + break; + case PROP_CAPABILITIES:{ + GstPhotographyCaps caps; + + caps = gst_ahc_src_get_capabilities (GST_PHOTOGRAPHY (self)); + g_value_set_ulong (value, caps); + } + break; + case PROP_EV_COMP:{ + gfloat ev; + + if (gst_ahc_src_get_ev_compensation (GST_PHOTOGRAPHY (self), &ev)) + g_value_set_float (value, ev); + } + break; + case PROP_FLICKER_MODE:{ + GstPhotographyFlickerReductionMode flicker; + + if (gst_ahc_src_get_flicker_mode (GST_PHOTOGRAPHY (self), &flicker)) + g_value_set_enum (value, flicker); + } + break; + case PROP_FOCUS_MODE:{ + GstPhotographyFocusMode focus; + + if (gst_ahc_src_get_focus_mode (GST_PHOTOGRAPHY (self), &focus)) + g_value_set_enum (value, focus); + } + break; + case PROP_ZOOM:{ + gfloat zoom; + + if (gst_ahc_src_get_zoom (GST_PHOTOGRAPHY (self), &zoom)) + g_value_set_float (value, zoom); + } + break; + case PROP_IMAGE_CAPTURE_SUPPORTED_CAPS: + case PROP_IMAGE_PREVIEW_SUPPORTED_CAPS: + case PROP_NOISE_REDUCTION: + case PROP_ISO_SPEED: + case PROP_APERTURE: + case PROP_EXPOSURE_MODE: + case PROP_WHITE_POINT: + case PROP_MIN_EXPOSURE_TIME: + case PROP_MAX_EXPOSURE_TIME: + case PROP_LENS_FOCUS: + case PROP_EXPOSURE_TIME: + case PROP_COLOR_TEMPERATURE: + case PROP_ANALOG_GAIN: + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +#if 0 +static const GList * +gst_ahc_src_probe_get_properties (GstPropertyProbe * probe) +{ + GstAHCSrcClass *ahc_class = GST_AHC_SRC_CLASS (probe); + GList **list = &ahc_class->probe_properties; + + if (!*list) { + *list = g_list_append (*list, properties[PROP_DEVICE]); + *list = g_list_append (*list, properties[PROP_EV_COMP]); + *list = g_list_append (*list, properties[PROP_ZOOM]); + *list = g_list_append (*list, properties[PROP_WB_MODE]); + *list = g_list_append (*list, properties[PROP_COLOUR_TONE]); + *list = g_list_append (*list, properties[PROP_FLASH_MODE]); + *list = g_list_append (*list, properties[PROP_FOCUS_MODE]); + *list = g_list_append (*list, properties[PROP_SCENE_MODE]); + *list = g_list_append (*list, properties[PROP_FLICKER_MODE]); + } + + return *list; +} + +#define PROBE_GET_ENUM_VALUES(name, type, struct_name) \ + if (self->camera) { \ + GstAHCParameters *params; \ + \ + params = gst_ah_camera_get_parameters (self->camera); \ + if (params) { \ + GList *list = gst_ahc_parameters_get_supported_##name (params); \ + \ + if (list) { \ + GValue value = { 0 }; \ + GList *i; \ + \ + array = g_value_array_new (g_list_length (list)); \ + g_value_init (&value, type); \ + for (i = list; i; i = i->next) { \ + struct_name mode; \ + const gchar *name = i->data; \ + \ + if (_##name##_to_enum (name, &mode)) { \ + g_value_set_enum (&value, mode); \ + g_value_array_append (array, &value); \ + } \ + } \ + g_value_unset (&value); \ + } \ + \ + gst_ahc_parameters_supported_##name##_free (list); \ + gst_ahc_parameters_free (params); \ + } \ + } + + +static GValueArray * +gst_ahc_src_probe_get_values (GstPropertyProbe * probe, + guint prop_id, const GParamSpec * pspec) +{ + GstAHCSrc *self = GST_AHC_SRC (probe); + GValueArray *array = NULL; + + /* g_object_class_find_property returns overriden property with + * param_id == 0, so we can't switch/case the prop_id and + * we need to check the pspec instead */ + if (pspec == properties[PROP_DEVICE]) { + GValue value = { 0 }; + gint num_cams = gst_ah_camera_get_number_of_cameras (); + gint i; + + array = g_value_array_new (num_cams); + g_value_init (&value, G_TYPE_STRING); + for (i = 0; i < num_cams; i++) { + g_value_take_string (&value, g_strdup_printf ("%d", i)); + g_value_array_append (array, &value); + } + g_value_unset (&value); + } else if (pspec == properties[PROP_EV_COMP]) { + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + gint min, max; + gfloat step; + + min = gst_ahc_parameters_get_min_exposure_compensation (params); + max = gst_ahc_parameters_get_max_exposure_compensation (params); + step = gst_ahc_parameters_get_exposure_compensation_step (params); + + if (step != 0.0 && min != max) { + GValue value = { 0 }; + gint i; + + /* Min and Max are inclusive */ + array = g_value_array_new (max - min + 1); + g_value_init (&value, G_TYPE_FLOAT); + for (i = min; i <= max; i++) { + g_value_set_float (&value, step * i); + g_value_array_append (array, &value); + } + g_value_unset (&value); + } + + gst_ahc_parameters_free (params); + } + } + } else if (pspec == properties[PROP_ZOOM]) { + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + GList *zoom_ratios = gst_ahc_parameters_get_zoom_ratios (params); + gint max_zoom = gst_ahc_parameters_get_max_zoom (params); + + if (zoom_ratios && g_list_length (zoom_ratios) == (max_zoom + 1)) { + GValue value = { 0 }; + GList *i; + + array = g_value_array_new (max_zoom + 1); + g_value_init (&value, G_TYPE_FLOAT); + for (i = zoom_ratios; i; i = i->next) { + gint zoom_value = GPOINTER_TO_INT (i->data); + gfloat zoom = (gfloat) zoom_value / 100.0; + + g_value_set_float (&value, zoom); + g_value_array_append (array, &value); + } + g_value_unset (&value); + } + + gst_ahc_parameters_zoom_ratios_free (zoom_ratios); + gst_ahc_parameters_free (params); + } + } + } else if (pspec == properties[PROP_WB_MODE]) { + PROBE_GET_ENUM_VALUES (white_balance, GST_TYPE_WHITE_BALANCE_MODE, + GstPhotographyWhiteBalanceMode); + } else if (pspec == properties[PROP_COLOUR_TONE]) { + PROBE_GET_ENUM_VALUES (color_effects, GST_TYPE_COLOUR_TONE_MODE, + GstPhotographyColorToneMode); + } else if (pspec == properties[PROP_FLASH_MODE]) { + PROBE_GET_ENUM_VALUES (flash_modes, GST_TYPE_FLASH_MODE, + GstPhotographyFlashMode); + } else if (pspec == properties[PROP_FOCUS_MODE]) { + PROBE_GET_ENUM_VALUES (focus_modes, GST_TYPE_FOCUS_MODE, + GstPhotographyFocusMode); + } else if (pspec == properties[PROP_SCENE_MODE]) { + PROBE_GET_ENUM_VALUES (scene_modes, GST_TYPE_SCENE_MODE, + GstPhotographySceneMode); + } else if (pspec == properties[PROP_FLICKER_MODE]) { + PROBE_GET_ENUM_VALUES (antibanding, GST_TYPE_FLICKER_REDUCTION_MODE, + GstPhotographyFlickerReductionMode); + } else { + G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); + } + + return array; +} +#endif + +static gboolean +_antibanding_to_enum (const gchar * antibanding, + GstPhotographyFlickerReductionMode * mode) +{ + if (antibanding == Parameters_ANTIBANDING_AUTO) + *mode = GST_PHOTOGRAPHY_FLICKER_REDUCTION_AUTO; + else if (antibanding == Parameters_ANTIBANDING_50HZ) + *mode = GST_PHOTOGRAPHY_FLICKER_REDUCTION_50HZ; + else if (antibanding == Parameters_ANTIBANDING_60HZ) + *mode = GST_PHOTOGRAPHY_FLICKER_REDUCTION_60HZ; + else if (antibanding == Parameters_ANTIBANDING_OFF) + *mode = GST_PHOTOGRAPHY_FLICKER_REDUCTION_OFF; + else + return FALSE; + + return TRUE; +} + +static gboolean +_white_balance_to_enum (const gchar * white_balance, + GstPhotographyWhiteBalanceMode * mode) +{ + if (white_balance == Parameters_WHITE_BALANCE_AUTO) + *mode = GST_PHOTOGRAPHY_WB_MODE_AUTO; + else if (white_balance == Parameters_WHITE_BALANCE_INCANDESCENT) + *mode = GST_PHOTOGRAPHY_WB_MODE_TUNGSTEN; + else if (white_balance == Parameters_WHITE_BALANCE_FLUORESCENT) + *mode = GST_PHOTOGRAPHY_WB_MODE_FLUORESCENT; + else if (white_balance == Parameters_WHITE_BALANCE_WARM_FLUORESCENT) + *mode = GST_PHOTOGRAPHY_WB_MODE_WARM_FLUORESCENT; + else if (white_balance == Parameters_WHITE_BALANCE_DAYLIGHT) + *mode = GST_PHOTOGRAPHY_WB_MODE_DAYLIGHT; + else if (white_balance == Parameters_WHITE_BALANCE_CLOUDY_DAYLIGHT) + *mode = GST_PHOTOGRAPHY_WB_MODE_CLOUDY; + else if (white_balance == Parameters_WHITE_BALANCE_TWILIGHT) + *mode = GST_PHOTOGRAPHY_WB_MODE_SUNSET; + else if (white_balance == Parameters_WHITE_BALANCE_SHADE) + *mode = GST_PHOTOGRAPHY_WB_MODE_SHADE; + else + return FALSE; + + return TRUE; +} + +static gboolean +_color_effects_to_enum (const gchar * color_effect, + GstPhotographyColorToneMode * mode) +{ + if (color_effect == Parameters_EFFECT_NONE) + *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_NORMAL; + else if (color_effect == Parameters_EFFECT_MONO) + *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_GRAYSCALE; + else if (color_effect == Parameters_EFFECT_NEGATIVE) + *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_NEGATIVE; + else if (color_effect == Parameters_EFFECT_SOLARIZE) + *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_SOLARIZE; + else if (color_effect == Parameters_EFFECT_SEPIA) + *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_SEPIA; + else if (color_effect == Parameters_EFFECT_POSTERIZE) + *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_POSTERIZE; + else if (color_effect == Parameters_EFFECT_WHITEBOARD) + *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_WHITEBOARD; + else if (color_effect == Parameters_EFFECT_BLACKBOARD) + *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_BLACKBOARD; + else if (color_effect == Parameters_EFFECT_AQUA) + *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_AQUA; + else + return FALSE; + + return TRUE; +} + +static gboolean +_scene_modes_to_enum (const gchar * scene, GstPhotographySceneMode * mode) +{ + if (scene == Parameters_SCENE_MODE_AUTO) + *mode = GST_PHOTOGRAPHY_SCENE_MODE_AUTO; + else if (scene == Parameters_SCENE_MODE_ACTION) + *mode = GST_PHOTOGRAPHY_SCENE_MODE_ACTION; + else if (scene == Parameters_SCENE_MODE_PORTRAIT) + *mode = GST_PHOTOGRAPHY_SCENE_MODE_PORTRAIT; + else if (scene == Parameters_SCENE_MODE_LANDSCAPE) + *mode = GST_PHOTOGRAPHY_SCENE_MODE_LANDSCAPE; + else if (scene == Parameters_SCENE_MODE_NIGHT) + *mode = GST_PHOTOGRAPHY_SCENE_MODE_NIGHT; + else if (scene == Parameters_SCENE_MODE_NIGHT_PORTRAIT) + *mode = GST_PHOTOGRAPHY_SCENE_MODE_NIGHT_PORTRAIT; + else if (scene == Parameters_SCENE_MODE_THEATRE) + *mode = GST_PHOTOGRAPHY_SCENE_MODE_THEATRE; + else if (scene == Parameters_SCENE_MODE_BEACH) + *mode = GST_PHOTOGRAPHY_SCENE_MODE_BEACH; + else if (scene == Parameters_SCENE_MODE_SNOW) + *mode = GST_PHOTOGRAPHY_SCENE_MODE_SNOW; + else if (scene == Parameters_SCENE_MODE_SUNSET) + *mode = GST_PHOTOGRAPHY_SCENE_MODE_SUNSET; + else if (scene == Parameters_SCENE_MODE_STEADYPHOTO) + *mode = GST_PHOTOGRAPHY_SCENE_MODE_STEADY_PHOTO; + else if (scene == Parameters_SCENE_MODE_FIREWORKS) + *mode = GST_PHOTOGRAPHY_SCENE_MODE_FIREWORKS; + else if (scene == Parameters_SCENE_MODE_SPORTS) + *mode = GST_PHOTOGRAPHY_SCENE_MODE_SPORT; + else if (scene == Parameters_SCENE_MODE_PARTY) + *mode = GST_PHOTOGRAPHY_SCENE_MODE_PARTY; + else if (scene == Parameters_SCENE_MODE_CANDLELIGHT) + *mode = GST_PHOTOGRAPHY_SCENE_MODE_CANDLELIGHT; + else if (scene == Parameters_SCENE_MODE_BARCODE) + *mode = GST_PHOTOGRAPHY_SCENE_MODE_BARCODE; + else + return FALSE; + + return TRUE; +} + +static gboolean +_flash_modes_to_enum (const gchar * flash, GstPhotographyFlashMode * mode) +{ + if (flash == Parameters_FLASH_MODE_OFF) + *mode = GST_PHOTOGRAPHY_FLASH_MODE_OFF; + else if (flash == Parameters_FLASH_MODE_AUTO) + *mode = GST_PHOTOGRAPHY_FLASH_MODE_AUTO; + else if (flash == Parameters_FLASH_MODE_ON) + *mode = GST_PHOTOGRAPHY_FLASH_MODE_ON; + else if (flash == Parameters_FLASH_MODE_RED_EYE) + *mode = GST_PHOTOGRAPHY_FLASH_MODE_RED_EYE; + else if (flash == Parameters_FLASH_MODE_TORCH) + *mode = GST_PHOTOGRAPHY_FLASH_MODE_FILL_IN; + else + return FALSE; + + return TRUE; +} + +static gboolean +_focus_modes_to_enum (const gchar * focus, GstPhotographyFocusMode * mode) +{ + if (focus == Parameters_FOCUS_MODE_AUTO) + *mode = GST_PHOTOGRAPHY_FOCUS_MODE_AUTO; + else if (focus == Parameters_FOCUS_MODE_INFINITY) + *mode = GST_PHOTOGRAPHY_FOCUS_MODE_INFINITY; + else if (focus == Parameters_FOCUS_MODE_MACRO) + *mode = GST_PHOTOGRAPHY_FOCUS_MODE_MACRO; + else if (focus == Parameters_FOCUS_MODE_FIXED) + *mode = GST_PHOTOGRAPHY_FOCUS_MODE_HYPERFOCAL; + else if (focus == Parameters_FOCUS_MODE_EDOF) + *mode = GST_PHOTOGRAPHY_FOCUS_MODE_EXTENDED; + else if (focus == Parameters_FOCUS_MODE_CONTINUOUS_VIDEO) + *mode = GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_EXTENDED; + else if (focus == Parameters_FOCUS_MODE_CONTINUOUS_PICTURE) + *mode = GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_NORMAL; + else + return FALSE; + + return TRUE; +} + +static gboolean +gst_ahc_src_get_ev_compensation (GstPhotography * photo, gfloat * ev_comp) +{ + GstAHCSrc *self = GST_AHC_SRC (photo); + gboolean ret = FALSE; + + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + gint ev, min, max; + gfloat step; + + ev = gst_ahc_parameters_get_exposure_compensation (params); + min = gst_ahc_parameters_get_min_exposure_compensation (params); + max = gst_ahc_parameters_get_max_exposure_compensation (params); + step = gst_ahc_parameters_get_exposure_compensation_step (params); + + if (step != 0.0 && min != max && min <= ev && ev <= max) { + if (ev_comp) + *ev_comp = ev * step; + ret = TRUE; + } + gst_ahc_parameters_free (params); + } + } + + return ret; +} + +static gboolean +gst_ahc_src_get_white_balance_mode (GstPhotography * photo, + GstPhotographyWhiteBalanceMode * wb_mode) +{ + GstAHCSrc *self = GST_AHC_SRC (photo); + gboolean ret = FALSE; + + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + const gchar *wb = gst_ahc_parameters_get_white_balance (params); + GstPhotographyWhiteBalanceMode mode = GST_PHOTOGRAPHY_WB_MODE_AUTO; + + if (_white_balance_to_enum (wb, &mode)) { + ret = TRUE; + + if (wb_mode) + *wb_mode = mode; + } + + gst_ahc_parameters_free (params); + } + } + + return ret; +} + +static gboolean +gst_ahc_src_get_colour_tone_mode (GstPhotography * photo, + GstPhotographyColorToneMode * tone_mode) +{ + GstAHCSrc *self = GST_AHC_SRC (photo); + gboolean ret = FALSE; + + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + const gchar *effect = gst_ahc_parameters_get_color_effect (params); + GstPhotographyColorToneMode mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_NORMAL; + + if (_color_effects_to_enum (effect, &mode)) { + ret = TRUE; + + if (tone_mode) + *tone_mode = mode; + } + + gst_ahc_parameters_free (params); + } + } + + return ret; +} + +static gboolean +gst_ahc_src_get_scene_mode (GstPhotography * photo, + GstPhotographySceneMode * scene_mode) +{ + GstAHCSrc *self = GST_AHC_SRC (photo); + gboolean ret = FALSE; + + if (scene_mode && self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + const gchar *scene = gst_ahc_parameters_get_scene_mode (params); + GstPhotographySceneMode mode = GST_PHOTOGRAPHY_SCENE_MODE_AUTO; + + if (_scene_modes_to_enum (scene, &mode)) { + ret = TRUE; + + if (scene_mode) + *scene_mode = mode; + } + + gst_ahc_parameters_free (params); + } + } + + return ret; +} + +static gboolean +gst_ahc_src_get_flash_mode (GstPhotography * photo, + GstPhotographyFlashMode * flash_mode) +{ + GstAHCSrc *self = GST_AHC_SRC (photo); + gboolean ret = FALSE; + + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + const gchar *flash = gst_ahc_parameters_get_flash_mode (params); + GstPhotographyFlashMode mode = GST_PHOTOGRAPHY_FLASH_MODE_OFF; + + if (_flash_modes_to_enum (flash, &mode)) { + ret = TRUE; + + if (flash_mode) + *flash_mode = mode; + } + + gst_ahc_parameters_free (params); + } + } + + return ret; +} + +static gboolean +gst_ahc_src_get_zoom (GstPhotography * photo, gfloat * zoom) +{ + GstAHCSrc *self = GST_AHC_SRC (photo); + gboolean ret = FALSE; + + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + GList *zoom_ratios = gst_ahc_parameters_get_zoom_ratios (params); + gint zoom_idx = gst_ahc_parameters_get_zoom (params); + gint max_zoom = gst_ahc_parameters_get_max_zoom (params); + + if (zoom_ratios && g_list_length (zoom_ratios) == (max_zoom + 1) && + zoom_idx >= 0 && zoom_idx < max_zoom) { + gint zoom_value; + + zoom_value = GPOINTER_TO_INT (g_list_nth_data (zoom_ratios, zoom_idx)); + if (zoom) + *zoom = (gfloat) zoom_value / 100.0; + + ret = TRUE; + } + + gst_ahc_parameters_zoom_ratios_free (zoom_ratios); + gst_ahc_parameters_free (params); + } + } + + return ret; +} + +static gboolean +gst_ahc_src_get_flicker_mode (GstPhotography * photo, + GstPhotographyFlickerReductionMode * flicker_mode) +{ + GstAHCSrc *self = GST_AHC_SRC (photo); + gboolean ret = FALSE; + + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + const gchar *antibanding = gst_ahc_parameters_get_antibanding (params); + GstPhotographyFlickerReductionMode mode = + GST_PHOTOGRAPHY_FLICKER_REDUCTION_AUTO; + + if (_antibanding_to_enum (antibanding, &mode)) { + ret = TRUE; + + if (flicker_mode) + *flicker_mode = mode; + } + + gst_ahc_parameters_free (params); + } + } + + return ret; +} + +static gboolean +gst_ahc_src_get_focus_mode (GstPhotography * photo, + GstPhotographyFocusMode * focus_mode) +{ + GstAHCSrc *self = GST_AHC_SRC (photo); + gboolean ret = FALSE; + + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + const gchar *focus = gst_ahc_parameters_get_focus_mode (params); + GstPhotographyFocusMode mode = GST_PHOTOGRAPHY_FOCUS_MODE_AUTO; + + if (_focus_modes_to_enum (focus, &mode)) { + ret = TRUE; + + if (focus_mode) + *focus_mode = mode; + } + + gst_ahc_parameters_free (params); + } + } + + return ret; +} + + +static gboolean +gst_ahc_src_set_ev_compensation (GstPhotography * photo, gfloat ev_comp) +{ + GstAHCSrc *self = GST_AHC_SRC (photo); + gboolean ret = FALSE; + + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + gint ev, min, max; + gfloat step; + + ev = gst_ahc_parameters_get_exposure_compensation (params); + min = gst_ahc_parameters_get_min_exposure_compensation (params); + max = gst_ahc_parameters_get_max_exposure_compensation (params); + step = gst_ahc_parameters_get_exposure_compensation_step (params); + if (step != 0.0 && min != max && + (min * step) <= ev_comp && ev_comp <= (max * step)) { + ev = ev_comp / step; + if ((ev * step) == ev_comp) { + gst_ahc_parameters_set_exposure_compensation (params, ev); + ret = gst_ah_camera_set_parameters (self->camera, params); + } + } + } + gst_ahc_parameters_free (params); + } + + return ret; +} + +static gboolean +gst_ahc_src_set_white_balance_mode (GstPhotography * photo, + GstPhotographyWhiteBalanceMode wb_mode) +{ + GstAHCSrc *self = GST_AHC_SRC (photo); + gboolean ret = FALSE; + + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + const gchar *white_balance = NULL; + + switch (wb_mode) { + case GST_PHOTOGRAPHY_WB_MODE_AUTO: + white_balance = Parameters_WHITE_BALANCE_AUTO; + break; + case GST_PHOTOGRAPHY_WB_MODE_DAYLIGHT: + white_balance = Parameters_WHITE_BALANCE_DAYLIGHT; + break; + case GST_PHOTOGRAPHY_WB_MODE_CLOUDY: + white_balance = Parameters_WHITE_BALANCE_CLOUDY_DAYLIGHT; + break; + case GST_PHOTOGRAPHY_WB_MODE_SUNSET: + white_balance = Parameters_WHITE_BALANCE_TWILIGHT; + break; + case GST_PHOTOGRAPHY_WB_MODE_TUNGSTEN: + white_balance = Parameters_WHITE_BALANCE_INCANDESCENT; + break; + case GST_PHOTOGRAPHY_WB_MODE_FLUORESCENT: + white_balance = Parameters_WHITE_BALANCE_FLUORESCENT; + break; + case GST_PHOTOGRAPHY_WB_MODE_WARM_FLUORESCENT: + white_balance = Parameters_WHITE_BALANCE_WARM_FLUORESCENT; + break; + case GST_PHOTOGRAPHY_WB_MODE_SHADE: + white_balance = Parameters_WHITE_BALANCE_SHADE; + break; + default: + white_balance = NULL; + break; + } + + if (white_balance) { + gst_ahc_parameters_set_white_balance (params, white_balance); + ret = gst_ah_camera_set_parameters (self->camera, params); + } + gst_ahc_parameters_free (params); + } + } + + return ret; +} + +static gboolean +gst_ahc_src_set_colour_tone_mode (GstPhotography * photo, + GstPhotographyColorToneMode tone_mode) +{ + GstAHCSrc *self = GST_AHC_SRC (photo); + gboolean ret = FALSE; + + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + const gchar *color_effect = NULL; + + switch (tone_mode) { + case GST_PHOTOGRAPHY_COLOR_TONE_MODE_NORMAL: + color_effect = Parameters_EFFECT_NONE; + break; + case GST_PHOTOGRAPHY_COLOR_TONE_MODE_SEPIA: + color_effect = Parameters_EFFECT_SEPIA; + break; + case GST_PHOTOGRAPHY_COLOR_TONE_MODE_NEGATIVE: + color_effect = Parameters_EFFECT_NEGATIVE; + break; + case GST_PHOTOGRAPHY_COLOR_TONE_MODE_GRAYSCALE: + color_effect = Parameters_EFFECT_MONO; + break; + case GST_PHOTOGRAPHY_COLOR_TONE_MODE_SOLARIZE: + color_effect = Parameters_EFFECT_SOLARIZE; + break; + case GST_PHOTOGRAPHY_COLOR_TONE_MODE_POSTERIZE: + color_effect = Parameters_EFFECT_POSTERIZE; + break; + case GST_PHOTOGRAPHY_COLOR_TONE_MODE_WHITEBOARD: + color_effect = Parameters_EFFECT_WHITEBOARD; + break; + case GST_PHOTOGRAPHY_COLOR_TONE_MODE_BLACKBOARD: + color_effect = Parameters_EFFECT_BLACKBOARD; + break; + case GST_PHOTOGRAPHY_COLOR_TONE_MODE_AQUA: + color_effect = Parameters_EFFECT_AQUA; + break; + case GST_PHOTOGRAPHY_COLOR_TONE_MODE_NATURAL: + case GST_PHOTOGRAPHY_COLOR_TONE_MODE_VIVID: + case GST_PHOTOGRAPHY_COLOR_TONE_MODE_COLORSWAP: + case GST_PHOTOGRAPHY_COLOR_TONE_MODE_OUT_OF_FOCUS: + case GST_PHOTOGRAPHY_COLOR_TONE_MODE_SKY_BLUE: + case GST_PHOTOGRAPHY_COLOR_TONE_MODE_GRASS_GREEN: + case GST_PHOTOGRAPHY_COLOR_TONE_MODE_SKIN_WHITEN: + default: + color_effect = NULL; + break; + } + + if (color_effect) { + gst_ahc_parameters_set_color_effect (params, color_effect); + ret = gst_ah_camera_set_parameters (self->camera, params); + } + gst_ahc_parameters_free (params); + } + } + + return ret; +} + +static gboolean +gst_ahc_src_set_scene_mode (GstPhotography * photo, + GstPhotographySceneMode scene_mode) +{ + GstAHCSrc *self = GST_AHC_SRC (photo); + gboolean ret = FALSE; + + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + const gchar *scene = NULL; + + switch (scene_mode) { + case GST_PHOTOGRAPHY_SCENE_MODE_PORTRAIT: + scene = Parameters_SCENE_MODE_PORTRAIT; + break; + case GST_PHOTOGRAPHY_SCENE_MODE_LANDSCAPE: + scene = Parameters_SCENE_MODE_LANDSCAPE; + break; + case GST_PHOTOGRAPHY_SCENE_MODE_SPORT: + scene = Parameters_SCENE_MODE_SPORTS; + break; + case GST_PHOTOGRAPHY_SCENE_MODE_NIGHT: + scene = Parameters_SCENE_MODE_NIGHT; + break; + case GST_PHOTOGRAPHY_SCENE_MODE_AUTO: + scene = Parameters_SCENE_MODE_AUTO; + break; + case GST_PHOTOGRAPHY_SCENE_MODE_ACTION: + scene = Parameters_SCENE_MODE_ACTION; + break; + case GST_PHOTOGRAPHY_SCENE_MODE_NIGHT_PORTRAIT: + scene = Parameters_SCENE_MODE_NIGHT_PORTRAIT; + break; + case GST_PHOTOGRAPHY_SCENE_MODE_THEATRE: + scene = Parameters_SCENE_MODE_THEATRE; + break; + case GST_PHOTOGRAPHY_SCENE_MODE_BEACH: + scene = Parameters_SCENE_MODE_BEACH; + break; + case GST_PHOTOGRAPHY_SCENE_MODE_SNOW: + scene = Parameters_SCENE_MODE_SNOW; + break; + case GST_PHOTOGRAPHY_SCENE_MODE_SUNSET: + scene = Parameters_SCENE_MODE_SUNSET; + break; + case GST_PHOTOGRAPHY_SCENE_MODE_STEADY_PHOTO: + scene = Parameters_SCENE_MODE_STEADYPHOTO; + break; + case GST_PHOTOGRAPHY_SCENE_MODE_FIREWORKS: + scene = Parameters_SCENE_MODE_FIREWORKS; + break; + case GST_PHOTOGRAPHY_SCENE_MODE_PARTY: + scene = Parameters_SCENE_MODE_PARTY; + break; + case GST_PHOTOGRAPHY_SCENE_MODE_CANDLELIGHT: + scene = Parameters_SCENE_MODE_CANDLELIGHT; + break; + case GST_PHOTOGRAPHY_SCENE_MODE_BARCODE: + scene = Parameters_SCENE_MODE_BARCODE; + break; + case GST_PHOTOGRAPHY_SCENE_MODE_MANUAL: + case GST_PHOTOGRAPHY_SCENE_MODE_CLOSEUP: + default: + scene = NULL; + break; + } + + if (scene) { + gst_ahc_parameters_set_scene_mode (params, scene); + ret = gst_ah_camera_set_parameters (self->camera, params); + } + gst_ahc_parameters_free (params); + } + } + + return ret; +} + +static gboolean +gst_ahc_src_set_flash_mode (GstPhotography * photo, + GstPhotographyFlashMode flash_mode) +{ + GstAHCSrc *self = GST_AHC_SRC (photo); + gboolean ret = FALSE; + + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + const gchar *flash = NULL; + + switch (flash_mode) { + case GST_PHOTOGRAPHY_FLASH_MODE_AUTO: + flash = Parameters_FLASH_MODE_AUTO; + break; + case GST_PHOTOGRAPHY_FLASH_MODE_OFF: + flash = Parameters_FLASH_MODE_OFF; + break; + case GST_PHOTOGRAPHY_FLASH_MODE_ON: + flash = Parameters_FLASH_MODE_ON; + break; + case GST_PHOTOGRAPHY_FLASH_MODE_FILL_IN: + flash = Parameters_FLASH_MODE_TORCH; + break; + case GST_PHOTOGRAPHY_FLASH_MODE_RED_EYE: + flash = Parameters_FLASH_MODE_RED_EYE; + break; + default: + flash = NULL; + break; + } + + if (flash) { + gst_ahc_parameters_set_flash_mode (params, flash); + ret = gst_ah_camera_set_parameters (self->camera, params); + } + gst_ahc_parameters_free (params); + } + } + + return ret; +} + +static gboolean +gst_ahc_src_set_zoom (GstPhotography * photo, gfloat zoom) +{ + GstAHCSrc *self = GST_AHC_SRC (photo); + gboolean ret = FALSE; + + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + GList *zoom_ratios = gst_ahc_parameters_get_zoom_ratios (params); + gint max_zoom = gst_ahc_parameters_get_max_zoom (params); + gint zoom_idx = -1; + + if (zoom_ratios && g_list_length (zoom_ratios) == (max_zoom + 1)) { + gint i; + gint value = zoom * 100; + + for (i = 0; i < max_zoom + 1; i++) { + gint zoom_value = GPOINTER_TO_INT (g_list_nth_data (zoom_ratios, i)); + + if (value == zoom_value) + zoom_idx = i; + } + } + + if (zoom_idx != -1) { + if (self->smooth_zoom && + gst_ahc_parameters_is_smooth_zoom_supported (params)) { + // First, we need to cancel any previous smooth zoom operation + gst_ah_camera_stop_smooth_zoom (self->camera); + ret = gst_ah_camera_start_smooth_zoom (self->camera, zoom_idx); + } else { + gst_ahc_parameters_set_zoom (params, zoom_idx); + ret = gst_ah_camera_set_parameters (self->camera, params); + } + } + + gst_ahc_parameters_zoom_ratios_free (zoom_ratios); + gst_ahc_parameters_free (params); + } + } + + return ret; +} + +static gboolean +gst_ahc_src_set_flicker_mode (GstPhotography * photo, + GstPhotographyFlickerReductionMode flicker_mode) +{ + GstAHCSrc *self = GST_AHC_SRC (photo); + gboolean ret = FALSE; + + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + const gchar *antibanding = NULL; + + switch (flicker_mode) { + case GST_PHOTOGRAPHY_FLICKER_REDUCTION_OFF: + antibanding = Parameters_ANTIBANDING_OFF; + break; + case GST_PHOTOGRAPHY_FLICKER_REDUCTION_50HZ: + antibanding = Parameters_ANTIBANDING_50HZ; + break; + case GST_PHOTOGRAPHY_FLICKER_REDUCTION_60HZ: + antibanding = Parameters_ANTIBANDING_60HZ; + break; + case GST_PHOTOGRAPHY_FLICKER_REDUCTION_AUTO: + antibanding = Parameters_ANTIBANDING_AUTO; + break; + default: + antibanding = NULL; + break; + } + + if (antibanding) { + gst_ahc_parameters_set_antibanding (params, antibanding); + ret = gst_ah_camera_set_parameters (self->camera, params); + } + gst_ahc_parameters_free (params); + } + } + + return ret; +} + +static gboolean +gst_ahc_src_set_focus_mode (GstPhotography * photo, + GstPhotographyFocusMode focus_mode) +{ + GstAHCSrc *self = GST_AHC_SRC (photo); + gboolean ret = FALSE; + + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + const gchar *focus = NULL; + + switch (focus_mode) { + case GST_PHOTOGRAPHY_FOCUS_MODE_AUTO: + focus = Parameters_FOCUS_MODE_AUTO; + break; + case GST_PHOTOGRAPHY_FOCUS_MODE_MACRO: + focus = Parameters_FOCUS_MODE_MACRO; + break; + case GST_PHOTOGRAPHY_FOCUS_MODE_INFINITY: + focus = Parameters_FOCUS_MODE_INFINITY; + break; + case GST_PHOTOGRAPHY_FOCUS_MODE_HYPERFOCAL: + focus = Parameters_FOCUS_MODE_FIXED; + break; + case GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_NORMAL: + focus = Parameters_FOCUS_MODE_CONTINUOUS_PICTURE; + break; + case GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_EXTENDED: + focus = Parameters_FOCUS_MODE_CONTINUOUS_VIDEO; + break; + case GST_PHOTOGRAPHY_FOCUS_MODE_EXTENDED: + focus = Parameters_FOCUS_MODE_EDOF; + break; + case GST_PHOTOGRAPHY_FOCUS_MODE_PORTRAIT: + default: + focus = NULL; + break; + } + + if (focus) { + gst_ahc_parameters_set_focus_mode (params, focus); + ret = gst_ah_camera_set_parameters (self->camera, params); + } + gst_ahc_parameters_free (params); + } + } + + return ret; +} + +static GstPhotographyCaps +gst_ahc_src_get_capabilities (GstPhotography * photo) +{ + GstAHCSrc *self = GST_AHC_SRC (photo); + + GstPhotographyCaps caps = GST_PHOTOGRAPHY_CAPS_EV_COMP | + GST_PHOTOGRAPHY_CAPS_WB_MODE | GST_PHOTOGRAPHY_CAPS_TONE | + GST_PHOTOGRAPHY_CAPS_SCENE | GST_PHOTOGRAPHY_CAPS_FLASH | + GST_PHOTOGRAPHY_CAPS_FOCUS | GST_PHOTOGRAPHY_CAPS_ZOOM; + + if (self->camera) { + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (!gst_ahc_parameters_is_zoom_supported (params)) + caps &= ~GST_PHOTOGRAPHY_CAPS_ZOOM; + + gst_ahc_parameters_free (params); + } + + return caps; +} + +static void +gst_ahc_src_on_auto_focus (gboolean success, gpointer user_data) +{ + GstAHCSrc *self = GST_AHC_SRC (user_data); + + GST_WARNING_OBJECT (self, "Auto focus completed : %d", success); + gst_element_post_message (GST_ELEMENT (self), + gst_message_new_custom (GST_MESSAGE_ELEMENT, GST_OBJECT (self), + gst_structure_new_empty (GST_PHOTOGRAPHY_AUTOFOCUS_DONE))); +} + +static void +gst_ahc_src_set_autofocus (GstPhotography * photo, gboolean on) +{ + GstAHCSrc *self = GST_AHC_SRC (photo); + + if (self->camera) { + if (on) + gst_ah_camera_auto_focus (self->camera, gst_ahc_src_on_auto_focus, self); + else + gst_ah_camera_cancel_auto_focus (self->camera); + } + +} + +static gint +_compare_formats (int f1, int f2) +{ + if (f1 == f2) + return 0; + /* YV12 has priority */ + if (f1 == ImageFormat_YV12) + return -1; + if (f2 == ImageFormat_YV12) + return 1; + /* Then NV21 */ + if (f1 == ImageFormat_NV21) + return -1; + if (f2 == ImageFormat_NV21) + return 1; + /* Then we don't care */ + return f2 - f1; +} + +static gint +_compare_sizes (GstAHCSize * s1, GstAHCSize * s2) +{ + return ((s2->width * s2->height) - (s1->width * s1->height)); +} + + +static gint +_compare_ranges (int *r1, int *r2) +{ + if (r1[1] == r2[1]) + /* Smallest range */ + return (r1[1] - r1[0]) - (r2[1] - r2[0]); + else + /* Highest fps */ + return r2[1] - r1[1]; +} + +static GstCaps * +gst_ahc_src_getcaps (GstBaseSrc * src, GstCaps * filter) +{ + GstAHCSrc *self = GST_AHC_SRC (src); + + if (self->camera) { + GstCaps *ret = gst_caps_new_empty (); + GstAHCParameters *params; + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + GList *formats, *sizes, *ranges; + GList *i, *j, *k; + int previous_format = ImageFormat_UNKNOWN; + + formats = gst_ahc_parameters_get_supported_preview_formats (params); + formats = g_list_sort (formats, (GCompareFunc) _compare_formats); + sizes = gst_ahc_parameters_get_supported_preview_sizes (params); + sizes = g_list_sort (sizes, (GCompareFunc) _compare_sizes); + ranges = gst_ahc_parameters_get_supported_preview_fps_range (params); + ranges = g_list_sort (ranges, (GCompareFunc) _compare_ranges); + GST_DEBUG_OBJECT (self, "Supported preview formats:"); + + for (i = formats; i; i = i->next) { + int f = GPOINTER_TO_INT (i->data); + gchar *format_string = NULL; + GstStructure *format = NULL; + + /* Ignore duplicates */ + if (f == previous_format) + continue; + + /* Can't use switch/case because the values are not constants */ + if (f == ImageFormat_NV16) { + GST_DEBUG_OBJECT (self, " NV16 (%d)", f); + format_string = g_strdup ("NV16"); + } else if (f == ImageFormat_NV21) { + GST_DEBUG_OBJECT (self, " NV21 (%d)", f); + format_string = g_strdup ("NV21"); + } else if (f == ImageFormat_RGB_565) { + GstVideoFormat vformat; + vformat = gst_video_format_from_masks (16, 16, G_LITTLE_ENDIAN, + 0xf800, 0x07e0, 0x001f, 0x0); + GST_DEBUG_OBJECT (self, " RGB565 (%d)", f); + format_string = g_strdup (gst_video_format_to_string (vformat)); + } else if (f == ImageFormat_YUY2) { + GST_DEBUG_OBJECT (self, " YUY2 (%d)", f); + format_string = g_strdup ("YUY2"); + } else if (f == ImageFormat_YV12) { + GST_DEBUG_OBJECT (self, " YV12 (%d)", f); + format_string = g_strdup ("YV12"); + } + previous_format = f; + + if (format_string) { + format = gst_structure_new ("video/x-raw", + "format", G_TYPE_STRING, format_string, NULL); + g_free (format_string); + } + + if (format) { + for (j = sizes; j; j = j->next) { + GstAHCSize *s = j->data; + GstStructure *size; + + size = gst_structure_copy (format); + gst_structure_set (size, "width", G_TYPE_INT, s->width, + "height", G_TYPE_INT, s->height, + "interlaced", G_TYPE_BOOLEAN, FALSE, + "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL); + + for (k = ranges; k; k = k->next) { + int *range = k->data; + GstStructure *s; + + s = gst_structure_copy (size); + if (range[0] == range[1]) { + gst_structure_set (s, "framerate", GST_TYPE_FRACTION, + range[0], 1000, NULL); + } else { + gst_structure_set (s, "framerate", GST_TYPE_FRACTION_RANGE, + range[0], 1000, range[1], 1000, NULL); + } + gst_caps_append_structure (ret, s); + } + gst_structure_free (size); + } + gst_structure_free (format); + } + } + GST_DEBUG_OBJECT (self, "Supported preview sizes:"); + for (i = sizes; i; i = i->next) { + GstAHCSize *s = i->data; + + GST_DEBUG_OBJECT (self, " %dx%d", s->width, s->height); + } + GST_DEBUG_OBJECT (self, "Supported preview fps range:"); + for (i = ranges; i; i = i->next) { + int *range = i->data; + + GST_DEBUG_OBJECT (self, " [%d, %d]", range[0], range[1]); + } + + gst_ahc_parameters_supported_preview_formats_free (formats); + gst_ahc_parameters_supported_preview_sizes_free (sizes); + gst_ahc_parameters_supported_preview_fps_range_free (ranges); + gst_ahc_parameters_free (params); + } + + return ret; + } else { + return NULL; + } +} + +static GstCaps * +gst_ahc_src_fixate (GstBaseSrc * src, GstCaps * caps) +{ + GstAHCSrc *self = GST_AHC_SRC (src); + GstStructure *s = gst_caps_get_structure (caps, 0); + + GST_DEBUG_OBJECT (self, "Fixating : %" GST_PTR_FORMAT, caps); + + caps = gst_caps_make_writable (caps); + + /* Width/height will be fixed already here, format will + * be left for fixation by the default handler. + * We only have to fixate framerate here, to the + * highest possible framerate. + */ + gst_structure_fixate_field_nearest_fraction (s, "framerate", G_MAXINT, 1); + + caps = GST_BASE_SRC_CLASS (parent_class)->fixate (src, caps); + + return caps; +} + +static gboolean +gst_ahc_src_setcaps (GstBaseSrc * src, GstCaps * caps) +{ + GstAHCSrc *self = GST_AHC_SRC (src); + gboolean ret = FALSE; + GstAHCParameters *params = NULL; + + if (!self->camera) { + GST_WARNING_OBJECT (self, "setcaps called without a camera available"); + goto end; + } + + params = gst_ah_camera_get_parameters (self->camera); + if (params) { + GstStructure *s; + const gchar *format_str = NULL; + GstVideoFormat format; + gint fmt; + gint width, height, fps_n, fps_d, buffer_size; + GList *ranges, *l; + gint range_size = G_MAXINT; + + s = gst_caps_get_structure (caps, 0); + + format_str = gst_structure_get_string (s, "format"); + format = gst_video_format_from_string (format_str); + + gst_structure_get_int (s, "width", &width); + gst_structure_get_int (s, "height", &height); + gst_structure_get_fraction (s, "framerate", &fps_n, &fps_d); + + fps_n *= 1000 / fps_d; + + /* Select the best range that contains our framerate. + * We *must* set a range of those returned by the camera + * according to the API docs and can't use a subset of any + * of those ranges. + * We chose the smallest range that contains the target + * framerate. + */ + self->fps_max = self->fps_min = 0; + ranges = gst_ahc_parameters_get_supported_preview_fps_range (params); + ranges = g_list_sort (ranges, (GCompareFunc) _compare_ranges); + for (l = ranges; l; l = l->next) { + int *range = l->data; + + if (fps_n >= range[0] && fps_n <= range[1] && + range_size > (range[1] - range[0])) { + self->fps_min = range[0]; + self->fps_max = range[1]; + range_size = range[1] - range[0]; + } + } + gst_ahc_parameters_supported_preview_fps_range_free (ranges); + if (self->fps_max == 0) { + GST_ERROR_OBJECT (self, "Couldn't find an applicable FPS range"); + goto end; + } + + switch (format) { + case GST_VIDEO_FORMAT_YV12: + fmt = ImageFormat_YV12; + break; + case GST_VIDEO_FORMAT_NV21: + fmt = ImageFormat_NV21; + break; + case GST_VIDEO_FORMAT_YUY2: + fmt = ImageFormat_YUY2; + break; + case GST_VIDEO_FORMAT_RGB16: + fmt = ImageFormat_RGB_565; + break; + /* GST_VIDEO_FORMAT_NV16 doesn't exist */ + //case GST_VIDEO_FORMAT_NV16: + //fmt = ImageFormat_NV16; + //break; + default: + fmt = ImageFormat_UNKNOWN; + break; + } + + if (fmt == ImageFormat_UNKNOWN) { + GST_WARNING_OBJECT (self, "unsupported video format (%s)", format_str); + goto end; + } + + gst_ahc_parameters_set_preview_size (params, width, height); + gst_ahc_parameters_set_preview_format (params, fmt); + gst_ahc_parameters_set_preview_fps_range (params, self->fps_min, + self->fps_max); + + GST_DEBUG_OBJECT (self, "Setting camera parameters : %d %dx%d @ [%f, %f]", + fmt, width, height, self->fps_min / 1000.0, self->fps_max / 1000.0); + + if (!gst_ah_camera_set_parameters (self->camera, params)) { + GST_WARNING_OBJECT (self, "Unable to set video parameters"); + goto end; + } + + self->width = width; + self->height = height; + self->format = fmt; + buffer_size = width * height * + ((double) gst_ag_imageformat_get_bits_per_pixel (fmt) / 8); + + if (buffer_size > self->buffer_size) { + JNIEnv *env = gst_amc_jni_get_env (); + gint i; + + for (i = 0; i < NUM_CALLBACK_BUFFERS; i++) { + jbyteArray array = (*env)->NewByteArray (env, buffer_size); + + if (array) { + gst_ah_camera_add_callback_buffer (self->camera, array); + (*env)->DeleteLocalRef (env, array); + } + } + } + self->buffer_size = buffer_size; + + GST_DEBUG_OBJECT (self, "setting buffer w:%d h:%d buffer_size: %d", + self->width, self->height, self->buffer_size); + + ret = TRUE; + } + +end: + if (params) + gst_ahc_parameters_free (params); + + if (ret && self->start) { + GST_DEBUG_OBJECT (self, "Starting preview"); + ret = gst_ah_camera_start_preview (self->camera); + if (ret) { + /* Need to reset callbacks after every startPreview */ + gst_ah_camera_set_preview_callback_with_buffer (self->camera, + gst_ahc_src_on_preview_frame, self); + gst_ah_camera_set_error_callback (self->camera, gst_ahc_src_on_error, + self); + self->start = FALSE; + } + } + return ret; +} + +typedef struct +{ + GstAHCSrc *self; + jbyteArray array; + jbyte *data; +} FreeFuncBuffer; + +static void +gst_ahc_src_buffer_free_func (gpointer priv) +{ + FreeFuncBuffer *data = (FreeFuncBuffer *) priv; + GstAHCSrc *self = data->self; + JNIEnv *env = gst_amc_jni_get_env (); + + g_mutex_lock (&self->mutex); + + GST_DEBUG_OBJECT (self, "release %p->%p", data, data->array); + + (*env)->ReleaseByteArrayElements (env, data->array, data->data, JNI_ABORT); + if (self->camera) + gst_ah_camera_add_callback_buffer (self->camera, data->array); + + (*env)->DeleteGlobalRef (env, data->array); + + g_slice_free (FreeFuncBuffer, data); + + g_mutex_unlock (&self->mutex); + gst_object_unref (self); +} + +static void +_data_queue_item_free (GstDataQueueItem * item) +{ + GST_DEBUG ("release %p", item->object); + + gst_buffer_unref (GST_BUFFER (item->object)); + g_slice_free (GstDataQueueItem, item); +} + +static void +gst_ahc_src_on_preview_frame (jbyteArray array, gpointer user_data) +{ + GstAHCSrc *self = GST_AHC_SRC (user_data); + JNIEnv *env = gst_amc_jni_get_env (); + GstBuffer *buffer; + GstDataQueueItem *item = NULL; + FreeFuncBuffer *malloc_data = NULL; + GstClockTime timestamp = GST_CLOCK_TIME_NONE; + GstClockTime duration = 0; + GstClock *clock; + gboolean queued = FALSE; + + g_mutex_lock (&self->mutex); + + if (array == NULL) { + GST_DEBUG_OBJECT (self, "Size of array in queue is too small, dropping it"); + goto done; + } + + if ((clock = GST_ELEMENT_CLOCK (self))) { + GstClockTime base_time = GST_ELEMENT_CAST (self)->base_time; + GstClockTime current_ts; + + gst_object_ref (clock); + current_ts = gst_clock_get_time (clock) - base_time; + gst_object_unref (clock); + if (GST_CLOCK_TIME_IS_VALID (self->previous_ts)) { + timestamp = self->previous_ts; + duration = current_ts - self->previous_ts; + self->previous_ts = current_ts; + } else { + /* Drop the first buffer */ + self->previous_ts = current_ts; + gst_ah_camera_add_callback_buffer (self->camera, array); + GST_DEBUG_OBJECT (self, "dropping the first buffer"); + goto done; + } + } else { + GST_DEBUG_OBJECT (self, "element clock hasn't created yet."); + gst_ah_camera_add_callback_buffer (self->camera, array); + goto done; + } + + GST_DEBUG_OBJECT (self, "Received data buffer %p", array); + + malloc_data = g_slice_new0 (FreeFuncBuffer); + malloc_data->self = gst_object_ref (self); + malloc_data->array = (*env)->NewGlobalRef (env, array); + malloc_data->data = (*env)->GetByteArrayElements (env, array, NULL); + + buffer = + gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, malloc_data->data, + self->buffer_size, 0, self->buffer_size, malloc_data, + gst_ahc_src_buffer_free_func); + GST_BUFFER_DURATION (buffer) = duration; + GST_BUFFER_PTS (buffer) = timestamp; + + GST_DEBUG_OBJECT (self, "creating wrapped buffer (size: %d)", + self->buffer_size); + + item = g_slice_new0 (GstDataQueueItem); + item->object = GST_MINI_OBJECT (buffer); + item->size = gst_buffer_get_size (buffer); + item->duration = GST_BUFFER_DURATION (buffer); + item->visible = TRUE; + item->destroy = (GDestroyNotify) _data_queue_item_free; + + GST_DEBUG_OBJECT (self, "wrapping jni array %p->%p %p->%p", item, + item->object, malloc_data, malloc_data->array); + + queued = gst_data_queue_push (self->queue, item); + +done: + g_mutex_unlock (&self->mutex); + + if (item && !queued) { + GST_INFO_OBJECT (self, "could not add buffer to queue"); + /* Can't add buffer to queue. Must be flushing. */ + _data_queue_item_free (item); + } +} + +static void +gst_ahc_src_on_error (gint error, gpointer user_data) +{ + GstAHCSrc *self = GST_AHC_SRC (user_data); + + GST_WARNING_OBJECT (self, "Received error code : %d", error); +} + +static gboolean +gst_ahc_src_open (GstAHCSrc * self) +{ + GST_DEBUG_OBJECT (self, "Openning camera"); + + self->camera = gst_ah_camera_open (self->device); + + if (self->camera) { + GST_DEBUG_OBJECT (self, "Opened camera"); + + self->texture = gst_ag_surfacetexture_new (0); + gst_ah_camera_set_preview_texture (self->camera, self->texture); + self->buffer_size = 0; + } else { + gint num_cams = gst_ah_camera_get_number_of_cameras (); + if (num_cams > 0 && self->device < num_cams) { + GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND, + ("Unable to open device '%d'.", self->device), GST_ERROR_SYSTEM); + } else if (num_cams > 0) { + GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND, + ("Device '%d' does not exist.", self->device), GST_ERROR_SYSTEM); + } else { + GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND, + ("There are no cameras available on this device."), GST_ERROR_SYSTEM); + } + } + + return (self->camera != NULL); +} + +static void +gst_ahc_src_close (GstAHCSrc * self) +{ + if (self->camera) { + gst_ah_camera_set_error_callback (self->camera, NULL, NULL); + gst_ah_camera_set_preview_callback_with_buffer (self->camera, NULL, NULL); + gst_ah_camera_release (self->camera); + gst_ah_camera_free (self->camera); + } + self->camera = NULL; + + if (self->texture) { + gst_ag_surfacetexture_release (self->texture); + gst_ag_surfacetexture_free (self->texture); + } + self->texture = NULL; +} + +static GstStateChangeReturn +gst_ahc_src_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstAHCSrc *self = GST_AHC_SRC (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + if (!gst_ahc_src_open (self)) + return GST_STATE_CHANGE_FAILURE; + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_NULL: + gst_ahc_src_close (self); + break; + default: + break; + } + + return ret; +} + +static gboolean +gst_ahc_src_start (GstBaseSrc * bsrc) +{ + GstAHCSrc *self = GST_AHC_SRC (bsrc); + + GST_DEBUG_OBJECT (self, "Starting preview"); + if (self->camera) { + self->previous_ts = GST_CLOCK_TIME_NONE; + self->fps_min = self->fps_max = self->width = self->height = 0; + self->format = ImageFormat_UNKNOWN; + self->start = TRUE; + + return TRUE; + } else { + return FALSE; + } +} + +static gboolean +gst_ahc_src_stop (GstBaseSrc * bsrc) +{ + GstAHCSrc *self = GST_AHC_SRC (bsrc); + + GST_DEBUG_OBJECT (self, "Stopping preview"); + if (self->camera) { + gst_data_queue_flush (self->queue); + self->start = FALSE; + gst_ah_camera_set_error_callback (self->camera, NULL, NULL); + return gst_ah_camera_stop_preview (self->camera); + } + return TRUE; +} + +static gboolean +gst_ahc_src_unlock (GstBaseSrc * bsrc) +{ + GstAHCSrc *self = GST_AHC_SRC (bsrc); + + GST_DEBUG_OBJECT (self, "Unlocking create"); + gst_data_queue_set_flushing (self->queue, TRUE); + + return TRUE; +} + +static gboolean +gst_ahc_src_unlock_stop (GstBaseSrc * bsrc) +{ + GstAHCSrc *self = GST_AHC_SRC (bsrc); + + GST_DEBUG_OBJECT (self, "Stopping unlock"); + gst_data_queue_set_flushing (self->queue, FALSE); + + return TRUE; +} + +static GstFlowReturn +gst_ahc_src_create (GstPushSrc * src, GstBuffer ** buffer) +{ + GstAHCSrc *self = GST_AHC_SRC (src); + GstDataQueueItem *item; + + if (!gst_data_queue_pop (self->queue, &item)) { + GST_INFO_OBJECT (self, "empty queue"); + return GST_FLOW_FLUSHING; + } + + GST_DEBUG_OBJECT (self, "creating buffer %p->%p", item, item->object); + + *buffer = GST_BUFFER (item->object); + g_slice_free (GstDataQueueItem, item); + + return GST_FLOW_OK; +} + +static gboolean +gst_ahc_src_query (GstBaseSrc * bsrc, GstQuery * query) +{ + GstAHCSrc *self = GST_AHC_SRC (bsrc); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_LATENCY:{ + GstClockTime min; + + /* Allow of 1 frame latency base on the longer frame duration */ + gst_query_parse_latency (query, NULL, &min, NULL); + min = gst_util_uint64_scale (GST_SECOND, 1000, self->fps_min); + GST_DEBUG_OBJECT (self, + "Reporting latency min: %" GST_TIME_FORMAT, GST_TIME_ARGS (min)); + gst_query_set_latency (query, TRUE, min, min); + + return TRUE; + break; + } + default: + return GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query); + break; + } + + g_assert_not_reached (); +} diff --git a/sys/androidmedia/gstahcsrc.h b/sys/androidmedia/gstahcsrc.h new file mode 100644 index 0000000000..fc24989277 --- /dev/null +++ b/sys/androidmedia/gstahcsrc.h @@ -0,0 +1,89 @@ +/* GStreamer android.hardware.Camera Source + * + * Copyright (C) 2012, Cisco Systems, Inc. + * Author: Youness Alaoui + * + * Copyright (C) 2015, Collabora Ltd. + * Author: Justin Kim + * + * 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_SRC_H__ +#define __GST_AHC_SRC_H__ + +#include +#include +#include + +#include "gst-android-hardware-camera.h" + +G_BEGIN_DECLS + +#define GST_TYPE_AHC_SRC \ + (gst_ahc_src_get_type()) +#define GST_AHC_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_AHC_SRC, GstAHCSrc)) +#define GST_AHC_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_AHC_SRC, GstAHCSrcClass)) +#define GST_IS_AHC_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_AHC_SRC)) +#define GST_IS_AHC_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_AHC_SRC)) + + +typedef struct _GstAHCSrc GstAHCSrc; +typedef struct _GstAHCSrcClass GstAHCSrcClass; + +/** + * GstAHCSrc: + * + * Opaque data structure. + */ +struct _GstAHCSrc +{ + /*< private >*/ + GstPushSrc parent; + + GstAHCamera *camera; + GstAGSurfaceTexture *texture; + GList *data; + GstDataQueue *queue; + gint buffer_size; + GstClockTime previous_ts; + gint format; + gint width; + gint height; + gint fps_min; + gint fps_max; + gboolean start; + gboolean smooth_zoom; + GMutex mutex; + + /* Properties */ + gint device; +}; + +struct _GstAHCSrcClass +{ + GstPushSrcClass parent_class; + GList *probe_properties; +}; + +GType gst_ahc_src_get_type (void); + +G_END_DECLS +#endif /* __GST_AHC_SRC_H__ */ diff --git a/sys/androidmedia/gstamc.c b/sys/androidmedia/gstamc.c index f333820789..5a72e0e1d5 100644 --- a/sys/androidmedia/gstamc.c +++ b/sys/androidmedia/gstamc.c @@ -29,6 +29,8 @@ #define orc_memcpy memcpy #endif +#include "gstahcsrc.h" + #include "gstamc.h" #include "gstamc-constants.h" @@ -3316,6 +3318,28 @@ plugin_init (GstPlugin * plugin) if (!register_codecs (plugin)) return FALSE; + if (!gst_android_graphics_surfacetexture_init ()) { + GST_ERROR ("Failed to init android surface texture"); + return FALSE; + } + + if (!gst_android_graphics_imageformat_init ()) { + GST_ERROR ("Failed to init android image format"); + gst_android_graphics_surfacetexture_deinit (); + return FALSE; + } + + if (!gst_android_hardware_camera_init ()) { + gst_android_graphics_surfacetexture_deinit (); + gst_android_graphics_imageformat_deinit (); + return FALSE; + } + + if (!gst_element_register (plugin, "ahcsrc", GST_RANK_NONE, GST_TYPE_AHC_SRC)) { + GST_ERROR ("Failed to register android camera source"); + return FALSE; + } + return TRUE; } diff --git a/sys/androidmedia/org/freedesktop/gstreamer/androidmedia/GstAhcCallback.java b/sys/androidmedia/org/freedesktop/gstreamer/androidmedia/GstAhcCallback.java new file mode 100644 index 0000000000..53811a9d33 --- /dev/null +++ b/sys/androidmedia/org/freedesktop/gstreamer/androidmedia/GstAhcCallback.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2012, Collabora Ltd. + * Author: Youness Alaoui + * + * Copyright (C) 2015, Collabora Ltd. + * Author: Justin Kim + * + * 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 + * + */ + +package org.freedesktop.gstreamer.androidmedia; + +import android.hardware.Camera; + +public class GstAhcCallback implements Camera.PreviewCallback, + Camera.ErrorCallback, + Camera.AutoFocusCallback { + 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 static native void gst_ah_camera_on_auto_focus(boolean success, 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); + } + + @Override + public void onAutoFocus(boolean success, Camera camera) { + gst_ah_camera_on_auto_focus(success, camera, mCallback, mUserData); + } +}