[FFmpeg-devel] [PATCH 2/5] lavu/jni: add more JNI helper

Michael Niedermayer michael at niedermayer.cc
Sat Oct 10 03:18:38 CEST 2015


On Fri, Oct 09, 2015 at 06:26:50PM +0200, Matthieu Bouron wrote:
> From: Matthieu Bouron <matthieu.bouron at stupeflix.com>
> 
> ---
>  libavutil/jni_internal.c | 290 +++++++++++++++++++++++++++++++++++++++++++++++
>  libavutil/jni_internal.h | 101 +++++++++++++++++
>  2 files changed, 391 insertions(+)
> 
> diff --git a/libavutil/jni_internal.c b/libavutil/jni_internal.c
> index b17275d..2c1dc70 100644
> --- a/libavutil/jni_internal.c
> +++ b/libavutil/jni_internal.c
> @@ -18,6 +18,7 @@
>   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
>   */
>  
> +#include "bprint.h"
>  #include "config.h"
>  #include "jni.h"
>  #include "jni_internal.h"
> @@ -67,3 +68,292 @@ int avpriv_jni_detach_env(void *log_ctx)
>  
>      return (*java_vm)->DetachCurrentThread(java_vm);
>  }
> +
> +char *avpriv_jni_jstring_to_utf_chars(JNIEnv *env, jstring string, void *log_ctx)
> +{
> +    char *ret = NULL;
> +    const char *utf_chars = NULL;
> +
> +    jboolean copy = 0;
> +
> +    utf_chars = (*env)->GetStringUTFChars(env, string, &copy);
> +    if ((*env)->ExceptionCheck(env)) {
> +        (*env)->ExceptionClear(env);
> +        av_log(log_ctx, AV_LOG_ERROR, "String.getStringUTFChars() threw an exception\n");
> +        return NULL;
> +    }
> +
> +    ret = av_strdup(utf_chars);
> +
> +    (*env)->ReleaseStringUTFChars(env, string, utf_chars);
> +    if ((*env)->ExceptionCheck(env)) {
> +        (*env)->ExceptionClear(env);
> +        av_log(log_ctx, AV_LOG_ERROR, "String.releaseStringUTFChars() threw an exception\n");
> +        return NULL;;
> +    }
> +
> +    return ret;
> +}
> +
> +jstring avpriv_jni_utf_chars_to_jstring(JNIEnv *env, const char *utf_chars, void *log_ctx)
> +{
> +    jstring ret;
> +
> +    ret = (*env)->NewStringUTF(env, utf_chars);
> +    if ((*env)->ExceptionCheck(env)) {
> +        (*env)->ExceptionClear(env);
> +        av_log(log_ctx, AV_LOG_ERROR, "NewStringUTF() threw an exception\n");
> +        return NULL;
> +    }
> +
> +    return ret;
> +}
> +
> +int avpriv_jni_exception_get_summary(JNIEnv *env, jthrowable exception, char **error, void *log_ctx)
> +{
> +    int ret = 0;
> +
> +    AVBPrint bp;
> +
> +    char *name = NULL;
> +    char *message = NULL;
> +
> +    jclass class_class = NULL;
> +    jmethodID get_name_id = NULL;
> +
> +    jclass exception_class = NULL;
> +    jmethodID get_message_id = NULL;
> +
> +    jstring string;
> +
> +    av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
> +
> +    exception_class = (*env)->GetObjectClass(env, exception);
> +    if ((*env)->ExceptionCheck(env)) {
> +        (*env)->ExceptionClear(env);
> +        av_log(log_ctx, AV_LOG_ERROR, "Could not find Throwable class\n");
> +        ret = AVERROR_EXTERNAL;
> +        goto done;
> +    }
> +
> +    class_class = (*env)->GetObjectClass(env, exception_class);
> +    if ((*env)->ExceptionCheck(env)) {
> +        (*env)->ExceptionClear(env);
> +        av_log(log_ctx, AV_LOG_ERROR, "Could not find Throwable class's class\n");
> +        ret = AVERROR_EXTERNAL;
> +        goto done;
> +    }
> +
> +    get_name_id = (*env)->GetMethodID(env, class_class, "getName", "()Ljava/lang/String;");
> +    if ((*env)->ExceptionCheck(env)) {
> +        (*env)->ExceptionClear(env);
> +        av_log(log_ctx, AV_LOG_ERROR, "Could not find method Class.getName()\n");
> +        ret = AVERROR_EXTERNAL;
> +        goto done;
> +    }
> +
> +    string = (*env)->CallObjectMethod(env, exception_class, get_name_id);
> +    if ((*env)->ExceptionCheck(env)) {
> +        (*env)->ExceptionClear(env);
> +        av_log(log_ctx, AV_LOG_ERROR, "Class.getName() threw an exception\n");
> +        ret = AVERROR_EXTERNAL;
> +        goto done;
> +    }
> +
> +    name = avpriv_jni_jstring_to_utf_chars(env, string, log_ctx);
> +    if (!name) {
> +        ret = AVERROR(ENOMEM);
> +        goto done;
> +    }
> +
> +    (*env)->DeleteLocalRef(env, string);
> +
> +    get_message_id = (*env)->GetMethodID(env, exception_class, "getMessage", "()Ljava/lang/String;");
> +    if ((*env)->ExceptionCheck(env)) {
> +        (*env)->ExceptionClear(env);
> +        av_log(log_ctx, AV_LOG_ERROR, "Could not find method java/lang/Throwable.getMessage()\n");
> +        ret = AVERROR_EXTERNAL;
> +        goto done;
> +    }
> +
> +    string = (*env)->CallObjectMethod(env, exception, get_message_id);
> +    if ((*env)->ExceptionCheck(env)) {
> +        (*env)->ExceptionClear(env);
> +        av_log(log_ctx, AV_LOG_ERROR, "Throwable.getMessage() threw an exception\n");
> +        ret = AVERROR_EXTERNAL;
> +        goto done;
> +    }
> +
> +    message = avpriv_jni_jstring_to_utf_chars(env, string, log_ctx);
> +    if (!message) {
> +        ret = AVERROR(ENOMEM);
> +        goto done;
> +    }
> +
> +    (*env)->DeleteLocalRef(env, string);
> +
> +    av_bprintf(&bp, "%s: %s", name, message);
> +    ret = av_bprint_finalize(&bp, error);
> +
> +done:
> +
> +    av_free(name);
> +    av_free(message);
> +
> +    if (class_class) {
> +        (*env)->DeleteLocalRef(env, class_class);
> +    }
> +
> +    if (exception_class) {
> +        (*env)->DeleteLocalRef(env, exception_class);
> +    }
> +
> +    return ret;
> +}
> +
> +int avpriv_jni_exception_check(JNIEnv *env, int log, void *log_ctx)
> +{
> +    int ret;
> +
> +    jthrowable exception;
> +
> +    char *message;
> +
> +    if (!(*(env))->ExceptionCheck((env))) {
> +        return 0;
> +    }
> +
> +    if (!log) {
> +        (*(env))->ExceptionClear((env));
> +        return -1;
> +    }
> +
> +    exception = (*env)->ExceptionOccurred(env);
> +    (*(env))->ExceptionClear((env));
> +
> +    if ((ret = avpriv_jni_exception_get_summary(env, exception, &message, log_ctx)) < 0) {
> +        return ret;
> +    }
> +
> +    (*env)->DeleteLocalRef(env, exception);
> +
> +    av_log(log_ctx, AV_LOG_ERROR, "%s\n", message);
> +    av_free(message);
> +

> +    return -1;

probably should be a AVERROR code, same for the other -1


> +}
> +
> +int avpriv_jni_init_jfields(JNIEnv *env, void *jfields, const struct FFJniField *jfields_mapping, int global, void *log_ctx)
> +{
> +    int i, ret = 0;
> +    jclass last_clazz = NULL;
> +
> +    for (i = 0; jfields_mapping[i].name; i++) {
> +        int mandatory = jfields_mapping[i].mandatory;
> +        enum FFJniFieldType type = jfields_mapping[i].type;
> +
> +        if (type == FF_JNI_CLASS) {
> +            jclass clazz;
> +
> +            last_clazz = NULL;
> +
> +            clazz = (*env)->FindClass(env, jfields_mapping[i].name);

> +            if ((ret = avpriv_jni_exception_check(env, mandatory, log_ctx) && mandatory) < 0) {

the < 0 looks wrongly placed

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Those who are best at talking, realize last or never when they are wrong.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20151010/fbc3316c/attachment.sig>


More information about the ffmpeg-devel mailing list