[Android] jni/medialist: use only indexes and medias returned by events

Thomas Guillem git at videolan.org
Wed Feb 4 15:39:52 CET 2015


vlc-ports/android | branch: master | Thomas Guillem <thomas at gllm.fr> | Tue Feb  3 13:20:01 2015 +0100| [b9e3eba01c7770da089c957e96dd37e2ae2dc598] | committer: Thomas Guillem

jni/medialist: use only indexes and medias returned by events

Fix deadlock when creating a new Media From Java MediaList. Indeed the
libvlc_media_list can be already locked in that case.

> http://git.videolan.org/gitweb.cgi/vlc-ports/android.git/?a=commit;h=b9e3eba01c7770da089c957e96dd37e2ae2dc598
---

 libvlc/jni/libvlcjni-media.c     |    6 +--
 libvlc/jni/libvlcjni-medialist.c |  108 ++++++++++++++++++++++++++++++++++++--
 2 files changed, 108 insertions(+), 6 deletions(-)

diff --git a/libvlc/jni/libvlcjni-media.c b/libvlc/jni/libvlcjni-media.c
index 8b62c66..afe1a71 100644
--- a/libvlc/jni/libvlcjni-media.c
+++ b/libvlc/jni/libvlcjni-media.c
@@ -23,6 +23,8 @@
 
 #include "libvlcjni-vlcobject.h"
 
+libvlc_media_t *MediaList_get_media(vlcjni_object *p_obj, int index);
+
 #define META_MAX 25
 
 struct vlcjni_object_sys
@@ -168,9 +170,7 @@ Java_org_videolan_libvlc_Media_nativeNewFromMediaList(JNIEnv *env, jobject thiz,
         return;
     }
 
-    libvlc_media_list_lock(p_ml_obj->u.p_ml);
-    p_obj->u.p_m = libvlc_media_list_item_at_index(p_ml_obj->u.p_ml, index);
-    libvlc_media_list_unlock(p_ml_obj->u.p_ml);
+    p_obj->u.p_m = MediaList_get_media(p_ml_obj, index);
 
     Media_nativeNewCommon(env, thiz, p_obj);
 }
diff --git a/libvlc/jni/libvlcjni-medialist.c b/libvlc/jni/libvlcjni-medialist.c
index 6e4443a..0f25cd0 100644
--- a/libvlc/jni/libvlcjni-medialist.c
+++ b/libvlc/jni/libvlcjni-medialist.c
@@ -18,8 +18,20 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
+#include <pthread.h>
+
 #include "libvlcjni-vlcobject.h"
 
+#define MEDIAS_INIT_SIZE 32
+
+struct vlcjni_object_sys
+{
+    pthread_mutex_t lock;
+    libvlc_media_t **pp_medias;
+    unsigned int i_medias_size;
+    unsigned int i_medias_max;
+};
+
 static const libvlc_event_type_t ml_events[] = {
     libvlc_MediaListItemAdded,
     //libvlc_MediaListWillAddItem,
@@ -29,17 +41,98 @@ static const libvlc_event_type_t ml_events[] = {
     -1,
 };
 
+static int
+MediaList_add_media(vlcjni_object *p_obj, int index, libvlc_media_t *p_m)
+{
+    vlcjni_object_sys *p_sys = p_obj->p_sys;
+    unsigned int i_new_medias_size;
+
+    pthread_mutex_lock(&p_sys->lock);
+
+    i_new_medias_size = p_sys->i_medias_size + 1;
+
+    // realloc
+    if (i_new_medias_size > p_sys->i_medias_max)
+    {
+        libvlc_media_t *pp_new_medias;
+        unsigned int i_new_medias_max = p_sys->i_medias_max + MEDIAS_INIT_SIZE;
+
+        pp_new_medias = realloc(p_sys->pp_medias,
+                                i_new_medias_max * sizeof(libvlc_media_t *));
+        if (!pp_new_medias)
+        {
+            pthread_mutex_unlock(&p_sys->lock);
+            return -1;
+        }
+        p_sys->i_medias_max = i_new_medias_max;
+        p_sys->pp_medias = pp_new_medias;
+    }
+
+    // move in case of insert
+    if (index != p_sys->i_medias_size)
+    {
+        memmove(&p_sys->pp_medias[index + 1],
+                &p_sys->pp_medias[index],
+                p_sys->i_medias_size - index * sizeof(libvlc_media_t *));
+    }
+    p_sys->pp_medias[index] = p_m;
+    p_sys->i_medias_size = i_new_medias_size;
+
+    pthread_mutex_unlock(&p_sys->lock);
+    return 0;
+}
+
+static void
+MediaList_remove_media(vlcjni_object *p_obj, int index, libvlc_media_t *p_md)
+{
+    vlcjni_object_sys *p_sys = p_obj->p_sys;
+
+    pthread_mutex_lock(&p_sys->lock);
+    if (index < p_sys->i_medias_size - 1)
+    {
+        memmove(&p_sys->pp_medias[index],
+                &p_sys->pp_medias[index + 1],
+                (p_sys->i_medias_size - index - 1) * sizeof(libvlc_media_t *));
+    }
+    p_sys->i_medias_size--;
+    pthread_mutex_unlock(&p_sys->lock);
+}
+
+libvlc_media_t *
+MediaList_get_media(vlcjni_object *p_obj, int index)
+{
+    vlcjni_object_sys *p_sys = p_obj->p_sys;
+    libvlc_media_t *p_m = NULL;
+
+    pthread_mutex_lock(&p_sys->lock);
+    if (index >= 0 && index < p_sys->i_medias_size)
+    {
+        p_m = p_sys->pp_medias[index];
+        libvlc_media_retain(p_m);
+    }
+    pthread_mutex_unlock(&p_sys->lock);
+    return p_m;
+}
+
 static bool
 MediaList_event_cb(vlcjni_object *p_obj, const libvlc_event_t *p_ev,
                    java_event *p_java_event)
 {
+    int index;
     switch (p_ev->type)
     {
         case libvlc_MediaListItemAdded:
-            p_java_event->arg1 = p_ev->u.media_list_item_added.index;
+            index = p_ev->u.media_list_item_added.index;
+            if (MediaList_add_media(p_obj, index,
+                                    p_ev->u.media_list_item_added.item) == -1)
+                return false;
+            p_java_event->arg1 = index;
             break;
         case libvlc_MediaListItemDeleted:
-            p_java_event->arg1 = p_ev->u.media_list_item_deleted.index;
+            index = p_ev->u.media_list_item_deleted.index;
+            MediaList_remove_media(p_obj, index,
+                                   p_ev->u.media_list_item_deleted.item);
+            p_java_event->arg1 = index;
             break;
     }
     p_java_event->type = p_ev->type;
@@ -49,12 +142,17 @@ MediaList_event_cb(vlcjni_object *p_obj, const libvlc_event_t *p_ev,
 static void
 MediaList_nativeNewCommon(JNIEnv *env, jobject thiz, vlcjni_object *p_obj)
 {
-    if (!p_obj->u.p_ml)
+    p_obj->p_sys = calloc(1, sizeof(vlcjni_object_sys));
+
+    if (!p_obj->u.p_ml || !p_obj->p_sys)
     {
+        free(p_obj->p_sys);
         VLCJniObject_release(env, thiz, p_obj);
         throw_IllegalStateException(env, "can't create MediaList instance");
         return;
     }
+    pthread_mutex_init(&p_obj->p_sys->lock, NULL);
+
     VLCJniObject_attachEvents(p_obj, MediaList_event_cb,
                               libvlc_media_list_event_manager(p_obj->u.p_ml),
                               ml_events);
@@ -140,6 +238,10 @@ Java_org_videolan_libvlc_MediaList_nativeRelease(JNIEnv *env, jobject thiz)
 
     libvlc_media_list_release(p_obj->u.p_ml);
 
+    pthread_mutex_destroy(&p_obj->p_sys->lock);
+    free(p_obj->p_sys->pp_medias);
+    free(p_obj->p_sys);
+
     VLCJniObject_release(env, thiz, p_obj);
 }
 



More information about the Android mailing list