<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body><div><div style="font-family: Calibri,sans-serif; font-size: 11pt;">Hi, <br><br>Thanks. I've sent already the patch today to the vlc list.<br><br>Can you check that ?<br><br>Thanks,<br>Paulo </div></div><div dir="ltr"><hr><span style="font-family: Calibri,sans-serif; font-size: 11pt; font-weight: bold;">De: </span><span style="font-family: Calibri,sans-serif; font-size: 11pt;"><a href="mailto:thomas@gllm.fr">Thomas Guillem</a></span><br><span style="font-family: Calibri,sans-serif; font-size: 11pt; font-weight: bold;">Enviada em: </span><span style="font-family: Calibri,sans-serif; font-size: 11pt;">‎02/‎12/‎2014 09:28</span><br><span style="font-family: Calibri,sans-serif; font-size: 11pt; font-weight: bold;">Para: </span><span style="font-family: Calibri,sans-serif; font-size: 11pt;"><a href="mailto:android@videolan.org">android@videolan.org</a></span><br><span style="font-family: Calibri,sans-serif; font-size: 11pt; font-weight: bold;">Assunto: </span><span style="font-family: Calibri,sans-serif; font-size: 11pt;">Re: [Android] [PATCH] Add support for multiple video instances.</span><br><br></div>Good solution for NativeCrashHandler, it's far better now.<br><br>I'm OK with this patch, I'll merge it when patches on vlc are applied.<br>Can you propose the final patch on vlc-devel too ?<br><br>On Tue, Dec 2, 2014, at 11:28, Paulo Vitor Magacho da Silva wrote:<br>> ---<br>>  libvlc/jni/libvlcjni-equalizer.c                   |   4 +-<br>>  libvlc/jni/libvlcjni-util.c                        |  17 --<br>>  libvlc/jni/libvlcjni.c                             | 179<br>>  +++++++++++---------<br>>  libvlc/jni/native_crash_handler.c                  |  25 +--<br>>  libvlc/jni/native_crash_handler.h                  |   5 +-<br>>  libvlc/jni/utils.h                                 |   2 -<br>>  libvlc/jni/vout.c                                  | 186<br>>  ++++++++++++---------<br>>  libvlc/jni/vout.h                                  |  24 ++-<br>>  libvlc/src/org/videolan/libvlc/EventHandler.java   |   8 -<br>>  libvlc/src/org/videolan/libvlc/LibVLC.java         |  98 +++--------<br>>  libvlc/src/org/videolan/libvlc/LibVlcUtil.java     |  56 ++++++-<br>>  .../org/videolan/libvlc/NativeCrashHandler.java    |  64 +++++++<br>>  .../src/org/videolan/vlc/VLCApplication.java       |  15 +-<br>>  .../src/org/videolan/vlc/audio/AudioService.java   |  14 +-<br>>  .../org/videolan/vlc/gui/PreferencesActivity.java  |   2 +-<br>>  .../vlc/gui/video/VideoPlayerActivity.java         |   9 +-<br>>  .../src/org/videolan/vlc/util/VLCInstance.java     |  14 +-<br>>  17 files changed, 399 insertions(+), 323 deletions(-)<br>>  create mode 100644<br>>  libvlc/src/org/videolan/libvlc/NativeCrashHandler.java<br>> <br>> diff --git a/libvlc/jni/libvlcjni-equalizer.c<br>> b/libvlc/jni/libvlcjni-equalizer.c<br>> index 2dad0e4..d11f24d 100644<br>> --- a/libvlc/jni/libvlcjni-equalizer.c<br>> +++ b/libvlc/jni/libvlcjni-equalizer.c<br>> @@ -89,10 +89,10 @@ jfloatArray<br>> Java_org_videolan_libvlc_LibVLC_getPreset(JNIEnv *env, jobject thiz,<br>>   * apply equalizer settings (param bands is float[] (first element is<br>>   preamp, then bands))<br>>   */<br>>  //"--audio-filter=equalizer", "--equalizer-bands=-3.5 -4.5 -1 0 0 5 8 8<br>>  8 8",<br>> -jint Java_org_videolan_libvlc_LibVLC_setNativeEqualizer(JNIEnv *env,<br>> jobject thiz, jlong media_player, jfloatArray bands)<br>> +jint Java_org_videolan_libvlc_LibVLC_setNativeEqualizer(JNIEnv *env,<br>> jobject thiz, jfloatArray bands)<br>>  {<br>>      jint res = -1;<br>> -    libvlc_media_player_t *mp =<br>> (libvlc_media_player_t*)(intptr_t)media_player;<br>> +    libvlc_media_player_t *mp = getMediaPlayer(env, thiz);<br>>      if (!mp)<br>>          return res;<br>>  <br>> diff --git a/libvlc/jni/libvlcjni-util.c b/libvlc/jni/libvlcjni-util.c<br>> index 205d59d..67c2554 100644<br>> --- a/libvlc/jni/libvlcjni-util.c<br>> +++ b/libvlc/jni/libvlcjni-util.c<br>> @@ -131,23 +131,6 @@ void arrayListStringAdd(JNIEnv *env, jclass class,<br>> jmethodID methodID, jobject a<br>>      (*env)->DeleteLocalRef(env, jstr);<br>>  }<br>>  <br>> -jobject getEventHandlerReference(JNIEnv *env, jobject thiz, jobject<br>> eventHandler)<br>> -{<br>> -    jclass cls = (*env)->GetObjectClass(env, eventHandler);<br>> -    if (!cls) {<br>> -        LOGE("setEventHandler: failed to get class reference");<br>> -        return NULL;<br>> -    }<br>> -<br>> -    jmethodID methodID = (*env)->GetMethodID(env, cls, "callback",<br>> "(ILandroid/os/Bundle;)V");<br>> -    if (!methodID) {<br>> -        LOGE("setEventHandler: failed to get the callback method");<br>> -        return NULL;<br>> -    }<br>> -<br>> -    return (*env)->NewGlobalRef(env, eventHandler);<br>> -}<br>> -<br>>  static void debug_buffer_log(void *data, int level, const char *fmt,<br>>  va_list ap)<br>>  {<br>>      bool isAttached = false;<br>> diff --git a/libvlc/jni/libvlcjni.c b/libvlc/jni/libvlcjni.c<br>> index ecfb02e..6f35182 100644<br>> --- a/libvlc/jni/libvlcjni.c<br>> +++ b/libvlc/jni/libvlcjni.c<br>> @@ -38,7 +38,6 @@<br>>  #include "aout.h"<br>>  #include "vout.h"<br>>  #include "utils.h"<br>> -#include "native_crash_handler.h"<br>>  <br>>  #define VOUT_ANDROID_SURFACE 0<br>>  #define VOUT_OPENGLES2       1<br>> @@ -60,6 +59,26 @@ int jni_attach_thread(JNIEnv **env, const char<br>> *thread_name);<br>>  void jni_detach_thread();<br>>  int jni_get_env(JNIEnv **env);<br>>  <br>> +static void setLibVlcSysInstance(JNIEnv *env, jobject thiz,<br>> libvlc_instance_sys_t *p_sys)<br>> +{<br>> +    setLong(env, thiz, "mLibVlcInstance", (jlong)(intptr_t) p_sys);<br>> +}<br>> +<br>> +static libvlc_instance_sys_t *getLibVlcSysInstance(JNIEnv *env, jobject<br>> thiz)<br>> +{<br>> +    return (libvlc_instance_sys_t *)(intptr_t)getLong(env, thiz,<br>> "mLibVlcInstance");<br>> +}<br>> +<br>> +static void releaseMediaPlayer(JNIEnv *env, jobject thiz)<br>> +{<br>> +    libvlc_media_player_t *p_mp = getMediaPlayer(env, thiz);<br>> +    if (p_mp)<br>> +    {<br>> +        libvlc_media_player_stop(p_mp);<br>> +        libvlc_media_player_release(p_mp);<br>> +    }<br>> +}<br>> +<br>>  static void add_media_options(libvlc_media_t *p_md, JNIEnv *env,<br>>  jobjectArray mediaOptions)<br>>  {<br>>      int stringCount = (*env)->GetArrayLength(env, mediaOptions);<br>> @@ -98,24 +117,20 @@ libvlc_media_t *new_media(JNIEnv *env, jobject thiz,<br>> jstring fileLocation, bool<br>>  <br>>  libvlc_instance_t *getLibVlcInstance(JNIEnv *env, jobject thiz)<br>>  {<br>> -    return (libvlc_instance_t*)(intptr_t)getLong(env, thiz,<br>> "mLibVlcInstance");<br>> +    libvlc_instance_sys_t *p_sys = getLibVlcSysInstance(env, thiz);<br>> +    return p_sys ? p_sys->p_libvlc : NULL;<br>>  }<br>>  <br>> -libvlc_media_player_t *getMediaPlayer(JNIEnv *env, jobject thiz)<br>> +android_surf_value_t *getAndroidSurfaceInstance(JNIEnv *env, jobject<br>> thiz)<br>>  {<br>> -    return (libvlc_media_player_t*)(intptr_t)getLong(env, thiz,<br>> "mInternalMediaPlayerInstance");<br>> +    libvlc_instance_sys_t *p_sys = getLibVlcSysInstance(env, thiz);<br>> +    return p_sys ? p_sys->p_surf : NULL;<br>>  }<br>>  <br>> -<br>> -static void releaseMediaPlayer(JNIEnv *env, jobject thiz)<br>> +libvlc_media_player_t *getMediaPlayer(JNIEnv *env, jobject thiz)<br>>  {<br>> -    libvlc_media_player_t* p_mp = getMediaPlayer(env, thiz);<br>> -    if (p_mp)<br>> -    {<br>> -        libvlc_media_player_stop(p_mp);<br>> -        libvlc_media_player_release(p_mp);<br>> -        setLong(env, thiz, "mInternalMediaPlayerInstance", 0);<br>> -    }<br>> +    libvlc_instance_sys_t *p_sys = getLibVlcSysInstance(env, thiz);<br>> +    return p_sys ? p_sys->p_mp : NULL;<br>>  }<br>>  <br>>  /* Pointer to the Java virtual machine<br>> @@ -124,17 +139,12 @@ static void releaseMediaPlayer(JNIEnv *env, jobject<br>> thiz)<br>>   */<br>>  static JavaVM *myVm;<br>>  <br>> -static jobject eventHandlerInstance = NULL;<br>> -<br>>  static void vlc_event_callback(const libvlc_event_t *ev, void *data)<br>>  {<br>>      JNIEnv *env;<br>>  <br>>      bool isAttached = false;<br>>  <br>> -    if (eventHandlerInstance == NULL)<br>> -        return;<br>> -<br>>      if (jni_get_env(&env) < 0) {<br>>          if (jni_attach_thread(&env, THREAD_NAME) < 0)<br>>              return;<br>> @@ -193,20 +203,31 @@ static void vlc_event_callback(const libvlc_event_t<br>> *ev, void *data)<br>>          free(mrl);<br>>      }<br>>  <br>> +    /* The LibVLC object */<br>> +    jobject vlcObject = (jobject) data;<br>> +<br>> +    /* Get the event handler object */<br>> +    jclass cls = (*env)->GetObjectClass(env, vlcObject);<br>> +    jmethodID methodId = (*env)->GetMethodID(env, cls,<br>> "getEventHandler", "()Lorg/videolan/libvlc/EventHandler;");<br>> +    jobject eventHandlerInstance = (*env)->CallObjectMethod(env,<br>> vlcObject, methodId);<br>> +<br>> +    (*env)->DeleteLocalRef(env, cls);<br>> +<br>>      /* Get the object class */<br>> -    jclass cls = (*env)->GetObjectClass(env, eventHandlerInstance);<br>> +    cls = (*env)->GetObjectClass(env, eventHandlerInstance);<br>>      if (!cls) {<br>>          LOGE("EventHandler: failed to get class reference");<br>>          goto end;<br>>      }<br>>  <br>>      /* Find the callback ID */<br>> -    jmethodID methodID = (*env)->GetMethodID(env, cls, "callback",<br>> "(ILandroid/os/Bundle;)V");<br>> -    if (methodID) {<br>> -        (*env)->CallVoidMethod(env, eventHandlerInstance, methodID,<br>> ev->type, bundle);<br>> +    methodId = (*env)->GetMethodID(env, cls, "callback",<br>> "(ILandroid/os/Bundle;)V");<br>> +    if (methodId) {<br>> +        (*env)->CallVoidMethod(env, eventHandlerInstance, methodId,<br>> ev->type, bundle);<br>>      } else {<br>>          LOGE("EventHandler: failed to get the callback method");<br>>      }<br>> +    (*env)->DeleteLocalRef(env, cls);<br>>  <br>>  end:<br>>      (*env)->DeleteLocalRef(env, bundle);<br>> @@ -219,16 +240,12 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved)<br>>      // Keep a reference on the Java VM.<br>>      myVm = vm;<br>>  <br>> -    pthread_mutex_init(&vout_android_lock, NULL);<br>> -    pthread_cond_init(&vout_android_surf_attached, NULL);<br>> -<br>>      LOGD("JNI interface loaded.");<br>>      return VLC_JNI_VERSION;<br>>  }<br>>  <br>>  void JNI_OnUnload(JavaVM* vm, void* reserved) {<br>> -    pthread_mutex_destroy(&vout_android_lock);<br>> -    pthread_cond_destroy(&vout_android_surf_attached);<br>> +    LOGD("JNI interface un-loaded.");<br>>  }<br>>  <br>>  int jni_attach_thread(JNIEnv **env, const char *thread_name)<br>> @@ -353,8 +370,6 @@ void<br>> Java_org_videolan_libvlc_LibVLC_nativeInit(JNIEnv *env, jobject thiz)<br>>      };<br>>      libvlc_instance_t *instance = libvlc_new(sizeof(argv) /<br>>      sizeof(*argv), argv);<br>>  <br>> -    setLong(env, thiz, "mLibVlcInstance", (jlong)(intptr_t) instance);<br>> -<br>>      (*env)->ReleaseStringUTFChars(env, chroma, chromastr);<br>>      (*env)->ReleaseStringUTFChars(env, subsencoding, subsencodingstr);<br>>  <br>> @@ -364,45 +379,45 @@ void<br>> Java_org_videolan_libvlc_LibVLC_nativeInit(JNIEnv *env, jobject thiz)<br>>          (*env)->ThrowNew(env, exc, "Unable to instantiate LibVLC");<br>>      }<br>>  <br>> +    /* Set values to libvlc sys instance */<br>> +    libvlc_instance_sys_t  *p_sys = (libvlc_instance_sys_t *) calloc(1,<br>> sizeof(libvlc_instance_sys_t));<br>> +    p_sys->p_libvlc = instance;<br>> +    p_sys->p_surf = (android_surf_value_t *) calloc(1,<br>> sizeof(android_surf_value_t));<br>> +    p_sys->p_this = (*env)->NewGlobalRef(env, thiz);<br>> +<br>> +    pthread_mutex_init(&p_sys->p_surf->vout_android_lock, NULL);<br>> +    pthread_cond_init(&p_sys->p_surf->vout_android_surf_attached, NULL);<br>> +<br>> +    setLibVlcSysInstance(env, thiz, p_sys);<br>> +<br>>      LOGI("LibVLC initialized: %p", instance);<br>>  <br>>      libvlc_log_set(instance, debug_log, &verbosity);<br>> -<br>> -    init_native_crash_handler(env, thiz);<br>>  }<br>>  <br>>  void Java_org_videolan_libvlc_LibVLC_nativeDestroy(JNIEnv *env, jobject<br>>  thiz)<br>>  {<br>> -    destroy_native_crash_handler(env);<br>> +    libvlc_instance_sys_t *p_sys = getLibVlcSysInstance(env, thiz);<br>> +    if (p_sys == NULL)<br>> +        return; // Already destroyed<br>>  <br>>      releaseMediaPlayer(env, thiz);<br>> -    jlong libVlcInstance = getLong(env, thiz, "mLibVlcInstance");<br>> -    if (!libVlcInstance)<br>> -        return; // Already destroyed<br>>  <br>> -    libvlc_instance_t *instance = (libvlc_instance_t*)(intptr_t)<br>> libVlcInstance;<br>> +    libvlc_instance_t *instance = p_sys->p_libvlc;<br>> +    LOGI("LibVLC destroyed: %p", instance);<br>> +<br>>      libvlc_log_unset(instance);<br>>      libvlc_release(instance);<br>>  <br>> -    setLong(env, thiz, "mLibVlcInstance", 0);<br>> -}<br>> +    (*env)->DeleteGlobalRef(env, p_sys->p_this);<br>>  <br>> -void Java_org_videolan_libvlc_LibVLC_detachEventHandler(JNIEnv *env,<br>> jobject thiz)<br>> -{<br>> -    if (eventHandlerInstance != NULL) {<br>> -        (*env)->DeleteGlobalRef(env, eventHandlerInstance);<br>> -        eventHandlerInstance = NULL;<br>> -    }<br>> -}<br>> +    pthread_mutex_destroy(&p_sys->p_surf->vout_android_lock);<br>> +    pthread_cond_destroy(&p_sys->p_surf->vout_android_surf_attached);<br>>  <br>> -void Java_org_videolan_libvlc_LibVLC_setEventHandler(JNIEnv *env,<br>> jobject thiz, jobject eventHandler)<br>> -{<br>> -    if (eventHandlerInstance != NULL) {<br>> -        (*env)->DeleteGlobalRef(env, eventHandlerInstance);<br>> -        eventHandlerInstance = NULL;<br>> -    }<br>> +    free(p_sys->p_surf);<br>> +    free(p_sys);<br>>  <br>> -    eventHandlerInstance = getEventHandlerReference(env, thiz,<br>> eventHandler);<br>> +    setLibVlcSysInstance(env, thiz, NULL);<br>>  }<br>>  <br>>  void Java_org_videolan_libvlc_LibVLC_playMRL(JNIEnv *env, jobject thiz,<br>> @@ -411,25 +426,24 @@ void Java_org_videolan_libvlc_LibVLC_playMRL(JNIEnv<br>> *env, jobject thiz,<br>>      /* Release previous media player, if any */<br>>      releaseMediaPlayer(env, thiz);<br>>  <br>> -    libvlc_instance_t *p_instance = getLibVlcInstance(env, thiz);<br>> +    libvlc_instance_sys_t *p_sys = getLibVlcSysInstance(env, thiz);<br>>  <br>>      /* Create a media player playing environment */<br>> -    libvlc_media_player_t *mp = libvlc_media_player_new(p_instance);<br>> -    libvlc_media_player_set_video_title_display(mp,<br>> libvlc_position_disable, 0);<br>> -    jobject myJavaLibVLC = (*env)->NewGlobalRef(env, thiz);<br>> +    p_sys->p_mp = libvlc_media_player_new(p_sys->p_libvlc);<br>> +<br>> +    libvlc_media_player_set_video_title_display(p_sys->p_mp,<br>> libvlc_position_disable, 0);<br>>  <br>>      //if AOUT_AUDIOTRACK_JAVA, we use amem<br>>      jclass cls = (*env)->GetObjectClass(env, thiz);<br>>      jmethodID methodId = (*env)->GetMethodID(env, cls, "getAout",<br>>      "()I");<br>>      if ( (*env)->CallIntMethod(env, thiz, methodId) ==<br>>      AOUT_AUDIOTRACK_JAVA )<br>>      {<br>> -        libvlc_audio_set_callbacks(mp, aout_play, aout_pause, NULL,<br>> NULL, NULL,<br>> -                                   (void*) myJavaLibVLC);<br>> -        libvlc_audio_set_format_callbacks(mp, aout_open, aout_close);<br>> +        libvlc_audio_set_callbacks(p_sys->p_mp, aout_play, aout_pause,<br>> NULL, NULL, NULL, p_sys->p_this);<br>> +        libvlc_audio_set_format_callbacks(p_sys->p_mp, aout_open,<br>> aout_close);<br>>      }<br>>  <br>>      /* Connect the event manager */<br>> -    libvlc_event_manager_t *ev = libvlc_media_player_event_manager(mp);<br>> +    libvlc_event_manager_t *ev =<br>> libvlc_media_player_event_manager(p_sys->p_mp);<br>>      static const libvlc_event_type_t mp_events[] = {<br>>          libvlc_MediaPlayerPlaying,<br>>          libvlc_MediaPlayerPaused,<br>> @@ -441,10 +455,7 @@ void Java_org_videolan_libvlc_LibVLC_playMRL(JNIEnv<br>> *env, jobject thiz,<br>>          libvlc_MediaPlayerEncounteredError<br>>      };<br>>      for(int i = 0; i < (sizeof(mp_events) / sizeof(*mp_events)); i++)<br>> -        libvlc_event_attach(ev, mp_events[i], vlc_event_callback, myVm);<br>> -<br>> -    /* Keep a pointer to this media player */<br>> -    setLong(env, thiz, "mInternalMediaPlayerInstance",<br>> (jlong)(intptr_t)mp);<br>> +        libvlc_event_attach(ev, mp_events[i], vlc_event_callback,<br>> p_sys->p_this);<br>>  <br>>      cls = (*env)->GetObjectClass(env, thiz);<br>>      jmethodID methodID = (*env)->GetMethodID(env, cls, "applyEqualizer",<br>>      "()V");<br>> @@ -452,13 +463,16 @@ void Java_org_videolan_libvlc_LibVLC_playMRL(JNIEnv<br>> *env, jobject thiz,<br>>  <br>>      const char* p_mrl = (*env)->GetStringUTFChars(env, mrl, 0);<br>>  <br>> -    libvlc_media_t* p_md = libvlc_media_new_location(p_instance, p_mrl);<br>> +    libvlc_media_t* p_md = libvlc_media_new_location(p_sys->p_libvlc,<br>> p_mrl);<br>>      /* media options */<br>>      if (mediaOptions != NULL)<br>>          add_media_options(p_md, env, mediaOptions);<br>>  <br>>      (*env)->ReleaseStringUTFChars(env, mrl, p_mrl);<br>>  <br>> +    /* set the Android surface value structure before playing */<br>> +    libvlc_media_player_set_androidobject(p_sys->p_mp, p_sys->p_surf);<br>> +<br>>      /* Connect the media event ma<br><div>[A mensagem original inteira não está incluída.]</div></body></html>