ijksdl_android_jni.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*****************************************************************************
  2. * ijksdl_android.c
  3. *****************************************************************************
  4. *
  5. * Copyright (c) 2013 Bilibili
  6. * copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
  7. *
  8. * This file is part of ijkPlayer.
  9. *
  10. * ijkPlayer is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation; either
  13. * version 2.1 of the License, or (at your option) any later version.
  14. *
  15. * ijkPlayer is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with ijkPlayer; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. */
  24. #include "ijksdl_android_jni.h"
  25. #include <unistd.h>
  26. #include "j4a/class/android/os/Build.h"
  27. #include "ijksdl_inc_internal_android.h"
  28. #include "ijksdl_codec_android_mediaformat_java.h"
  29. #include "ijksdl_codec_android_mediacodec_java.h"
  30. static JavaVM *g_jvm;
  31. static pthread_key_t g_thread_key;
  32. static pthread_once_t g_key_once = PTHREAD_ONCE_INIT;
  33. JavaVM *SDL_JNI_GetJvm()
  34. {
  35. return g_jvm;
  36. }
  37. static void SDL_JNI_ThreadDestroyed(void* value)
  38. {
  39. JNIEnv *env = (JNIEnv*) value;
  40. if (env != NULL) {
  41. ALOGE("%s: [%d] didn't call SDL_JNI_DetachThreadEnv() explicity\n", __func__, (int)gettid());
  42. (*g_jvm)->DetachCurrentThread(g_jvm);
  43. pthread_setspecific(g_thread_key, NULL);
  44. }
  45. }
  46. static void make_thread_key()
  47. {
  48. pthread_key_create(&g_thread_key, SDL_JNI_ThreadDestroyed);
  49. }
  50. jint SDL_JNI_SetupThreadEnv(JNIEnv **p_env)
  51. {
  52. JavaVM *jvm = g_jvm;
  53. if (!jvm) {
  54. ALOGE("SDL_JNI_GetJvm: AttachCurrentThread: NULL jvm");
  55. return -1;
  56. }
  57. pthread_once(&g_key_once, make_thread_key);
  58. JNIEnv *env = (JNIEnv*) pthread_getspecific(g_thread_key);
  59. if (env) {
  60. *p_env = env;
  61. return 0;
  62. }
  63. if ((*jvm)->AttachCurrentThread(jvm, &env, NULL) == JNI_OK) {
  64. pthread_setspecific(g_thread_key, env);
  65. *p_env = env;
  66. return 0;
  67. }
  68. return -1;
  69. }
  70. void SDL_JNI_DetachThreadEnv()
  71. {
  72. JavaVM *jvm = g_jvm;
  73. ALOGI("%s: [%d]\n", __func__, (int)gettid());
  74. pthread_once(&g_key_once, make_thread_key);
  75. JNIEnv *env = pthread_getspecific(g_thread_key);
  76. if (!env)
  77. return;
  78. pthread_setspecific(g_thread_key, NULL);
  79. if ((*jvm)->DetachCurrentThread(jvm) == JNI_OK)
  80. return;
  81. return;
  82. }
  83. int SDL_JNI_ThrowException(JNIEnv* env, const char* className, const char* msg)
  84. {
  85. if ((*env)->ExceptionCheck(env)) {
  86. jthrowable exception = (*env)->ExceptionOccurred(env);
  87. (*env)->ExceptionClear(env);
  88. if (exception != NULL) {
  89. ALOGW("Discarding pending exception (%s) to throw", className);
  90. (*env)->DeleteLocalRef(env, exception);
  91. }
  92. }
  93. jclass exceptionClass = (*env)->FindClass(env, className);
  94. if (exceptionClass == NULL) {
  95. ALOGE("Unable to find exception class %s", className);
  96. /* ClassNotFoundException now pending */
  97. goto fail;
  98. }
  99. if ((*env)->ThrowNew(env, exceptionClass, msg) != JNI_OK) {
  100. ALOGE("Failed throwing '%s' '%s'", className, msg);
  101. /* an exception, most likely OOM, will now be pending */
  102. goto fail;
  103. }
  104. return 0;
  105. fail:
  106. if (exceptionClass)
  107. (*env)->DeleteLocalRef(env, exceptionClass);
  108. return -1;
  109. }
  110. int SDL_JNI_ThrowIllegalStateException(JNIEnv *env, const char* msg)
  111. {
  112. return SDL_JNI_ThrowException(env, "java/lang/IllegalStateException", msg);
  113. }
  114. jobject SDL_JNI_NewObjectAsGlobalRef(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
  115. {
  116. va_list args;
  117. va_start(args, methodID);
  118. jobject global_object = NULL;
  119. jobject local_object = (*env)->NewObjectV(env, clazz, methodID, args);
  120. if (!J4A_ExceptionCheck__throwAny(env) && local_object) {
  121. global_object = (*env)->NewGlobalRef(env, local_object);
  122. SDL_JNI_DeleteLocalRefP(env, &local_object);
  123. }
  124. va_end(args);
  125. return global_object;
  126. }
  127. void SDL_JNI_DeleteGlobalRefP(JNIEnv *env, jobject *obj_ptr)
  128. {
  129. if (!obj_ptr || !*obj_ptr)
  130. return;
  131. (*env)->DeleteGlobalRef(env, *obj_ptr);
  132. *obj_ptr = NULL;
  133. }
  134. void SDL_JNI_DeleteLocalRefP(JNIEnv *env, jobject *obj_ptr)
  135. {
  136. if (!obj_ptr || !*obj_ptr)
  137. return;
  138. (*env)->DeleteLocalRef(env, *obj_ptr);
  139. *obj_ptr = NULL;
  140. }
  141. int SDL_Android_GetApiLevel()
  142. {
  143. static int SDK_INT = 0;
  144. if (SDK_INT > 0)
  145. return SDK_INT;
  146. JNIEnv *env = NULL;
  147. if (JNI_OK != SDL_JNI_SetupThreadEnv(&env)) {
  148. ALOGE("SDL_Android_GetApiLevel: SetupThreadEnv failed");
  149. return 0;
  150. }
  151. SDK_INT = J4AC_android_os_Build__VERSION__SDK_INT__get__catchAll(env);
  152. ALOGI("API-Level: %d\n", SDK_INT);
  153. return SDK_INT;
  154. #if 0
  155. char value[PROP_VALUE_MAX];
  156. memset(value, 0, sizeof(value));
  157. __system_property_get("ro.build.version.sdk", value);
  158. SDK_INT = atoi(value);
  159. return SDK_INT;
  160. #endif
  161. }
  162. JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
  163. {
  164. int retval;
  165. JNIEnv* env = NULL;
  166. g_jvm = vm;
  167. if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
  168. return -1;
  169. }
  170. retval = J4A_LoadAll__catchAll(env);
  171. JNI_CHECK_RET(retval == 0, env, NULL, NULL, -1);
  172. return JNI_VERSION_1_4;
  173. }
  174. JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *jvm, void *reserved)
  175. {
  176. }