[Android] [PATCH 3/3] Add support for multiple video instance.

Paulo Vitor Magacho da Silva pvmagacho at gmail.com
Tue Nov 25 10:33:43 CET 2014


Hi,

> You can use calloc, instead of setting everything to NULL

Ok. Will fix that.

> Where does myJavaLibVLC come from ?

My mistake. I will fix this. I could have missed a commit. This is the
LibVLC java object. You can change it to "thiz".

> I won't apply on master.
> I just removed jni_LockAndGetAndroidSurface and vout_android_surf  in a
> recent commit.
> And I added this new function: jni_AndroidJavaSurfaceToNativeSurface.
> But It should be easy to merge since it'll work with your new
> android_surface struct.

I made the commit based on master. You won't find
jni_LockAndGetAndroidSurface. I will remove
vout_android_surf from the struct.

> Why not having EventHandler an object inside LibVLC ?
> So, To get the EventHandler: mLibVlc.getEventHandler() (from java and
> native).
> That way, you can get ride of all hashmap and you don't have to call
> EventHandler methods with an instance of LibVlc.

Will check that. Will take a little while to get that done.

Thanks

2014-11-25 6:35 GMT-02:00 Thomas Guillem <thomas at gllm.fr>:

> Great, I was waiting for this, I can't stand the static everywhere...
>
> On Tue, Nov 25, 2014, at 01:28, Paulo Vitor Magacho da Silva wrote:
> > ---
> >  libvlc/jni/libvlcjni-util.c                        |   2 +-
> >  libvlc/jni/libvlcjni.c                             |  59 ++++++--
> >  libvlc/jni/native_crash_handler.c                  |  81 +++++++++-
> >  libvlc/jni/native_crash_handler.h                  |   4 +-
> >  libvlc/jni/vout.c                                  | 163
> >  ++++++++++++---------
> >  libvlc/jni/vout.h                                  |  14 +-
> >  libvlc/src/org/videolan/libvlc/EventHandler.java   |  33 +++--
> >  libvlc/src/org/videolan/libvlc/LibVLC.java         |  21 ++-
> >  libvlc/src/org/videolan/libvlc/MediaList.java      |   8 +-
> >  .../src/org/videolan/vlc/audio/AudioService.java   |  16 +-
> >  .../src/org/videolan/vlc/gui/HistoryAdapter.java   |   2 +-
> >  .../org/videolan/vlc/gui/PreferencesActivity.java  |   2 +-
> >  .../vlc/gui/video/VideoPlayerActivity.java         |   6 +-
> >  13 files changed, 290 insertions(+), 121 deletions(-)
> >
> > diff --git a/libvlc/jni/libvlcjni-util.c b/libvlc/jni/libvlcjni-util.c
> > index 205d59d..0a3cae9 100644
> > --- a/libvlc/jni/libvlcjni-util.c
> > +++ b/libvlc/jni/libvlcjni-util.c
> > @@ -139,7 +139,7 @@ jobject getEventHandlerReference(JNIEnv *env, jobject
> > thiz, jobject eventHandler
> >          return NULL;
> >      }
> >
> > -    jmethodID methodID = (*env)->GetMethodID(env, cls, "callback",
> > "(ILandroid/os/Bundle;)V");
> > +    jmethodID methodID = (*env)->GetMethodID(env, cls, "callback",
> > "(ILandroid/os/Bundle;Lorg/videolan/libvlc/LibVLC;)V");
> >      if (!methodID) {
> >          LOGE("setEventHandler: failed to get the callback method");
> >          return NULL;
> > diff --git a/libvlc/jni/libvlcjni.c b/libvlc/jni/libvlcjni.c
> > index 7edd52f..833bbef 100644
> > --- a/libvlc/jni/libvlcjni.c
> > +++ b/libvlc/jni/libvlcjni.c
> > @@ -195,9 +195,10 @@ static void vlc_event_callback(const libvlc_event_t
> > *ev, void *data)
> >      }
> >
> >      /* Find the callback ID */
> > -    jmethodID methodID = (*env)->GetMethodID(env, cls, "callback",
> > "(ILandroid/os/Bundle;)V");
> > +    jobject vlcObject = (jobject) data;
> > +    jmethodID methodID = (*env)->GetMethodID(env, cls, "callback",
> > "(ILandroid/os/Bundle;Lorg/videolan/libvlc/LibVLC;)V");
> >      if (methodID) {
> > -        (*env)->CallVoidMethod(env, eventHandlerInstance, methodID,
> > ev->type, bundle);
> > +        (*env)->CallVoidMethod(env, eventHandlerInstance, methodID,
> > ev->type, bundle, vlcObject);
> >      } else {
> >          LOGE("EventHandler: failed to get the callback method");
> >      }
> > @@ -213,16 +214,27 @@ 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);
> > +    JNIEnv* env;
> > +    if (jni_get_env(&env) < 0) {
> > +        return -1;
> > +    }
> > +
> > +    jclass eventHandlerCls = (*env)->FindClass(env,
> > "org/videolan/libvlc/EventHandler");
> > +    jmethodID methodId = (*env)->GetStaticMethodID(env, eventHandlerCls,
> > "getInstance", "()Lorg/videolan/libvlc/EventHandler;");
> > +    jobject eventHandler = (*env)->CallStaticObjectMethod(env,
> > eventHandlerCls, methodId);
> > +
> > +    eventHandlerInstance = (*env)->NewGlobalRef(env, eventHandler);
> >
> >      LOGD("JNI interface loaded.");
> >      return VLC_JNI_VERSION;
> >  }
> >
> >  void JNI_OnUnload(JavaVM* vm, void* reserved) {
> > -    pthread_mutex_destroy(&vout_android_lock);
> > -    pthread_cond_destroy(&vout_android_surf_attached);
> > +    JNIEnv* env;
> > +    if (jni_get_env(&env) == 0 && eventHandlerInstance != NULL) {
> > +        (*env)->DeleteGlobalRef(env, eventHandlerInstance);
> > +    }
> > +    LOGD("JNI interface un-loaded.");
> >  }
> >
> >  int jni_attach_thread(JNIEnv **env, const char *thread_name)
> > @@ -251,8 +263,22 @@ int jni_get_env(JNIEnv **env)
> >  // FIXME: use atomics
> >  static bool verbosity;
> >
> > +
> >  void Java_org_videolan_libvlc_LibVLC_nativeInit(JNIEnv *env, jobject
> >  thiz)
> >  {
> > +    // initialize android_surface_value_t structure
> > +    android_surf_value_t *android_surface = (android_surf_value_t *)
> > malloc(sizeof(android_surf_value_t));
> > +
> > +    android_surface->vout_android_surf = NULL;
> > +    android_surface->vout_android_gui = NULL;
> > +    android_surface->vout_android_java_surf = NULL;
> > +    android_surface->vout_android_subtitles_surf = NULL;
>
> You can use calloc, instead of setting everything to NULL
>
> > +
> > +    pthread_mutex_init(&android_surface->vout_android_lock, NULL);
> > +    pthread_cond_init(&android_surface->vout_android_surf_attached,
> > NULL);
> > +
> > +    setLong(env, thiz, "mAndroidSurfaceValue",
> > (jlong)(intptr_t)android_surface);
> > +
> >      //only use OpenSLES if java side says we can
> >      jclass cls = (*env)->GetObjectClass(env, thiz);
> >      jmethodID methodId = (*env)->GetMethodID(env, cls, "getAout",
> >      "()I");
> > @@ -373,9 +399,13 @@ void
> > Java_org_videolan_libvlc_LibVLC_nativeInit(JNIEnv *env, jobject thiz)
> >
> >  void Java_org_videolan_libvlc_LibVLC_nativeDestroy(JNIEnv *env, jobject
> >  thiz)
> >  {
> > -    destroy_native_crash_handler(env);
> > +    destroy_native_crash_handler(env, thiz);
> >
> >      releaseMediaPlayer(env, thiz);
> > +
> > +    // set the Android surface value structure before playing
> > +    android_surf_value_t *android_surface = (android_surf_value_t
> > *)(intptr_t)getLong(env, thiz, "mAndroidSurfaceValue");
> > +
> >      jlong libVlcInstance = getLong(env, thiz, "mLibVlcInstance");
> >      if (!libVlcInstance)
> >          return; // Already destroyed
> > @@ -385,6 +415,13 @@ void
> > Java_org_videolan_libvlc_LibVLC_nativeDestroy(JNIEnv *env, jobject thiz)
> >      libvlc_release(instance);
> >
> >      setLong(env, thiz, "mLibVlcInstance", 0);
> > +
> > +    pthread_mutex_destroy(&android_surface->vout_android_lock);
> > +    pthread_cond_destroy(&android_surface->vout_android_surf_attached);
> > +
> > +    free(android_surface);
> > +
> > +    setLong(env, thiz, "mAndroidSurfaceValue", 0);
> >  }
> >
> >  void Java_org_videolan_libvlc_LibVLC_detachEventHandler(JNIEnv *env,
> >  jobject thiz)
> > @@ -439,7 +476,7 @@ void Java_org_videolan_libvlc_LibVLC_playMRL(JNIEnv
> > *env, jobject thiz, jlong in
> >          libvlc_MediaPlayerEncounteredError
> >      };
> >      for(int i = 0; i < (sizeof(mp_events) / sizeof(*mp_events)); i++)
> > -        libvlc_event_attach(ev, mp_events[i], vlc_event_callback, myVm);
> > +        libvlc_event_attach(ev, mp_events[i], vlc_event_callback,
> > (void*) myJavaLibVLC);
>
> Where does myJavaLibVLC come from ?
>
> >
> >      /* Keep a pointer to this media player */
> >      setLong(env, thiz, "mInternalMediaPlayerInstance",
> >      (jlong)(intptr_t)mp);
> > @@ -457,13 +494,17 @@ void Java_org_videolan_libvlc_LibVLC_playMRL(JNIEnv
> > *env, jobject thiz, jlong in
> >
> >      (*env)->ReleaseStringUTFChars(env, mrl, p_mrl);
> >
> > +    // set the Android surface value structure before playing
> > +    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[] = {
> >          libvlc_MediaParsedChanged
> >      };
> >      for(int i = 0; i < (sizeof(mp_media_events) /
> >      sizeof(*mp_media_events)); i++)
> > -        libvlc_event_attach(ev_media, mp_media_events[i],
> > vlc_event_callback, myVm);
> > +        libvlc_event_attach(ev_media, mp_media_events[i],
> > vlc_event_callback, (void*) myJavaLibVLC);
> >
> >      libvlc_media_player_set_media(mp, p_md);
> >      libvlc_media_player_play(mp);
> > diff --git a/libvlc/jni/native_crash_handler.c
> > b/libvlc/jni/native_crash_handler.c
> > index 2cb1590..f4a97be 100644
> > --- a/libvlc/jni/native_crash_handler.c
> > +++ b/libvlc/jni/native_crash_handler.c
> > @@ -19,11 +19,19 @@
> >
>  *****************************************************************************/
> >
> >  #include <signal.h>
> > +#include <pthread.h>
> >
> >  #include "native_crash_handler.h"
> >
> > +struct libvlc_crash_handler_t {
> > +    jobject j_libVLC;
> > +    libvlc_crash_handler_t *next;
> > +    libvlc_crash_handler_t *prev;
> > +};
> > +
> >  static struct sigaction old_actions[NSIG];
> > -static jobject j_libVLC;
> > +static libvlc_crash_handler_t *first = NULL;
> > +static libvlc_crash_handler_t *last = NULL;
> >
> >  #define THREAD_NAME "native_crash_handler"
> >  extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
> > @@ -45,6 +53,8 @@ static const int monitored_signals[] = {
> >  };
> >
> >
> > +pthread_mutex_t native_handler_lock = PTHREAD_MUTEX_INITIALIZER;
> > +
> >  /**
> >   * Callback called when a monitored signal is triggered.
> >   */
> > @@ -54,11 +64,24 @@ void sigaction_callback(int signal, siginfo_t *info,
> > void *reserved)
> >      JNIEnv *env;
> >      jni_attach_thread(&env, THREAD_NAME);
> >
> > -    jclass cls = (*env)->GetObjectClass(env, j_libVLC);
> > -    jmethodID methodId = (*env)->GetMethodID(env, cls, "onNativeCrash",
> > "()V");
> > -    (*env)->CallVoidMethod(env, j_libVLC, methodId);
> > +    pthread_mutex_lock(&native_handler_lock);
> > +
> > +    libvlc_crash_handler_t *lp = first;
> > +    while (lp != NULL)
> > +    {
> > +        jclass cls = (*env)->GetObjectClass(env, lp->j_libVLC);
> > +        jmethodID methodId = (*env)->GetMethodID(env, cls,
> > "onNativeCrash", "()V");
> > +        (*env)->CallVoidMethod(env, lp->j_libVLC, methodId);
> > +
> > +        (*env)->DeleteLocalRef(env, cls);
> > +
> > +        libvlc_crash_handler_t *todelete = lp;
> > +        lp = lp->next;
> > +
> > +        free(todelete);
> > +    }
> > +    pthread_mutex_unlock(&native_handler_lock);
> >
> > -    (*env)->DeleteLocalRef(env, cls);
> >      jni_detach_thread();
> >
> >      // Call the old signal handler.
> > @@ -68,7 +91,19 @@ void sigaction_callback(int signal, siginfo_t *info,
> > void *reserved)
> >
> >  void init_native_crash_handler(JNIEnv *env, jobject j_libVLC_local)
> >  {
> > -    j_libVLC = (*env)->NewGlobalRef(env, j_libVLC_local);
> > +    pthread_mutex_lock(&native_handler_lock);
> > +
> > +    libvlc_crash_handler_t *current = (libvlc_crash_handler_t *)
> > malloc(sizeof(libvlc_crash_handler_t));
> > +    current->j_libVLC = (*env)->NewGlobalRef(env, j_libVLC_local);
> > +    current->prev = last;
> > +
> > +    // update values
> > +    if (first == NULL)
> > +        first = current;
> > +    if (last != NULL)
> > +        last->next = current;
> > +    last = current;
> > +
> >      struct sigaction handler;
> >      memset(&handler, 0, sizeof(struct sigaction));
> >
> > @@ -81,11 +116,15 @@ void init_native_crash_handler(JNIEnv *env, jobject
> > j_libVLC_local)
> >          const int s = monitored_signals[i];
> >          sigaction(s, &handler, &old_actions[s]);
> >      }
> > +
> > +    pthread_mutex_unlock(&native_handler_lock);
> >  }
> >
> >
> > -void destroy_native_crash_handler(JNIEnv *env)
> > +void destroy_native_crash_handler(JNIEnv *env, jobject j_libVLC_local)
> >  {
> > +    pthread_mutex_lock(&native_handler_lock);
> > +
> >      // Uninstall the signal handlers and restore their old actions.
> >      for (unsigned i = 0; i < sizeof(monitored_signals) / sizeof(int);
> >      ++i)
> >      {
> > @@ -93,5 +132,31 @@ void destroy_native_crash_handler(JNIEnv *env)
> >          sigaction(s, &old_actions[s], NULL);
> >      }
> >
> > -    (*env)->DeleteGlobalRef(env, j_libVLC);
> > +    libvlc_crash_handler_t *lp = first;
> > +    while (lp != NULL)
> > +    {
> > +        if (j_libVLC_local == lp->j_libVLC) {
> > +            (*env)->DeleteGlobalRef(env, lp->j_libVLC);
> > +
> > +            libvlc_crash_handler_t *todelete = lp;
> > +            libvlc_crash_handler_t *prev = lp->prev;
> > +            libvlc_crash_handler_t *next = lp->next;
> > +            if (lp == first) {
> > +                first = next;
> > +                if (first != NULL)
> > +                    first->prev = NULL;
> > +            } else if (lp == last) {
> > +                last = prev;
> > +                last->next = NULL;
> > +            } else {
> > +                 prev->next = next;
> > +                 next->prev = prev;
> > +            }
> > +
> > +            free(todelete);
> > +            break;
> > +        }
> > +    }
> > +
> > +    pthread_mutex_unlock(&native_handler_lock);
> >  }
> > diff --git a/libvlc/jni/native_crash_handler.h
> > b/libvlc/jni/native_crash_handler.h
> > index a57e61e..4c5530b 100644
> > --- a/libvlc/jni/native_crash_handler.h
> > +++ b/libvlc/jni/native_crash_handler.h
> > @@ -23,7 +23,9 @@
> >
> >  #include <jni.h>
> >
> > +typedef struct libvlc_crash_handler_t libvlc_crash_handler_t;
> > +
> >  void init_native_crash_handler(JNIEnv *env, jobject j_libVLC_local);
> > -void destroy_native_crash_handler(JNIEnv *env);
> > +void destroy_native_crash_handler(JNIEnv *env, jobject j_libVLC_local);
> >
> >  #endif // LIBVLCJNI_NATIVE_CRASH_HANDLER_H
> > diff --git a/libvlc/jni/vout.c b/libvlc/jni/vout.c
> > index 06dc605..107417b 100644
> > --- a/libvlc/jni/vout.c
> > +++ b/libvlc/jni/vout.c
> > @@ -22,43 +22,53 @@
> >  #include <vlc_common.h>
> >
> >  #include <jni.h>
> > +#include "vout.h"
> >
> >  #define THREAD_NAME "jni_vout"
> >  extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
> >  extern void jni_detach_thread();
> >  extern int jni_get_env(JNIEnv **env);
> >
> > -pthread_mutex_t vout_android_lock;
> > -pthread_cond_t vout_android_surf_attached;
> > -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(android_surf_value_t
> > *android_surface) {
> > +    if (android_surface->vout_android_subtitles_surf == NULL)
> > +        return;
> >
> > -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;
> > +    pthread_mutex_lock(&android_surface->vout_android_lock);
> > +    while (android_surface->vout_android_subtitles_surf == NULL)
> > +        pthread_cond_wait(&android_surface->vout_android_surf_attached,
> > &android_surface->vout_android_lock);
> > +    return android_surface->vout_android_subtitles_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;
> > +void *jni_LockAndGetAndroidSurface(android_surf_value_t
> > *android_surface) {
> > +    if (android_surface->vout_android_surf == NULL)
> > +        return;
> > +
> > +    pthread_mutex_lock(&android_surface->vout_android_lock);
> > +    while (android_surface->vout_android_surf == NULL)
> > +        pthread_cond_wait(&android_surface->vout_android_surf_attached,
> > &android_surface->vout_android_lock);
> > +    return android_surface->vout_android_surf;
> >  }
>
> I won't apply on master.
> I just removed jni_LockAndGetAndroidSurface and vout_android_surf  in a
> recent commit.
> And I added this new function: jni_AndroidJavaSurfaceToNativeSurface.
> But It should be easy to merge since it'll work with your new
> android_surface struct.
>
> >
> > -void jni_UnlockAndroidSurface() {
> > -    pthread_mutex_unlock(&vout_android_lock);
> > +jobject jni_LockAndGetAndroidJavaSurface(android_surf_value_t
> > *android_surface) {
> > +    if (android_surface->vout_android_java_surf == NULL)
> > +        return;
> > +
> > +    pthread_mutex_lock(&android_surface->vout_android_lock);
> > +    while (android_surface->vout_android_java_surf == NULL)
> > +        pthread_cond_wait(&android_surface->vout_android_surf_attached,
> > &android_surface->vout_android_lock);
> > +    return android_surface->vout_android_java_surf;
> >  }
> >
> > -void jni_EventHardwareAccelerationError()
> > +void jni_UnlockAndroidSurface(android_surf_value_t *android_surface) {
> > +    pthread_mutex_unlock(&android_surface->vout_android_lock);
> > +}
> > +
> > +void jni_EventHardwareAccelerationError(android_surf_value_t
> > *android_surface)
> >  {
> >      JNIEnv *env;
> >      bool isAttached = false;
> >
> > -    if (vout_android_gui == NULL)
> > +    if (android_surface->vout_android_gui == NULL)
> >          return;
> >
> >      if (jni_get_env(&env) < 0) {
> > @@ -67,39 +77,42 @@ void jni_EventHardwareAccelerationError()
> >          isAttached = true;
> >      }
> >
> > -    jclass cls = (*env)->GetObjectClass(env, vout_android_gui);
> > +    jclass cls = (*env)->GetObjectClass(env,
> > android_surface->vout_android_gui);
> >      jmethodID methodId = (*env)->GetMethodID(env, cls,
> >      "eventHardwareAccelerationError", "()V");
> > -    (*env)->CallVoidMethod(env, vout_android_gui, methodId);
> > +    (*env)->CallVoidMethod(env, android_surface->vout_android_gui,
> > methodId);
> >
> >      (*env)->DeleteLocalRef(env, cls);
> >      if (isAttached)
> >          jni_detach_thread();
> >  }
> >
> > -static void jni_SetSurfaceLayoutEnv(JNIEnv *p_env, int width, int
> > height, int visible_width, int visible_height, int sar_num, int sar_den)
> > +void jni_SetSurfaceLayoutEnv(JNIEnv *p_env, android_surf_value_t
> > *android_surface, int width, int height, int visible_width, int
> > visible_height, int sar_num, int sar_den)
> >  {
> > -    if (vout_android_gui == NULL)
> > +    if (android_surface->vout_android_gui == NULL)
> >          return;
> >
> > -    jclass cls = (*p_env)->GetObjectClass (p_env, vout_android_gui);
> > +    jclass cls = (*p_env)->GetObjectClass (p_env,
> > android_surface->vout_android_gui);
> >      jmethodID methodId = (*p_env)->GetMethodID (p_env, cls,
> >      "setSurfaceLayout", "(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, android_surface->vout_android_gui,
> > methodId, width, height, visible_width, visible_height, sar_num,
> > sar_den);
> >
> >      (*p_env)->DeleteLocalRef(p_env, cls);
> >  }
> >
> > -void jni_SetSurfaceLayout(int width, int height, int visible_width, int
> > visible_height, int sar_num, int sar_den)
> > +void jni_SetSurfaceLayout(android_surf_value_t *android_surface, int
> > width, int height, int visible_width, int visible_height, int sar_num,
> > int sar_den)
> >  {
> >      JNIEnv *p_env;
> >      bool isAttached = false;
> >
> > +    if (android_surface == NULL)
> > +        return;
> > +
> >      if (jni_get_env(&p_env) < 0) {
> >          if (jni_attach_thread(&p_env, THREAD_NAME) < 0)
> >              return;
> >          isAttached = true;
> >      }
> > -    jni_SetSurfaceLayoutEnv(p_env, width, height, visible_width,
> > visible_height, sar_num, sar_den);
> > +    jni_SetSurfaceLayoutEnv(p_env, android_surface, width, height,
> > visible_width, visible_height, sar_num, sar_den);
> >
> >      if (isAttached)
> >          jni_detach_thread();
> > @@ -144,7 +157,7 @@ void *jni_AndroidJavaSurfaceToNativeSurface(jobject
> > *surf)
> >      return native_surface;
> >  }
> >
> > -int jni_ConfigureSurface(jobject jsurf, int width, int height, int hal,
> > bool *configured)
> > +int jni_ConfigureSurface(jobject jsurf, android_surf_value_t
> > *android_surface, int width, int height, int hal, bool *configured)
> >  {
> >      JNIEnv *p_env;
> >      bool isAttached = false;
> > @@ -155,9 +168,9 @@ int jni_ConfigureSurface(jobject jsurf, int width,
> > int height, int hal, bool *co
> >              return -1;
> >          isAttached = true;
> >      }
> > -    jclass clz = (*p_env)->GetObjectClass (p_env, vout_android_gui);
> > +    jclass clz = (*p_env)->GetObjectClass (p_env,
> > android_surface->vout_android_gui);
> >      jmethodID methodId = (*p_env)->GetMethodID (p_env, clz,
> >      "configureSurface", "(Landroid/view/Surface;III)I");
> > -    ret = (*p_env)->CallIntMethod (p_env, vout_android_gui, methodId,
> > jsurf, width, height, hal);
> > +    ret = (*p_env)->CallIntMethod (p_env,
> > android_surface->vout_android_gui, methodId, jsurf, width, height, hal);
> >      if (ret >= 0 && configured)
> >          *configured = ret == 1;
> >
> > @@ -166,58 +179,76 @@ int jni_ConfigureSurface(jobject jsurf, int width,
> > int height, int hal, bool *co
> >      return ret == -1 ? -1 : 0;
> >  }
> >
> > -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
> > *android_surface) {
> > +    pthread_mutex_lock(&android_surface->vout_android_lock);
> > +    bool result = android_surface->vout_video_player_activity_created;
> > +    pthread_mutex_unlock(&android_surface->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 * android_surface = (android_surf_value_t
> > *)(intptr_t)getLong(env, thiz, "mAndroidSurfaceValue");
> > +    pthread_mutex_lock(&android_surface->vout_android_lock);
> > +    android_surface->vout_video_player_activity_created = created;
> > +    pthread_mutex_unlock(&android_surface->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 * android_surface = (android_surf_value_t
> > *)(intptr_t)getLong(env, thiz, "mAndroidSurfaceValue");
> > +    if (android_surface == NULL)
> > +        return;
> > +
> > +    pthread_mutex_lock(&android_surface->vout_android_lock);
> >
> > -    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 = (*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);
> > +    if (android_surface->vout_android_gui != NULL)
> > +        (*env)->DeleteGlobalRef(env, android_surface->vout_android_gui);
> > +    if (android_surface->vout_android_java_surf != NULL)
> > +        (*env)->DeleteGlobalRef(env,
> > android_surface->vout_android_java_surf);
> > +    android_surface->vout_android_gui = (*env)->NewGlobalRef(env, gui);
> > +    android_surface->vout_android_java_surf = (*env)->NewGlobalRef(env,
> > surf);
> > +    pthread_cond_signal(&android_surface->vout_android_surf_attached);
> > +    pthread_mutex_unlock(&android_surface->vout_android_lock);
> >  }
> >
> >  void Java_org_videolan_libvlc_LibVLC_detachSurface(JNIEnv *env, jobject
> >  thiz) {
> > -    pthread_mutex_lock(&vout_android_lock);
> > -    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 * android_surface = (android_surf_value_t
> > *)(intptr_t)getLong(env, thiz, "mAndroidSurfaceValue");
> > +    if (android_surface == NULL)
> > +        return;
> > +
> > +    pthread_mutex_lock(&android_surface->vout_android_lock);
> > +    android_surface->vout_android_surf = NULL;
> > +    if (android_surface->vout_android_gui != NULL)
> > +        (*env)->DeleteGlobalRef(env, android_surface->vout_android_gui);
> > +    if (android_surface->vout_android_java_surf != NULL)
> > +        (*env)->DeleteGlobalRef(env,
> > android_surface->vout_android_java_surf);
> > +    android_surface->vout_android_gui = NULL;
> > +    android_surface->vout_android_java_surf = NULL;
> > +    pthread_mutex_unlock(&android_surface->vout_android_lock);
> >  }
> >
> >  void Java_org_videolan_libvlc_LibVLC_attachSubtitlesSurface(JNIEnv *env,
> >  jobject thiz, jobject surf) {
> > -    pthread_mutex_lock(&vout_android_lock);
> > -    if (vout_android_subtitles_surf != NULL)
> > -        (*env)->DeleteGlobalRef(env, vout_android_subtitles_surf);
> > -    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 * android_surface = (android_surf_value_t
> > *)(intptr_t)getLong(env, thiz, "mAndroidSurfaceValue");
> > +    if (android_surface == NULL)
> > +        return;
> > +
> > +    pthread_mutex_lock(&android_surface->vout_android_lock);
> > +    if (android_surface->vout_android_subtitles_surf != NULL)
> > +        (*env)->DeleteGlobalRef(env,
> > android_surface->vout_android_subtitles_surf);
> > +    android_surface->vout_android_subtitles_surf =
> > (*env)->NewGlobalRef(env, surf);
> > +    pthread_cond_signal(&android_surface->vout_android_surf_attached);
> > +    pthread_mutex_unlock(&android_surface->vout_android_lock);
> >  }
> >
> >  void Java_org_videolan_libvlc_LibVLC_detachSubtitlesSurface(JNIEnv *env,
> >  jobject thiz) {
> > -    pthread_mutex_lock(&vout_android_lock);
> > -    if (vout_android_subtitles_surf != NULL)
> > -        (*env)->DeleteGlobalRef(env, vout_android_subtitles_surf);
> > -    vout_android_subtitles_surf = NULL;
> > -    pthread_mutex_unlock(&vout_android_lock);
> > +    android_surf_value_t * android_surface = (android_surf_value_t
> > *)(intptr_t)getLong(env, thiz, "mAndroidSurfaceValue");
> > +    if (android_surface == NULL)
> > +        return;
> > +
> > +    pthread_mutex_lock(&android_surface->vout_android_lock);
> > +    if (android_surface->vout_android_subtitles_surf != NULL)
> > +        (*env)->DeleteGlobalRef(env,
> > android_surface->vout_android_subtitles_surf);
> > +    android_surface->vout_android_subtitles_surf = NULL;
> > +    pthread_mutex_unlock(&android_surface->vout_android_lock);
> >  }
> >
> >  static int mouse_x = -1;
> > diff --git a/libvlc/jni/vout.h b/libvlc/jni/vout.h
> > index c3d4fd7..c439c12 100644
> > --- a/libvlc/jni/vout.h
> > +++ b/libvlc/jni/vout.h
> > @@ -21,8 +21,16 @@
> >  #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;
> > +#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;
> >
> >  #endif // LIBVLCJNI_VOUT_H
> > diff --git a/libvlc/src/org/videolan/libvlc/EventHandler.java
> > b/libvlc/src/org/videolan/libvlc/EventHandler.java
> > index 16a0791..03b8821 100644
> > --- a/libvlc/src/org/videolan/libvlc/EventHandler.java
> > +++ b/libvlc/src/org/videolan/libvlc/EventHandler.java
> > @@ -21,6 +21,9 @@
> >  package org.videolan.libvlc;
> >
> >  import java.util.ArrayList;
> > +import java.util.HashMap;
> > +import java.util.List;
> > +import java.util.Map;
> >
> >  import android.os.Bundle;
> >  import android.os.Handler;
> > @@ -96,36 +99,44 @@ public class EventHandler {
> >
> >      public static final int HardwareAccelerationError         = 0x3000;
> >
> > -    private ArrayList<Handler> mEventHandler;
> > +    private Map<LibVLC, ArrayList<Handler>> mMapHandler;
> >      private static EventHandler mInstance;
> >
> >      EventHandler() {
> > -        mEventHandler = new ArrayList<Handler>();
> > +        mMapHandler = new HashMap<LibVLC, ArrayList<Handler>>();
> >      }
> >
> > -    public static EventHandler getInstance() {
> > +    public synchronized static EventHandler getInstance() {
> >          if (mInstance == null) {
> >              mInstance = new EventHandler();
> >          }
> >          return mInstance;
> >      }
> >
> > -    public void addHandler(Handler handler) {
> > -        if (!mEventHandler.contains(handler))
> > -            mEventHandler.add(handler);
> > +    public synchronized void addHandler(LibVLC vlcObject, Handler
> > handler) {
> > +        if (!mMapHandler.containsKey(vlcObject)) {
> > +            mMapHandler.put(vlcObject, new ArrayList<Handler>());
> > +        }
> > +        mMapHandler.get(vlcObject).add(handler);
> >      }
> >
> > -    public void removeHandler(Handler handler) {
> > -        mEventHandler.remove(handler);
> > +    public synchronized void removeHandler(LibVLC vlcObject, Handler
> > handler) {
> > +        mMapHandler.get(vlcObject).remove(handler);
> >      }
> >
> >      /** This method is called by a native thread **/
> > -    public void callback(int event, Bundle b) {
> > +    public synchronized void callback(int event, Bundle b, LibVLC
> > vlcObject) {
> > +        List<Handler> eventHandlers = mMapHandler.get(vlcObject);
> > +        if (eventHandlers == null) {
> > +            return;
> > +        }
> > +
> >          b.putInt("event", event);
> > -        for (int i = 0; i < mEventHandler.size(); i++) {
> > +        for (int i = 0; i < eventHandlers.size(); i++) {
> >              Message msg = Message.obtain();
> >              msg.setData(b);
> > -            mEventHandler.get(i).sendMessage(msg);
> > +            msg.obj = vlcObject;
> > +            eventHandlers.get(i).sendMessage(msg);
> >          }
> >      }
> >  }
>
> Why not having EventHandler an object inside LibVLC ?
> So, To get the EventHandler: mLibVlc.getEventHandler() (from java and
> native).
> That way, you can get ride of all hashmap and you don't have to call
> EventHandler methods with an instance of LibVlc.
>
>
> > diff --git a/libvlc/src/org/videolan/libvlc/LibVLC.java
> > b/libvlc/src/org/videolan/libvlc/LibVLC.java
> > index 8eb25ad..4a2aa2f 100644
> > --- a/libvlc/src/org/videolan/libvlc/LibVLC.java
> > +++ b/libvlc/src/org/videolan/libvlc/LibVLC.java
> > @@ -67,6 +67,9 @@ public class LibVLC {
> >      private int mInternalMediaPlayerIndex = 0; // Read-only, reserved
> >      for JNI
> >      private long mInternalMediaPlayerInstance = 0; // Read-only,
> >      reserved for JNI
> >
> > +    // Android surface structure
> > +    protected long mAndroidSurfaceValue = 0; // Read-only, reserved for
> > JNI
> > +
> >      private MediaList mMediaList; // Pointer to media list being
> >      followed
> >      private MediaList mPrimaryList; // Primary/default media list; see
> >      getPrimaryMediaList()
> >
> > @@ -192,10 +195,9 @@ public class LibVLC {
> >      }
> >
> >      /**
> > -     * Constructor
> > -     * It is private because this class is a singleton.
> > +     * Constructor.
> >       */
> > -    private LibVLC() {
> > +    public LibVLC() {
> >          mAout = new AudioOutput();
> >      }
> >
> > @@ -261,7 +263,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();
> > @@ -272,6 +274,15 @@ public class LibVLC {
> >          }
> >      }
> >
> > +    public void restart(Context context) {
> > +        try {
> > +            this.destroy();
> > +            this.init(context);
> > +        } catch (LibVlcException lve) {
> > +            Log.e(TAG, "Unable to reinit libvlc: " + lve);
> > +        }
> > +    }
> > +
> >      /**
> >       * those get/is* are called from native code to get settings values.
> >       */
> > @@ -490,7 +501,7 @@ public class LibVLC {
> >          applyEqualizer();
> >      }
> >
> > -    private void applyEqualizer()
> > +    protected void applyEqualizer()
> >      {
> >          setNativeEqualizer(mInternalMediaPlayerInstance,
> >          this.equalizer);
> >      }
> > diff --git a/libvlc/src/org/videolan/libvlc/MediaList.java
> > b/libvlc/src/org/videolan/libvlc/MediaList.java
> > index 666568e..5c60236 100644
> > --- a/libvlc/src/org/videolan/libvlc/MediaList.java
> > +++ b/libvlc/src/org/videolan/libvlc/MediaList.java
> > @@ -105,12 +105,12 @@ public class MediaList {
> >          ArrayList<String> children = new ArrayList<String>();
> >          int ret = expandMedia(mLibVLC, position, children);
> >          if(ret == 0) {
> > -
> > mEventHandler.callback(EventHandler.CustomMediaListExpanding, new
> > Bundle());
> > +
> > mEventHandler.callback(EventHandler.CustomMediaListExpanding, new
> > Bundle(), mLibVLC);
> >              this.remove(position);
> >              for(String mrl : children) {
> >                  this.insert(position, mrl);
> >              }
> > -
> > mEventHandler.callback(EventHandler.CustomMediaListExpandingEnd, new
> > Bundle());
> > +
> > mEventHandler.callback(EventHandler.CustomMediaListExpandingEnd, new
> > Bundle(), mLibVLC);
> >          }
> >          return ret;
> >      }
> > @@ -155,7 +155,7 @@ public class MediaList {
> >          Bundle b = new Bundle();
> >          b.putInt("index_before", startPosition);
> >          b.putInt("index_after", endPosition);
> > -        mEventHandler.callback(EventHandler.CustomMediaListItemMoved,
> > b);
> > +        mEventHandler.callback(EventHandler.CustomMediaListItemMoved, b,
> > mLibVLC);
> >      }
> >
> >      public void remove(int position) {
> > @@ -231,6 +231,6 @@ public class MediaList {
> >          Bundle b = new Bundle();
> >          b.putString("item_uri", uri);
> >          b.putInt("item_index", position);
> > -        mEventHandler.callback(event, b);
> > +        mEventHandler.callback(event, b, mLibVLC);
> >      }
> >  }
> > diff --git a/vlc-android/src/org/videolan/vlc/audio/AudioService.java
> > b/vlc-android/src/org/videolan/vlc/audio/AudioService.java
> > index bf4e85f..6420d72 100644
> > --- a/vlc-android/src/org/videolan/vlc/audio/AudioService.java
> > +++ b/vlc-android/src/org/videolan/vlc/audio/AudioService.java
> > @@ -618,7 +618,7 @@ public class AudioService extends Service {
> >          String MRL = mLibVLC.getMediaList().getMRL(mCurrentIndex);
> >          int index = mCurrentIndex;
> >          mCurrentIndex = -1;
> > -        mEventHandler.removeHandler(mVlcEventHandler);
> > +        mEventHandler.removeHandler(mLibVLC, mVlcEventHandler);
> >          // Preserve playback when switching to video
> >          hideNotification(false);
> >
> > @@ -821,8 +821,8 @@ public class AudioService extends Service {
> >
> >      private void stop() {
> >          mLibVLC.stop();
> > -        mEventHandler.removeHandler(mVlcEventHandler);
> > -
> >
> mLibVLC.getMediaList().getEventHandler().removeHandler(mListEventHandler);
> > +        mEventHandler.removeHandler(mLibVLC, mVlcEventHandler);
> > +        mLibVLC.getMediaList().getEventHandler().removeHandler(mLibVLC,
> > mListEventHandler);
> >
> setRemoteControlClientPlaybackState(EventHandler.MediaPlayerStopped);
> >          mCurrentIndex = -1;
> >          mPrevious.clear();
> > @@ -1138,9 +1138,9 @@ public class AudioService extends Service {
> >                  throws RemoteException {
> >
> >              Log.v(TAG, "Loading position " +
> >              ((Integer)position).toString() + " in " +
> >              mediaPathList.toString());
> > -            mEventHandler.addHandler(mVlcEventHandler);
> > +            mEventHandler.addHandler(mLibVLC, mVlcEventHandler);
> >
> > -
> >
> mLibVLC.getMediaList().getEventHandler().removeHandler(mListEventHandler);
> > +
> > mLibVLC.getMediaList().getEventHandler().removeHandler(mLibVLC,
> > mListEventHandler);
> >              mLibVLC.setMediaList();
> >              mLibVLC.getPrimaryMediaList().clear();
> >              MediaList mediaList = mLibVLC.getMediaList();
> > @@ -1175,7 +1175,7 @@ public class AudioService extends Service {
> >              }
> >
> >              // Add handler after loading the list
> > -
> > mLibVLC.getMediaList().getEventHandler().addHandler(mListEventHandler);
> > +            mLibVLC.getMediaList().getEventHandler().addHandler(mLibVLC,
> > mListEventHandler);
> >
> >              mLibVLC.playIndex(mCurrentIndex);
> >              mHandler.sendEmptyMessage(SHOW_PROGRESS);
> > @@ -1206,7 +1206,7 @@ public class AudioService extends Service {
> >                  mCurrentIndex = 0;
> >              }
> >
> > -            mEventHandler.addHandler(mVlcEventHandler);
> > +            mEventHandler.addHandler(mLibVLC, mVlcEventHandler);
> >              mLibVLC.playIndex(mCurrentIndex);
> >              mHandler.sendEmptyMessage(SHOW_PROGRESS);
> >              setUpRemoteControlClient();
> > @@ -1230,7 +1230,7 @@ public class AudioService extends Service {
> >
> >              if(URI == null || !mLibVLC.isPlaying())
> >                  return;
> > -            mEventHandler.addHandler(mVlcEventHandler);
> > +            mEventHandler.addHandler(mLibVLC, mVlcEventHandler);
> >              mCurrentIndex = index;
> >
> >              // Notify everyone
> > diff --git a/vlc-android/src/org/videolan/vlc/gui/HistoryAdapter.java
> > b/vlc-android/src/org/videolan/vlc/gui/HistoryAdapter.java
> > index f24577c..b80438b 100644
> > --- a/vlc-android/src/org/videolan/vlc/gui/HistoryAdapter.java
> > +++ b/vlc-android/src/org/videolan/vlc/gui/HistoryAdapter.java
> > @@ -56,7 +56,7 @@ public class HistoryAdapter extends BaseAdapter {
> >          }
> >
> >          EventHandler em =
> >          mLibVLC.getPrimaryMediaList().getEventHandler();
> > -        em.addHandler(new HistoryEventHandler(this));
> > +        em.addHandler(mLibVLC, new HistoryEventHandler(this));
> >      }
> >
> >      @Override
> > diff --git
> > a/vlc-android/src/org/videolan/vlc/gui/PreferencesActivity.java
> > b/vlc-android/src/org/videolan/vlc/gui/PreferencesActivity.java
> > index 9f0109c..b069452 100644
> > --- a/vlc-android/src/org/videolan/vlc/gui/PreferencesActivity.java
> > +++ b/vlc-android/src/org/videolan/vlc/gui/PreferencesActivity.java
> > @@ -292,7 +292,7 @@ public class PreferencesActivity extends
> > PreferenceActivity implements OnSharedP
> >                  || key.equalsIgnoreCase("network_caching")
> >                  || key.equalsIgnoreCase("dev_hardware_decoder")) {
> >              VLCInstance.updateLibVlcSettings(sharedPreferences);
> > -            LibVLC.restart(this);
> > +            LibVLC.restartInstance(this);
> >          }
> >      }
> >
> > diff --git
> > a/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.java
> > b/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.java
> > index faf4d10..2fa6236 100644
> > --- a/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.java
> > +++ b/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.java
> > @@ -438,7 +438,7 @@ public class VideoPlayerActivity extends
> > ActionBarActivity implements IVideoPlay
> >          mLibVLC.eventVideoPlayerActivityCreated(true);
> >
> >          EventHandler em = EventHandler.getInstance();
> > -        em.addHandler(eventHandler);
> > +        em.addHandler(mLibVLC, eventHandler);
> >
> >          this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
> >
> > @@ -561,7 +561,7 @@ public class VideoPlayerActivity extends
> > ActionBarActivity implements IVideoPlay
> >          unregisterReceiver(mReceiver);
> >
> >          EventHandler em = EventHandler.getInstance();
> > -        em.removeHandler(eventHandler);
> > +        em.removeHandler(mLibVLC, eventHandler);
> >
> >          // MediaCodec opaque direct rendering should not be used anymore
> >          since there is no surface to attach.
> >          mLibVLC.eventVideoPlayerActivityCreated(false);
> > @@ -1205,7 +1205,7 @@ public class VideoPlayerActivity extends
> > ActionBarActivity implements IVideoPlay
> >
> >      public void eventHardwareAccelerationError() {
> >          EventHandler em = EventHandler.getInstance();
> > -        em.callback(EventHandler.HardwareAccelerationError, new
> > Bundle());
> > +        em.callback(EventHandler.HardwareAccelerationError, new
> > Bundle(), mLibVLC);
> >      }
> >
> >      private void handleHardwareAccelerationError() {
> > --
> > 1.9.3 (Apple Git-50)
> >
> > _______________________________________________
> > Android mailing list
> > Android at videolan.org
> > https://mailman.videolan.org/listinfo/android
> >
>
> _______________________________________________
> Android mailing list
> Android at videolan.org
> https://mailman.videolan.org/listinfo/android
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/android/attachments/20141125/b38ba5e5/attachment-0001.html>


More information about the Android mailing list