summaryrefslogtreecommitdiff
path: root/sys/androidmedia
diff options
context:
space:
mode:
authorMatthieu Bouron <matthieu.bouron@collabora.com>2014-06-02 12:37:09 +0100
committerSebastian Dröge <sebastian@centricular.com>2015-03-15 16:28:03 +0000
commitbe2378a071728c48f49cbf43ebaa8d1336c7b12e (patch)
tree453c4d3a28e51ce4c2f11aa047fa7233799f8f09 /sys/androidmedia
parent5c3652dd22e0201402abdcb80ad9c4ace21e0f4c (diff)
downloadgstreamer-plugins-bad-be2378a071728c48f49cbf43ebaa8d1336c7b12e.tar.gz
androidmedia: Split jni code to gstjniutils.c
Diffstat (limited to 'sys/androidmedia')
-rw-r--r--sys/androidmedia/Makefile.am6
-rw-r--r--sys/androidmedia/gstamc.c724
-rw-r--r--sys/androidmedia/gstjniutils.c484
-rw-r--r--sys/androidmedia/gstjniutils.h45
4 files changed, 676 insertions, 583 deletions
diff --git a/sys/androidmedia/Makefile.am b/sys/androidmedia/Makefile.am
index 3f1758803..937ce32ac 100644
--- a/sys/androidmedia/Makefile.am
+++ b/sys/androidmedia/Makefile.am
@@ -4,14 +4,16 @@ libgstandroidmedia_la_SOURCES = \
gstamc.c \
gstamcaudiodec.c \
gstamcvideodec.c \
- gstamcvideoenc.c
+ gstamcvideoenc.c \
+ gstjniutils.c
noinst_HEADERS = \
gstamc.h \
gstamc-constants.h \
gstamcaudiodec.h \
gstamcvideodec.h \
- gstamcvideoenc.h
+ gstamcvideoenc.h \
+ gstjniutils.h
libgstandroidmedia_la_CFLAGS = \
$(GST_PLUGINS_BASE_CFLAGS) \
diff --git a/sys/androidmedia/gstamc.c b/sys/androidmedia/gstamc.c
index 36e437285..57024f27a 100644
--- a/sys/androidmedia/gstamc.c
+++ b/sys/androidmedia/gstamc.c
@@ -34,215 +34,12 @@
#include "gstamcvideodec.h"
#include "gstamcvideoenc.h"
#include "gstamcaudiodec.h"
+#include "gstjniutils.h"
-#include <gmodule.h>
#include <gst/gst.h>
#include <gst/video/video.h>
#include <gst/audio/audio.h>
#include <string.h>
-#include <jni.h>
-
-/* getExceptionSummary() and getStackTrace() taken from Android's
- * platform/libnativehelper/JNIHelp.cpp
- * Modified to work with normal C strings and without C++.
- *
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Returns a human-readable summary of an exception object. The buffer will
- * be populated with the "binary" class name and, if present, the
- * exception message.
- */
-static gchar *
-getExceptionSummary (JNIEnv * env, jthrowable exception)
-{
- GString *gs = g_string_new ("");
- jclass exceptionClass = NULL, classClass = NULL;
- jmethodID classGetNameMethod, getMessage;
- jstring classNameStr = NULL, messageStr = NULL;
- const char *classNameChars, *messageChars;
-
- /* get the name of the exception's class */
- exceptionClass = (*env)->GetObjectClass (env, exception);
- classClass = (*env)->GetObjectClass (env, exceptionClass);
- classGetNameMethod =
- (*env)->GetMethodID (env, classClass, "getName", "()Ljava/lang/String;");
-
- classNameStr =
- (jstring) (*env)->CallObjectMethod (env, exceptionClass,
- classGetNameMethod);
-
- if (classNameStr == NULL) {
- if ((*env)->ExceptionCheck (env))
- (*env)->ExceptionClear (env);
- g_string_append (gs, "<error getting class name>");
- goto done;
- }
-
- classNameChars = (*env)->GetStringUTFChars (env, classNameStr, NULL);
- if (classNameChars == NULL) {
- if ((*env)->ExceptionCheck (env))
- (*env)->ExceptionClear (env);
- g_string_append (gs, "<error getting class name UTF-8>");
- goto done;
- }
-
- g_string_append (gs, classNameChars);
-
- (*env)->ReleaseStringUTFChars (env, classNameStr, classNameChars);
-
- /* if the exception has a detail message, get that */
- getMessage =
- (*env)->GetMethodID (env, exceptionClass, "getMessage",
- "()Ljava/lang/String;");
- messageStr = (jstring) (*env)->CallObjectMethod (env, exception, getMessage);
- if (messageStr == NULL) {
- if ((*env)->ExceptionCheck (env))
- (*env)->ExceptionClear (env);
- goto done;
- }
- g_string_append (gs, ": ");
-
- messageChars = (*env)->GetStringUTFChars (env, messageStr, NULL);
- if (messageChars != NULL) {
- g_string_append (gs, messageChars);
- (*env)->ReleaseStringUTFChars (env, messageStr, messageChars);
- } else {
- if ((*env)->ExceptionCheck (env))
- (*env)->ExceptionClear (env);
- g_string_append (gs, "<error getting message>");
- }
-
-done:
- if (exceptionClass)
- (*env)->DeleteLocalRef (env, exceptionClass);
- if (classClass)
- (*env)->DeleteLocalRef (env, classClass);
- if (classNameStr)
- (*env)->DeleteLocalRef (env, classNameStr);
- if (messageStr)
- (*env)->DeleteLocalRef (env, messageStr);
-
- return g_string_free (gs, FALSE);
-}
-
-/*
- * Returns an exception (with stack trace) as a string.
- */
-static gchar *
-getStackTrace (JNIEnv * env, jthrowable exception)
-{
- GString *gs = g_string_new ("");
- jclass stringWriterClass = NULL, printWriterClass = NULL;
- jclass exceptionClass = NULL;
- jmethodID stringWriterCtor, stringWriterToStringMethod;
- jmethodID printWriterCtor, printStackTraceMethod;
- jobject stringWriter = NULL, printWriter = NULL;
- jstring messageStr = NULL;
- const char *utfChars;
-
- stringWriterClass = (*env)->FindClass (env, "java/io/StringWriter");
-
- if (stringWriterClass == NULL) {
- g_string_append (gs, "<error getting java.io.StringWriter class>");
- goto done;
- }
-
- stringWriterCtor =
- (*env)->GetMethodID (env, stringWriterClass, "<init>", "()V");
- stringWriterToStringMethod =
- (*env)->GetMethodID (env, stringWriterClass, "toString",
- "()Ljava/lang/String;");
-
- printWriterClass = (*env)->FindClass (env, "java/io/PrintWriter");
- if (printWriterClass == NULL) {
- g_string_append (gs, "<error getting java.io.PrintWriter class>");
- goto done;
- }
-
- printWriterCtor =
- (*env)->GetMethodID (env, printWriterClass, "<init>",
- "(Ljava/io/Writer;)V");
- stringWriter = (*env)->NewObject (env, stringWriterClass, stringWriterCtor);
- if (stringWriter == NULL) {
- if ((*env)->ExceptionCheck (env))
- (*env)->ExceptionClear (env);
- g_string_append (gs, "<error creating new StringWriter instance>");
- goto done;
- }
-
- printWriter =
- (*env)->NewObject (env, printWriterClass, printWriterCtor, stringWriter);
- if (printWriter == NULL) {
- if ((*env)->ExceptionCheck (env))
- (*env)->ExceptionClear (env);
- g_string_append (gs, "<error creating new PrintWriter instance>");
- goto done;
- }
-
- exceptionClass = (*env)->GetObjectClass (env, exception);
- printStackTraceMethod =
- (*env)->GetMethodID (env, exceptionClass, "printStackTrace",
- "(Ljava/io/PrintWriter;)V");
- (*env)->CallVoidMethod (env, exception, printStackTraceMethod, printWriter);
- if ((*env)->ExceptionCheck (env)) {
- (*env)->ExceptionClear (env);
- g_string_append (gs, "<exception while printing stack trace>");
- goto done;
- }
-
- messageStr = (jstring) (*env)->CallObjectMethod (env, stringWriter,
- stringWriterToStringMethod);
- if (messageStr == NULL) {
- if ((*env)->ExceptionCheck (env))
- (*env)->ExceptionClear (env);
- g_string_append (gs, "<failed to call StringWriter.toString()>");
- goto done;
- }
-
- utfChars = (*env)->GetStringUTFChars (env, messageStr, NULL);
- if (utfChars == NULL) {
- if ((*env)->ExceptionCheck (env))
- (*env)->ExceptionClear (env);
- g_string_append (gs, "<failed to get UTF chars for message>");
- goto done;
- }
-
- g_string_append (gs, utfChars);
-
- (*env)->ReleaseStringUTFChars (env, messageStr, utfChars);
-
-done:
- if (stringWriterClass)
- (*env)->DeleteLocalRef (env, stringWriterClass);
- if (printWriterClass)
- (*env)->DeleteLocalRef (env, printWriterClass);
- if (exceptionClass)
- (*env)->DeleteLocalRef (env, exceptionClass);
- if (stringWriter)
- (*env)->DeleteLocalRef (env, stringWriter);
- if (printWriter)
- (*env)->DeleteLocalRef (env, printWriter);
- if (messageStr)
- (*env)->DeleteLocalRef (env, messageStr);
-
- return g_string_free (gs, FALSE);
-}
-
-#include <pthread.h>
GST_DEBUG_CATEGORY (gst_amc_debug);
#define GST_CAT_DEFAULT gst_amc_debug
@@ -256,13 +53,6 @@ static gboolean ignore_unknown_color_formats = TRUE;
static gboolean ignore_unknown_color_formats = FALSE;
#endif
-static GModule *java_module;
-static jint (*get_created_java_vms) (JavaVM ** vmBuf, jsize bufLen,
- jsize * nVMs);
-static jint (*create_java_vm) (JavaVM ** p_vm, JNIEnv ** p_env, void *vm_args);
-static JavaVM *java_vm;
-static gboolean started_java_vm = FALSE;
-
static gboolean accepted_color_formats (GstAmcCodecType * type,
gboolean is_encoder);
@@ -315,233 +105,6 @@ static struct
jmethodID set_byte_buffer;
} media_format;
-static pthread_key_t current_jni_env;
-
-static JNIEnv *
-gst_amc_attach_current_thread (void)
-{
- JNIEnv *env;
- JavaVMAttachArgs args;
-
- GST_DEBUG ("Attaching thread %p", g_thread_self ());
- args.version = JNI_VERSION_1_6;
- args.name = NULL;
- args.group = NULL;
-
- if ((*java_vm)->AttachCurrentThread (java_vm, &env, &args) < 0) {
- GST_ERROR ("Failed to attach current thread");
- return NULL;
- }
-
- return env;
-}
-
-static void
-gst_amc_detach_current_thread (void *env)
-{
- GST_DEBUG ("Detaching thread %p", g_thread_self ());
- (*java_vm)->DetachCurrentThread (java_vm);
-}
-
-static JNIEnv *
-gst_amc_get_jni_env (void)
-{
- JNIEnv *env;
-
- if ((env = pthread_getspecific (current_jni_env)) == NULL) {
- env = gst_amc_attach_current_thread ();
- pthread_setspecific (current_jni_env, env);
- }
-
- return env;
-}
-
-static gboolean
-check_nativehelper (void)
-{
- GModule *module;
- void **jni_invocation = NULL;
- gboolean ret = FALSE;
-
- module = g_module_open (NULL, G_MODULE_BIND_LOCAL);
- if (!module)
- return ret;
-
- /* Check if libnativehelper is loaded in the process and if
- * it has these awful wrappers for JNI_CreateJavaVM and
- * JNI_GetCreatedJavaVMs that crash the app if you don't
- * create a JniInvocation instance first. If it isn't we
- * just fail here and don't initialize anything.
- * See this code for reference:
- * https://android.googlesource.com/platform/libnativehelper/+/master/JniInvocation.cpp
- */
- if (!g_module_symbol (module, "_ZN13JniInvocation15jni_invocation_E",
- (gpointer *) & jni_invocation)) {
- ret = TRUE;
- } else {
- ret = (jni_invocation != NULL && *jni_invocation != NULL);
- }
-
- g_module_close (module);
-
- return ret;
-}
-
-static gboolean
-load_java_module (const gchar * name)
-{
- java_module = g_module_open (name, G_MODULE_BIND_LOCAL);
- if (!java_module)
- goto load_failed;
-
- if (!g_module_symbol (java_module, "JNI_CreateJavaVM",
- (gpointer *) & create_java_vm))
- goto symbol_error;
-
- if (!g_module_symbol (java_module, "JNI_GetCreatedJavaVMs",
- (gpointer *) & get_created_java_vms))
- goto symbol_error;
-
- return TRUE;
-
-load_failed:
- {
- GST_ERROR ("Failed to load Java module '%s': %s", GST_STR_NULL (name),
- g_module_error ());
- return FALSE;
- }
-symbol_error:
- {
- GST_ERROR ("Failed to locate required JNI symbols in '%s': %s",
- GST_STR_NULL (name), g_module_error ());
- g_module_close (java_module);
- java_module = NULL;
- return FALSE;
- }
-}
-
-static gboolean
-initialize_java_vm (void)
-{
- jsize n_vms;
-
- /* Returns TRUE if we can safely
- * a) get the current VMs and
- * b) start a VM if none is started yet
- *
- * FIXME: On Android >= 4.4 we won't be able to safely start a
- * VM on our own without using private C++ API!
- */
- if (!check_nativehelper ()) {
- GST_ERROR ("Can't safely check for VMs or start a VM");
- return FALSE;
- }
-
- if (!load_java_module (NULL)) {
- if (!load_java_module ("libdvm"))
- return FALSE;
- }
-
- n_vms = 0;
- if (get_created_java_vms (&java_vm, 1, &n_vms) < 0)
- goto get_created_failed;
-
- if (n_vms > 0) {
- GST_DEBUG ("Successfully got existing Java VM %p", java_vm);
- } else {
- JNIEnv *env;
- JavaVMInitArgs vm_args;
- JavaVMOption options[4];
-
- GST_DEBUG ("Found no existing Java VM, trying to start one");
-
- options[0].optionString = "-verbose:jni";
- options[1].optionString = "-verbose:gc";
- options[2].optionString = "-Xcheck:jni";
- options[3].optionString = "-Xdebug";
-
- vm_args.version = JNI_VERSION_1_4;
- vm_args.options = options;
- vm_args.nOptions = 4;
- vm_args.ignoreUnrecognized = JNI_TRUE;
- if (create_java_vm (&java_vm, &env, &vm_args) < 0)
- goto create_failed;
- GST_DEBUG ("Successfully created Java VM %p", java_vm);
-
- started_java_vm = TRUE;
- }
-
- return java_vm != NULL;
-
-get_created_failed:
- {
- GST_ERROR ("Failed to get already created VMs");
- g_module_close (java_module);
- java_module = NULL;
- return FALSE;
- }
-create_failed:
- {
- GST_ERROR ("Failed to create a Java VM");
- g_module_close (java_module);
- java_module = NULL;
- return FALSE;
- }
-}
-
-static void
-gst_amc_set_error_string (JNIEnv * env, GQuark domain, gint code, GError ** err,
- const gchar * message)
-{
- jthrowable exception;
-
- if (!err) {
- if ((*env)->ExceptionCheck (env))
- (*env)->ExceptionClear (env);
- return;
- }
-
- if ((*env)->ExceptionCheck (env)) {
- if ((exception = (*env)->ExceptionOccurred (env))) {
- gchar *exception_description, *exception_stacktrace;
-
- /* Clear exception so that we can call Java methods again */
- (*env)->ExceptionClear (env);
-
- exception_description = getExceptionSummary (env, exception);
- exception_stacktrace = getStackTrace (env, exception);
- g_set_error (err, domain, code, "%s: %s\n%s", message,
- exception_description, exception_stacktrace);
- g_free (exception_description);
- g_free (exception_stacktrace);
-
- (*env)->DeleteLocalRef (env, exception);
- } else {
- (*env)->ExceptionClear (env);
- g_set_error (err, domain, code, "%s", message);
- }
- } else {
- g_set_error (err, domain, code, "%s", message);
- }
-}
-
-G_GNUC_PRINTF (5, 6)
- static void
- gst_amc_set_error (JNIEnv * env, GQuark domain, gint code,
- GError ** err, const gchar * format, ...)
-{
- gchar *message;
- va_list var_args;
-
- va_start (var_args, format);
- message = g_strdup_vprintf (format, var_args);
- va_end (var_args);
-
- gst_amc_set_error_string (env, domain, code, err, message);
-
- g_free (message);
-}
-
GstAmcCodec *
gst_amc_codec_new (const gchar * name, GError ** err)
{
@@ -552,11 +115,11 @@ gst_amc_codec_new (const gchar * name, GError ** err)
g_return_val_if_fail (name != NULL, NULL);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
name_str = (*env)->NewStringUTF (env, name);
if (name_str == NULL) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_INIT, err,
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_INIT, err,
"Failed to create Java String");
goto error;
}
@@ -567,14 +130,14 @@ gst_amc_codec_new (const gchar * name, GError ** err)
(*env)->CallStaticObjectMethod (env, media_codec.klass,
media_codec.create_by_codec_name, name_str);
if ((*env)->ExceptionCheck (env) || !object) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_INIT, err,
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_INIT, err,
"Failed to create codec '%s'", name);
goto error;
}
codec->object = (*env)->NewGlobalRef (env, object);
if (!codec->object) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_INIT, err,
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_INIT, err,
"Failed to create global codec reference");
goto error;
}
@@ -602,7 +165,7 @@ gst_amc_codec_free (GstAmcCodec * codec)
g_return_if_fail (codec != NULL);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
(*env)->DeleteGlobalRef (env, codec->object);
g_slice_free (GstAmcCodec, codec);
}
@@ -617,13 +180,13 @@ gst_amc_codec_configure (GstAmcCodec * codec, GstAmcFormat * format, gint flags,
g_return_val_if_fail (codec != NULL, FALSE);
g_return_val_if_fail (format != NULL, FALSE);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
(*env)->CallVoidMethod (env, codec->object, media_codec.configure,
format->object, NULL, NULL, flags);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_SETTINGS, err,
- "Failed to configure codec");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_SETTINGS,
+ err, "Failed to configure codec");
ret = FALSE;
goto done;
}
@@ -642,14 +205,14 @@ gst_amc_codec_get_output_format (GstAmcCodec * codec, GError ** err)
g_return_val_if_fail (codec != NULL, NULL);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
object =
(*env)->CallObjectMethod (env, codec->object,
media_codec.get_output_format);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_SETTINGS, err,
- "Failed to get output format");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_SETTINGS,
+ err, "Failed to get output format");
goto done;
}
@@ -657,8 +220,8 @@ gst_amc_codec_get_output_format (GstAmcCodec * codec, GError ** err)
ret->object = (*env)->NewGlobalRef (env, object);
if (!ret->object) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_SETTINGS, err,
- "Failed to create global format reference");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_SETTINGS,
+ err, "Failed to create global format reference");
g_slice_free (GstAmcFormat, ret);
ret = NULL;
}
@@ -678,12 +241,12 @@ gst_amc_codec_start (GstAmcCodec * codec, GError ** err)
g_return_val_if_fail (codec != NULL, FALSE);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
(*env)->CallVoidMethod (env, codec->object, media_codec.start);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to start codec");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to start codec");
ret = FALSE;
goto done;
}
@@ -701,12 +264,12 @@ gst_amc_codec_stop (GstAmcCodec * codec, GError ** err)
g_return_val_if_fail (codec != NULL, FALSE);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
(*env)->CallVoidMethod (env, codec->object, media_codec.stop);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to stop codec");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to stop codec");
ret = FALSE;
goto done;
}
@@ -724,12 +287,12 @@ gst_amc_codec_flush (GstAmcCodec * codec, GError ** err)
g_return_val_if_fail (codec != NULL, FALSE);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
(*env)->CallVoidMethod (env, codec->object, media_codec.flush);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to flush codec");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to flush codec");
ret = FALSE;
goto done;
}
@@ -747,12 +310,12 @@ gst_amc_codec_release (GstAmcCodec * codec, GError ** err)
g_return_val_if_fail (codec != NULL, FALSE);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
(*env)->CallVoidMethod (env, codec->object, media_codec.release);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to release codec");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to release codec");
ret = FALSE;
goto done;
}
@@ -770,7 +333,7 @@ gst_amc_codec_free_buffers (GstAmcBuffer * buffers, gsize n_buffers)
g_return_if_fail (buffers != NULL);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
for (i = 0; i < n_buffers; i++) {
if (buffers[i].object)
@@ -793,21 +356,21 @@ gst_amc_codec_get_output_buffers (GstAmcCodec * codec, gsize * n_buffers,
g_return_val_if_fail (n_buffers != NULL, NULL);
*n_buffers = 0;
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
output_buffers =
(*env)->CallObjectMethod (env, codec->object,
media_codec.get_output_buffers);
if ((*env)->ExceptionCheck (env) || !output_buffers) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to get output buffers");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to get output buffers");
goto done;
}
n_output_buffers = (*env)->GetArrayLength (env, output_buffers);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to get output buffers array length");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to get output buffers array length");
goto done;
}
@@ -819,23 +382,23 @@ gst_amc_codec_get_output_buffers (GstAmcCodec * codec, gsize * n_buffers,
buffer = (*env)->GetObjectArrayElement (env, output_buffers, i);
if ((*env)->ExceptionCheck (env) || !buffer) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to get output buffer %d", i);
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to get output buffer %d", i);
goto error;
}
ret[i].object = (*env)->NewGlobalRef (env, buffer);
(*env)->DeleteLocalRef (env, buffer);
if (!ret[i].object) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to create global output buffer reference %d", i);
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to create global output buffer reference %d", i);
goto error;
}
ret[i].data = (*env)->GetDirectBufferAddress (env, ret[i].object);
if (!ret[i].data) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to get output buffer address %d", i);
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to get output buffer address %d", i);
goto error;
}
ret[i].size = (*env)->GetDirectBufferCapacity (env, ret[i].object);
@@ -869,21 +432,21 @@ gst_amc_codec_get_input_buffers (GstAmcCodec * codec, gsize * n_buffers,
g_return_val_if_fail (n_buffers != NULL, NULL);
*n_buffers = 0;
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
input_buffers =
(*env)->CallObjectMethod (env, codec->object,
media_codec.get_input_buffers);
if ((*env)->ExceptionCheck (env) || !input_buffers) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to get input buffers");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to get input buffers");
goto done;
}
n_input_buffers = (*env)->GetArrayLength (env, input_buffers);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to get input buffers array length");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to get input buffers array length");
goto done;
}
@@ -895,23 +458,23 @@ gst_amc_codec_get_input_buffers (GstAmcCodec * codec, gsize * n_buffers,
buffer = (*env)->GetObjectArrayElement (env, input_buffers, i);
if ((*env)->ExceptionCheck (env) || !buffer) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to get input buffer %d", i);
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to get input buffer %d", i);
goto error;
}
ret[i].object = (*env)->NewGlobalRef (env, buffer);
(*env)->DeleteLocalRef (env, buffer);
if (!ret[i].object) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to create global input buffer reference %d", i);
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to create global input buffer reference %d", i);
goto error;
}
ret[i].data = (*env)->GetDirectBufferAddress (env, ret[i].object);
if (!ret[i].data) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to get input buffer address %d", i);
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to get input buffer address %d", i);
goto error;
}
ret[i].size = (*env)->GetDirectBufferCapacity (env, ret[i].object);
@@ -940,14 +503,14 @@ gst_amc_codec_dequeue_input_buffer (GstAmcCodec * codec, gint64 timeoutUs,
g_return_val_if_fail (codec != NULL, G_MININT);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
ret =
(*env)->CallIntMethod (env, codec->object,
media_codec.dequeue_input_buffer, timeoutUs);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to dequeue input buffer");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to dequeue input buffer");
ret = G_MININT;
goto done;
}
@@ -966,16 +529,16 @@ gst_amc_codec_fill_buffer_info (JNIEnv * env, jobject buffer_info,
info->flags =
(*env)->GetIntField (env, buffer_info, media_codec_buffer_info.flags);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to get buffer info flags");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to get buffer info flags");
return FALSE;
}
info->offset =
(*env)->GetIntField (env, buffer_info, media_codec_buffer_info.offset);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to get buffer info offset");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to get buffer info offset");
return FALSE;
}
@@ -983,8 +546,8 @@ gst_amc_codec_fill_buffer_info (JNIEnv * env, jobject buffer_info,
(*env)->GetLongField (env, buffer_info,
media_codec_buffer_info.presentation_time_us);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to get buffer info pts");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to get buffer info pts");
return FALSE;
}
@@ -992,8 +555,8 @@ gst_amc_codec_fill_buffer_info (JNIEnv * env, jobject buffer_info,
(*env)->GetIntField (env, buffer_info, media_codec_buffer_info.size);
if ((*env)->ExceptionCheck (env)) {
(*env)->ExceptionClear (env);
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to get buffer info size");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to get buffer info size");
return FALSE;
}
@@ -1010,14 +573,14 @@ gst_amc_codec_dequeue_output_buffer (GstAmcCodec * codec,
g_return_val_if_fail (codec != NULL, G_MININT);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
info_o =
(*env)->NewObject (env, media_codec_buffer_info.klass,
media_codec_buffer_info.constructor);
if (!info_o) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to create buffer info instance");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to create buffer info instance");
goto done;
}
@@ -1025,8 +588,8 @@ gst_amc_codec_dequeue_output_buffer (GstAmcCodec * codec,
(*env)->CallIntMethod (env, codec->object,
media_codec.dequeue_output_buffer, info_o, timeoutUs);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to dequeue output buffer");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to dequeue output buffer");
ret = G_MININT;
goto done;
}
@@ -1054,13 +617,13 @@ gst_amc_codec_queue_input_buffer (GstAmcCodec * codec, gint index,
g_return_val_if_fail (codec != NULL, FALSE);
g_return_val_if_fail (info != NULL, FALSE);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
(*env)->CallVoidMethod (env, codec->object, media_codec.queue_input_buffer,
index, info->offset, info->size, info->presentation_time_us, info->flags);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to queue input buffer");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to queue input buffer");
ret = FALSE;
goto done;
}
@@ -1079,13 +642,13 @@ gst_amc_codec_release_output_buffer (GstAmcCodec * codec, gint index,
g_return_val_if_fail (codec != NULL, FALSE);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
(*env)->CallVoidMethod (env, codec->object, media_codec.release_output_buffer,
index, JNI_FALSE);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to release output buffer");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to release output buffer");
ret = FALSE;
goto done;
}
@@ -1106,11 +669,11 @@ gst_amc_format_new_audio (const gchar * mime, gint sample_rate, gint channels,
g_return_val_if_fail (mime != NULL, NULL);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
mime_str = (*env)->NewStringUTF (env, mime);
if (mime_str == NULL) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_INIT, err,
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_INIT, err,
"Failed to create Java string");
goto error;
}
@@ -1121,14 +684,14 @@ gst_amc_format_new_audio (const gchar * mime, gint sample_rate, gint channels,
(*env)->CallStaticObjectMethod (env, media_format.klass,
media_format.create_audio_format, mime_str, sample_rate, channels);
if ((*env)->ExceptionCheck (env) || !object) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_INIT, err,
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_INIT, err,
"Failed to create format instance '%s'", mime);
goto error;
}
format->object = (*env)->NewGlobalRef (env, object);
if (!format->object) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_INIT, err,
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_INIT, err,
"Failed to create global format reference");
goto error;
}
@@ -1160,11 +723,11 @@ gst_amc_format_new_video (const gchar * mime, gint width, gint height,
g_return_val_if_fail (mime != NULL, NULL);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
mime_str = (*env)->NewStringUTF (env, mime);
if (mime_str == NULL) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_INIT, err,
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_INIT, err,
"Failed to create Java string");
goto error;
}
@@ -1175,14 +738,14 @@ gst_amc_format_new_video (const gchar * mime, gint width, gint height,
(*env)->CallStaticObjectMethod (env, media_format.klass,
media_format.create_video_format, mime_str, width, height);
if ((*env)->ExceptionCheck (env) || !object) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_INIT, err,
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_INIT, err,
"Failed to create format instance '%s'", mime);
goto error;
}
format->object = (*env)->NewGlobalRef (env, object);
if (!format->object) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_INIT, err,
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_INIT, err,
"Failed to create global format reference");
goto error;
}
@@ -1210,7 +773,7 @@ gst_amc_format_free (GstAmcFormat * format)
g_return_if_fail (format != NULL);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
(*env)->DeleteGlobalRef (env, format->object);
g_slice_free (GstAmcFormat, format);
}
@@ -1225,20 +788,20 @@ gst_amc_format_to_string (GstAmcFormat * format, GError ** err)
g_return_val_if_fail (format != NULL, FALSE);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
v_str =
(*env)->CallObjectMethod (env, format->object, media_format.to_string);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to convert format to string");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to convert format to string");
goto done;
}
v = (*env)->GetStringUTFChars (env, v_str, NULL);
if (!v) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to get UTF8 string");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to get UTF8 string");
goto done;
}
@@ -1264,12 +827,12 @@ gst_amc_format_contains_key (GstAmcFormat * format, const gchar * key,
g_return_val_if_fail (format != NULL, FALSE);
g_return_val_if_fail (key != NULL, FALSE);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
key_str = (*env)->NewStringUTF (env, key);
if (!key_str) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to create Java string");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to create Java string");
goto done;
}
@@ -1277,8 +840,8 @@ gst_amc_format_contains_key (GstAmcFormat * format, const gchar * key,
(*env)->CallBooleanMethod (env, format->object, media_format.contains_key,
key_str);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to check if format contains key '%s'", key);
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to check if format contains key '%s'", key);
goto done;
}
@@ -1302,12 +865,12 @@ gst_amc_format_get_float (GstAmcFormat * format, const gchar * key,
g_return_val_if_fail (value != NULL, FALSE);
*value = 0;
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
key_str = (*env)->NewStringUTF (env, key);
if (!key_str) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to create Java string");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to create Java string");
goto done;
}
@@ -1315,8 +878,8 @@ gst_amc_format_get_float (GstAmcFormat * format, const gchar * key,
(*env)->CallFloatMethod (env, format->object, media_format.get_float,
key_str);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed get float key '%s'", key);
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed get float key '%s'", key);
goto done;
}
ret = TRUE;
@@ -1338,20 +901,20 @@ gst_amc_format_set_float (GstAmcFormat * format, const gchar * key,
g_return_if_fail (format != NULL);
g_return_if_fail (key != NULL);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
key_str = (*env)->NewStringUTF (env, key);
if (!key_str) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to create Java string");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to create Java string");
goto done;
}
(*env)->CallVoidMethod (env, format->object, media_format.set_float, key_str,
value);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed set float key '%s'", key);
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed set float key '%s'", key);
goto done;
}
@@ -1373,12 +936,12 @@ gst_amc_format_get_int (GstAmcFormat * format, const gchar * key, gint * value,
g_return_val_if_fail (value != NULL, FALSE);
*value = 0;
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
key_str = (*env)->NewStringUTF (env, key);
if (!key_str) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to create Java string");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to create Java string");
goto done;
}
@@ -1386,8 +949,8 @@ gst_amc_format_get_int (GstAmcFormat * format, const gchar * key, gint * value,
(*env)->CallIntMethod (env, format->object, media_format.get_integer,
key_str);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed get integer key '%s'", key);
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed get integer key '%s'", key);
goto done;
}
ret = TRUE;
@@ -1410,20 +973,20 @@ gst_amc_format_set_int (GstAmcFormat * format, const gchar * key, gint value,
g_return_if_fail (format != NULL);
g_return_if_fail (key != NULL);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
key_str = (*env)->NewStringUTF (env, key);
if (!key_str) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to create Java string");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to create Java string");
goto done;
}
(*env)->CallVoidMethod (env, format->object, media_format.set_integer,
key_str, value);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed set integer key '%s'", key);
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed set integer key '%s'", key);
goto done;
}
@@ -1447,12 +1010,12 @@ gst_amc_format_get_string (GstAmcFormat * format, const gchar * key,
g_return_val_if_fail (value != NULL, FALSE);
*value = 0;
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
key_str = (*env)->NewStringUTF (env, key);
if (!key_str) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to create Java string");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to create Java string");
goto done;
}
@@ -1460,15 +1023,15 @@ gst_amc_format_get_string (GstAmcFormat * format, const gchar * key,
(*env)->CallObjectMethod (env, format->object, media_format.get_string,
key_str);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed get string key '%s'", key);
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed get string key '%s'", key);
goto done;
}
v = (*env)->GetStringUTFChars (env, v_str, NULL);
if (!v) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed get string UTF8 characters");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed get string UTF8 characters");
goto done;
}
@@ -1499,27 +1062,27 @@ gst_amc_format_set_string (GstAmcFormat * format, const gchar * key,
g_return_if_fail (key != NULL);
g_return_if_fail (value != NULL);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
key_str = (*env)->NewStringUTF (env, key);
if (!key_str) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to create Java string");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to create Java string");
goto done;
}
v_str = (*env)->NewStringUTF (env, value);
if (!v_str) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to create Java string");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to create Java string");
goto done;
}
(*env)->CallVoidMethod (env, format->object, media_format.set_string, key_str,
v_str);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed set string key '%s'", key);
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed set string key '%s'", key);
goto done;
}
@@ -1546,27 +1109,27 @@ gst_amc_format_get_buffer (GstAmcFormat * format, const gchar * key,
*data = NULL;
*size = 0;
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
key_str = (*env)->NewStringUTF (env, key);
if (!key_str) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to create Java string");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to create Java string");
goto done;
}
v = (*env)->CallObjectMethod (env, format->object,
media_format.get_byte_buffer, key_str);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed get buffer key '%s'", key);
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed get buffer key '%s'", key);
goto done;
}
*data = (*env)->GetDirectBufferAddress (env, v);
if (!data) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed get buffer address");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed get buffer address");
goto done;
}
*size = (*env)->GetDirectBufferCapacity (env, v);
@@ -1595,28 +1158,28 @@ gst_amc_format_set_buffer (GstAmcFormat * format, const gchar * key,
g_return_if_fail (key != NULL);
g_return_if_fail (data != NULL);
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
key_str = (*env)->NewStringUTF (env, key);
if (!key_str) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed to create Java string");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed to create Java string");
goto done;
}
/* FIXME: The memory must remain valid until the codec is stopped */
v = (*env)->NewDirectByteBuffer (env, data, size);
if (!v) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed create Java byte buffer");
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed create Java byte buffer");
goto done;
}
(*env)->CallVoidMethod (env, format->object, media_format.set_byte_buffer,
key_str, v);
if ((*env)->ExceptionCheck (env)) {
- gst_amc_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, err,
- "Failed set buffer key '%s'", key);
+ gst_amc_jni_set_error (env, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED,
+ err, "Failed set buffer key '%s'", key);
goto done;
}
@@ -1636,7 +1199,7 @@ get_java_classes (void)
GST_DEBUG ("Retrieving Java classes");
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
tmp = (*env)->FindClass (env, "java/lang/String");
if (!tmp) {
@@ -1968,7 +1531,7 @@ scan_codecs (GstPlugin * plugin)
return TRUE;
}
- env = gst_amc_get_jni_env ();
+ env = gst_amc_jni_get_env ();
codec_list_class = (*env)->FindClass (env, "android/media/MediaCodecList");
if (!codec_list_class) {
@@ -2108,7 +1671,8 @@ scan_codecs (GstPlugin * plugin)
* VM via the non-public AndroidRuntime class. Can we somehow
* initialize all this?
*/
- if (started_java_vm && !g_str_has_prefix (name_str, "OMX.google.")) {
+ if (gst_amc_jni_is_vm_started () &&
+ !g_str_has_prefix (name_str, "OMX.google.")) {
GST_INFO ("Skipping non-Google codec '%s' in standalone mode", name_str);
valid_codec = FALSE;
goto next_codec;
@@ -3709,9 +3273,7 @@ plugin_init (GstPlugin * plugin)
GST_DEBUG_CATEGORY_INIT (gst_amc_debug, "amc", 0, "android-media-codec");
- pthread_key_create (&current_jni_env, gst_amc_detach_current_thread);
-
- if (!initialize_java_vm ())
+ if (!gst_amc_jni_initialize ())
return FALSE;
gst_plugin_add_dependency_simple (plugin, NULL, "/etc", "media_codecs.xml",
diff --git a/sys/androidmedia/gstjniutils.c b/sys/androidmedia/gstjniutils.c
new file mode 100644
index 000000000..9d8a4777f
--- /dev/null
+++ b/sys/androidmedia/gstjniutils.c
@@ -0,0 +1,484 @@
+/*
+ * Copyright (C) 2012, Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ * Copyright (C) 2013, Fluendo S.A.
+ * Author: Andoni Morales <amorales@fluendo.com>
+ * Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.com>
+ * Copyright (C) 2014, Collabora Ltd.
+ * Author: Matthieu Bouron <matthieu.bouron@collabora.com>
+ *
+ * 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/gst.h>
+#include <pthread.h>
+#include <gmodule.h>
+
+#include "gstjniutils.h"
+
+static GModule *java_module;
+static jint (*get_created_java_vms) (JavaVM ** vmBuf, jsize bufLen,
+ jsize * nVMs);
+static jint (*create_java_vm) (JavaVM ** p_vm, JNIEnv ** p_env, void *vm_args);
+static JavaVM *java_vm;
+static gboolean initialized = FALSE;
+static gboolean started_java_vm = FALSE;
+static pthread_key_t current_jni_env;
+
+/* getExceptionSummary() and getStackTrace() taken from Android's
+ * platform/libnativehelper/JNIHelp.cpp
+ * Modified to work with normal C strings and without C++.
+ *
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Returns a human-readable summary of an exception object. The buffer will
+ * be populated with the "binary" class name and, if present, the
+ * exception message.
+ */
+static gchar *
+getExceptionSummary (JNIEnv * env, jthrowable exception)
+{
+ GString *gs = g_string_new ("");
+ jclass exceptionClass = NULL, classClass = NULL;
+ jmethodID classGetNameMethod, getMessage;
+ jstring classNameStr = NULL, messageStr = NULL;
+ const char *classNameChars, *messageChars;
+
+ /* get the name of the exception's class */
+ exceptionClass = (*env)->GetObjectClass (env, exception);
+ classClass = (*env)->GetObjectClass (env, exceptionClass);
+ classGetNameMethod =
+ (*env)->GetMethodID (env, classClass, "getName", "()Ljava/lang/String;");
+
+ classNameStr =
+ (jstring) (*env)->CallObjectMethod (env, exceptionClass,
+ classGetNameMethod);
+
+ if (classNameStr == NULL) {
+ if ((*env)->ExceptionCheck (env))
+ (*env)->ExceptionClear (env);
+ g_string_append (gs, "<error getting class name>");
+ goto done;
+ }
+
+ classNameChars = (*env)->GetStringUTFChars (env, classNameStr, NULL);
+ if (classNameChars == NULL) {
+ if ((*env)->ExceptionCheck (env))
+ (*env)->ExceptionClear (env);
+ g_string_append (gs, "<error getting class name UTF-8>");
+ goto done;
+ }
+
+ g_string_append (gs, classNameChars);
+
+ (*env)->ReleaseStringUTFChars (env, classNameStr, classNameChars);
+
+ /* if the exception has a detail message, get that */
+ getMessage =
+ (*env)->GetMethodID (env, exceptionClass, "getMessage",
+ "()Ljava/lang/String;");
+ messageStr = (jstring) (*env)->CallObjectMethod (env, exception, getMessage);
+ if (messageStr == NULL) {
+ if ((*env)->ExceptionCheck (env))
+ (*env)->ExceptionClear (env);
+ goto done;
+ }
+ g_string_append (gs, ": ");
+
+ messageChars = (*env)->GetStringUTFChars (env, messageStr, NULL);
+ if (messageChars != NULL) {
+ g_string_append (gs, messageChars);
+ (*env)->ReleaseStringUTFChars (env, messageStr, messageChars);
+ } else {
+ if ((*env)->ExceptionCheck (env))
+ (*env)->ExceptionClear (env);
+ g_string_append (gs, "<error getting message>");
+ }
+
+done:
+ if (exceptionClass)
+ (*env)->DeleteLocalRef (env, exceptionClass);
+ if (classClass)
+ (*env)->DeleteLocalRef (env, classClass);
+ if (classNameStr)
+ (*env)->DeleteLocalRef (env, classNameStr);
+ if (messageStr)
+ (*env)->DeleteLocalRef (env, messageStr);
+
+ return g_string_free (gs, FALSE);
+}
+
+/*
+ * Returns an exception (with stack trace) as a string.
+ */
+static gchar *
+getStackTrace (JNIEnv * env, jthrowable exception)
+{
+ GString *gs = g_string_new ("");
+ jclass stringWriterClass = NULL, printWriterClass = NULL;
+ jclass exceptionClass = NULL;
+ jmethodID stringWriterCtor, stringWriterToStringMethod;
+ jmethodID printWriterCtor, printStackTraceMethod;
+ jobject stringWriter = NULL, printWriter = NULL;
+ jstring messageStr = NULL;
+ const char *utfChars;
+
+ stringWriterClass = (*env)->FindClass (env, "java/io/StringWriter");
+
+ if (stringWriterClass == NULL) {
+ g_string_append (gs, "<error getting java.io.StringWriter class>");
+ goto done;
+ }
+
+ stringWriterCtor =
+ (*env)->GetMethodID (env, stringWriterClass, "<init>", "()V");
+ stringWriterToStringMethod =
+ (*env)->GetMethodID (env, stringWriterClass, "toString",
+ "()Ljava/lang/String;");
+
+ printWriterClass = (*env)->FindClass (env, "java/io/PrintWriter");
+ if (printWriterClass == NULL) {
+ g_string_append (gs, "<error getting java.io.PrintWriter class>");
+ goto done;
+ }
+
+ printWriterCtor =
+ (*env)->GetMethodID (env, printWriterClass, "<init>",
+ "(Ljava/io/Writer;)V");
+ stringWriter = (*env)->NewObject (env, stringWriterClass, stringWriterCtor);
+ if (stringWriter == NULL) {
+ if ((*env)->ExceptionCheck (env))
+ (*env)->ExceptionClear (env);
+ g_string_append (gs, "<error creating new StringWriter instance>");
+ goto done;
+ }
+
+ printWriter =
+ (*env)->NewObject (env, printWriterClass, printWriterCtor, stringWriter);
+ if (printWriter == NULL) {
+ if ((*env)->ExceptionCheck (env))
+ (*env)->ExceptionClear (env);
+ g_string_append (gs, "<error creating new PrintWriter instance>");
+ goto done;
+ }
+
+ exceptionClass = (*env)->GetObjectClass (env, exception);
+ printStackTraceMethod =
+ (*env)->GetMethodID (env, exceptionClass, "printStackTrace",
+ "(Ljava/io/PrintWriter;)V");
+ (*env)->CallVoidMethod (env, exception, printStackTraceMethod, printWriter);
+ if ((*env)->ExceptionCheck (env)) {
+ (*env)->ExceptionClear (env);
+ g_string_append (gs, "<exception while printing stack trace>");
+ goto done;
+ }
+
+ messageStr = (jstring) (*env)->CallObjectMethod (env, stringWriter,
+ stringWriterToStringMethod);
+ if (messageStr == NULL) {
+ if ((*env)->ExceptionCheck (env))
+ (*env)->ExceptionClear (env);
+ g_string_append (gs, "<failed to call StringWriter.toString()>");
+ goto done;
+ }
+
+ utfChars = (*env)->GetStringUTFChars (env, messageStr, NULL);
+ if (utfChars == NULL) {
+ if ((*env)->ExceptionCheck (env))
+ (*env)->ExceptionClear (env);
+ g_string_append (gs, "<failed to get UTF chars for message>");
+ goto done;
+ }
+
+ g_string_append (gs, utfChars);
+
+ (*env)->ReleaseStringUTFChars (env, messageStr, utfChars);
+
+done:
+ if (stringWriterClass)
+ (*env)->DeleteLocalRef (env, stringWriterClass);
+ if (printWriterClass)
+ (*env)->DeleteLocalRef (env, printWriterClass);
+ if (exceptionClass)
+ (*env)->DeleteLocalRef (env, exceptionClass);
+ if (stringWriter)
+ (*env)->DeleteLocalRef (env, stringWriter);
+ if (printWriter)
+ (*env)->DeleteLocalRef (env, printWriter);
+ if (messageStr)
+ (*env)->DeleteLocalRef (env, messageStr);
+
+ return g_string_free (gs, FALSE);
+}
+
+static JNIEnv *
+gst_amc_jni_attach_current_thread (void)
+{
+ JNIEnv *env;
+ JavaVMAttachArgs args;
+
+ GST_DEBUG ("Attaching thread %p", g_thread_self ());
+ args.version = JNI_VERSION_1_6;
+ args.name = NULL;
+ args.group = NULL;
+
+ if ((*java_vm)->AttachCurrentThread (java_vm, &env, &args) < 0) {
+ GST_ERROR ("Failed to attach current thread");
+ return NULL;
+ }
+
+ return env;
+}
+
+static void
+gst_amc_jni_detach_current_thread (void *env)
+{
+ GST_DEBUG ("Detaching thread %p", g_thread_self ());
+ (*java_vm)->DetachCurrentThread (java_vm);
+}
+
+static gboolean
+check_nativehelper (void)
+{
+ GModule *module;
+ void **jni_invocation = NULL;
+ gboolean ret = FALSE;
+
+ module = g_module_open (NULL, G_MODULE_BIND_LOCAL);
+ if (!module)
+ return ret;
+
+ /* Check if libnativehelper is loaded in the process and if
+ * it has these awful wrappers for JNI_CreateJavaVM and
+ * JNI_GetCreatedJavaVMs that crash the app if you don't
+ * create a JniInvocation instance first. If it isn't we
+ * just fail here and don't initialize anything.
+ * See this code for reference:
+ * https://android.googlesource.com/platform/libnativehelper/+/master/JniInvocation.cpp
+ */
+ if (!g_module_symbol (module, "_ZN13JniInvocation15jni_invocation_E",
+ (gpointer *) & jni_invocation)) {
+ ret = TRUE;
+ } else {
+ ret = (jni_invocation != NULL && *jni_invocation != NULL);
+ }
+
+ g_module_close (module);
+
+ return ret;
+}
+
+static gboolean
+load_java_module (const gchar * name)
+{
+ java_module = g_module_open (name, G_MODULE_BIND_LOCAL);
+ if (!java_module)
+ goto load_failed;
+
+ if (!g_module_symbol (java_module, "JNI_CreateJavaVM",
+ (gpointer *) & create_java_vm))
+ goto symbol_error;
+
+ if (!g_module_symbol (java_module, "JNI_GetCreatedJavaVMs",
+ (gpointer *) & get_created_java_vms))
+ goto symbol_error;
+
+ return TRUE;
+
+load_failed:
+ {
+ GST_ERROR ("Failed to load Java module '%s': %s", GST_STR_NULL (name),
+ g_module_error ());
+ return FALSE;
+ }
+symbol_error:
+ {
+ GST_ERROR ("Failed to locate required JNI symbols in '%s': %s",
+ GST_STR_NULL (name), g_module_error ());
+ g_module_close (java_module);
+ java_module = NULL;
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_amc_jni_initialize_java_vm (void)
+{
+ jsize n_vms;
+
+ /* Returns TRUE if we can safely
+ * a) get the current VMs and
+ * b) start a VM if none is started yet
+ *
+ * FIXME: On Android >= 4.4 we won't be able to safely start a
+ * VM on our own without using private C++ API!
+ */
+ if (!check_nativehelper ()) {
+ GST_ERROR ("Can't safely check for VMs or start a VM");
+ return FALSE;
+ }
+
+ if (!load_java_module (NULL)) {
+ if (!load_java_module ("libdvm"))
+ return FALSE;
+ }
+
+ n_vms = 0;
+ if (get_created_java_vms (&java_vm, 1, &n_vms) < 0)
+ goto get_created_failed;
+
+ if (n_vms > 0) {
+ GST_DEBUG ("Successfully got existing Java VM %p", java_vm);
+ } else {
+ JNIEnv *env;
+ JavaVMInitArgs vm_args;
+ JavaVMOption options[4];
+
+ GST_DEBUG ("Found no existing Java VM, trying to start one");
+
+ options[0].optionString = "-verbose:jni";
+ options[1].optionString = "-verbose:gc";
+ options[2].optionString = "-Xcheck:jni";
+ options[3].optionString = "-Xdebug";
+
+ vm_args.version = JNI_VERSION_1_4;
+ vm_args.options = options;
+ vm_args.nOptions = 4;
+ vm_args.ignoreUnrecognized = JNI_TRUE;
+ if (create_java_vm (&java_vm, &env, &vm_args) < 0)
+ goto create_failed;
+ GST_DEBUG ("Successfully created Java VM %p", java_vm);
+
+ started_java_vm = TRUE;
+ }
+
+ return java_vm != NULL;
+
+get_created_failed:
+ {
+ GST_ERROR ("Failed to get already created VMs");
+ g_module_close (java_module);
+ java_module = NULL;
+ return FALSE;
+ }
+create_failed:
+ {
+ GST_ERROR ("Failed to create a Java VM");
+ g_module_close (java_module);
+ java_module = NULL;
+ return FALSE;
+ }
+}
+
+static void
+gst_amc_jni_set_error_string (JNIEnv * env, GQuark domain, gint code,
+ GError ** err, const gchar * message)
+{
+ jthrowable exception;
+
+ if (!err) {
+ if ((*env)->ExceptionCheck (env))
+ (*env)->ExceptionClear (env);
+ return;
+ }
+
+ if ((*env)->ExceptionCheck (env)) {
+ if ((exception = (*env)->ExceptionOccurred (env))) {
+ gchar *exception_description, *exception_stacktrace;
+
+ /* Clear exception so that we can call Java methods again */
+ (*env)->ExceptionClear (env);
+
+ exception_description = getExceptionSummary (env, exception);
+ exception_stacktrace = getStackTrace (env, exception);
+ g_set_error (err, domain, code, "%s: %s\n%s", message,
+ exception_description, exception_stacktrace);
+ g_free (exception_description);
+ g_free (exception_stacktrace);
+
+ (*env)->DeleteLocalRef (env, exception);
+ } else {
+ (*env)->ExceptionClear (env);
+ g_set_error (err, domain, code, "%s", message);
+ }
+ } else {
+ g_set_error (err, domain, code, "%s", message);
+ }
+}
+
+G_GNUC_PRINTF (5, 6)
+ void gst_amc_jni_set_error (JNIEnv * env, GQuark domain, gint code,
+ GError ** err, const gchar * format, ...)
+{
+ gchar *message;
+ va_list var_args;
+
+ va_start (var_args, format);
+ message = g_strdup_vprintf (format, var_args);
+ va_end (var_args);
+
+ gst_amc_jni_set_error_string (env, domain, code, err, message);
+
+ g_free (message);
+}
+
+
+gboolean
+gst_amc_jni_initialize (void)
+{
+ if (!initialized) {
+ pthread_key_create (&current_jni_env, gst_amc_jni_detach_current_thread);
+ initialized = gst_amc_jni_initialize_java_vm ();
+ }
+ return initialized;
+}
+
+JNIEnv *
+gst_amc_jni_get_env (void)
+{
+ JNIEnv *env;
+
+ if ((env = pthread_getspecific (current_jni_env)) == NULL) {
+ env = gst_amc_jni_attach_current_thread ();
+ pthread_setspecific (current_jni_env, env);
+ }
+
+ return env;
+}
+
+gboolean
+gst_amc_jni_is_vm_started (void)
+{
+ return started_java_vm;
+}
diff --git a/sys/androidmedia/gstjniutils.h b/sys/androidmedia/gstjniutils.h
new file mode 100644
index 000000000..ad4e2f424
--- /dev/null
+++ b/sys/androidmedia/gstjniutils.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012, Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ * Copyright (C) 2013, Fluendo S.A.
+ * Author: Andoni Morales <amorales@fluendo.com>
+ * Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.com>
+ * Copyright (C) 2014, Collabora Ltd.
+ * Author: Matthieu Bouron <matthieu.bouron@collabora.com>
+ *
+ * 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_AMC_JNI_UTILS_H__
+#define __GST_AMC_JNI_UTILS_H__
+
+#include <jni.h>
+#include <glib.h>
+#include <gst/gst.h>
+
+G_GNUC_PRINTF (5, 6)
+void gst_amc_jni_set_error (JNIEnv * env,
+ GQuark domain,
+ gint code,
+ GError ** error,
+ const gchar * format, ...);
+
+gboolean gst_amc_jni_initialize (void);
+
+gboolean gst_amc_jni_is_vm_started (void);
+
+JNIEnv *gst_amc_jni_get_env (void);
+
+#endif