[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