[vlc-devel] [PATCH] Support for mulitple player instances

Paulo Vitor Magacho da Silva pvmagacho at gmail.com
Sun Jul 27 20:43:40 CEST 2014


---
 include/vlc/libvlc_media_player.h           | 17 +++++++++++
 lib/media_player.c                          | 30 +++++++++++++++++++
 modules/video_output/android/nativewindow.c | 24 ++++++++++-----
 modules/video_output/android/surface.c      | 45 ++++++++++++++---------------
 modules/video_output/android/utils.h        | 10 +++++++
 src/libvlc.c                                |  3 ++
 6 files changed, 98 insertions(+), 31 deletions(-)

diff --git a/include/vlc/libvlc_media_player.h b/include/vlc/libvlc_media_player.h
index 4b2f449..335e543 100644
--- a/include/vlc/libvlc_media_player.h
+++ b/include/vlc/libvlc_media_player.h
@@ -437,6 +437,23 @@ LIBVLC_API void libvlc_media_player_set_nsobject ( libvlc_media_player_t *p_mi,
 LIBVLC_API void * libvlc_media_player_get_nsobject ( libvlc_media_player_t *p_mi );
 
 /**
+ * Set the android_surface_value_t structure handler holding the Android surface information where
+ * the media player should render its video output.
+ *
+ * \param p_mi the Media Player
+ * \param object the android_surface_value_t structure to set.
+ */
+LIBVLC_API void libvlc_media_player_set_surfacevalue ( libvlc_media_player_t *p_mi, void * object );
+
+/**
+ * Gets a handler to the android_surface_value_t structure holding Android Surface object information.
+ *
+ * \param p_mi the Media Player
+ * \return the android_surface_value_t pointer or 0 if none where set
+ */
+LIBVLC_API void * libvlc_media_player_get_surfacevalue ( libvlc_media_player_t *p_mi );
+
+/**
  * Set the agl handler where the media player should render its video output.
  *
  * \param p_mi the Media Player
diff --git a/lib/media_player.c b/lib/media_player.c
index b31a832..ae1c211 100644
--- a/lib/media_player.c
+++ b/lib/media_player.c
@@ -422,6 +422,9 @@ libvlc_media_player_new( libvlc_instance_t *instance )
     var_Create (mp, "drawable-agl", VLC_VAR_INTEGER);
     var_Create (mp, "drawable-nsobject", VLC_VAR_ADDRESS);
 #endif
+#ifdef __ANDROID__
+    var_Create (mp, "drawable-surfacevalue", VLC_VAR_ADDRESS);
+#endif
 
     var_Create (mp, "keyboard-events", VLC_VAR_BOOL);
     var_SetBool (mp, "keyboard-events", true);
@@ -901,6 +904,33 @@ void * libvlc_media_player_get_nsobject( libvlc_media_player_t *p_mi )
 }
 
 /**************************************************************************
+ * set_surfacevalue
+ **************************************************************************/
+void libvlc_media_player_set_surfacevalue( libvlc_media_player_t *p_mi,
+                                           void * object )
+{
+    assert (p_mi != NULL);
+#ifdef __ANDROID__
+    var_SetAddress (p_mi, "drawable-surfacevalue", object);
+#else
+    (void) p_mi; (void)object;
+#endif
+}
+
+/**************************************************************************
+ * get_surfacevalue
+ **************************************************************************/
+void * libvlc_media_player_get_surfacevalue( libvlc_media_player_t *p_mi )
+{
+    assert (p_mi != NULL);
+#ifdef __ANDROID__
+    return var_GetAddress (p_mi, "drawable-surfacevalue");
+#else
+    return NULL;
+#endif
+}
+
+/**************************************************************************
  * set_agl
  **************************************************************************/
 void libvlc_media_player_set_agl( libvlc_media_player_t *p_mi,
diff --git a/modules/video_output/android/nativewindow.c b/modules/video_output/android/nativewindow.c
index 29014b5..18ca932 100644
--- a/modules/video_output/android/nativewindow.c
+++ b/modules/video_output/android/nativewindow.c
@@ -38,9 +38,9 @@
 #include "utils.h"
 
 extern JavaVM *myVm;
-extern jobject jni_LockAndGetAndroidJavaSurface();
-extern void jni_UnlockAndroidSurface();
-extern void  jni_SetAndroidSurfaceSize(int width, int height, int visible_width, int visible_height, int sar_num, int sar_den);
+extern jobject jni_LockAndGetAndroidJavaSurface(android_surf_value_t *android_surface);
+extern void jni_UnlockAndroidSurface(android_surf_value_t *android_surface);
+extern void  jni_SetAndroidSurfaceSize(android_surf_value_t *android_surface, int width, int height, int visible_width, int visible_height, int sar_num, int sar_den);
 
 static int Open(vout_window_t *, const vout_window_cfg_t *);
 static void Close(vout_window_t *);
@@ -65,6 +65,8 @@ struct vout_window_sys_t
     native_window_api_t native_window;
 
     ANativeWindow *window;
+
+    android_surf_value_t *android_surface;
 };
 
 /**
@@ -83,8 +85,15 @@ static int Open(vout_window_t *wnd, const vout_window_cfg_t *cfg)
         return VLC_EGENERIC;
     }
 
+    p_sys->android_surface = var_CreateGetAddress (wnd, "drawable-surfacevalue");
+    if (!p_sys->android_surface) {
+        free(p_sys);
+        msg_Err(wnd, "No android surface set.");
+        return VLC_EGENERIC;
+    }
+
     // Create the native window by first getting the Java surface.
-    jobject javaSurface = jni_LockAndGetAndroidJavaSurface();
+    jobject javaSurface = jni_LockAndGetAndroidJavaSurface(p_sys->android_surface);
     if (javaSurface == NULL)
         goto error;
 
@@ -93,7 +102,7 @@ static int Open(vout_window_t *wnd, const vout_window_cfg_t *cfg)
     p_sys->window = p_sys->native_window.winFromSurface(p_env, javaSurface); // ANativeWindow_fromSurface call.
     (*myVm)->DetachCurrentThread(myVm);
 
-    jni_UnlockAndroidSurface();
+    jni_UnlockAndroidSurface(p_sys->android_surface);
 
     if (p_sys->window == NULL)
         goto error;
@@ -103,7 +112,7 @@ static int Open(vout_window_t *wnd, const vout_window_cfg_t *cfg)
     wnd->sys = p_sys;
 
     // Set the Java surface size.
-    jni_SetAndroidSurfaceSize(cfg->width, cfg->height, cfg->width, cfg->height, 1, 1);
+    jni_SetAndroidSurfaceSize(p_sys->android_surface, cfg->width, cfg->height, cfg->width, cfg->height, 1, 1);
 
     return VLC_SUCCESS;
 
@@ -131,13 +140,14 @@ static void Close(vout_window_t *wnd)
  */
 static int Control(vout_window_t *wnd, int cmd, va_list ap)
 {
+    vout_window_sys_t *p_sys = wnd->sys;
     switch (cmd)
     {
         case VOUT_WINDOW_SET_SIZE:
         {
             unsigned width = va_arg(ap, unsigned);
             unsigned height = va_arg(ap, unsigned);
-            jni_SetAndroidSurfaceSize(width, height, width, height, 1, 1);
+            jni_SetAndroidSurfaceSize(p_sys->android_surface, width, height, width, height, 1, 1);
             break;
         }
         case VOUT_WINDOW_SET_STATE:
diff --git a/modules/video_output/android/surface.c b/modules/video_output/android/surface.c
index f6a183e..bd344cb 100644
--- a/modules/video_output/android/surface.c
+++ b/modules/video_output/android/surface.c
@@ -74,10 +74,10 @@ vlc_module_end()
  *****************************************************************************/
 
 extern JavaVM *myVm;
-extern void *jni_LockAndGetAndroidSurface();
-extern jobject jni_LockAndGetAndroidJavaSurface();
-extern void  jni_UnlockAndroidSurface();
-extern void  jni_SetAndroidSurfaceSize(int width, int height, int visible_width, int visible_height, int sar_num, int sar_den);
+extern void *jni_LockAndGetAndroidSurface(android_surf_value_t *android_surface);
+extern jobject jni_LockAndGetAndroidJavaSurface(android_surf_value_t *android_surface);
+extern void  jni_UnlockAndroidSurface(android_surf_value_t *android_surface);
+extern void  jni_SetAndroidSurfaceSize(android_surf_value_t *android_surface, int width, int height, int visible_width, int visible_height, int sar_num, int sar_den);
 
 // _ZN7android7Surface4lockEPNS0_11SurfaceInfoEb
 typedef void (*Surface_lock)(void *, void *, int);
@@ -123,6 +123,8 @@ struct vout_display_sys_t {
 
     video_format_t fmt;
     bool b_changed_crop;
+
+    android_surf_value_t *android_surface;
 };
 
 struct picture_sys_t {
@@ -134,8 +136,6 @@ struct picture_sys_t {
 static int  AndroidLockSurface(picture_t *);
 static void AndroidUnlockSurface(picture_t *);
 
-static vlc_mutex_t single_instance = VLC_STATIC_MUTEX;
-
 static inline void *LoadSurface(const char *psz_lib, vout_display_sys_t *sys)
 {
     void *p_library = dlopen(psz_lib, RTLD_NOW);
@@ -178,19 +178,19 @@ static int Open(vlc_object_t *p_this)
     if (fmt.i_chroma == VLC_CODEC_ANDROID_OPAQUE)
         return VLC_EGENERIC;
 
-    /* */
-    if (vlc_mutex_trylock(&single_instance) != 0) {
-        msg_Err(vd, "Can't start more than one instance at a time");
-        return VLC_EGENERIC;
-    }
-
     /* Allocate structure */
     vout_display_sys_t *sys = (struct vout_display_sys_t*) calloc(1, sizeof(*sys));
     if (!sys) {
-        vlc_mutex_unlock(&single_instance);
         return VLC_ENOMEM;
     }
 
+    sys->android_surface = var_CreateGetAddress (vd, "drawable-surfacevalue");
+    if (!sys->android_surface) {
+        free(sys);
+        msg_Err(vd, "No android surface set.");
+        return VLC_EGENERIC;
+    }
+
     /* */
     sys->p_library = LoadNativeWindowAPI(&sys->native_window);
     sys->s_unlockAndPost = (Surface_unlockAndPost)sys->native_window.unlockAndPost;
@@ -199,7 +199,6 @@ static int Open(vlc_object_t *p_this)
     if (!sys->p_library) {
         free(sys);
         msg_Err(vd, "Could not initialize libandroid.so/libui.so/libgui.so/libsurfaceflinger_client.so!");
-        vlc_mutex_unlock(&single_instance);
         return VLC_EGENERIC;
     }
 
@@ -286,7 +285,6 @@ static int Open(vlc_object_t *p_this)
 enomem:
     dlclose(sys->p_library);
     free(sys);
-    vlc_mutex_unlock(&single_instance);
     return VLC_ENOMEM;
 }
 
@@ -300,7 +298,6 @@ static void Close(vlc_object_t *p_this)
         sys->native_window.winRelease(sys->window);
     dlclose(sys->p_library);
     free(sys);
-    vlc_mutex_unlock(&single_instance);
 }
 
 static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
@@ -357,9 +354,9 @@ static int  AndroidLockSurface(picture_t *picture)
     sh = sys->fmt.i_height;
 
     if (sys->native_window.winFromSurface) {
-        jobject jsurf = jni_LockAndGetAndroidJavaSurface();
+        jobject jsurf = jni_LockAndGetAndroidJavaSurface(sys->android_surface);
         if (unlikely(!jsurf)) {
-            jni_UnlockAndroidSurface();
+            jni_UnlockAndroidSurface(sys->android_surface);
             return VLC_EGENERIC;
         }
         if (sys->window && jsurf != sys->jsurf) {
@@ -377,9 +374,9 @@ static int  AndroidLockSurface(picture_t *picture)
         // as parameter to the unlock function
         picsys->surf = surf = sys->window;
     } else {
-        picsys->surf = surf = jni_LockAndGetAndroidSurface();
+        picsys->surf = surf = jni_LockAndGetAndroidSurface(sys->android_surface);
         if (unlikely(!surf)) {
-            jni_UnlockAndroidSurface();
+            jni_UnlockAndroidSurface(sys->android_surface);
             return VLC_EGENERIC;
         }
     }
@@ -389,7 +386,7 @@ static int  AndroidLockSurface(picture_t *picture)
         ANativeWindow_Buffer buf = { 0 };
         int32_t err = sys->native_window.winLock(sys->window, &buf, NULL);
         if (err) {
-            jni_UnlockAndroidSurface();
+            jni_UnlockAndroidSurface(sys->android_surface);
             return VLC_EGENERIC;
         }
         info->w      = buf.width;
@@ -408,12 +405,12 @@ static int  AndroidLockSurface(picture_t *picture)
 
     if (info->w != aligned_width || info->h != sh || sys->b_changed_crop) {
         // input size doesn't match the surface size -> request a resize
-        jni_SetAndroidSurfaceSize(aligned_width, sh, sys->fmt.i_visible_width, sys->fmt.i_visible_height, sys->i_sar_num, sys->i_sar_den);
+        jni_SetAndroidSurfaceSize(sys->android_surface, aligned_width, sh, sys->fmt.i_visible_width, sys->fmt.i_visible_height, sys->i_sar_num, sys->i_sar_den);
         // When using ANativeWindow, one should use ANativeWindow_setBuffersGeometry
         // to set the size and format. In our case, these are set via the SurfaceHolder
         // in Java, so we seem to manage without calling this ANativeWindow function.
         sys->s_unlockAndPost(surf);
-        jni_UnlockAndroidSurface();
+        jni_UnlockAndroidSurface(sys->android_surface);
         sys->b_changed_crop = false;
         return VLC_EGENERIC;
     }
@@ -435,7 +432,7 @@ static void AndroidUnlockSurface(picture_t *picture)
 
     if (likely(picsys->surf))
         sys->s_unlockAndPost(picsys->surf);
-    jni_UnlockAndroidSurface();
+    jni_UnlockAndroidSurface(sys->android_surface);
 }
 
 static void Display(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture)
diff --git a/modules/video_output/android/utils.h b/modules/video_output/android/utils.h
index 9a72df6..f55416f 100644
--- a/modules/video_output/android/utils.h
+++ b/modules/video_output/android/utils.h
@@ -36,6 +36,16 @@ typedef void (*ptr_ANativeWindow_release)(ANativeWindow*);
 typedef int32_t (*ptr_ANativeWindow_lock)(ANativeWindow*, ANativeWindow_Buffer*, ARect*);
 typedef void (*ptr_ANativeWindow_unlockAndPost)(ANativeWindow*);
 
+typedef struct android_surf_value_t {
+    pthread_mutex_t vout_android_lock;
+    pthread_cond_t vout_android_surf_attached;
+    void *vout_android_surf;
+    void *vout_android_gui;
+    jobject vout_android_java_surf;
+    jobject vout_android_subtitles_surf;
+    bool vout_video_player_activity_created;
+} android_surf_value_t;
+
 typedef struct
 {
     ptr_ANativeWindow_fromSurface winFromSurface;
diff --git a/src/libvlc.c b/src/libvlc.c
index 946ce2e..676131d 100644
--- a/src/libvlc.c
+++ b/src/libvlc.c
@@ -485,6 +485,9 @@ dbus_out:
     var_Create( p_libvlc, "drawable-clip-right", VLC_VAR_INTEGER );
     var_Create( p_libvlc, "drawable-nsobject", VLC_VAR_ADDRESS );
 #endif
+#ifdef __ANDROID__
+    var_Create( p_libvlc, "drawable-surfacevalue", VLC_VAR_ADDRESS);
+#endif
 #if defined (_WIN32) || defined (__OS2__)
     var_Create( p_libvlc, "drawable-hwnd", VLC_VAR_INTEGER );
 #endif
-- 
1.8.5.2 (Apple Git-48)




More information about the vlc-devel mailing list