[Android] [PATCH] Add support for multiple video instances.

Thomas Guillem thomas at gllm.fr
Tue Dec 2 12:27:57 CET 2014


Good solution for NativeCrashHandler, it's far better now.

I'm OK with this patch, I'll merge it when patches on vlc are applied.
Can you propose the final patch on vlc-devel too ?

On Tue, Dec 2, 2014, at 11:28, Paulo Vitor Magacho da Silva wrote:
> ---
>  libvlc/jni/libvlcjni-equalizer.c                   |   4 +-
>  libvlc/jni/libvlcjni-util.c                        |  17 --
>  libvlc/jni/libvlcjni.c                             | 179
>  +++++++++++---------
>  libvlc/jni/native_crash_handler.c                  |  25 +--
>  libvlc/jni/native_crash_handler.h                  |   5 +-
>  libvlc/jni/utils.h                                 |   2 -
>  libvlc/jni/vout.c                                  | 186
>  ++++++++++++---------
>  libvlc/jni/vout.h                                  |  24 ++-
>  libvlc/src/org/videolan/libvlc/EventHandler.java   |   8 -
>  libvlc/src/org/videolan/libvlc/LibVLC.java         |  98 +++--------
>  libvlc/src/org/videolan/libvlc/LibVlcUtil.java     |  56 ++++++-
>  .../org/videolan/libvlc/NativeCrashHandler.java    |  64 +++++++
>  .../src/org/videolan/vlc/VLCApplication.java       |  15 +-
>  .../src/org/videolan/vlc/audio/AudioService.java   |  14 +-
>  .../org/videolan/vlc/gui/PreferencesActivity.java  |   2 +-
>  .../vlc/gui/video/VideoPlayerActivity.java         |   9 +-
>  .../src/org/videolan/vlc/util/VLCInstance.java     |  14 +-
>  17 files changed, 399 insertions(+), 323 deletions(-)
>  create mode 100644
>  libvlc/src/org/videolan/libvlc/NativeCrashHandler.java
> 
> diff --git a/libvlc/jni/libvlcjni-equalizer.c
> b/libvlc/jni/libvlcjni-equalizer.c
> index 2dad0e4..d11f24d 100644
> --- a/libvlc/jni/libvlcjni-equalizer.c
> +++ b/libvlc/jni/libvlcjni-equalizer.c
> @@ -89,10 +89,10 @@ jfloatArray
> Java_org_videolan_libvlc_LibVLC_getPreset(JNIEnv *env, jobject thiz,
>   * apply equalizer settings (param bands is float[] (first element is
>   preamp, then bands))
>   */
>  //"--audio-filter=equalizer", "--equalizer-bands=-3.5 -4.5 -1 0 0 5 8 8
>  8 8",
> -jint Java_org_videolan_libvlc_LibVLC_setNativeEqualizer(JNIEnv *env,
> jobject thiz, jlong media_player, jfloatArray bands)
> +jint Java_org_videolan_libvlc_LibVLC_setNativeEqualizer(JNIEnv *env,
> jobject thiz, jfloatArray bands)
>  {
>      jint res = -1;
> -    libvlc_media_player_t *mp =
> (libvlc_media_player_t*)(intptr_t)media_player;
> +    libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
>      if (!mp)
>          return res;
>  
> diff --git a/libvlc/jni/libvlcjni-util.c b/libvlc/jni/libvlcjni-util.c
> index 205d59d..67c2554 100644
> --- a/libvlc/jni/libvlcjni-util.c
> +++ b/libvlc/jni/libvlcjni-util.c
> @@ -131,23 +131,6 @@ void arrayListStringAdd(JNIEnv *env, jclass class,
> jmethodID methodID, jobject a
>      (*env)->DeleteLocalRef(env, jstr);
>  }
>  
> -jobject getEventHandlerReference(JNIEnv *env, jobject thiz, jobject
> eventHandler)
> -{
> -    jclass cls = (*env)->GetObjectClass(env, eventHandler);
> -    if (!cls) {
> -        LOGE("setEventHandler: failed to get class reference");
> -        return NULL;
> -    }
> -
> -    jmethodID methodID = (*env)->GetMethodID(env, cls, "callback",
> "(ILandroid/os/Bundle;)V");
> -    if (!methodID) {
> -        LOGE("setEventHandler: failed to get the callback method");
> -        return NULL;
> -    }
> -
> -    return (*env)->NewGlobalRef(env, eventHandler);
> -}
> -
>  static void debug_buffer_log(void *data, int level, const char *fmt,
>  va_list ap)
>  {
>      bool isAttached = false;
> diff --git a/libvlc/jni/libvlcjni.c b/libvlc/jni/libvlcjni.c
> index ecfb02e..6f35182 100644
> --- a/libvlc/jni/libvlcjni.c
> +++ b/libvlc/jni/libvlcjni.c
> @@ -38,7 +38,6 @@
>  #include "aout.h"
>  #include "vout.h"
>  #include "utils.h"
> -#include "native_crash_handler.h"
>  
>  #define VOUT_ANDROID_SURFACE 0
>  #define VOUT_OPENGLES2       1
> @@ -60,6 +59,26 @@ int jni_attach_thread(JNIEnv **env, const char
> *thread_name);
>  void jni_detach_thread();
>  int jni_get_env(JNIEnv **env);
>  
> +static void setLibVlcSysInstance(JNIEnv *env, jobject thiz,
> libvlc_instance_sys_t *p_sys)
> +{
> +    setLong(env, thiz, "mLibVlcInstance", (jlong)(intptr_t) p_sys);
> +}
> +
> +static libvlc_instance_sys_t *getLibVlcSysInstance(JNIEnv *env, jobject
> thiz)
> +{
> +    return (libvlc_instance_sys_t *)(intptr_t)getLong(env, thiz,
> "mLibVlcInstance");
> +}
> +
> +static void releaseMediaPlayer(JNIEnv *env, jobject thiz)
> +{
> +    libvlc_media_player_t *p_mp = getMediaPlayer(env, thiz);
> +    if (p_mp)
> +    {
> +        libvlc_media_player_stop(p_mp);
> +        libvlc_media_player_release(p_mp);
> +    }
> +}
> +
>  static void add_media_options(libvlc_media_t *p_md, JNIEnv *env,
>  jobjectArray mediaOptions)
>  {
>      int stringCount = (*env)->GetArrayLength(env, mediaOptions);
> @@ -98,24 +117,20 @@ libvlc_media_t *new_media(JNIEnv *env, jobject thiz,
> jstring fileLocation, bool
>  
>  libvlc_instance_t *getLibVlcInstance(JNIEnv *env, jobject thiz)
>  {
> -    return (libvlc_instance_t*)(intptr_t)getLong(env, thiz,
> "mLibVlcInstance");
> +    libvlc_instance_sys_t *p_sys = getLibVlcSysInstance(env, thiz);
> +    return p_sys ? p_sys->p_libvlc : NULL;
>  }
>  
> -libvlc_media_player_t *getMediaPlayer(JNIEnv *env, jobject thiz)
> +android_surf_value_t *getAndroidSurfaceInstance(JNIEnv *env, jobject
> thiz)
>  {
> -    return (libvlc_media_player_t*)(intptr_t)getLong(env, thiz,
> "mInternalMediaPlayerInstance");
> +    libvlc_instance_sys_t *p_sys = getLibVlcSysInstance(env, thiz);
> +    return p_sys ? p_sys->p_surf : NULL;
>  }
>  
> -
> -static void releaseMediaPlayer(JNIEnv *env, jobject thiz)
> +libvlc_media_player_t *getMediaPlayer(JNIEnv *env, jobject thiz)
>  {
> -    libvlc_media_player_t* p_mp = getMediaPlayer(env, thiz);
> -    if (p_mp)
> -    {
> -        libvlc_media_player_stop(p_mp);
> -        libvlc_media_player_release(p_mp);
> -        setLong(env, thiz, "mInternalMediaPlayerInstance", 0);
> -    }
> +    libvlc_instance_sys_t *p_sys = getLibVlcSysInstance(env, thiz);
> +    return p_sys ? p_sys->p_mp : NULL;
>  }
>  
>  /* Pointer to the Java virtual machine
> @@ -124,17 +139,12 @@ static void releaseMediaPlayer(JNIEnv *env, jobject
> thiz)
>   */
>  static JavaVM *myVm;
>  
> -static jobject eventHandlerInstance = NULL;
> -
>  static void vlc_event_callback(const libvlc_event_t *ev, void *data)
>  {
>      JNIEnv *env;
>  
>      bool isAttached = false;
>  
> -    if (eventHandlerInstance == NULL)
> -        return;
> -
>      if (jni_get_env(&env) < 0) {
>          if (jni_attach_thread(&env, THREAD_NAME) < 0)
>              return;
> @@ -193,20 +203,31 @@ static void vlc_event_callback(const libvlc_event_t
> *ev, void *data)
>          free(mrl);
>      }
>  
> +    /* The LibVLC object */
> +    jobject vlcObject = (jobject) data;
> +
> +    /* Get the event handler object */
> +    jclass cls = (*env)->GetObjectClass(env, vlcObject);
> +    jmethodID methodId = (*env)->GetMethodID(env, cls,
> "getEventHandler", "()Lorg/videolan/libvlc/EventHandler;");
> +    jobject eventHandlerInstance = (*env)->CallObjectMethod(env,
> vlcObject, methodId);
> +
> +    (*env)->DeleteLocalRef(env, cls);
> +
>      /* Get the object class */
> -    jclass cls = (*env)->GetObjectClass(env, eventHandlerInstance);
> +    cls = (*env)->GetObjectClass(env, eventHandlerInstance);
>      if (!cls) {
>          LOGE("EventHandler: failed to get class reference");
>          goto end;
>      }
>  
>      /* Find the callback ID */
> -    jmethodID methodID = (*env)->GetMethodID(env, cls, "callback",
> "(ILandroid/os/Bundle;)V");
> -    if (methodID) {
> -        (*env)->CallVoidMethod(env, eventHandlerInstance, methodID,
> ev->type, bundle);
> +    methodId = (*env)->GetMethodID(env, cls, "callback",
> "(ILandroid/os/Bundle;)V");
> +    if (methodId) {
> +        (*env)->CallVoidMethod(env, eventHandlerInstance, methodId,
> ev->type, bundle);
>      } else {
>          LOGE("EventHandler: failed to get the callback method");
>      }
> +    (*env)->DeleteLocalRef(env, cls);
>  
>  end:
>      (*env)->DeleteLocalRef(env, bundle);
> @@ -219,16 +240,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 VLC_JNI_VERSION;
>  }
>  
>  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.");
>  }
>  
>  int jni_attach_thread(JNIEnv **env, const char *thread_name)
> @@ -353,8 +370,6 @@ void
> Java_org_videolan_libvlc_LibVLC_nativeInit(JNIEnv *env, jobject thiz)
>      };
>      libvlc_instance_t *instance = libvlc_new(sizeof(argv) /
>      sizeof(*argv), argv);
>  
> -    setLong(env, thiz, "mLibVlcInstance", (jlong)(intptr_t) instance);
> -
>      (*env)->ReleaseStringUTFChars(env, chroma, chromastr);
>      (*env)->ReleaseStringUTFChars(env, subsencoding, subsencodingstr);
>  
> @@ -364,45 +379,45 @@ void
> Java_org_videolan_libvlc_LibVLC_nativeInit(JNIEnv *env, jobject thiz)
>          (*env)->ThrowNew(env, exc, "Unable to instantiate LibVLC");
>      }
>  
> +    /* Set values to libvlc sys instance */
> +    libvlc_instance_sys_t  *p_sys = (libvlc_instance_sys_t *) calloc(1,
> sizeof(libvlc_instance_sys_t));
> +    p_sys->p_libvlc = instance;
> +    p_sys->p_surf = (android_surf_value_t *) calloc(1,
> sizeof(android_surf_value_t));
> +    p_sys->p_this = (*env)->NewGlobalRef(env, thiz);
> +
> +    pthread_mutex_init(&p_sys->p_surf->vout_android_lock, NULL);
> +    pthread_cond_init(&p_sys->p_surf->vout_android_surf_attached, NULL);
> +
> +    setLibVlcSysInstance(env, thiz, p_sys);
> +
>      LOGI("LibVLC initialized: %p", instance);
>  
>      libvlc_log_set(instance, debug_log, &verbosity);
> -
> -    init_native_crash_handler(env, thiz);
>  }
>  
>  void Java_org_videolan_libvlc_LibVLC_nativeDestroy(JNIEnv *env, jobject
>  thiz)
>  {
> -    destroy_native_crash_handler(env);
> +    libvlc_instance_sys_t *p_sys = getLibVlcSysInstance(env, thiz);
> +    if (p_sys == NULL)
> +        return; // Already destroyed
>  
>      releaseMediaPlayer(env, thiz);
> -    jlong libVlcInstance = getLong(env, thiz, "mLibVlcInstance");
> -    if (!libVlcInstance)
> -        return; // Already destroyed
>  
> -    libvlc_instance_t *instance = (libvlc_instance_t*)(intptr_t)
> libVlcInstance;
> +    libvlc_instance_t *instance = p_sys->p_libvlc;
> +    LOGI("LibVLC destroyed: %p", instance);
> +
>      libvlc_log_unset(instance);
>      libvlc_release(instance);
>  
> -    setLong(env, thiz, "mLibVlcInstance", 0);
> -}
> +    (*env)->DeleteGlobalRef(env, p_sys->p_this);
>  
> -void Java_org_videolan_libvlc_LibVLC_detachEventHandler(JNIEnv *env,
> jobject thiz)
> -{
> -    if (eventHandlerInstance != NULL) {
> -        (*env)->DeleteGlobalRef(env, eventHandlerInstance);
> -        eventHandlerInstance = NULL;
> -    }
> -}
> +    pthread_mutex_destroy(&p_sys->p_surf->vout_android_lock);
> +    pthread_cond_destroy(&p_sys->p_surf->vout_android_surf_attached);
>  
> -void Java_org_videolan_libvlc_LibVLC_setEventHandler(JNIEnv *env,
> jobject thiz, jobject eventHandler)
> -{
> -    if (eventHandlerInstance != NULL) {
> -        (*env)->DeleteGlobalRef(env, eventHandlerInstance);
> -        eventHandlerInstance = NULL;
> -    }
> +    free(p_sys->p_surf);
> +    free(p_sys);
>  
> -    eventHandlerInstance = getEventHandlerReference(env, thiz,
> eventHandler);
> +    setLibVlcSysInstance(env, thiz, NULL);
>  }
>  
>  void Java_org_videolan_libvlc_LibVLC_playMRL(JNIEnv *env, jobject thiz,
> @@ -411,25 +426,24 @@ void Java_org_videolan_libvlc_LibVLC_playMRL(JNIEnv
> *env, jobject thiz,
>      /* Release previous media player, if any */
>      releaseMediaPlayer(env, thiz);
>  
> -    libvlc_instance_t *p_instance = getLibVlcInstance(env, thiz);
> +    libvlc_instance_sys_t *p_sys = getLibVlcSysInstance(env, thiz);
>  
>      /* Create a media player playing environment */
> -    libvlc_media_player_t *mp = libvlc_media_player_new(p_instance);
> -    libvlc_media_player_set_video_title_display(mp,
> libvlc_position_disable, 0);
> -    jobject myJavaLibVLC = (*env)->NewGlobalRef(env, thiz);
> +    p_sys->p_mp = libvlc_media_player_new(p_sys->p_libvlc);
> +
> +    libvlc_media_player_set_video_title_display(p_sys->p_mp,
> libvlc_position_disable, 0);
>  
>      //if AOUT_AUDIOTRACK_JAVA, we use amem
>      jclass cls = (*env)->GetObjectClass(env, thiz);
>      jmethodID methodId = (*env)->GetMethodID(env, cls, "getAout",
>      "()I");
>      if ( (*env)->CallIntMethod(env, thiz, methodId) ==
>      AOUT_AUDIOTRACK_JAVA )
>      {
> -        libvlc_audio_set_callbacks(mp, aout_play, aout_pause, NULL,
> NULL, NULL,
> -                                   (void*) myJavaLibVLC);
> -        libvlc_audio_set_format_callbacks(mp, aout_open, aout_close);
> +        libvlc_audio_set_callbacks(p_sys->p_mp, aout_play, aout_pause,
> NULL, NULL, NULL, p_sys->p_this);
> +        libvlc_audio_set_format_callbacks(p_sys->p_mp, aout_open,
> aout_close);
>      }
>  
>      /* Connect the event manager */
> -    libvlc_event_manager_t *ev = libvlc_media_player_event_manager(mp);
> +    libvlc_event_manager_t *ev =
> libvlc_media_player_event_manager(p_sys->p_mp);
>      static const libvlc_event_type_t mp_events[] = {
>          libvlc_MediaPlayerPlaying,
>          libvlc_MediaPlayerPaused,
> @@ -441,10 +455,7 @@ void Java_org_videolan_libvlc_LibVLC_playMRL(JNIEnv
> *env, jobject thiz,
>          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);
> -
> -    /* Keep a pointer to this media player */
> -    setLong(env, thiz, "mInternalMediaPlayerInstance",
> (jlong)(intptr_t)mp);
> +        libvlc_event_attach(ev, mp_events[i], vlc_event_callback,
> p_sys->p_this);
>  
>      cls = (*env)->GetObjectClass(env, thiz);
>      jmethodID methodID = (*env)->GetMethodID(env, cls, "applyEqualizer",
>      "()V");
> @@ -452,13 +463,16 @@ void Java_org_videolan_libvlc_LibVLC_playMRL(JNIEnv
> *env, jobject thiz,
>  
>      const char* p_mrl = (*env)->GetStringUTFChars(env, mrl, 0);
>  
> -    libvlc_media_t* p_md = libvlc_media_new_location(p_instance, p_mrl);
> +    libvlc_media_t* p_md = libvlc_media_new_location(p_sys->p_libvlc,
> p_mrl);
>      /* media options */
>      if (mediaOptions != NULL)
>          add_media_options(p_md, env, mediaOptions);
>  
>      (*env)->ReleaseStringUTFChars(env, mrl, p_mrl);
>  
> +    /* set the Android surface value structure before playing */
> +    libvlc_media_player_set_androidobject(p_sys->p_mp, p_sys->p_surf);
> +
>      /* 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[] = {
> @@ -466,10 +480,10 @@ void Java_org_videolan_libvlc_LibVLC_playMRL(JNIEnv
> *env, jobject thiz,
>          libvlc_MediaMetaChanged,
>      };
>      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, p_sys->p_this);
>  
> -    libvlc_media_player_set_media(mp, p_md);
> -    libvlc_media_player_play(mp);
> +    libvlc_media_player_set_media(p_sys->p_mp, p_md);
> +    libvlc_media_player_play(p_sys->p_mp);
>  }
>  
>  jfloat Java_org_videolan_libvlc_LibVLC_getRate(JNIEnv *env, jobject
>  thiz) {
> @@ -654,23 +668,26 @@ void
> Java_org_videolan_libvlc_LibVLC_playerNavigate(JNIEnv *env, jobject thiz,
> j
>          libvlc_media_player_navigate(mp, (unsigned) nav);
>  }
>  
> -// TODO: remove static variables
> -static int i_window_width = 0;
> -static int i_window_height = 0;
> -
>  void Java_org_videolan_libvlc_LibVLC_setWindowSize(JNIEnv *env, jobject
>  thiz, jint width, jint height)
>  {
> -    pthread_mutex_lock(&vout_android_lock);
> -    i_window_width = width;
> -    i_window_height = height;
> -    pthread_mutex_unlock(&vout_android_lock);
> +    android_surf_value_t *android_surface =
> getAndroidSurfaceInstance(env, thiz);
> +    if (android_surface == NULL)
> +        return;
> +
> +    pthread_mutex_lock(&android_surface->vout_android_lock);
> +    android_surface->i_window_width = width;
> +    android_surface->i_window_height = height;
> +    pthread_mutex_unlock(&android_surface->vout_android_lock);
>  }
>  
> -int jni_GetWindowSize(int *width, int *height)
> +int jni_GetWindowSize(android_surf_value_t *android_surface, int *width,
> int *height)
>  {
> -    pthread_mutex_lock(&vout_android_lock);
> -    *width = i_window_width;
> -    *height = i_window_height;
> -    pthread_mutex_unlock(&vout_android_lock);
> +    if (android_surface == NULL)
> +        return;
> +
> +    pthread_mutex_lock(&android_surface->vout_android_lock);
> +    *width = android_surface->i_window_width;
> +    *height = android_surface->i_window_height;
> +    pthread_mutex_unlock(&android_surface->vout_android_lock);
>      return 0;
>  }
> diff --git a/libvlc/jni/native_crash_handler.c
> b/libvlc/jni/native_crash_handler.c
> index 2cb1590..73b1e1e 100644
> --- a/libvlc/jni/native_crash_handler.c
> +++ b/libvlc/jni/native_crash_handler.c
> @@ -23,7 +23,7 @@
>  #include "native_crash_handler.h"
>  
>  static struct sigaction old_actions[NSIG];
> -static jobject j_libVLC;
> +static jobject j_NativeCrashHandler = NULL;
>  
>  #define THREAD_NAME "native_crash_handler"
>  extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
> @@ -54,9 +54,9 @@ 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);
> +    jclass cls = (*env)->GetObjectClass(env, j_NativeCrashHandler);
>      jmethodID methodId = (*env)->GetMethodID(env, cls, "onNativeCrash",
>      "()V");
> -    (*env)->CallVoidMethod(env, j_libVLC, methodId);
> +    (*env)->CallVoidMethod(env, j_NativeCrashHandler, methodId);
>  
>      (*env)->DeleteLocalRef(env, cls);
>      jni_detach_thread();
> @@ -65,10 +65,8 @@ void sigaction_callback(int signal, siginfo_t *info,
> void *reserved)
>      old_actions[signal].sa_handler(signal);
>  }
>  
> -
> -void init_native_crash_handler(JNIEnv *env, jobject j_libVLC_local)
> +void Java_org_videolan_libvlc_NativeCrashHandler_nativeInit(JNIEnv *env,
> jobject thiz)
>  {
> -    j_libVLC = (*env)->NewGlobalRef(env, j_libVLC_local);
>      struct sigaction handler;
>      memset(&handler, 0, sizeof(struct sigaction));
>  
> @@ -81,17 +79,6 @@ void init_native_crash_handler(JNIEnv *env, jobject
> j_libVLC_local)
>          const int s = monitored_signals[i];
>          sigaction(s, &handler, &old_actions[s]);
>      }
> -}
> -
> -
> -void destroy_native_crash_handler(JNIEnv *env)
> -{
> -    // Uninstall the signal handlers and restore their old actions.
> -    for (unsigned i = 0; i < sizeof(monitored_signals) / sizeof(int);
> ++i)
> -    {
> -        const int s = monitored_signals[i];
> -        sigaction(s, &old_actions[s], NULL);
> -    }
>  
> -    (*env)->DeleteGlobalRef(env, j_libVLC);
> -}
> +    j_NativeCrashHandler = (*env)->NewGlobalRef(env, thiz);;
> +}
> \ No newline at end of file
> diff --git a/libvlc/jni/native_crash_handler.h
> b/libvlc/jni/native_crash_handler.h
> index a57e61e..d220af5 100644
> --- a/libvlc/jni/native_crash_handler.h
> +++ b/libvlc/jni/native_crash_handler.h
> @@ -23,7 +23,4 @@
>  
>  #include <jni.h>
>  
> -void init_native_crash_handler(JNIEnv *env, jobject j_libVLC_local);
> -void destroy_native_crash_handler(JNIEnv *env);
> -
> -#endif // LIBVLCJNI_NATIVE_CRASH_HANDLER_H
> +#endif // LIBVLCJNI_NATIVE_CRASH_HANDLER_H
> \ No newline at end of file
> diff --git a/libvlc/jni/utils.h b/libvlc/jni/utils.h
> index f5b9f8d..e136bcb 100644
> --- a/libvlc/jni/utils.h
> +++ b/libvlc/jni/utils.h
> @@ -43,8 +43,6 @@ void arrayListGetIDs(JNIEnv *env, jclass* p_class,
> jmethodID* p_add, jmethodID*
>  
>  void arrayListStringAdd(JNIEnv *env, jclass class, jmethodID methodID,
>  jobject arrayList, const char* str);
>  
> -jobject getEventHandlerReference(JNIEnv *env, jobject thiz, jobject
> eventHandler);
> -
>  void debug_log(void *data, int level, const libvlc_log_t *ctx, const
>  char *fmt, va_list ap);
>  
>  #endif // LIBVLCJNI_UTILS_H
> diff --git a/libvlc/jni/vout.c b/libvlc/jni/vout.c
> index 04c933c..7cdc234 100644
> --- a/libvlc/jni/vout.c
> +++ b/libvlc/jni/vout.c
> @@ -22,100 +22,104 @@
>  #include <vlc_common.h>
>  
>  #include <jni.h>
> +#include "vout.h"
> +
> +#define LOG_TAG "VLC/JNI/vout"
> +#include "log.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() {
> -    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
> *android_surface) {
> +    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(android_surf_value_t
> *android_surface) {
> +    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;
>  }
>  
> -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_LockAndroidSurface(android_surf_value_t *android_surface) {
> +    pthread_mutex_lock(&android_surface->vout_android_lock);
>  }
>  
> -void jni_UnlockAndroidSurface() {
> -    pthread_mutex_unlock(&vout_android_lock);
> +void jni_UnlockAndroidSurface(android_surf_value_t *android_surface) {
> +    pthread_mutex_unlock(&android_surface->vout_android_lock);
>  }
>  
> -void jni_EventHardwareAccelerationError()
> +void jni_EventHardwareAccelerationError(android_surf_value_t
> *android_surface)
>  {
>      JNIEnv *env;
>      bool isAttached = false;
>  
> -    pthread_mutex_lock(&vout_android_lock);
> -    if (vout_android_gui == NULL) {
> -        pthread_mutex_unlock(&vout_android_lock);
> +    pthread_mutex_lock(&android_surface->vout_android_lock);
> +    if (android_surface->vout_android_gui == NULL) {
> +        pthread_mutex_unlock(&android_surface->vout_android_lock);
>          return;
>      }
>  
>      if (jni_get_env(&env) < 0) {
>          if (jni_attach_thread(&env, THREAD_NAME) < 0) {
> -            pthread_mutex_unlock(&vout_android_lock);
> +            pthread_mutex_unlock(&android_surface->vout_android_lock);
>              return;
>          }
>          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();
> -    pthread_mutex_unlock(&vout_android_lock);
> +    pthread_mutex_unlock(&android_surface->vout_android_lock);
>  }
>  
> -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)
>  {
> -    pthread_mutex_lock(&vout_android_lock);
> -    if (vout_android_gui == NULL) {
> -        pthread_mutex_unlock(&vout_android_lock);
> +    pthread_mutex_lock(&android_surface->vout_android_lock);
> +    if (android_surface->vout_android_gui == NULL) {
> +        pthread_mutex_unlock(&android_surface->vout_android_lock);
>          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);
> -    pthread_mutex_unlock(&vout_android_lock);
> +    pthread_mutex_unlock(&android_surface->vout_android_lock);
>  }
>  
> -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();
>  }
>  
> -void *jni_AndroidJavaSurfaceToNativeSurface(jobject *surf)
> +void *jni_AndroidJavaSurfaceToNativeSurface(jobject surf)
>  {
>      JNIEnv *p_env;
>      jclass clz;
> @@ -154,28 +158,29 @@ void *jni_AndroidJavaSurfaceToNativeSurface(jobject
> *surf)
>      return native_surface;
>  }
>  
> -int jni_ConfigureSurface(jobject jsurf, int width, int height, int hal,
> bool *configured)
> +int jni_ConfigureSurface(android_surf_value_t *android_surface, int
> width, int height, int hal, bool *configured)
>  {
>      JNIEnv *p_env;
>      bool isAttached = false;
>      int ret;
>  
> -    pthread_mutex_lock(&vout_android_lock);
> -    if (vout_android_gui == NULL) {
> -        pthread_mutex_unlock(&vout_android_lock);
> +    pthread_mutex_lock(&android_surface->vout_android_lock);
> +    if (android_surface->vout_android_gui == NULL) {
> +        pthread_mutex_unlock(&android_surface->vout_android_lock);
>          return -1;
>      }
>  
>      if (jni_get_env(&p_env) < 0) {
>          if (jni_attach_thread(&p_env, THREAD_NAME) < 0) {
> -            pthread_mutex_unlock(&vout_android_lock);
> +            pthread_mutex_unlock(&android_surface->vout_android_lock);
>              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,
> +                                  
> android_surface->vout_android_java_surf, width, height, hal);
>      if (ret >= 0 && configured)
>          *configured = ret == 1;
>  
> @@ -183,62 +188,81 @@ int jni_ConfigureSurface(jobject jsurf, int width,
> int height, int hal, bool *co
>  
>      if (isAttached)
>          jni_detach_thread();
> -    pthread_mutex_unlock(&vout_android_lock);
> +    pthread_mutex_unlock(&android_surface->vout_android_lock);
>      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 =
> getAndroidSurfaceInstance(env, thiz);
> +    if (android_surface == NULL)
> +        return;
> +
> +    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);
> -
> -    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);
> +    android_surf_value_t * android_surface =
> getAndroidSurfaceInstance(env, thiz);
> +    if (android_surface == NULL)
> +        return;
> +
> +    pthread_mutex_lock(&android_surface->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 =
> getAndroidSurfaceInstance(env, thiz);
> +    if (android_surface == NULL)
> +        return;
> +
> +    pthread_mutex_lock(&android_surface->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 = 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 =
> getAndroidSurfaceInstance(env, thiz);
> +    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 =
> getAndroidSurfaceInstance(env, thiz);
> +    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..ac13413 100644
> --- a/libvlc/jni/vout.h
> +++ b/libvlc/jni/vout.h
> @@ -21,8 +21,26 @@
>  #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_gui;
> +    jobject           vout_android_java_surf;
> +    jobject           vout_android_subtitles_surf;
> +    bool              vout_video_player_activity_created;
> +    int               i_window_width;
> +    int               i_window_height;
> +} android_surf_value_t;
> +
> +typedef struct libvlc_instance_sys_t {
> +    void                    *p_this;
> +    libvlc_instance_t       *p_libvlc;
> +    libvlc_media_player_t   *p_mp;
> +    android_surf_value_t    *p_surf;
> +} libvlc_instance_sys_t;
> +
> +android_surf_value_t *getAndroidSurfaceInstance(JNIEnv *env, jobject
> thiz);
>  
>  #endif // LIBVLCJNI_VOUT_H
> diff --git a/libvlc/src/org/videolan/libvlc/EventHandler.java
> b/libvlc/src/org/videolan/libvlc/EventHandler.java
> index 4ec0861..2d13d30 100644
> --- a/libvlc/src/org/videolan/libvlc/EventHandler.java
> +++ b/libvlc/src/org/videolan/libvlc/EventHandler.java
> @@ -97,19 +97,11 @@ public class EventHandler {
>      public static final int HardwareAccelerationError         = 0x3000;
>  
>      private ArrayList<Handler> mEventHandler;
> -    private static EventHandler mInstance;
>  
>      EventHandler() {
>          mEventHandler = new ArrayList<Handler>();
>      }
>  
> -    public static EventHandler getInstance() {
> -        if (mInstance == null) {
> -            mInstance = new EventHandler();
> -        }
> -        return mInstance;
> -    }
> -
>      public void addHandler(Handler handler) {
>          if (!mEventHandler.contains(handler))
>              mEventHandler.add(handler);
> diff --git a/libvlc/src/org/videolan/libvlc/LibVLC.java
> b/libvlc/src/org/videolan/libvlc/LibVLC.java
> index fde2704..aaf640f 100644
> --- a/libvlc/src/org/videolan/libvlc/LibVLC.java
> +++ b/libvlc/src/org/videolan/libvlc/LibVLC.java
> @@ -1,7 +1,7 @@
>  /*****************************************************************************
>   * LibVLC.java
>   *****************************************************************************
> - * Copyright © 2010-2013 VLC authors and VideoLAN
> + * Copyright © 2010-2014 VLC authors and VideoLAN
>   *
>   * This program is free software; you can redistribute it and/or modify
>   it
>   * under the terms of the GNU Lesser General Public License as published
>   by
> @@ -25,7 +25,6 @@ import java.util.ArrayList;
>  import java.util.Map;
>  
>  import android.content.Context;
> -import android.os.Build;
>  import android.util.Log;
>  import android.view.Surface;
>  
> @@ -61,11 +60,12 @@ public class LibVLC {
>  
>      private static LibVLC sInstance;
>  
> +    private final EventHandler eventHandler = new EventHandler();
> +
>      /** libVLC instance C pointer */
>      private long mLibVlcInstance = 0; // Read-only, reserved for JNI
>      /** libvlc_media_player pointer and index */
>      private int mInternalMediaPlayerIndex = 0; // Read-only, reserved
>      for JNI
> -    private long mInternalMediaPlayerInstance = 0; // Read-only,
> reserved for JNI
>  
>      private MediaList mMediaList; // Pointer to media list being
>      followed
>      private MediaList mPrimaryList; // Primary/default media list; see
>      getPrimaryMediaList()
> @@ -99,9 +99,6 @@ public class LibVLC {
>      /** Path of application-specific cache */
>      private String mCachePath = "";
>  
> -    /** Native crash handler */
> -    private OnNativeCrashListener mOnNativeCrashListener;
> -
>      /** Check in libVLC already initialized otherwise crash */
>      private boolean mIsInitialized = false;
>      public native void attachSurface(Surface surface, IVideoPlayer
>      player);
> @@ -113,52 +110,6 @@ public class LibVLC {
>  
>      public native void eventVideoPlayerActivityCreated(boolean created);
>  
> -    /* Load library before object instantiation */
> -    static {
> -        if (Build.VERSION.SDK_INT >=
> Build.VERSION_CODES.GINGERBREAD_MR1) {
> -            try {
> -                if (Build.VERSION.SDK_INT <=
> Build.VERSION_CODES.HONEYCOMB_MR1)
> -                    System.loadLibrary("anw.10");
> -                else if (Build.VERSION.SDK_INT <=
> Build.VERSION_CODES.HONEYCOMB_MR2)
> -                    System.loadLibrary("anw.13");
> -                else if (Build.VERSION.SDK_INT <=
> Build.VERSION_CODES.JELLY_BEAN_MR1)
> -                    System.loadLibrary("anw.14");
> -                else
> -                    System.loadLibrary("anw.18");
> -            } catch (Throwable t) {
> -                Log.w(TAG, "Unable to load the anw library: " + t);
> -            }
> -        }
> -
> -        try {
> -            if (Build.VERSION.SDK_INT <=
> Build.VERSION_CODES.GINGERBREAD_MR1)
> -                System.loadLibrary("iomx.10");
> -            else if (Build.VERSION.SDK_INT <=
> Build.VERSION_CODES.HONEYCOMB_MR2)
> -                System.loadLibrary("iomx.13");
> -            else if (Build.VERSION.SDK_INT <=
> Build.VERSION_CODES.JELLY_BEAN_MR1)
> -                System.loadLibrary("iomx.14");
> -            else if (Build.VERSION.SDK_INT <=
> Build.VERSION_CODES.JELLY_BEAN_MR2)
> -                System.loadLibrary("iomx.18");
> -            else if (Build.VERSION.SDK_INT <=
> Build.VERSION_CODES.KITKAT)
> -                System.loadLibrary("iomx.19");
> -        } catch (Throwable t) {
> -            // No need to warn if it isn't found, when we intentionally
> don't build these except for debug
> -            if (Build.VERSION.SDK_INT <=
> Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
> -                Log.w(TAG, "Unable to load the iomx library: " + t);
> -        }
> -        try {
> -            System.loadLibrary("vlcjni");
> -        } catch (UnsatisfiedLinkError ule) {
> -            Log.e(TAG, "Can't load vlcjni library: " + ule);
> -            /// FIXME Alert user
> -            System.exit(1);
> -        } catch (SecurityException se) {
> -            Log.e(TAG, "Encountered a security issue when loading vlcjni
> library: " + se);
> -            /// FIXME Alert user
> -            System.exit(1);
> -        }
> -    }
> -
>      /**
>       * Singleton constructor of libVLC Without surface and vout to
>       create the
>       * thumbnail and get information e.g. on the MediaLibraryActivity
> @@ -190,10 +141,9 @@ public class LibVLC {
>      }
>  
>      /**
> -     * Constructor
> -     * It is private because this class is a singleton.
> +     * Constructor.
>       */
> -    private LibVLC() {
> +    public LibVLC() {
>          mAout = new AudioOutput();
>      }
>  
> @@ -259,7 +209,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();
> @@ -270,6 +220,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.
>       */
> @@ -491,11 +450,11 @@ public class LibVLC {
>          applyEqualizer();
>      }
>  
> -    private void applyEqualizer()
> +    protected void applyEqualizer()
>      {
> -        setNativeEqualizer(mInternalMediaPlayerInstance,
> this.equalizer);
> +        setNativeEqualizer(this.equalizer);
>      }
> -    private native int setNativeEqualizer(long mediaPlayer, float[]
> bands);
> +    private native int setNativeEqualizer(float[] bands);
>  
>      public boolean frameSkipEnabled() {
>          return frameSkip;
> @@ -531,7 +490,7 @@ public class LibVLC {
>      public void init(Context context) throws LibVlcException {
>          Log.v(TAG, "Initializing LibVLC");
>          mDebugLogBuffer = new StringBuffer();
> -        if (!mIsInitialized) {
> +        if (LibVlcUtil.isLibraryLoaded() && !mIsInitialized) {
>              if(!LibVlcUtil.hasCompatibleCPU(context)) {
>                  Log.e(TAG, LibVlcUtil.getErrorMsg());
>                  throw new LibVlcException();
> @@ -541,7 +500,6 @@ public class LibVLC {
>              mCachePath = (cacheDir != null) ? cacheDir.getAbsolutePath()
>              : null;
>              nativeInit();
>              mMediaList = mPrimaryList = new MediaList(this);
> -            setEventHandler(EventHandler.getInstance());
>              mIsInitialized = true;
>          }
>      }
> @@ -553,7 +511,6 @@ public class LibVLC {
>      public void destroy() {
>          Log.v(TAG, "Destroying LibVLC instance");
>          nativeDestroy();
> -        detachEventHandler();
>          mIsInitialized = false;
>      }
>  
> @@ -833,27 +790,14 @@ public class LibVLC {
>          return mMediaList.expandMedia(mInternalMediaPlayerIndex);
>      }
>  
> -    private native void setEventHandler(EventHandler eventHandler);
> -
> -    private native void detachEventHandler();
> -
>      public native float[] getBands();
>  
>      public native String[] getPresets();
>  
>      public native float[] getPreset(int index);
>  
> -    public static interface OnNativeCrashListener {
> -        public void onNativeCrash();
> -    }
> -
> -    public void setOnNativeCrashListener(OnNativeCrashListener l) {
> -        mOnNativeCrashListener = l;
> -    }
> -
> -    private void onNativeCrash() {
> -        if (mOnNativeCrashListener != null)
> -            mOnNativeCrashListener.onNativeCrash();
> +    public EventHandler getEventHandler() {
> +        return eventHandler;
>      }
>  
>      public String getCachePath() {
> diff --git a/libvlc/src/org/videolan/libvlc/LibVlcUtil.java
> b/libvlc/src/org/videolan/libvlc/LibVlcUtil.java
> index 0ddf780..6c7dc97 100644
> --- a/libvlc/src/org/videolan/libvlc/LibVlcUtil.java
> +++ b/libvlc/src/org/videolan/libvlc/LibVlcUtil.java
> @@ -1,7 +1,7 @@
>  /*****************************************************************************
>   * LibVlcUtil.java
>   *****************************************************************************
> - * Copyright © 2011-2013 VLC authors and VideoLAN
> + * Copyright © 2011-2014 VLC authors and VideoLAN
>   *
>   * This program is free software; you can redistribute it and/or modify
>   it
>   * under the terms of the GNU Lesser General Public License as published
>   by
> @@ -39,6 +39,60 @@ import android.util.Log;
>  public class LibVlcUtil {
>      public final static String TAG = "VLC/LibVLC/Util";
>  
> +    public static boolean libraryLoaded = false;
> +
> +    /* Load library before object instantiation */
> +    static {
> +        if (Build.VERSION.SDK_INT >=
> Build.VERSION_CODES.GINGERBREAD_MR1) {
> +            try {
> +                if (Build.VERSION.SDK_INT <=
> Build.VERSION_CODES.HONEYCOMB_MR1)
> +                    System.loadLibrary("anw.10");
> +                else if (Build.VERSION.SDK_INT <=
> Build.VERSION_CODES.HONEYCOMB_MR2)
> +                    System.loadLibrary("anw.13");
> +                else if (Build.VERSION.SDK_INT <=
> Build.VERSION_CODES.JELLY_BEAN_MR1)
> +                    System.loadLibrary("anw.14");
> +                else
> +                    System.loadLibrary("anw.18");
> +            } catch (Throwable t) {
> +                Log.w(TAG, "Unable to load the anw library: " + t);
> +            }
> +        }
> +
> +        try {
> +            if (Build.VERSION.SDK_INT <=
> Build.VERSION_CODES.GINGERBREAD_MR1)
> +                System.loadLibrary("iomx.10");
> +            else if (Build.VERSION.SDK_INT <=
> Build.VERSION_CODES.HONEYCOMB_MR2)
> +                System.loadLibrary("iomx.13");
> +            else if (Build.VERSION.SDK_INT <=
> Build.VERSION_CODES.JELLY_BEAN_MR1)
> +                System.loadLibrary("iomx.14");
> +            else if (Build.VERSION.SDK_INT <=
> Build.VERSION_CODES.JELLY_BEAN_MR2)
> +                System.loadLibrary("iomx.18");
> +            else if (Build.VERSION.SDK_INT <=
> Build.VERSION_CODES.KITKAT)
> +                System.loadLibrary("iomx.19");
> +        } catch (Throwable t) {
> +            // No need to warn if it isn't found, when we intentionally
> don't build these except for debug
> +            if (Build.VERSION.SDK_INT <=
> Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
> +                Log.w(TAG, "Unable to load the iomx library: " + t);
> +        }
> +        try {
> +            System.loadLibrary("vlcjni");
> +        } catch (UnsatisfiedLinkError ule) {
> +            Log.e(TAG, "Can't load vlcjni library: " + ule);
> +            /// FIXME Alert user
> +            System.exit(1);
> +        } catch (SecurityException se) {
> +            Log.e(TAG, "Encountered a security issue when loading vlcjni
> library: " + se);
> +            /// FIXME Alert user
> +            System.exit(1);
> +        }
> +
> +        libraryLoaded = true;
> +    }
> +
> +    public static boolean isLibraryLoaded() {
> +        return libraryLoaded;
> +    }
> +
>      public static boolean isFroyoOrLater()
>      {
>          return android.os.Build.VERSION.SDK_INT >=
>          android.os.Build.VERSION_CODES.FROYO;
> diff --git a/libvlc/src/org/videolan/libvlc/NativeCrashHandler.java
> b/libvlc/src/org/videolan/libvlc/NativeCrashHandler.java
> new file mode 100644
> index 0000000..ec10698
> --- /dev/null
> +++ b/libvlc/src/org/videolan/libvlc/NativeCrashHandler.java
> @@ -0,0 +1,64 @@
> +/*****************************************************************************
> + * NativeCrashHandler.java
> +
> *****************************************************************************
> + * Copyright © 2014 VLC authors and VideoLAN
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA
> 02110-1301, USA.
> +
> *****************************************************************************/
> +
> +package org.videolan.libvlc;
> +
> +import android.os.Build;
> +import android.util.Log;
> +
> +public class NativeCrashHandler {
> +    public final static String TAG = "VLC/NativeCrashHandler";
> +
> +    /** Native crash handler */
> +    private OnNativeCrashListener mOnNativeCrashListener;
> +
> +    private static NativeCrashHandler sInstance;
> +
> +    private NativeCrashHandler() {
> +    }
> +
> +    public static interface OnNativeCrashListener {
> +        public void onNativeCrash();
> +    }
> +
> +    public static NativeCrashHandler getInstance() {
> +        synchronized (NativeCrashHandler.class) {
> +            if (sInstance == null) {
> +                /* First call */
> +                sInstance = new NativeCrashHandler();
> +                if (LibVlcUtil.isLibraryLoaded())
> +                    sInstance.nativeInit();
> +            }
> +        }
> +
> +        return sInstance;
> +    }
> +
> +    public void setOnNativeCrashListener(OnNativeCrashListener l) {
> +        mOnNativeCrashListener = l;
> +    }
> +
> +    public void onNativeCrash() {
> +        if (mOnNativeCrashListener != null)
> +            mOnNativeCrashListener.onNativeCrash();
> +    }
> +
> +    private native void nativeInit();
> +}
> \ No newline at end of file
> diff --git a/vlc-android/src/org/videolan/vlc/VLCApplication.java
> b/vlc-android/src/org/videolan/vlc/VLCApplication.java
> index e915a46..ba34827 100644
> --- a/vlc-android/src/org/videolan/vlc/VLCApplication.java
> +++ b/vlc-android/src/org/videolan/vlc/VLCApplication.java
> @@ -1,7 +1,7 @@
>  /*****************************************************************************
>   * VLCApplication.java
>   *****************************************************************************
> - * Copyright © 2010-2013 VLC authors and VideoLAN
> + * Copyright © 2010-2014 VLC authors and VideoLAN
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License as published by
> @@ -21,11 +21,14 @@ package org.videolan.vlc;
>  
>  import java.util.Locale;
>  
> +import org.videolan.libvlc.NativeCrashHandler;
>  import org.videolan.vlc.gui.audio.AudioUtil;
> +import org.videolan.vlc.gui.NativeCrashActivity;
>  import org.videolan.vlc.util.BitmapCache;
>  
>  import android.app.Application;
>  import android.content.Context;
> +import android.content.Intent;
>  import android.content.SharedPreferences;
>  import android.content.res.Configuration;
>  import android.content.res.Resources;
> @@ -81,6 +84,16 @@ public class VLCApplication extends Application {
>          MediaDatabase.getInstance();
>          // Prepare cache folder constants
>          AudioUtil.prepareCacheFolder(this);
> +
> +        NativeCrashHandler.getInstance().setOnNativeCrashListener(new
> NativeCrashHandler.OnNativeCrashListener() {
> +            @Override
> +            public void onNativeCrash() {
> +                Intent i = new Intent(instance,
> NativeCrashActivity.class);
> +                i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
> +                i.putExtra("PID", android.os.Process.myPid());
> +                instance.startActivity(i);
> +            }
> +        });
>      }
>  
>      /**
> diff --git a/vlc-android/src/org/videolan/vlc/audio/AudioService.java
> b/vlc-android/src/org/videolan/vlc/audio/AudioService.java
> index c33abc8..d039fba 100644
> --- a/vlc-android/src/org/videolan/vlc/audio/AudioService.java
> +++ b/vlc-android/src/org/videolan/vlc/audio/AudioService.java
> @@ -116,7 +116,6 @@ public class AudioService extends Service {
>  
>      private LibVLC mLibVLC;
>      private HashMap<IAudioServiceCallback, Integer> mCallback;
> -    private EventHandler mEventHandler;
>      private OnAudioFocusChangeListener audioFocusListener;
>      private boolean mDetectHeadset = true;
>      private PowerManager.WakeLock mWakeLock;
> @@ -165,7 +164,6 @@ public class AudioService extends Service {
>          mPrevIndex = -1;
>          mNextIndex = -1;
>          mPrevious = new Stack<Integer>();
> -        mEventHandler = EventHandler.getInstance();
>          mRemoteControlClientReceiverComponent = new
>          ComponentName(getPackageName(),
>                  RemoteControlClientReceiver.class.getName());
>  
> @@ -346,7 +344,7 @@ public class AudioService extends Service {
>              }
>  
>              /*
> -             * Incoming Call : Pause if VLC is playing audio or video. 
> +             * Incoming Call : Pause if VLC is playing audio or video.
>               */
>              if
>              (action.equalsIgnoreCase(VLCApplication.INCOMING_CALL_INTENT))
>              {
>                  mWasPlayingAudio = mLibVLC.isPlaying() &&
>                  mLibVLC.getVideoTracksCount() < 1;
> @@ -625,7 +623,7 @@ public class AudioService extends Service {
>          String MRL = mLibVLC.getMediaList().getMRL(mCurrentIndex);
>          int index = mCurrentIndex;
>          mCurrentIndex = -1;
> -        mEventHandler.removeHandler(mVlcEventHandler);
> +        mLibVLC.getEventHandler().removeHandler(mVlcEventHandler);
>          // Preserve playback when switching to video
>          hideNotification(false);
>  
> @@ -833,7 +831,7 @@ public class AudioService extends Service {
>  
>      private void stop() {
>          mLibVLC.stop();
> -        mEventHandler.removeHandler(mVlcEventHandler);
> +        mLibVLC.getEventHandler().removeHandler(mVlcEventHandler);
>          mLibVLC.getMediaList().getEventHandler().removeHandler(mListEventHandler);
>          setRemoteControlClientPlaybackState(EventHandler.MediaPlayerStopped);
>          mCurrentIndex = -1;
> @@ -1158,7 +1156,7 @@ public class AudioService extends Service {
>                  throws RemoteException {
>  
>              Log.v(TAG, "Loading position " +
>              ((Integer)position).toString() + " in " +
>              mediaPathList.toString());
> -            mEventHandler.addHandler(mVlcEventHandler);
> +            mLibVLC.getEventHandler().addHandler(mVlcEventHandler);
>  
>              mLibVLC.getMediaList().getEventHandler().removeHandler(mListEventHandler);
>              mLibVLC.setMediaList();
> @@ -1226,7 +1224,7 @@ public class AudioService extends Service {
>                  mCurrentIndex = 0;
>              }
>  
> -            mEventHandler.addHandler(mVlcEventHandler);
> +            mLibVLC.getEventHandler().addHandler(mVlcEventHandler);
>              mLibVLC.playIndex(mCurrentIndex);
>              mHandler.sendEmptyMessage(SHOW_PROGRESS);
>              setUpRemoteControlClient();
> @@ -1250,7 +1248,7 @@ public class AudioService extends Service {
>  
>              if(URI == null || !mLibVLC.isPlaying())
>                  return;
> -            mEventHandler.addHandler(mVlcEventHandler);
> +            mLibVLC.getEventHandler().addHandler(mVlcEventHandler);
>              mCurrentIndex = index;
>  
>              // Notify everyone
> 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 4cf4793..195de50 100644
> --- a/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.java
> +++ b/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.java
> @@ -439,8 +439,7 @@ public class VideoPlayerActivity extends
> ActionBarActivity implements IVideoPlay
>          // SurfaceView is now available for MediaCodec direct rendering.
>          mLibVLC.eventVideoPlayerActivityCreated(true);
>  
> -        EventHandler em = EventHandler.getInstance();
> -        em.addHandler(eventHandler);
> +        mLibVLC.getEventHandler().addHandler(eventHandler);
>  
>          this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
>  
> @@ -590,8 +589,7 @@ public class VideoPlayerActivity extends
> ActionBarActivity implements IVideoPlay
>          super.onDestroy();
>          unregisterReceiver(mReceiver);
>  
> -        EventHandler em = EventHandler.getInstance();
> -        em.removeHandler(eventHandler);
> +        mLibVLC.getEventHandler().removeHandler(eventHandler);
>  
>          // MediaCodec opaque direct rendering should not be used anymore
>          since there is no surface to attach.
>          mLibVLC.eventVideoPlayerActivityCreated(false);
> @@ -1228,8 +1226,7 @@ public class VideoPlayerActivity extends
> ActionBarActivity implements IVideoPlay
>      }
>  
>      public void eventHardwareAccelerationError() {
> -        EventHandler em = EventHandler.getInstance();
> -        em.callback(EventHandler.HardwareAccelerationError, new
> Bundle());
> +       
> mLibVLC.getEventHandler().callback(EventHandler.HardwareAccelerationError,
> new Bundle());
>      }
>  
>      private void handleHardwareAccelerationError() {
> diff --git a/vlc-android/src/org/videolan/vlc/util/VLCInstance.java
> b/vlc-android/src/org/videolan/vlc/util/VLCInstance.java
> index d0212c6..9b65285 100644
> --- a/vlc-android/src/org/videolan/vlc/util/VLCInstance.java
> +++ b/vlc-android/src/org/videolan/vlc/util/VLCInstance.java
> @@ -24,7 +24,6 @@ import org.videolan.libvlc.LibVLC;
>  import org.videolan.libvlc.LibVlcException;
>  import org.videolan.vlc.VLCApplication;
>  import org.videolan.vlc.VLCCrashHandler;
> -import org.videolan.vlc.gui.NativeCrashActivity;
>  
>  import android.content.Context;
>  import android.content.Intent;
> @@ -45,15 +44,6 @@ public class VLCInstance {
>              SharedPreferences pref =
>              PreferenceManager.getDefaultSharedPreferences(context);
>              VLCInstance.updateLibVlcSettings(pref);
>              instance.init(context);
> -            instance.setOnNativeCrashListener(new
> LibVLC.OnNativeCrashListener() {
> -                @Override
> -                public void onNativeCrash() {
> -                    Intent i = new Intent(context,
> NativeCrashActivity.class);
> -                    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
> -                    i.putExtra("PID", android.os.Process.myPid());
> -                    context.startActivity(i);
> -                }
> -            });
>          }
>          return instance;
>      }
> @@ -81,10 +71,10 @@ public class VLCInstance {
>          }
>          int vout;
>          try {
> -               vout = Integer.parseInt(pref.getString("vout", "-1"));
> +            vout = Integer.parseInt(pref.getString("vout", "-1"));
>          }
>          catch (NumberFormatException nfe) {
> -               vout = -1;
> +            vout = -1;
>          }
>          int deblocking;
>          try {
> -- 
> 1.9.3 (Apple Git-50)
> 
> _______________________________________________
> Android mailing list
> Android at videolan.org
> https://mailman.videolan.org/listinfo/android


More information about the Android mailing list