[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