[vlc-devel] [PATCH] android: simplify/improve the attachment of a thread to the Java VM

Thomas Guillem thomas at gllm.fr
Thu Apr 2 10:59:58 CEST 2015


There is now only one way to get a JNIEnv: jni_get_env. This function use the
thread-specific data (TSD) areas to save a JNIEnv into a TSD key. The thread
will be automatically detached to the Java VM when it's canceled or exited.
---
 modules/audio_output/audiotrack.c             | 23 ++++++-----------------
 modules/codec/omxil/android_mediacodec.c      | 26 +++++++++++---------------
 modules/codec/omxil/omxil.c                   |  8 +++-----
 modules/video_output/android/android_window.c |  7 ++-----
 modules/video_output/android/nativewindow.c   |  7 +++----
 modules/video_output/android/surface.c        |  3 ---
 6 files changed, 25 insertions(+), 49 deletions(-)

diff --git a/modules/audio_output/audiotrack.c b/modules/audio_output/audiotrack.c
index 1471793..813fd6b 100644
--- a/modules/audio_output/audiotrack.c
+++ b/modules/audio_output/audiotrack.c
@@ -149,10 +149,7 @@ struct thread_cmd
 };
 
 #define THREAD_NAME "android_audiotrack"
-
-extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
-extern void jni_detach_thread();
-extern int jni_get_env(JNIEnv **env);
+extern JNIEnv *jni_get_env(const char *name);
 
 static struct
 {
@@ -220,7 +217,7 @@ InitJNIFields( audio_output_t *p_aout )
 {
     static vlc_mutex_t lock = VLC_STATIC_MUTEX;
     static int i_init_state = -1;
-    bool ret, b_attached = false;
+    bool ret;
     jclass clazz;
     jfieldID field;
     JNIEnv* env = NULL;
@@ -230,15 +227,10 @@ InitJNIFields( audio_output_t *p_aout )
     if( i_init_state != -1 )
         goto end;
 
-    if( jni_get_env(&env) < 0 )
+    if (!(env = jni_get_env(THREAD_NAME)))
     {
-        jni_attach_thread( &env, THREAD_NAME );
-        if( !env )
-        {
-            i_init_state = 0;
-            goto end;
-        }
-        b_attached = true;
+        i_init_state = 0;
+        goto end;
     }
 
 #define CHECK_EXCEPTION( what, critical ) do { \
@@ -378,8 +370,6 @@ end:
     ret = i_init_state == 1;
     if( !ret )
         msg_Err( p_aout, "AudioTrack jni init failed" );
-    if( b_attached )
-        jni_detach_thread();
     vlc_mutex_unlock( &lock );
     return ret;
 }
@@ -1264,7 +1254,7 @@ JNIThread( void *data )
     mtime_t i_play_deadline = 0;
     JNIEnv* env;
 
-    jni_attach_thread( &env, THREAD_NAME );
+    env = jni_get_env(THREAD_NAME);
 
     vlc_mutex_lock( &p_sys->mutex );
     if( !env )
@@ -1420,7 +1410,6 @@ end:
             (*env)->DeleteGlobalRef( env, p_sys->p_floatarray );
         if( p_sys->p_bytebuffer )
             (*env)->DeleteGlobalRef( env, p_sys->p_bytebuffer );
-        jni_detach_thread();
     }
     vlc_mutex_unlock( &p_sys->mutex );
     return NULL;
diff --git a/modules/codec/omxil/android_mediacodec.c b/modules/codec/omxil/android_mediacodec.c
index be2e196..d9058d3 100644
--- a/modules/codec/omxil/android_mediacodec.c
+++ b/modules/codec/omxil/android_mediacodec.c
@@ -49,9 +49,8 @@
 #define INFO_TRY_AGAIN_LATER        -1
 
 #define THREAD_NAME "android_mediacodec"
+extern JNIEnv *jni_get_env(const char *name);
 
-extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
-extern void jni_detach_thread();
 /* JNI functions to get/set an Android Surface object. */
 extern jobject jni_LockAndGetAndroidJavaSurface();
 extern void jni_UnlockAndroidSurface();
@@ -372,7 +371,8 @@ static int OpenDecoder(vlc_object_t *p_this)
     p_dec->b_need_packetized = true;
 
     JNIEnv* env = NULL;
-    jni_attach_thread(&env, THREAD_NAME);
+    if (!(env = jni_get_env(THREAD_NAME)))
+        goto error;
 
     for (int i = 0; classes[i].name; i++) {
         *(jclass*)((uint8_t*)p_sys + classes[i].offset) =
@@ -651,8 +651,6 @@ loopclean:
     p_sys->buffer_info = (*env)->NewGlobalRef(env, p_sys->buffer_info);
     (*env)->DeleteLocalRef(env, format);
 
-    jni_detach_thread();
-
     const int timestamp_fifo_size = 32;
     p_sys->timestamp_fifo = timestamp_FifoNew(timestamp_fifo_size);
     if (!p_sys->timestamp_fifo)
@@ -661,7 +659,6 @@ loopclean:
     return VLC_SUCCESS;
 
  error:
-    jni_detach_thread();
     CloseDecoder(p_this);
     return VLC_EGENERIC;
 }
@@ -679,7 +676,10 @@ 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);
-    jni_attach_thread(&env, THREAD_NAME);
+
+    if (!(env = jni_get_env(THREAD_NAME)))
+        goto cleanup;
+
     if (p_sys->input_buffers)
         (*env)->DeleteGlobalRef(env, p_sys->input_buffers);
     if (p_sys->output_buffers)
@@ -701,8 +701,8 @@ static void CloseDecoder(vlc_object_t *p_this)
     }
     if (p_sys->buffer_info)
         (*env)->DeleteGlobalRef(env, p_sys->buffer_info);
-    jni_detach_thread();
 
+cleanup:
     free(p_sys->name);
     ArchitectureSpecificCopyHooksDestroy(p_sys->pixel_format, &p_sys->architecture_specific_data);
     free(p_sys->pp_inflight_pictures);
@@ -752,9 +752,8 @@ static void UnlockPicture(picture_t* p_pic, bool b_render)
 
     /* Release the MediaCodec buffer. */
     JNIEnv *env = NULL;
-    jni_attach_thread(&env, THREAD_NAME);
-    ReleaseOutputBuffer(p_dec, env, i_index, b_render);
-    jni_detach_thread();
+    if ((env = jni_get_env(THREAD_NAME)))
+        ReleaseOutputBuffer(p_dec, env, i_index, b_render);
     p_picsys->priv.hw.b_valid = false;
 
     vlc_mutex_unlock(get_android_opaque_mutex());
@@ -1020,8 +1019,7 @@ static picture_t *DecodeVideo(decoder_t *p_dec, block_t **pp_block)
     if (p_sys->error_state)
         goto endclean;
 
-    jni_attach_thread(&env, THREAD_NAME);
-    if (!env)
+    if (!(env = jni_get_env(THREAD_NAME)))
         goto endclean;
 
     if ((*pp_block)->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) {
@@ -1115,8 +1113,6 @@ endclean:
             p_sys->error_event_sent = true;
         }
     }
-    if (env != NULL)
-        jni_detach_thread();
 
     return p_pic;
 }
diff --git a/modules/codec/omxil/omxil.c b/modules/codec/omxil/omxil.c
index 06244bc..9211f76 100644
--- a/modules/codec/omxil/omxil.c
+++ b/modules/codec/omxil/omxil.c
@@ -68,8 +68,7 @@
 #if defined(USE_IOMX)
 /* JNI functions to get/set an Android Surface object. */
 #define THREAD_NAME "omxil"
-extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
-extern void jni_detach_thread();
+extern JNIEnv *jni_get_env(const char *name);
 extern jobject jni_LockAndGetAndroidJavaSurface();
 extern void jni_UnlockAndroidSurface();
 extern bool jni_IsVideoPlayerActivityCreated();
@@ -2096,9 +2095,8 @@ static void HwBuffer_Init( decoder_t *p_dec, OmxPort *p_port )
         goto error;
     }
 
-    jni_attach_thread( &p_env, THREAD_NAME );
-    p_port->p_hwbuf->window = p_port->p_hwbuf->native_window.winFromSurface( p_env, surf );
-    jni_detach_thread();
+    if ((p_env = jni_get_env(THREAD_NAME)))
+        p_port->p_hwbuf->window = p_port->p_hwbuf->native_window.winFromSurface( p_env, surf );
 
     jni_UnlockAndroidSurface();
     if( !p_port->p_hwbuf->window ) {
diff --git a/modules/video_output/android/android_window.c b/modules/video_output/android/android_window.c
index 600f450..6d4f16a 100644
--- a/modules/video_output/android/android_window.c
+++ b/modules/video_output/android/android_window.c
@@ -66,8 +66,7 @@ vlc_module_end()
  *****************************************************************************/
 
 #define THREAD_NAME "android_window"
-extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
-extern void jni_detach_thread();
+extern JNIEnv *jni_get_env(const char *name);
 
 extern jobject jni_LockAndGetAndroidJavaSurface();
 extern jobject jni_LockAndGetSubtitlesSurface();
@@ -368,11 +367,9 @@ static int AndroidWindow_SetSurface(vout_display_sys_t *sys,
     if (!p_window->p_handle && !p_window->b_opaque) {
         JNIEnv *p_env;
 
-        jni_attach_thread(&p_env, THREAD_NAME);
-        if (!p_env)
+        if (!(p_env = jni_get_env(THREAD_NAME)))
             return -1;
         p_window->p_handle = sys->anw.winFromSurface(p_env, p_window->jsurf);
-        jni_detach_thread();
         if (!p_window->p_handle)
             return -1;
     }
diff --git a/modules/video_output/android/nativewindow.c b/modules/video_output/android/nativewindow.c
index 98c03fa..ac8d62c 100644
--- a/modules/video_output/android/nativewindow.c
+++ b/modules/video_output/android/nativewindow.c
@@ -38,8 +38,7 @@
 #include "utils.h"
 
 #define THREAD_NAME "ANativeWindow"
-extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
-extern void jni_detach_thread();
+extern JNIEnv *jni_get_env(const char *name);
 extern jobject jni_LockAndGetAndroidJavaSurface();
 extern void jni_UnlockAndroidSurface();
 extern void  jni_SetSurfaceLayout(int width, int height, int visible_width, int visible_height, int sar_num, int sar_den);
@@ -95,9 +94,9 @@ static int Open(vout_window_t *wnd, const vout_window_cfg_t *cfg)
         goto error;
 
     JNIEnv *p_env;
-    jni_attach_thread(&p_env, THREAD_NAME);
+    if (!(p_env = jni_get_env(THREAD_NAME)))
+        goto error;
     p_sys->window = p_sys->native_window.winFromSurface(p_env, javaSurface); // ANativeWindow_fromSurface call.
-    jni_detach_thread();
 
     jni_UnlockAndroidSurface();
 
diff --git a/modules/video_output/android/surface.c b/modules/video_output/android/surface.c
index afd748a..15e1f54 100644
--- a/modules/video_output/android/surface.c
+++ b/modules/video_output/android/surface.c
@@ -73,9 +73,6 @@ vlc_module_end()
  * JNI prototypes
  *****************************************************************************/
 
-#define THREAD_NAME "AndroidSurface"
-extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
-extern void jni_detach_thread();
 extern jobject jni_LockAndGetAndroidJavaSurface();
 extern void  jni_UnlockAndroidSurface();
 extern void *jni_AndroidJavaSurfaceToNativeSurface(jobject surf);
-- 
2.1.3




More information about the vlc-devel mailing list