From: Matthieu Bouron <matthieu.bou...@stupeflix.com> --- libavutil/jni.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++ libavutil/jni.h | 28 +++++++++++++ libavutil/jni_internal.c | 30 ++++++++++++++ libavutil/jni_internal.h | 11 +++++ 4 files changed, 173 insertions(+)
diff --git a/libavutil/jni.c b/libavutil/jni.c index c6ce3a5..0c4c8ca 100644 --- a/libavutil/jni.c +++ b/libavutil/jni.c @@ -20,12 +20,18 @@ #include "config.h" #include "jni.h" +#include "jni_internal.h" #include "log.h" #include <stdlib.h> JavaVM *java_vm = NULL; +jobject application_context = NULL; + +jobject application_class_loader = NULL; +jmethodID find_class_id = NULL; + void av_jni_register_java_vm(JavaVM *vm) { java_vm = vm; @@ -35,3 +41,101 @@ JavaVM *av_jni_get_java_vm(void) { return java_vm; } + +#ifdef __ANDROID__ +int av_jni_register_application_context(JNIEnv *env, jobject context) +{ + int ret = 0; + + jclass application_context_class; + jmethodID get_class_loader_id; + + jclass application_class_loader_class; + + if (application_context) { + (*env)->DeleteGlobalRef(env, application_context); + application_context = NULL; + } + + if (application_class_loader) { + (*env)->DeleteGlobalRef(env, application_class_loader); + application_class_loader = NULL; + } + + application_context_class = (*env)->GetObjectClass(env, context); + if ((ret = avpriv_jni_exception_check(env, 1, NULL)) < 0) { + goto done; + } + + get_class_loader_id = (*env)->GetMethodID(env, application_context_class, "getClassLoader", "()Ljava/lang/ClassLoader;"); + if ((ret = avpriv_jni_exception_check(env, 1, NULL)) < 0) { + goto done; + } + + application_context = (*env)->NewGlobalRef(env, context); + application_class_loader = (*env)->CallObjectMethod(env, application_context, get_class_loader_id); + if ((ret = avpriv_jni_exception_check(env, 1, NULL)) < 0) { + goto done; + } + + application_class_loader = (*env)->NewGlobalRef(env, application_class_loader); + if ((ret = avpriv_jni_exception_check(env, 1, NULL)) < 0) { + goto done; + } + + application_class_loader_class = (*env)->GetObjectClass(env, application_class_loader); + if ((ret = avpriv_jni_exception_check(env, 1, NULL)) < 0) { + goto done; + } + + find_class_id = (*env)->GetMethodID(env, application_class_loader_class, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;"); + if ((ret = avpriv_jni_exception_check(env, 1, NULL)) < 0) { + goto done; + } + +done: + if (application_context_class) { + (*env)->DeleteLocalRef(env, application_context_class); + } + + if (application_class_loader_class) { + (*env)->DeleteLocalRef(env, application_class_loader_class); + } + + if (ret != 0) { + + if (application_context) { + (*env)->DeleteGlobalRef(env, application_context); + application_context = NULL; + } + + if (application_class_loader) { + (*env)->DeleteGlobalRef(env, application_class_loader); + application_context = NULL; + } + } + + return 0; +} + +jobject av_jni_get_application_context(void) +{ + return application_context; +} + +int av_jni_unregister_application_context(JNIEnv *env) +{ + if (application_context) { + (*env)->DeleteGlobalRef(env, application_context); + application_context = NULL; + } + + if (application_class_loader) { + (*env)->DeleteGlobalRef(env, application_class_loader); + application_class_loader = NULL; + } + + return 0; +} + +#endif diff --git a/libavutil/jni.h b/libavutil/jni.h index 3c36eaf..1bf783a 100644 --- a/libavutil/jni.h +++ b/libavutil/jni.h @@ -39,4 +39,32 @@ void av_jni_register_java_vm(JavaVM *vm); */ JavaVM *av_jni_get_java_vm(void); +#ifdef __ANDROID__ +/* + * Register an Android application context that will be used later on + * to load application classes. + * + * @param env JNI environment + * @param context application context + * @return 0 on success, a negative number otherwise + */ +int av_jni_register_application_context(JNIEnv *env, jobject context); + +/* + * Get the registered android application context. + * + * @return the registered android application context + */ +jobject av_jni_get_application_context(void); + +/* + * Unregister the previously registered Android application context. + * + * @param env JNI environment + * @return 0 on success, a negative number otherwise + * + */ +int av_jni_unregister_application_context(JNIEnv *env); +#endif + #endif /* AVUTIL_JNI_H */ diff --git a/libavutil/jni_internal.c b/libavutil/jni_internal.c index 2c1dc70..58eb570 100644 --- a/libavutil/jni_internal.c +++ b/libavutil/jni_internal.c @@ -28,6 +28,11 @@ extern JavaVM *java_vm; +extern jobject application_context; + +extern jobject application_class_loader; +extern jmethodID find_class_id; + JNIEnv *avpriv_jni_attach_env(void *log_ctx) { int ret = 0; @@ -357,3 +362,28 @@ int avpriv_jni_reset_jfields(JNIEnv *env, void *jfields, const struct FFJniField return 0; } + +jclass avpriv_jni_find_application_class(JNIEnv *env, const char *name, void *log_ctx) +{ + jobject ret; + jobject tmp; + + if (!application_class_loader || !find_class_id) { + av_log(log_ctx, AV_LOG_ERROR, "No application class loader has been registered\n"); + return NULL; + } + + tmp = avpriv_jni_utf_chars_to_jstring(env, name, log_ctx); + if (!tmp) { + return NULL; + } + + ret = (*env)->CallObjectMethod(env, application_class_loader, find_class_id, tmp); + if (avpriv_jni_exception_check(env, 1, log_ctx) < 0) { + ret = NULL; + } + + (*env)->DeleteLocalRef(env, tmp); + + return ret; +} diff --git a/libavutil/jni_internal.h b/libavutil/jni_internal.h index 3411c78..24c4b4e 100644 --- a/libavutil/jni_internal.h +++ b/libavutil/jni_internal.h @@ -140,4 +140,15 @@ int avpriv_jni_init_jfields(JNIEnv *env, void *jfields, const struct FFJniField */ int avpriv_jni_reset_jfields(JNIEnv *env, void *jfields, const struct FFJniField *jfields_mapping, int global, void *log_ctx); +/* + * Find an application class using the registered Android application context. + * + * @param env JNI environment + * @param name class name (for example: java/lang/String) + * @param log_ctx context used for logging, can be NULL + * @return a local reference to a class object corresponding the provided + * name, or NULL if the class cannot be found + */ +jclass avpriv_jni_find_application_class(JNIEnv *env, const char *name, void *log_ctx); + #endif /* AVUTIL_JNI_INTERNAL_H */ -- 2.6.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel