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

edward.c.wang at compdigitec.com edward.c.wang at compdigitec.com
Mon Feb 10 18:41:25 CET 2014




Zhang Rui <bbcallen at gmail.com> a écrit :
>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;


I would prefer the style vlcjni_thread_destroy over VlcJniThreadDestroy, but otherwise it looks OK.



Regards,
    Edward Wang


More information about the Android mailing list