/* * Copyright (C) 2012, Collabora Ltd. * 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 "gst-dvm.h" #include "gst-android-hardware-camera.h" static struct { jclass klass; jmethodID addCallbackBuffer; 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; static struct { jclass klass; jmethodID constructor; jfieldID facing; jfieldID orientation; jint CAMERA_FACING_BACK; jint CAMERA_FACING_FRONT; } android_hardware_camera_camerainfo; gint CameraInfo_CAMERA_FACING_BACK; gint CameraInfo_CAMERA_FACING_FRONT; static struct { jclass klass; jfieldID width; jfieldID height; } android_hardware_camera_size; /* TODO: Add other parameters */ static struct { jclass klass; jmethodID flatten; jmethodID getPreviewFormat; jmethodID getPreviewFpsRange; jmethodID getPreviewSize; jmethodID getSupportedPreviewFormats; jmethodID getSupportedPreviewFpsRange; jmethodID getSupportedPreviewSizes; jmethodID setPreviewFormat; jmethodID setPreviewFpsRange; jmethodID setPreviewSize; jmethodID unflatten; } android_hardware_camera_parameters; static struct { jclass klass; jmethodID iterator; } java_util_list; static struct { jclass klass; jmethodID hasNext; jmethodID next; } java_util_iterator; static struct { jclass klass; jmethodID intValue; } java_lang_integer; static struct { jclass klass; jmethodID constructor; } com_gstreamer_gstahccallback; 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; 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; cb (error, (gpointer) (gsize) user_data); } static JNINativeMethod native_methods[] = { {"gst_ah_camera_on_preview_frame", "([BLandroid/hardware/Camera;JJ)V", (void *) gst_ah_camera_on_preview_frame}, {"gst_ah_camera_on_error", "(ILandroid/hardware/Camera;JJ)V", (void *) gst_ah_camera_on_error} }; gboolean gst_android_hardware_camera_init () { JNIEnv *env = gst_dvm_get_env (); if (!gst_android_graphics_surfacetexture_init ()) return FALSE; if (!gst_android_graphics_imageformat_init ()) return FALSE; /* android.hardware.Camera */ GST_DVM_GET_CLASS (android_hardware_camera, "android/hardware/Camera"); GST_DVM_GET_METHOD (android_hardware_camera, addCallbackBuffer, "([B)V"); GST_DVM_GET_STATIC_METHOD (android_hardware_camera, getCameraInfo, "(ILandroid/hardware/Camera$CameraInfo;)V"); GST_DVM_GET_STATIC_METHOD (android_hardware_camera, getNumberOfCameras, "()I"); GST_DVM_GET_METHOD (android_hardware_camera, getParameters, "()Landroid/hardware/Camera$Parameters;"); GST_DVM_GET_METHOD (android_hardware_camera, lock, "()V"); GST_DVM_GET_STATIC_METHOD (android_hardware_camera, open, "(I)Landroid/hardware/Camera;"); GST_DVM_GET_METHOD (android_hardware_camera, reconnect, "()V"); GST_DVM_GET_METHOD (android_hardware_camera, release, "()V"); GST_DVM_GET_METHOD (android_hardware_camera, setErrorCallback, "(Landroid/hardware/Camera$ErrorCallback;)V"); GST_DVM_GET_METHOD (android_hardware_camera, setParameters, "(Landroid/hardware/Camera$Parameters;)V"); GST_DVM_GET_METHOD (android_hardware_camera, setPreviewCallbackWithBuffer, "(Landroid/hardware/Camera$PreviewCallback;)V"); GST_DVM_GET_METHOD (android_hardware_camera, setPreviewTexture, "(Landroid/graphics/SurfaceTexture;)V"); GST_DVM_GET_METHOD (android_hardware_camera, startPreview, "()V"); GST_DVM_GET_METHOD (android_hardware_camera, startSmoothZoom, "(I)V"); GST_DVM_GET_METHOD (android_hardware_camera, stopPreview, "()V"); GST_DVM_GET_METHOD (android_hardware_camera, stopSmoothZoom, "()V"); GST_DVM_GET_METHOD (android_hardware_camera, unlock, "()V"); /* android.hardware.Camera.CameraInfo */ GST_DVM_GET_CLASS (android_hardware_camera_camerainfo, "android/hardware/Camera$CameraInfo"); GST_DVM_GET_CONSTRUCTOR (android_hardware_camera_camerainfo, constructor, "()V"); GST_DVM_GET_FIELD (android_hardware_camera_camerainfo, facing, "I"); GST_DVM_GET_FIELD (android_hardware_camera_camerainfo, orientation, "I"); GST_DVM_GET_CONSTANT (android_hardware_camera_camerainfo, CAMERA_FACING_BACK, Int, "I"); CameraInfo_CAMERA_FACING_BACK = android_hardware_camera_camerainfo.CAMERA_FACING_BACK; GST_DVM_GET_CONSTANT (android_hardware_camera_camerainfo, CAMERA_FACING_FRONT, Int, "I"); CameraInfo_CAMERA_FACING_FRONT = android_hardware_camera_camerainfo.CAMERA_FACING_FRONT; /* android.hardware.Camera.Size */ GST_DVM_GET_CLASS (android_hardware_camera_size, "android/hardware/Camera$Size"); GST_DVM_GET_FIELD (android_hardware_camera_size, width, "I"); GST_DVM_GET_FIELD (android_hardware_camera_size, height, "I"); /* android.hardware.Camera.Parameters */ GST_DVM_GET_CLASS (android_hardware_camera_parameters, "android/hardware/Camera$Parameters"); GST_DVM_GET_METHOD (android_hardware_camera_parameters, flatten, "()Ljava/lang/String;"); GST_DVM_GET_METHOD (android_hardware_camera_parameters, getPreviewFormat, "()I"); GST_DVM_GET_METHOD (android_hardware_camera_parameters, getPreviewFpsRange, "([I)V"); GST_DVM_GET_METHOD (android_hardware_camera_parameters, getPreviewSize, "()Landroid/hardware/Camera$Size;"); GST_DVM_GET_METHOD (android_hardware_camera_parameters, getSupportedPreviewFormats, "()Ljava/util/List;"); GST_DVM_GET_METHOD (android_hardware_camera_parameters, getSupportedPreviewFpsRange, "()Ljava/util/List;"); GST_DVM_GET_METHOD (android_hardware_camera_parameters, getSupportedPreviewSizes, "()Ljava/util/List;"); GST_DVM_GET_METHOD (android_hardware_camera_parameters, setPreviewFormat, "(I)V"); GST_DVM_GET_METHOD (android_hardware_camera_parameters, setPreviewFpsRange, "(II)V"); GST_DVM_GET_METHOD (android_hardware_camera_parameters, setPreviewSize, "(II)V"); GST_DVM_GET_METHOD (android_hardware_camera_parameters, unflatten, "(Ljava/lang/String;)V"); /* java.util.List */ GST_DVM_GET_CLASS (java_util_list, "java/util/List"); GST_DVM_GET_METHOD (java_util_list, iterator, "()Ljava/util/Iterator;"); /* java.util.Iterator */ GST_DVM_GET_CLASS (java_util_iterator, "java/util/Iterator"); GST_DVM_GET_METHOD (java_util_iterator, hasNext, "()Z"); GST_DVM_GET_METHOD (java_util_iterator, next, "()Ljava/lang/Object;"); /* java.lang.Integer */ GST_DVM_GET_CLASS (java_lang_integer, "java/lang/Integer"); GST_DVM_GET_METHOD (java_lang_integer, intValue, "()I"); /* com.gstreamer.GstAhcCallback */ GST_DVM_GET_CLASS (com_gstreamer_gstahccallback, "com/gstreamer/GstAhcCallback"); GST_DVM_GET_CONSTRUCTOR (com_gstreamer_gstahccallback, constructor, "(JJ)V"); if ((*env)->RegisterNatives (env, com_gstreamer_gstahccallback.klass, native_methods, G_N_ELEMENTS (native_methods))) { GST_ERROR ("Failed to register native methods for GstAhcCallback"); return FALSE; } return TRUE; } /* android.hardware.Camera */ void gst_ah_camera_add_callback_buffer (GstAHCamera * self, jbyteArray buffer) { JNIEnv *env = gst_dvm_get_env (); /* TODO: use a java.nio.ByteBuffer if possible */ (*env)->CallVoidMethod (env, self->object, android_hardware_camera.addCallbackBuffer, buffer); } gboolean gst_ah_camera_get_camera_info (gint camera_id, GstAHCCameraInfo * camera_info) { JNIEnv *env = gst_dvm_get_env (); jobject jcamera_info = NULL; gboolean ret = TRUE; 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); ret = FALSE; goto done; } (*env)->CallStaticVoidMethod (env, android_hardware_camera.klass, android_hardware_camera.getCameraInfo, camera_id, jcamera_info); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); ret = FALSE; goto done; } 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); ret = FALSE; 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); ret = FALSE; goto done; } done: if (jcamera_info) (*env)->DeleteLocalRef (env, jcamera_info); return ret; } gint gst_ah_camera_get_number_of_cameras () { JNIEnv *env = gst_dvm_get_env (); gint num_cameras; num_cameras = (*env)->CallStaticIntMethod (env, android_hardware_camera.klass, android_hardware_camera.getNumberOfCameras); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); return -1; } return num_cameras; } GstAHCParameters * gst_ah_camera_get_parameters (GstAHCamera * self) { JNIEnv *env = gst_dvm_get_env (); jobject object = NULL; GstAHCParameters *params = NULL; object = (*env)->CallObjectMethod (env, self->object, android_hardware_camera.getParameters); if ((*env)->ExceptionCheck (env) || !object) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); return NULL; } params = g_slice_new0 (GstAHCParameters); params->object = (*env)->NewGlobalRef (env, object); if (!params->object) { GST_ERROR ("Failed to create global reference"); (*env)->ExceptionClear (env); g_slice_free (GstAHCParameters, params); params = NULL; } (*env)->DeleteLocalRef (env, object); return params; } gboolean gst_ah_camera_lock (GstAHCamera * self) { JNIEnv *env = gst_dvm_get_env (); (*env)->CallVoidMethod (env, self->object, android_hardware_camera.lock); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); return FALSE; } return TRUE; } GstAHCamera * gst_ah_camera_open (gint camera_id) { JNIEnv *env = gst_dvm_get_env (); jobject object = NULL; GstAHCamera *camera = NULL; object = (*env)->CallStaticObjectMethod (env, android_hardware_camera.klass, android_hardware_camera.open, camera_id); if ((*env)->ExceptionCheck (env) || !object) { /* TODO: return a GError ? */ //jthrowable e = (*env)->ExceptionOccurred(env); GST_ERROR ("Failed to call Java method"); (*env)->ExceptionDescribe (env); (*env)->ExceptionClear (env); return NULL; } camera = g_slice_new0 (GstAHCamera); camera->object = (*env)->NewGlobalRef (env, object); if (!camera->object) { GST_ERROR ("Failed to create global reference"); (*env)->ExceptionClear (env); g_slice_free (GstAHCamera, camera); camera = NULL; } (*env)->DeleteLocalRef (env, object); return camera; } gboolean gst_ah_camera_reconnect (GstAHCamera * self) { JNIEnv *env = gst_dvm_get_env (); (*env)->CallVoidMethod (env, self->object, android_hardware_camera.reconnect); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); return FALSE; } return TRUE; } void gst_ah_camera_release (GstAHCamera * self) { JNIEnv *env = gst_dvm_get_env (); (*env)->CallVoidMethod (env, self->object, android_hardware_camera.release); (*env)->DeleteGlobalRef (env, self->object); g_slice_free (GstAHCamera, self); } gboolean gst_ah_camera_set_parameters (GstAHCamera * self, GstAHCParameters * params) { JNIEnv *env = gst_dvm_get_env (); (*env)->CallVoidMethod (env, self->object, android_hardware_camera.setParameters, params->object); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); return FALSE; } return TRUE; } gboolean gst_ah_camera_set_error_callback (GstAHCamera * self, GstAHCErrorCallback cb, gpointer user_data) { JNIEnv *env = gst_dvm_get_env (); jobject object; gboolean ret = TRUE; object = (*env)->NewObject (env, com_gstreamer_gstahccallback.klass, com_gstreamer_gstahccallback.constructor, *((jlong *) & cb), *((jlong *) & user_data)); if (!object) { GST_ERROR ("Failed to create callback object"); (*env)->ExceptionClear (env); ret = FALSE; goto done; } (*env)->CallVoidMethod (env, self->object, android_hardware_camera.setErrorCallback, object); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); ret = FALSE; goto done; } 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_dvm_get_env (); jobject object; gboolean ret = TRUE; object = (*env)->NewObject (env, com_gstreamer_gstahccallback.klass, com_gstreamer_gstahccallback.constructor, *((jlong *) & cb), *((jlong *) & user_data)); if (!object) { GST_ERROR ("Failed to create callback object"); (*env)->ExceptionClear (env); ret = FALSE; goto done; } (*env)->CallVoidMethod (env, self->object, android_hardware_camera.setPreviewCallbackWithBuffer, object); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); ret = FALSE; goto done; } done: if (object) (*env)->DeleteLocalRef (env, object); return ret; } void gst_ah_camera_set_preview_texture (GstAHCamera * self, GstAGSurfaceTexture * surfaceTexture) { JNIEnv *env = gst_dvm_get_env (); (*env)->CallVoidMethod (env, self->object, android_hardware_camera.setPreviewTexture, surfaceTexture->object); } gboolean gst_ah_camera_start_preview (GstAHCamera * self) { JNIEnv *env = gst_dvm_get_env (); (*env)->CallVoidMethod (env, self->object, android_hardware_camera.startPreview); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); return FALSE; } return TRUE; } gboolean gst_ah_camera_start_smooth_zoom (GstAHCamera * self, gint value) { JNIEnv *env = gst_dvm_get_env (); (*env)->CallVoidMethod (env, self->object, android_hardware_camera.startSmoothZoom, value); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); return FALSE; } return TRUE; } gboolean gst_ah_camera_stop_preview (GstAHCamera * self) { JNIEnv *env = gst_dvm_get_env (); (*env)->CallVoidMethod (env, self->object, android_hardware_camera.stopPreview); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); return FALSE; } return TRUE; } gboolean gst_ah_camera_stop_smooth_zoom (GstAHCamera * self) { JNIEnv *env = gst_dvm_get_env (); (*env)->CallVoidMethod (env, self->object, android_hardware_camera.stopSmoothZoom); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); return FALSE; } return TRUE; } gboolean gst_ah_camera_unlock (GstAHCamera * self) { JNIEnv *env = gst_dvm_get_env (); (*env)->CallVoidMethod (env, self->object, android_hardware_camera.unlock); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); return FALSE; } return TRUE; } /* 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); } /* android.hardware.Camera.Parameters */ gchar * gst_ahc_parameters_flatten (GstAHCParameters * self) { JNIEnv *env = gst_dvm_get_env (); jstring v_str = NULL; const gchar *v = NULL; gchar *ret = NULL; v_str = (*env)->CallObjectMethod (env, self->object, android_hardware_camera_parameters.flatten); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); goto done; } 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; } gint gst_ahc_parameters_get_preview_format (GstAHCParameters * self) { JNIEnv *env = gst_dvm_get_env (); gint format; format = (*env)->CallIntMethod (env, self->object, android_hardware_camera_parameters.getPreviewFormat); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); return 0; } return format; } gboolean gst_ahc_parameters_get_preview_fps_range (GstAHCParameters * self, gint * min, gint * max) { JNIEnv *env = gst_dvm_get_env (); gboolean ret = TRUE; jintArray range = NULL; jint *fps = NULL; range = (*env)->NewIntArray (env, 2); if (!fps) { (*env)->ExceptionClear (env); GST_ERROR ("Failed to create array"); ret = FALSE; goto done; } (*env)->CallVoidMethod (env, self->object, android_hardware_camera_parameters.getPreviewFpsRange, range); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); return 0; } fps = (*env)->GetIntArrayElements (env, range, NULL); if ((*env)->ExceptionCheck (env) || !fps) { (*env)->ExceptionClear (env); GST_ERROR ("Failed to get array elements"); ret = FALSE; goto done; } if (min) *min = fps[0]; if (max) *max = fps[1]; 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_dvm_get_env (); jobject jsize = NULL; GstAHCSize *size = NULL; jsize = (*env)->CallObjectMethod (env, self->object, android_hardware_camera_parameters.getPreviewSize); if ((*env)->ExceptionCheck (env) || !jsize) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); goto done; } 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; } static jobject java_util_list_iterator (JNIEnv * env, jobject obj) { return (*env)->CallObjectMethod (env, obj, java_util_list.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); } static jint java_lang_integer_int_value (JNIEnv * env, jobject obj) { return (*env)->CallIntMethod (env, obj, java_lang_integer.intValue); } GList * gst_ahc_parameters_get_supported_preview_formats (GstAHCParameters * self) { JNIEnv *env = gst_dvm_get_env (); jobject list = NULL; jobject iterator = NULL; GList *ret = NULL; list = (*env)->CallObjectMethod (env, self->object, android_hardware_camera_parameters.getSupportedPreviewFormats); if ((*env)->ExceptionCheck (env) || !list) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); return 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_dvm_get_env (); jobject list = NULL; jobject iterator = NULL; GList *ret = NULL; list = (*env)->CallObjectMethod (env, self->object, android_hardware_camera_parameters.getSupportedPreviewFpsRange); if ((*env)->ExceptionCheck (env) || !list) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); return 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 = malloc (sizeof (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_free_full (list, (GDestroyNotify) g_free); } GList * gst_ahc_parameters_get_supported_preview_sizes (GstAHCParameters * self) { JNIEnv *env = gst_dvm_get_env (); jobject list = NULL; jobject iterator = NULL; GList *ret = NULL; list = (*env)->CallObjectMethod (env, self->object, android_hardware_camera_parameters.getSupportedPreviewSizes); if ((*env)->ExceptionCheck (env) || !list) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); return 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_free_full (list, (GDestroyNotify) gst_ahc_size_free); } gboolean gst_ahc_parameters_set_preview_format (GstAHCParameters * self, gint format) { JNIEnv *env = gst_dvm_get_env (); (*env)->CallVoidMethod (env, self->object, android_hardware_camera_parameters.setPreviewFormat, format); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); return FALSE; } return TRUE; } gboolean gst_ahc_parameters_set_preview_fps_range (GstAHCParameters * self, gint min, gint max) { JNIEnv *env = gst_dvm_get_env (); (*env)->CallVoidMethod (env, self->object, android_hardware_camera_parameters.setPreviewFpsRange, min, max); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); return FALSE; } return TRUE; } gboolean gst_ahc_parameters_set_preview_size (GstAHCParameters * self, gint width, gint height) { JNIEnv *env = gst_dvm_get_env (); (*env)->CallVoidMethod (env, self->object, android_hardware_camera_parameters.setPreviewSize, width, height); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); return FALSE; } return TRUE; } gboolean gst_ahc_parameters_unflatten (GstAHCParameters * self, gchar * flattened) { JNIEnv *env = gst_dvm_get_env (); jstring v_str = NULL; gboolean ret = TRUE; v_str = (*env)->NewStringUTF (env, flattened); if (v_str == NULL) return FALSE; (*env)->CallVoidMethod (env, self->object, android_hardware_camera_parameters.unflatten, v_str); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); ret = FALSE; } (*env)->DeleteLocalRef (env, v_str); return ret; } void gst_ahc_parameters_free (GstAHCParameters * self) { JNIEnv *env = gst_dvm_get_env (); (*env)->DeleteGlobalRef (env, self->object); g_slice_free (GstAHCParameters, self); }