1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * JNI utility functions 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com> 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * This file is part of FFmpeg. 7cabdff1aSopenharmony_ci * 8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 12cabdff1aSopenharmony_ci * 13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16cabdff1aSopenharmony_ci * Lesser General Public License for more details. 17cabdff1aSopenharmony_ci * 18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21cabdff1aSopenharmony_ci */ 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#include <jni.h> 24cabdff1aSopenharmony_ci#include <pthread.h> 25cabdff1aSopenharmony_ci#include <stdlib.h> 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci#include "libavutil/bprint.h" 28cabdff1aSopenharmony_ci#include "libavutil/log.h" 29cabdff1aSopenharmony_ci#include "libavutil/mem.h" 30cabdff1aSopenharmony_ci 31cabdff1aSopenharmony_ci#include "config.h" 32cabdff1aSopenharmony_ci#include "jni.h" 33cabdff1aSopenharmony_ci#include "ffjni.h" 34cabdff1aSopenharmony_ci 35cabdff1aSopenharmony_cistatic JavaVM *java_vm; 36cabdff1aSopenharmony_cistatic pthread_key_t current_env; 37cabdff1aSopenharmony_cistatic pthread_once_t once = PTHREAD_ONCE_INIT; 38cabdff1aSopenharmony_cistatic pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; 39cabdff1aSopenharmony_ci 40cabdff1aSopenharmony_cistatic void jni_detach_env(void *data) 41cabdff1aSopenharmony_ci{ 42cabdff1aSopenharmony_ci if (java_vm) { 43cabdff1aSopenharmony_ci (*java_vm)->DetachCurrentThread(java_vm); 44cabdff1aSopenharmony_ci } 45cabdff1aSopenharmony_ci} 46cabdff1aSopenharmony_ci 47cabdff1aSopenharmony_cistatic void jni_create_pthread_key(void) 48cabdff1aSopenharmony_ci{ 49cabdff1aSopenharmony_ci pthread_key_create(¤t_env, jni_detach_env); 50cabdff1aSopenharmony_ci} 51cabdff1aSopenharmony_ci 52cabdff1aSopenharmony_ciJNIEnv *ff_jni_get_env(void *log_ctx) 53cabdff1aSopenharmony_ci{ 54cabdff1aSopenharmony_ci int ret = 0; 55cabdff1aSopenharmony_ci JNIEnv *env = NULL; 56cabdff1aSopenharmony_ci 57cabdff1aSopenharmony_ci pthread_mutex_lock(&lock); 58cabdff1aSopenharmony_ci if (java_vm == NULL) { 59cabdff1aSopenharmony_ci java_vm = av_jni_get_java_vm(log_ctx); 60cabdff1aSopenharmony_ci } 61cabdff1aSopenharmony_ci 62cabdff1aSopenharmony_ci if (!java_vm) { 63cabdff1aSopenharmony_ci av_log(log_ctx, AV_LOG_ERROR, "No Java virtual machine has been registered\n"); 64cabdff1aSopenharmony_ci goto done; 65cabdff1aSopenharmony_ci } 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_ci pthread_once(&once, jni_create_pthread_key); 68cabdff1aSopenharmony_ci 69cabdff1aSopenharmony_ci if ((env = pthread_getspecific(current_env)) != NULL) { 70cabdff1aSopenharmony_ci goto done; 71cabdff1aSopenharmony_ci } 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ci ret = (*java_vm)->GetEnv(java_vm, (void **)&env, JNI_VERSION_1_6); 74cabdff1aSopenharmony_ci switch(ret) { 75cabdff1aSopenharmony_ci case JNI_EDETACHED: 76cabdff1aSopenharmony_ci if ((*java_vm)->AttachCurrentThread(java_vm, &env, NULL) != 0) { 77cabdff1aSopenharmony_ci av_log(log_ctx, AV_LOG_ERROR, "Failed to attach the JNI environment to the current thread\n"); 78cabdff1aSopenharmony_ci env = NULL; 79cabdff1aSopenharmony_ci } else { 80cabdff1aSopenharmony_ci pthread_setspecific(current_env, env); 81cabdff1aSopenharmony_ci } 82cabdff1aSopenharmony_ci break; 83cabdff1aSopenharmony_ci case JNI_OK: 84cabdff1aSopenharmony_ci break; 85cabdff1aSopenharmony_ci case JNI_EVERSION: 86cabdff1aSopenharmony_ci av_log(log_ctx, AV_LOG_ERROR, "The specified JNI version is not supported\n"); 87cabdff1aSopenharmony_ci break; 88cabdff1aSopenharmony_ci default: 89cabdff1aSopenharmony_ci av_log(log_ctx, AV_LOG_ERROR, "Failed to get the JNI environment attached to this thread\n"); 90cabdff1aSopenharmony_ci break; 91cabdff1aSopenharmony_ci } 92cabdff1aSopenharmony_ci 93cabdff1aSopenharmony_cidone: 94cabdff1aSopenharmony_ci pthread_mutex_unlock(&lock); 95cabdff1aSopenharmony_ci return env; 96cabdff1aSopenharmony_ci} 97cabdff1aSopenharmony_ci 98cabdff1aSopenharmony_cichar *ff_jni_jstring_to_utf_chars(JNIEnv *env, jstring string, void *log_ctx) 99cabdff1aSopenharmony_ci{ 100cabdff1aSopenharmony_ci char *ret = NULL; 101cabdff1aSopenharmony_ci const char *utf_chars = NULL; 102cabdff1aSopenharmony_ci 103cabdff1aSopenharmony_ci jboolean copy = 0; 104cabdff1aSopenharmony_ci 105cabdff1aSopenharmony_ci if (!string) { 106cabdff1aSopenharmony_ci return NULL; 107cabdff1aSopenharmony_ci } 108cabdff1aSopenharmony_ci 109cabdff1aSopenharmony_ci utf_chars = (*env)->GetStringUTFChars(env, string, ©); 110cabdff1aSopenharmony_ci if ((*env)->ExceptionCheck(env)) { 111cabdff1aSopenharmony_ci (*env)->ExceptionClear(env); 112cabdff1aSopenharmony_ci av_log(log_ctx, AV_LOG_ERROR, "String.getStringUTFChars() threw an exception\n"); 113cabdff1aSopenharmony_ci return NULL; 114cabdff1aSopenharmony_ci } 115cabdff1aSopenharmony_ci 116cabdff1aSopenharmony_ci ret = av_strdup(utf_chars); 117cabdff1aSopenharmony_ci 118cabdff1aSopenharmony_ci (*env)->ReleaseStringUTFChars(env, string, utf_chars); 119cabdff1aSopenharmony_ci if ((*env)->ExceptionCheck(env)) { 120cabdff1aSopenharmony_ci (*env)->ExceptionClear(env); 121cabdff1aSopenharmony_ci av_log(log_ctx, AV_LOG_ERROR, "String.releaseStringUTFChars() threw an exception\n"); 122cabdff1aSopenharmony_ci return NULL; 123cabdff1aSopenharmony_ci } 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_ci return ret; 126cabdff1aSopenharmony_ci} 127cabdff1aSopenharmony_ci 128cabdff1aSopenharmony_cijstring ff_jni_utf_chars_to_jstring(JNIEnv *env, const char *utf_chars, void *log_ctx) 129cabdff1aSopenharmony_ci{ 130cabdff1aSopenharmony_ci jstring ret; 131cabdff1aSopenharmony_ci 132cabdff1aSopenharmony_ci ret = (*env)->NewStringUTF(env, utf_chars); 133cabdff1aSopenharmony_ci if ((*env)->ExceptionCheck(env)) { 134cabdff1aSopenharmony_ci (*env)->ExceptionClear(env); 135cabdff1aSopenharmony_ci av_log(log_ctx, AV_LOG_ERROR, "NewStringUTF() threw an exception\n"); 136cabdff1aSopenharmony_ci return NULL; 137cabdff1aSopenharmony_ci } 138cabdff1aSopenharmony_ci 139cabdff1aSopenharmony_ci return ret; 140cabdff1aSopenharmony_ci} 141cabdff1aSopenharmony_ci 142cabdff1aSopenharmony_ciint ff_jni_exception_get_summary(JNIEnv *env, jthrowable exception, char **error, void *log_ctx) 143cabdff1aSopenharmony_ci{ 144cabdff1aSopenharmony_ci int ret = 0; 145cabdff1aSopenharmony_ci 146cabdff1aSopenharmony_ci AVBPrint bp; 147cabdff1aSopenharmony_ci 148cabdff1aSopenharmony_ci char *name = NULL; 149cabdff1aSopenharmony_ci char *message = NULL; 150cabdff1aSopenharmony_ci 151cabdff1aSopenharmony_ci jclass class_class = NULL; 152cabdff1aSopenharmony_ci jmethodID get_name_id = NULL; 153cabdff1aSopenharmony_ci 154cabdff1aSopenharmony_ci jclass exception_class = NULL; 155cabdff1aSopenharmony_ci jmethodID get_message_id = NULL; 156cabdff1aSopenharmony_ci 157cabdff1aSopenharmony_ci jstring string = NULL; 158cabdff1aSopenharmony_ci 159cabdff1aSopenharmony_ci av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC); 160cabdff1aSopenharmony_ci 161cabdff1aSopenharmony_ci exception_class = (*env)->GetObjectClass(env, exception); 162cabdff1aSopenharmony_ci if ((*env)->ExceptionCheck(env)) { 163cabdff1aSopenharmony_ci (*env)->ExceptionClear(env); 164cabdff1aSopenharmony_ci av_log(log_ctx, AV_LOG_ERROR, "Could not find Throwable class\n"); 165cabdff1aSopenharmony_ci ret = AVERROR_EXTERNAL; 166cabdff1aSopenharmony_ci goto done; 167cabdff1aSopenharmony_ci } 168cabdff1aSopenharmony_ci 169cabdff1aSopenharmony_ci class_class = (*env)->GetObjectClass(env, exception_class); 170cabdff1aSopenharmony_ci if ((*env)->ExceptionCheck(env)) { 171cabdff1aSopenharmony_ci (*env)->ExceptionClear(env); 172cabdff1aSopenharmony_ci av_log(log_ctx, AV_LOG_ERROR, "Could not find Throwable class's class\n"); 173cabdff1aSopenharmony_ci ret = AVERROR_EXTERNAL; 174cabdff1aSopenharmony_ci goto done; 175cabdff1aSopenharmony_ci } 176cabdff1aSopenharmony_ci 177cabdff1aSopenharmony_ci get_name_id = (*env)->GetMethodID(env, class_class, "getName", "()Ljava/lang/String;"); 178cabdff1aSopenharmony_ci if ((*env)->ExceptionCheck(env)) { 179cabdff1aSopenharmony_ci (*env)->ExceptionClear(env); 180cabdff1aSopenharmony_ci av_log(log_ctx, AV_LOG_ERROR, "Could not find method Class.getName()\n"); 181cabdff1aSopenharmony_ci ret = AVERROR_EXTERNAL; 182cabdff1aSopenharmony_ci goto done; 183cabdff1aSopenharmony_ci } 184cabdff1aSopenharmony_ci 185cabdff1aSopenharmony_ci string = (*env)->CallObjectMethod(env, exception_class, get_name_id); 186cabdff1aSopenharmony_ci if ((*env)->ExceptionCheck(env)) { 187cabdff1aSopenharmony_ci (*env)->ExceptionClear(env); 188cabdff1aSopenharmony_ci av_log(log_ctx, AV_LOG_ERROR, "Class.getName() threw an exception\n"); 189cabdff1aSopenharmony_ci ret = AVERROR_EXTERNAL; 190cabdff1aSopenharmony_ci goto done; 191cabdff1aSopenharmony_ci } 192cabdff1aSopenharmony_ci 193cabdff1aSopenharmony_ci if (string) { 194cabdff1aSopenharmony_ci name = ff_jni_jstring_to_utf_chars(env, string, log_ctx); 195cabdff1aSopenharmony_ci (*env)->DeleteLocalRef(env, string); 196cabdff1aSopenharmony_ci string = NULL; 197cabdff1aSopenharmony_ci } 198cabdff1aSopenharmony_ci 199cabdff1aSopenharmony_ci get_message_id = (*env)->GetMethodID(env, exception_class, "getMessage", "()Ljava/lang/String;"); 200cabdff1aSopenharmony_ci if ((*env)->ExceptionCheck(env)) { 201cabdff1aSopenharmony_ci (*env)->ExceptionClear(env); 202cabdff1aSopenharmony_ci av_log(log_ctx, AV_LOG_ERROR, "Could not find method java/lang/Throwable.getMessage()\n"); 203cabdff1aSopenharmony_ci ret = AVERROR_EXTERNAL; 204cabdff1aSopenharmony_ci goto done; 205cabdff1aSopenharmony_ci } 206cabdff1aSopenharmony_ci 207cabdff1aSopenharmony_ci string = (*env)->CallObjectMethod(env, exception, get_message_id); 208cabdff1aSopenharmony_ci if ((*env)->ExceptionCheck(env)) { 209cabdff1aSopenharmony_ci (*env)->ExceptionClear(env); 210cabdff1aSopenharmony_ci av_log(log_ctx, AV_LOG_ERROR, "Throwable.getMessage() threw an exception\n"); 211cabdff1aSopenharmony_ci ret = AVERROR_EXTERNAL; 212cabdff1aSopenharmony_ci goto done; 213cabdff1aSopenharmony_ci } 214cabdff1aSopenharmony_ci 215cabdff1aSopenharmony_ci if (string) { 216cabdff1aSopenharmony_ci message = ff_jni_jstring_to_utf_chars(env, string, log_ctx); 217cabdff1aSopenharmony_ci (*env)->DeleteLocalRef(env, string); 218cabdff1aSopenharmony_ci string = NULL; 219cabdff1aSopenharmony_ci } 220cabdff1aSopenharmony_ci 221cabdff1aSopenharmony_ci if (name && message) { 222cabdff1aSopenharmony_ci av_bprintf(&bp, "%s: %s", name, message); 223cabdff1aSopenharmony_ci } else if (name && !message) { 224cabdff1aSopenharmony_ci av_bprintf(&bp, "%s occurred", name); 225cabdff1aSopenharmony_ci } else if (!name && message) { 226cabdff1aSopenharmony_ci av_bprintf(&bp, "Exception: %s", message); 227cabdff1aSopenharmony_ci } else { 228cabdff1aSopenharmony_ci av_log(log_ctx, AV_LOG_WARNING, "Could not retrieve exception name and message\n"); 229cabdff1aSopenharmony_ci av_bprintf(&bp, "Exception occurred"); 230cabdff1aSopenharmony_ci } 231cabdff1aSopenharmony_ci 232cabdff1aSopenharmony_ci ret = av_bprint_finalize(&bp, error); 233cabdff1aSopenharmony_cidone: 234cabdff1aSopenharmony_ci 235cabdff1aSopenharmony_ci av_free(name); 236cabdff1aSopenharmony_ci av_free(message); 237cabdff1aSopenharmony_ci 238cabdff1aSopenharmony_ci if (class_class) { 239cabdff1aSopenharmony_ci (*env)->DeleteLocalRef(env, class_class); 240cabdff1aSopenharmony_ci } 241cabdff1aSopenharmony_ci 242cabdff1aSopenharmony_ci if (exception_class) { 243cabdff1aSopenharmony_ci (*env)->DeleteLocalRef(env, exception_class); 244cabdff1aSopenharmony_ci } 245cabdff1aSopenharmony_ci 246cabdff1aSopenharmony_ci if (string) { 247cabdff1aSopenharmony_ci (*env)->DeleteLocalRef(env, string); 248cabdff1aSopenharmony_ci } 249cabdff1aSopenharmony_ci 250cabdff1aSopenharmony_ci return ret; 251cabdff1aSopenharmony_ci} 252cabdff1aSopenharmony_ci 253cabdff1aSopenharmony_ciint ff_jni_exception_check(JNIEnv *env, int log, void *log_ctx) 254cabdff1aSopenharmony_ci{ 255cabdff1aSopenharmony_ci int ret; 256cabdff1aSopenharmony_ci 257cabdff1aSopenharmony_ci jthrowable exception; 258cabdff1aSopenharmony_ci 259cabdff1aSopenharmony_ci char *message = NULL; 260cabdff1aSopenharmony_ci 261cabdff1aSopenharmony_ci if (!(*(env))->ExceptionCheck((env))) { 262cabdff1aSopenharmony_ci return 0; 263cabdff1aSopenharmony_ci } 264cabdff1aSopenharmony_ci 265cabdff1aSopenharmony_ci if (!log) { 266cabdff1aSopenharmony_ci (*(env))->ExceptionClear((env)); 267cabdff1aSopenharmony_ci return -1; 268cabdff1aSopenharmony_ci } 269cabdff1aSopenharmony_ci 270cabdff1aSopenharmony_ci exception = (*env)->ExceptionOccurred(env); 271cabdff1aSopenharmony_ci (*(env))->ExceptionClear((env)); 272cabdff1aSopenharmony_ci 273cabdff1aSopenharmony_ci if ((ret = ff_jni_exception_get_summary(env, exception, &message, log_ctx)) < 0) { 274cabdff1aSopenharmony_ci (*env)->DeleteLocalRef(env, exception); 275cabdff1aSopenharmony_ci return ret; 276cabdff1aSopenharmony_ci } 277cabdff1aSopenharmony_ci 278cabdff1aSopenharmony_ci (*env)->DeleteLocalRef(env, exception); 279cabdff1aSopenharmony_ci 280cabdff1aSopenharmony_ci av_log(log_ctx, AV_LOG_ERROR, "%s\n", message); 281cabdff1aSopenharmony_ci av_free(message); 282cabdff1aSopenharmony_ci 283cabdff1aSopenharmony_ci return -1; 284cabdff1aSopenharmony_ci} 285cabdff1aSopenharmony_ci 286cabdff1aSopenharmony_ciint ff_jni_init_jfields(JNIEnv *env, void *jfields, const struct FFJniField *jfields_mapping, int global, void *log_ctx) 287cabdff1aSopenharmony_ci{ 288cabdff1aSopenharmony_ci int i, ret = 0; 289cabdff1aSopenharmony_ci jclass last_clazz = NULL; 290cabdff1aSopenharmony_ci 291cabdff1aSopenharmony_ci for (i = 0; jfields_mapping[i].name; i++) { 292cabdff1aSopenharmony_ci int mandatory = jfields_mapping[i].mandatory; 293cabdff1aSopenharmony_ci enum FFJniFieldType type = jfields_mapping[i].type; 294cabdff1aSopenharmony_ci 295cabdff1aSopenharmony_ci if (type == FF_JNI_CLASS) { 296cabdff1aSopenharmony_ci jclass clazz; 297cabdff1aSopenharmony_ci 298cabdff1aSopenharmony_ci last_clazz = NULL; 299cabdff1aSopenharmony_ci 300cabdff1aSopenharmony_ci clazz = (*env)->FindClass(env, jfields_mapping[i].name); 301cabdff1aSopenharmony_ci if ((ret = ff_jni_exception_check(env, mandatory, log_ctx)) < 0 && mandatory) { 302cabdff1aSopenharmony_ci goto done; 303cabdff1aSopenharmony_ci } 304cabdff1aSopenharmony_ci 305cabdff1aSopenharmony_ci last_clazz = *(jclass*)((uint8_t*)jfields + jfields_mapping[i].offset) = 306cabdff1aSopenharmony_ci global ? (*env)->NewGlobalRef(env, clazz) : clazz; 307cabdff1aSopenharmony_ci 308cabdff1aSopenharmony_ci if (global) { 309cabdff1aSopenharmony_ci (*env)->DeleteLocalRef(env, clazz); 310cabdff1aSopenharmony_ci } 311cabdff1aSopenharmony_ci 312cabdff1aSopenharmony_ci } else { 313cabdff1aSopenharmony_ci 314cabdff1aSopenharmony_ci if (!last_clazz) { 315cabdff1aSopenharmony_ci ret = AVERROR_EXTERNAL; 316cabdff1aSopenharmony_ci break; 317cabdff1aSopenharmony_ci } 318cabdff1aSopenharmony_ci 319cabdff1aSopenharmony_ci switch(type) { 320cabdff1aSopenharmony_ci case FF_JNI_FIELD: { 321cabdff1aSopenharmony_ci jfieldID field_id = (*env)->GetFieldID(env, last_clazz, jfields_mapping[i].method, jfields_mapping[i].signature); 322cabdff1aSopenharmony_ci if ((ret = ff_jni_exception_check(env, mandatory, log_ctx)) < 0 && mandatory) { 323cabdff1aSopenharmony_ci goto done; 324cabdff1aSopenharmony_ci } 325cabdff1aSopenharmony_ci 326cabdff1aSopenharmony_ci *(jfieldID*)((uint8_t*)jfields + jfields_mapping[i].offset) = field_id; 327cabdff1aSopenharmony_ci break; 328cabdff1aSopenharmony_ci } 329cabdff1aSopenharmony_ci case FF_JNI_STATIC_FIELD: { 330cabdff1aSopenharmony_ci jfieldID field_id = (*env)->GetStaticFieldID(env, last_clazz, jfields_mapping[i].method, jfields_mapping[i].signature); 331cabdff1aSopenharmony_ci if ((ret = ff_jni_exception_check(env, mandatory, log_ctx)) < 0 && mandatory) { 332cabdff1aSopenharmony_ci goto done; 333cabdff1aSopenharmony_ci } 334cabdff1aSopenharmony_ci 335cabdff1aSopenharmony_ci *(jfieldID*)((uint8_t*)jfields + jfields_mapping[i].offset) = field_id; 336cabdff1aSopenharmony_ci break; 337cabdff1aSopenharmony_ci } 338cabdff1aSopenharmony_ci case FF_JNI_METHOD: { 339cabdff1aSopenharmony_ci jmethodID method_id = (*env)->GetMethodID(env, last_clazz, jfields_mapping[i].method, jfields_mapping[i].signature); 340cabdff1aSopenharmony_ci if ((ret = ff_jni_exception_check(env, mandatory, log_ctx)) < 0 && mandatory) { 341cabdff1aSopenharmony_ci goto done; 342cabdff1aSopenharmony_ci } 343cabdff1aSopenharmony_ci 344cabdff1aSopenharmony_ci *(jmethodID*)((uint8_t*)jfields + jfields_mapping[i].offset) = method_id; 345cabdff1aSopenharmony_ci break; 346cabdff1aSopenharmony_ci } 347cabdff1aSopenharmony_ci case FF_JNI_STATIC_METHOD: { 348cabdff1aSopenharmony_ci jmethodID method_id = (*env)->GetStaticMethodID(env, last_clazz, jfields_mapping[i].method, jfields_mapping[i].signature); 349cabdff1aSopenharmony_ci if ((ret = ff_jni_exception_check(env, mandatory, log_ctx)) < 0 && mandatory) { 350cabdff1aSopenharmony_ci goto done; 351cabdff1aSopenharmony_ci } 352cabdff1aSopenharmony_ci 353cabdff1aSopenharmony_ci *(jmethodID*)((uint8_t*)jfields + jfields_mapping[i].offset) = method_id; 354cabdff1aSopenharmony_ci break; 355cabdff1aSopenharmony_ci } 356cabdff1aSopenharmony_ci default: 357cabdff1aSopenharmony_ci av_log(log_ctx, AV_LOG_ERROR, "Unknown JNI field type\n"); 358cabdff1aSopenharmony_ci ret = AVERROR(EINVAL); 359cabdff1aSopenharmony_ci goto done; 360cabdff1aSopenharmony_ci } 361cabdff1aSopenharmony_ci 362cabdff1aSopenharmony_ci ret = 0; 363cabdff1aSopenharmony_ci } 364cabdff1aSopenharmony_ci } 365cabdff1aSopenharmony_ci 366cabdff1aSopenharmony_cidone: 367cabdff1aSopenharmony_ci if (ret < 0) { 368cabdff1aSopenharmony_ci /* reset jfields in case of failure so it does not leak references */ 369cabdff1aSopenharmony_ci ff_jni_reset_jfields(env, jfields, jfields_mapping, global, log_ctx); 370cabdff1aSopenharmony_ci } 371cabdff1aSopenharmony_ci 372cabdff1aSopenharmony_ci return ret; 373cabdff1aSopenharmony_ci} 374cabdff1aSopenharmony_ci 375cabdff1aSopenharmony_ciint ff_jni_reset_jfields(JNIEnv *env, void *jfields, const struct FFJniField *jfields_mapping, int global, void *log_ctx) 376cabdff1aSopenharmony_ci{ 377cabdff1aSopenharmony_ci int i; 378cabdff1aSopenharmony_ci 379cabdff1aSopenharmony_ci for (i = 0; jfields_mapping[i].name; i++) { 380cabdff1aSopenharmony_ci enum FFJniFieldType type = jfields_mapping[i].type; 381cabdff1aSopenharmony_ci 382cabdff1aSopenharmony_ci switch(type) { 383cabdff1aSopenharmony_ci case FF_JNI_CLASS: { 384cabdff1aSopenharmony_ci jclass clazz = *(jclass*)((uint8_t*)jfields + jfields_mapping[i].offset); 385cabdff1aSopenharmony_ci if (!clazz) 386cabdff1aSopenharmony_ci continue; 387cabdff1aSopenharmony_ci 388cabdff1aSopenharmony_ci if (global) { 389cabdff1aSopenharmony_ci (*env)->DeleteGlobalRef(env, clazz); 390cabdff1aSopenharmony_ci } else { 391cabdff1aSopenharmony_ci (*env)->DeleteLocalRef(env, clazz); 392cabdff1aSopenharmony_ci } 393cabdff1aSopenharmony_ci 394cabdff1aSopenharmony_ci *(jclass*)((uint8_t*)jfields + jfields_mapping[i].offset) = NULL; 395cabdff1aSopenharmony_ci break; 396cabdff1aSopenharmony_ci } 397cabdff1aSopenharmony_ci case FF_JNI_FIELD: { 398cabdff1aSopenharmony_ci *(jfieldID*)((uint8_t*)jfields + jfields_mapping[i].offset) = NULL; 399cabdff1aSopenharmony_ci break; 400cabdff1aSopenharmony_ci } 401cabdff1aSopenharmony_ci case FF_JNI_STATIC_FIELD: { 402cabdff1aSopenharmony_ci *(jfieldID*)((uint8_t*)jfields + jfields_mapping[i].offset) = NULL; 403cabdff1aSopenharmony_ci break; 404cabdff1aSopenharmony_ci } 405cabdff1aSopenharmony_ci case FF_JNI_METHOD: { 406cabdff1aSopenharmony_ci *(jmethodID*)((uint8_t*)jfields + jfields_mapping[i].offset) = NULL; 407cabdff1aSopenharmony_ci break; 408cabdff1aSopenharmony_ci } 409cabdff1aSopenharmony_ci case FF_JNI_STATIC_METHOD: { 410cabdff1aSopenharmony_ci *(jmethodID*)((uint8_t*)jfields + jfields_mapping[i].offset) = NULL; 411cabdff1aSopenharmony_ci break; 412cabdff1aSopenharmony_ci } 413cabdff1aSopenharmony_ci default: 414cabdff1aSopenharmony_ci av_log(log_ctx, AV_LOG_ERROR, "Unknown JNI field type\n"); 415cabdff1aSopenharmony_ci } 416cabdff1aSopenharmony_ci } 417cabdff1aSopenharmony_ci 418cabdff1aSopenharmony_ci return 0; 419cabdff1aSopenharmony_ci} 420