[Android] [PATCH 4/5] Support multiple video player instances.

Paulo Vitor Magacho da Silva pvmagacho at gmail.com
Fri Jul 25 04:14:32 CEST 2014


---
 vlc-android/jni/libvlcjni.c                        |  39 ++++--
 vlc-android/jni/utils.h                            |  12 ++
 vlc-android/jni/vout.c                             | 135 +++++++++++----------
 vlc-android/jni/vout.h                             |   4 -
 vlc-android/src/org/videolan/libvlc/LibVLC.java    |  33 +++--
 vlc-android/src/org/videolan/libvlc/MediaList.java |   2 +-
 .../org/videolan/vlc/gui/PreferencesActivity.java  |   2 +-
 7 files changed, 139 insertions(+), 88 deletions(-)

diff --git a/vlc-android/jni/libvlcjni.c b/vlc-android/jni/libvlcjni.c
index 6a08d85..1f11b20 100644
--- a/vlc-android/jni/libvlcjni.c
+++ b/vlc-android/jni/libvlcjni.c
@@ -200,16 +200,12 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved)
     // Keep a reference on the Java VM.
     myVm = vm;
 
-    pthread_mutex_init(&vout_android_lock, NULL);
-    pthread_cond_init(&vout_android_surf_attached, NULL);
-
     LOGD("JNI interface loaded.");
     return JNI_VERSION_1_2;
 }
 
 void JNI_OnUnload(JavaVM* vm, void* reserved) {
-    pthread_mutex_destroy(&vout_android_lock);
-    pthread_cond_destroy(&vout_android_surf_attached);
+    LOGD("JNI interface un-loaded.");
 }
 
 // FIXME: use atomics
@@ -217,6 +213,18 @@ static bool verbosity;
 
 void Java_org_videolan_libvlc_LibVLC_nativeInit(JNIEnv *env, jobject thiz)
 {
+    android_surf_value_t *object = (android_surf_value_t *) malloc(sizeof(android_surf_value_t));
+
+    object->vout_android_surf = NULL;
+    object->vout_android_gui = NULL;
+    object->vout_android_java_surf = NULL;
+    object->vout_android_subtitles_surf = NULL;
+
+    pthread_mutex_init(&object->vout_android_lock, NULL);
+    pthread_cond_init(&object->vout_android_surf_attached, NULL);
+
+    setLong(env, thiz, "mAndroidSurfaceValue", (jlong)(intptr_t)object);
+
     //only use OpenSLES if java side says we can
     jclass cls = (*env)->GetObjectClass(env, thiz);
     jmethodID methodId = (*env)->GetMethodID(env, cls, "getAout", "()I");
@@ -318,12 +326,23 @@ void Java_org_videolan_libvlc_LibVLC_nativeInit(JNIEnv *env, jobject thiz)
 
     libvlc_log_set(instance, debug_log, &verbosity);
 
-    init_native_crash_handler(env, thiz);
+    // init_native_crash_handler(env, thiz);
 }
 
 void Java_org_videolan_libvlc_LibVLC_nativeDestroy(JNIEnv *env, jobject thiz)
 {
-    destroy_native_crash_handler(env);
+    // clear surface lock and condition
+    android_surf_value_t *object = (android_surf_value_t *)(intptr_t)getLong(env, thiz, "mAndroidSurfaceValue");
+
+    if (object != NULL) {
+        pthread_mutex_destroy(&object->vout_android_lock);
+        pthread_cond_destroy(&object->vout_android_surf_attached);
+
+        free(object);
+    }
+    setLong(env, thiz, "mAndroidSurfaceValue", 0);
+
+    // destroy_native_crash_handler(env);
 
     releaseMediaPlayer(env, thiz);
     jlong libVlcInstance = getLong(env, thiz, "mLibVlcInstance");
@@ -413,9 +432,13 @@ void Java_org_videolan_libvlc_LibVLC_playMRL(JNIEnv *env, jobject thiz, jlong in
             (*env)->ReleaseStringUTFChars(env, option, p_st);
         }
     }
-
+
     (*env)->ReleaseStringUTFChars(env, mrl, p_mrl);
 
+    // set the Android surface value structure
+    android_surf_value_t *object = (android_surf_value_t *)(intptr_t)getLong(env, thiz, "mAndroidSurfaceValue");
+    libvlc_media_player_set_surfacevalue(mp, object);
+
     /* Connect the media event manager. */
     libvlc_event_manager_t *ev_media = libvlc_media_event_manager(p_md);
     static const libvlc_event_type_t mp_media_events[] = {
diff --git a/vlc-android/jni/utils.h b/vlc-android/jni/utils.h
index f8502d9..ccf23aa 100644
--- a/vlc-android/jni/utils.h
+++ b/vlc-android/jni/utils.h
@@ -21,6 +21,18 @@
 #ifndef LIBVLCJNI_UTILS_H
 #define LIBVLCJNI_UTILS_H
 
+#include <pthread.h>
+
+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;
+
 libvlc_media_t *new_media(jlong instance, JNIEnv *env, jobject thiz, jstring fileLocation, bool noOmx, bool noVideo);
 
 libvlc_media_player_t *getMediaPlayer(JNIEnv *env, jobject thiz);
diff --git a/vlc-android/jni/vout.c b/vlc-android/jni/vout.c
index f2f4346..74e1f1e 100644
--- a/vlc-android/jni/vout.c
+++ b/vlc-android/jni/vout.c
@@ -23,96 +23,94 @@
 
 #include <jni.h>
 
+#include "utils.h"
+
 /** Unique Java VM instance, as defined in libvlcjni.c */
 extern JavaVM *myVm;
 
-pthread_mutex_t vout_android_lock;
-pthread_cond_t vout_android_surf_attached;
-static void *vout_android_surf = NULL;
-static void *vout_android_gui = NULL;
-static jobject vout_android_java_surf = NULL;
-static jobject vout_android_subtitles_surf = NULL;
-static bool vout_video_player_activity_created = false;
-
-void *jni_LockAndGetSubtitlesSurface() {
-    pthread_mutex_lock(&vout_android_lock);
-    while (vout_android_subtitles_surf == NULL)
-        pthread_cond_wait(&vout_android_surf_attached, &vout_android_lock);
-    return vout_android_subtitles_surf;
+void *jni_LockAndGetSubtitlesSurface(android_surf_value_t *object) {
+    pthread_mutex_lock(&object->vout_android_lock);
+    while (object->vout_android_subtitles_surf == NULL)
+        pthread_cond_wait(&object->vout_android_surf_attached, &object->vout_android_lock);
+    return object->vout_android_subtitles_surf;
 }
 
-void *jni_LockAndGetAndroidSurface() {
-    pthread_mutex_lock(&vout_android_lock);
-    while (vout_android_surf == NULL)
-        pthread_cond_wait(&vout_android_surf_attached, &vout_android_lock);
-    return vout_android_surf;
+void *jni_LockAndGetAndroidSurface(android_surf_value_t *object) {
+    pthread_mutex_lock(&object->vout_android_lock);
+    while (object->vout_android_surf == NULL)
+        pthread_cond_wait(&object->vout_android_surf_attached, &object->vout_android_lock);
+    return object->vout_android_surf;
 }
 
-jobject jni_LockAndGetAndroidJavaSurface() {
-    pthread_mutex_lock(&vout_android_lock);
-    while (vout_android_java_surf == NULL)
-        pthread_cond_wait(&vout_android_surf_attached, &vout_android_lock);
-    return vout_android_java_surf;
+jobject jni_LockAndGetAndroidJavaSurface(android_surf_value_t *object) {
+    pthread_mutex_lock(&object->vout_android_lock);
+    while (object->vout_android_java_surf == NULL)
+        pthread_cond_wait(&object->vout_android_surf_attached, &object->vout_android_lock);
+    return object->vout_android_java_surf;
 }
 
-void jni_UnlockAndroidSurface() {
-    pthread_mutex_unlock(&vout_android_lock);
+void jni_UnlockAndroidSurface(android_surf_value_t *object) {
+    pthread_mutex_unlock(&object->vout_android_lock);
 }
 
-void jni_EventHardwareAccelerationError()
+void jni_EventHardwareAccelerationError(android_surf_value_t *object)
 {
-    if (vout_android_gui == NULL)
+    if (object->vout_android_gui == NULL)
         return;
 
     JNIEnv *env;
     (*myVm)->AttachCurrentThread(myVm, &env, NULL);
 
-    jclass cls = (*env)->GetObjectClass(env, vout_android_gui);
+    jclass cls = (*env)->GetObjectClass(env, object->vout_android_gui);
     jmethodID methodId = (*env)->GetMethodID(env, cls, "eventHardwareAccelerationError", "()V");
-    (*env)->CallVoidMethod(env, vout_android_gui, methodId);
+    (*env)->CallVoidMethod(env, object->vout_android_gui, methodId);
 
     (*env)->DeleteLocalRef(env, cls);
     (*myVm)->DetachCurrentThread(myVm);
 }
 
-void jni_SetAndroidSurfaceSizeEnv(JNIEnv *p_env, int width, int height, int visible_width, int visible_height, int sar_num, int sar_den)
+void jni_SetAndroidSurfaceSizeEnv(JNIEnv *p_env, android_surf_value_t *object, int width, int height, int visible_width, int visible_height, int sar_num, int sar_den)
 {
-    if (vout_android_gui == NULL)
+    if (object->vout_android_gui == NULL)
         return;
 
-    jclass cls = (*p_env)->GetObjectClass (p_env, vout_android_gui);
+    jclass cls = (*p_env)->GetObjectClass (p_env, object->vout_android_gui);
     jmethodID methodId = (*p_env)->GetMethodID (p_env, cls, "setSurfaceSize", "(IIIIII)V");
 
-    (*p_env)->CallVoidMethod (p_env, vout_android_gui, methodId, width, height, visible_width, visible_height, sar_num, sar_den);
+    (*p_env)->CallVoidMethod (p_env, object->vout_android_gui, methodId, width, height, visible_width, visible_height, sar_num, sar_den);
 
     (*p_env)->DeleteLocalRef(p_env, cls);
 }
 
-void jni_SetAndroidSurfaceSize(int width, int height, int visible_width, int visible_height, int sar_num, int sar_den)
+void jni_SetAndroidSurfaceSize(android_surf_value_t *object, int width, int height, int visible_width, int visible_height, int sar_num, int sar_den)
 {
     JNIEnv *p_env;
 
     (*myVm)->AttachCurrentThread (myVm, &p_env, NULL);
-    jni_SetAndroidSurfaceSizeEnv(p_env, width, height, visible_width, visible_height, sar_num, sar_den);
+    jni_SetAndroidSurfaceSizeEnv(p_env, object, width, height, visible_width, visible_height, sar_num, sar_den);
 
     (*myVm)->DetachCurrentThread (myVm);
 }
 
-bool jni_IsVideoPlayerActivityCreated() {
-    pthread_mutex_lock(&vout_android_lock);
-    bool result = vout_video_player_activity_created;
-    pthread_mutex_unlock(&vout_android_lock);
+bool jni_IsVideoPlayerActivityCreated(android_surf_value_t *object) {
+    pthread_mutex_lock(&object->vout_android_lock);
+    bool result = object->vout_video_player_activity_created;
+    pthread_mutex_unlock(&object->vout_android_lock);
     return result;
 }
 
 void Java_org_videolan_libvlc_LibVLC_eventVideoPlayerActivityCreated(JNIEnv *env, jobject thiz, jboolean created) {
-    pthread_mutex_lock(&vout_android_lock);
-    vout_video_player_activity_created = created;
-    pthread_mutex_unlock(&vout_android_lock);
+    android_surf_value_t * object = (android_surf_value_t *)(intptr_t)getLong(env, thiz, "mAndroidSurfaceValue");
+
+    pthread_mutex_lock(&object->vout_android_lock);
+    object->vout_video_player_activity_created = created;
+    pthread_mutex_unlock(&object->vout_android_lock);
 }
 
 void Java_org_videolan_libvlc_LibVLC_attachSurface(JNIEnv *env, jobject thiz, jobject surf, jobject gui) {
-    pthread_mutex_lock(&vout_android_lock);
+    android_surf_value_t * object = (android_surf_value_t *)(intptr_t)getLong(env, thiz, "mAndroidSurfaceValue");
+
+    pthread_mutex_lock(&object->vout_android_lock);
     jclass clz;
     jfieldID fid;
 
@@ -131,39 +129,46 @@ void Java_org_videolan_libvlc_LibVLC_attachSurface(JNIEnv *env, jobject thiz, jo
             }
             fid = (*env)->GetFieldID(env, clz, "mNativeSurface", "I");
         }
-        vout_android_surf = (void*)(*env)->GetIntField(env, surf, fid);
+
+        object->vout_android_surf = (void*)(*env)->GetIntField(env, surf, fid);
         (*env)->DeleteLocalRef(env, clz);
     }
-    vout_android_gui = (*env)->NewGlobalRef(env, gui);
-    vout_android_java_surf = (*env)->NewGlobalRef(env, surf);
-    pthread_cond_signal(&vout_android_surf_attached);
-    pthread_mutex_unlock(&vout_android_lock);
+    object->vout_android_gui = (*env)->NewGlobalRef(env, gui);
+    object->vout_android_java_surf = (*env)->NewGlobalRef(env, surf);
+    pthread_cond_signal(&object->vout_android_surf_attached);
+    pthread_mutex_unlock(&object->vout_android_lock);
 }
 
 void Java_org_videolan_libvlc_LibVLC_detachSurface(JNIEnv *env, jobject thiz) {
-    pthread_mutex_lock(&vout_android_lock);
-    vout_android_surf = NULL;
-    if (vout_android_gui != NULL)
-        (*env)->DeleteGlobalRef(env, vout_android_gui);
-    if (vout_android_java_surf != NULL)
-        (*env)->DeleteGlobalRef(env, vout_android_java_surf);
-    vout_android_gui = NULL;
-    vout_android_java_surf = NULL;
-    pthread_mutex_unlock(&vout_android_lock);
+    android_surf_value_t *object = (android_surf_value_t *)(intptr_t)getLong(env, thiz, "mAndroidSurfaceValue");
+
+    pthread_mutex_lock(&object->vout_android_lock);
+    object->vout_android_surf = NULL;
+    if (object->vout_android_gui != NULL)
+        (*env)->DeleteGlobalRef(env, object->vout_android_gui);
+    if (object->vout_android_java_surf != NULL)
+        (*env)->DeleteGlobalRef(env, object->vout_android_java_surf);
+    object->vout_android_gui = NULL;
+    object->vout_android_java_surf = NULL;
+    pthread_mutex_unlock(&object->vout_android_lock);
 }
 
 void Java_org_videolan_libvlc_LibVLC_attachSubtitlesSurface(JNIEnv *env, jobject thiz, jobject surf) {
-    pthread_mutex_lock(&vout_android_lock);
-    vout_android_subtitles_surf = (*env)->NewGlobalRef(env, surf);
-    pthread_cond_signal(&vout_android_surf_attached);
-    pthread_mutex_unlock(&vout_android_lock);
+    android_surf_value_t *object = (android_surf_value_t *)(intptr_t)getLong(env, thiz, "mAndroidSurfaceValue");
+
+    pthread_mutex_lock(&object->vout_android_lock);
+    object->vout_android_subtitles_surf = (*env)->NewGlobalRef(env, surf);
+    pthread_cond_signal(&object->vout_android_surf_attached);
+    pthread_mutex_unlock(&object->vout_android_lock);
 }
 
 void Java_org_videolan_libvlc_LibVLC_detachSubtitlesSurface(JNIEnv *env, jobject thiz) {
-    pthread_mutex_lock(&vout_android_lock);
-    (*env)->DeleteGlobalRef(env, vout_android_subtitles_surf);
-    vout_android_subtitles_surf = NULL;
-    pthread_mutex_unlock(&vout_android_lock);
+    android_surf_value_t *object = (android_surf_value_t *)(intptr_t)getLong(env, thiz, "mAndroidSurfaceValue");
+
+    pthread_mutex_lock(&object->vout_android_lock);
+    (*env)->DeleteGlobalRef(env, object->vout_android_subtitles_surf);
+    object->vout_android_subtitles_surf = NULL;
+    pthread_mutex_unlock(&object->vout_android_lock);
 }
 
 static int mouse_x = -1;
diff --git a/vlc-android/jni/vout.h b/vlc-android/jni/vout.h
index c3d4fd7..d14957a 100644
--- a/vlc-android/jni/vout.h
+++ b/vlc-android/jni/vout.h
@@ -21,8 +21,4 @@
 #ifndef LIBVLCJNI_VOUT_H
 #define LIBVLCJNI_VOUT_H
 
-/* vout lock initialized in vout.c */
-pthread_mutex_t vout_android_lock;
-pthread_cond_t vout_android_surf_attached;
-
 #endif // LIBVLCJNI_VOUT_H
diff --git a/vlc-android/src/org/videolan/libvlc/LibVLC.java b/vlc-android/src/org/videolan/libvlc/LibVLC.java
index 5ac201e..abc50a7 100644
--- a/vlc-android/src/org/videolan/libvlc/LibVLC.java
+++ b/vlc-android/src/org/videolan/libvlc/LibVLC.java
@@ -51,6 +51,9 @@ public class LibVLC {
     private int mInternalMediaPlayerIndex = 0; // Read-only, reserved for JNI
     private long mInternalMediaPlayerInstance = 0; // Read-only, reserved for JNI
 
+    private long mAndroidSurfaceValue = 0; // Read-only, reserved for JNI
+    private long mInternalSurface = 0; // Read-only, reserved for JNI
+
     private MediaList mMediaList; // Pointer to media list being followed
     private MediaList mPrimaryList; // Primary/default media list; see getPrimaryMediaList()
 
@@ -128,7 +131,7 @@ public class LibVLC {
     public static LibVLC getInstance() throws LibVlcException {
         synchronized (LibVLC.class) {
             if (sInstance == null) {
-                /* First call */
+                // First call //
                 sInstance = new LibVLC();
             }
         }
@@ -149,10 +152,9 @@ public class LibVLC {
     }
 
     /**
-     * Constructor
-     * It is private because this class is a singleton.
+     * Constructor.
      */
-    private LibVLC() {
+    public LibVLC() {
         mAout = new AudioOutput();
     }
 
@@ -218,7 +220,7 @@ public class LibVLC {
      */
     public native void setSurface(Surface f);
 
-    public static synchronized void restart(Context context) {
+    public static synchronized void restartInstance(Context context) {
         if (sInstance != null) {
             try {
                 sInstance.destroy();
@@ -226,6 +228,15 @@ public class LibVLC {
             } catch (LibVlcException lve) {
                 Log.e(TAG, "Unable to reinit libvlc: " + lve);
             }
+       }
+    }
+
+    public synchronized void restart(Context context) {
+        try {
+            this.destroy();
+            this.init(context);
+        } catch (LibVlcException lve) {
+            Log.e(TAG, "Unable to reinit libvlc: " + lve);
         }
     }
 
@@ -341,7 +352,7 @@ public class LibVLC {
         applyEqualizer();
     }
 
-    private void applyEqualizer()
+    protected void applyEqualizer()
     {
         setNativeEqualizer(mInternalMediaPlayerInstance, this.equalizer);
     }
@@ -381,7 +392,9 @@ public class LibVLC {
 
             File cacheDir = context.getCacheDir();
             mCachePath = (cacheDir != null) ? cacheDir.getAbsolutePath() : null;
-            nativeInit();
+            synchronized (LibVLC.class) {
+                nativeInit();
+            }
             mMediaList = mPrimaryList = new MediaList(this);
             setEventHandler(EventHandler.getInstance());
             mIsInitialized = true;
@@ -394,7 +407,9 @@ public class LibVLC {
      */
     public void destroy() {
         Log.v(TAG, "Destroying LibVLC instance");
-        nativeDestroy();
+        synchronized (LibVLC.class) {
+            nativeDestroy();
+        }
         detachEventHandler();
         mIsInitialized = false;
     }
@@ -647,7 +662,7 @@ public class LibVLC {
     public native int getSpuTracksCount();
 
     public static native String nativeToURI(String path);
-    
+
     public native static void sendMouseEvent( int action, int button, int x, int y);
 
     /**
diff --git a/vlc-android/src/org/videolan/libvlc/MediaList.java b/vlc-android/src/org/videolan/libvlc/MediaList.java
index 85b2d2a..1889481 100644
--- a/vlc-android/src/org/videolan/libvlc/MediaList.java
+++ b/vlc-android/src/org/videolan/libvlc/MediaList.java
@@ -32,7 +32,7 @@ public class MediaList {
 
     /* Since the libvlc_media_t is not created until the media plays, we have
      * to cache them here. */
-    private static class MediaHolder {
+    private class MediaHolder {
         Media m;
         boolean noVideo; // default false
         boolean noHardwareAcceleration; // default false
diff --git a/vlc-android/src/org/videolan/vlc/gui/PreferencesActivity.java b/vlc-android/src/org/videolan/vlc/gui/PreferencesActivity.java
index 4c9539f..eedadf5 100644
--- a/vlc-android/src/org/videolan/vlc/gui/PreferencesActivity.java
+++ b/vlc-android/src/org/videolan/vlc/gui/PreferencesActivity.java
@@ -291,7 +291,7 @@ public class PreferencesActivity extends PreferenceActivity implements OnSharedP
                 || key.equalsIgnoreCase("enable_verbose_mode")
                 || key.equalsIgnoreCase("network_caching")) {
             VLCInstance.updateLibVlcSettings(sharedPreferences);
-            LibVLC.restart(this);
+            LibVLC.restartInstance(this);
         }
     }
 
-- 
1.8.5.2 (Apple Git-48)



More information about the Android mailing list