<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>