[Android] [PATCH] MediaCodec: simplify jni thread attach/detach

Zhang Rui bbcallen at gmail.com
Mon Feb 10 17:18:56 CET 2014


Avoid repeatly AttachCurrentThread()/DetachCurrentThread()
---
 modules/codec/omxil/android_mediacodec.c | 57 +++++++++++++++++++++++++-------
 1 file changed, 45 insertions(+), 12 deletions(-)

diff --git a/modules/codec/omxil/android_mediacodec.c b/modules/codec/omxil/android_mediacodec.c
index bf53e76..59846cc 100644
--- a/modules/codec/omxil/android_mediacodec.c
+++ b/modules/codec/omxil/android_mediacodec.c
@@ -201,6 +201,47 @@ static int jstrcmp(JNIEnv* env, jobject str, const char* str2)
     return ret;
 }
 
+static pthread_key_t g_thread_key;
+static pthread_once_t g_key_once = PTHREAD_ONCE_INIT;
+static JavaVMAttachArgs g_vlc_thr_args = {JNI_VERSION_1_2, "MediaCodec", NULL};
+
+static void VlcJniThreadDestroy(void* value)
+{
+    JNIEnv *env = (JNIEnv*) value;
+    if (env != NULL) {
+        (*myVm)->DetachCurrentThread(myVm);
+        pthread_setspecific(g_thread_key, NULL);
+    }
+}
+
+static void VlcMakeThreadKey()
+{
+    pthread_key_create(&g_thread_key, VlcJniThreadDestroy);
+}
+
+jint VlcSetupThreadEnv(JNIEnv **p_env)
+{
+    JavaVM *jvm = myVm;
+    if (!jvm)
+        return -1;
+
+    pthread_once(&g_key_once, VlcMakeThreadKey);
+
+    JNIEnv *env = (JNIEnv*) pthread_getspecific(g_thread_key);
+    if (env) {
+        *p_env = env;
+        return 0;
+    }
+
+    if ((*jvm)->AttachCurrentThread(jvm, &env, &g_vlc_thr_args) == JNI_OK) {
+        pthread_setspecific(g_thread_key, env);
+        *p_env = env;
+        return 0;
+    }
+
+    return -1;
+}
+
 /*****************************************************************************
  * OpenDecoder: Create the decoder instance
  *****************************************************************************/
@@ -246,7 +287,7 @@ static int OpenDecoder(vlc_object_t *p_this)
     p_dec->b_need_packetized = true;
 
     JNIEnv* env = NULL;
-    (*myVm)->AttachCurrentThread(myVm, &env, NULL);
+    VlcSetupThreadEnv(&env);
 
     for (int i = 0; classes[i].name; i++) {
         *(jclass*)((uint8_t*)p_sys + classes[i].offset) =
@@ -413,11 +454,9 @@ static int OpenDecoder(vlc_object_t *p_this)
         goto error;
     (*env)->DeleteLocalRef(env, format);
 
-    (*myVm)->DetachCurrentThread(myVm);
     return VLC_SUCCESS;
 
  error:
-    (*myVm)->DetachCurrentThread(myVm);
     CloseDecoder(p_this);
     return VLC_EGENERIC;
 }
@@ -435,7 +474,7 @@ static void CloseDecoder(vlc_object_t *p_this)
      * to prevent the vout from using destroyed output buffers. */
     if (p_sys->direct_rendering)
         InvalidateAllPictures(p_dec);
-    (*myVm)->AttachCurrentThread(myVm, &env, NULL);
+    VlcSetupThreadEnv(&env);
     if (p_sys->input_buffers)
         (*env)->DeleteGlobalRef(env, p_sys->input_buffers);
     if (p_sys->output_buffers)
@@ -448,7 +487,6 @@ static void CloseDecoder(vlc_object_t *p_this)
     }
     if (p_sys->buffer_info)
         (*env)->DeleteGlobalRef(env, p_sys->buffer_info);
-    (*myVm)->DetachCurrentThread(myVm);
 
     free(p_sys->name);
     ArchitectureSpecificCopyHooksDestroy(p_sys->pixel_format, &p_sys->architecture_specific_data);
@@ -481,14 +519,13 @@ static void DisplayBuffer(picture_sys_t* p_picsys, bool b_render)
 
     /* Release the MediaCodec buffer. */
     JNIEnv *env = NULL;
-    (*myVm)->AttachCurrentThread(myVm, &env, NULL);
+    VlcSetupThreadEnv(&env);
     (*env)->CallVoidMethod(env, p_sys->codec, p_sys->release_output_buffer, i_index, b_render);
     if ((*env)->ExceptionOccurred(env)) {
         msg_Err(p_dec, "Exception in MediaCodec.releaseOutputBuffer (DisplayBuffer)");
         (*env)->ExceptionClear(env);
     }
 
-    (*myVm)->DetachCurrentThread(myVm);
     p_picsys->b_valid = false;
 
     vlc_mutex_unlock(get_android_opaque_mutex());
@@ -686,7 +723,7 @@ static picture_t *DecodeVideo(decoder_t *p_dec, block_t **pp_block)
 
     block_t *p_block = *pp_block;
 
-    (*myVm)->AttachCurrentThread(myVm, &env, NULL);
+    VlcSetupThreadEnv(&env);
 
     if (p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) {
         block_Release(p_block);
@@ -704,7 +741,6 @@ static picture_t *DecodeVideo(decoder_t *p_dec, block_t **pp_block)
             }
         }
         p_sys->decoded = false;
-        (*myVm)->DetachCurrentThread(myVm);
         return NULL;
     }
 
@@ -730,7 +766,6 @@ static picture_t *DecodeVideo(decoder_t *p_dec, block_t **pp_block)
                  * without assigning NULL to *pp_block. The next call
                  * to DecodeVideo will try to send the input packet again.
                  */
-                (*myVm)->DetachCurrentThread(myVm);
                 return p_pic;
             }
             timeout = 30*1000;
@@ -756,7 +791,6 @@ static picture_t *DecodeVideo(decoder_t *p_dec, block_t **pp_block)
                     block_Release(p_block);
                     *pp_block = NULL;
                 }
-                (*myVm)->DetachCurrentThread(myVm);
                 return invalid_picture;
             }
             continue;
@@ -780,7 +814,6 @@ static picture_t *DecodeVideo(decoder_t *p_dec, block_t **pp_block)
     }
     if (!p_pic)
         GetOutput(p_dec, env, &p_pic);
-    (*myVm)->DetachCurrentThread(myVm);
 
     block_Release(p_block);
     *pp_block = NULL;
-- 
1.8.3.4



More information about the Android mailing list