[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