From dc52e150b71b5d19d20e45c5b4fc1baccc48a313 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Thu, 4 Feb 2016 21:57:32 +0100 Subject: [PATCH] adapt android jni to MSFactory usage, and add linphone_core_reload_ms_plugins() as a new way of loading plugins after LinphoneCore has been created. This can be used on platforms where dynamic loading of plugins is not permitted, by doing things in this sequence: 1) Create the LinphoneCore as usual 2) call the libms*_init() routines of the plugins by passing them the MSFactory obtained via linphone_core_get_ms_factory() 3) call linphone_core_reload_ms_plugins() --- coreapi/linphonecore.c | 67 ++++++---- coreapi/linphonecore.h | 8 ++ coreapi/linphonecore_jni.cc | 121 ++++++++++-------- .../org/linphone/core/LinphoneCore.java | 6 + .../org/linphone/core/LinphoneCoreImpl.java | 10 +- mediastreamer2 | 2 +- 6 files changed, 132 insertions(+), 82 deletions(-) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 815b1f1f2..9afb4304f 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1158,8 +1158,7 @@ static bool_t linphone_core_codec_supported(LinphoneCore *lc, SalStreamType type } else if (type == SalText) { return TRUE; } - //ms_filter_codec_supported(mime) - return ms_factory_codec_supported (lc->factory, mime ); + return ms_factory_codec_supported(lc->factory, mime); } @@ -1207,24 +1206,44 @@ static bool_t get_codec(LinphoneCore *lc, SalStreamType type, int index, Payload return TRUE; } +static SalStreamType payload_type_get_stream_type(const PayloadType *pt){ + switch(pt->type){ + case PAYLOAD_AUDIO_PACKETIZED: + case PAYLOAD_AUDIO_CONTINUOUS: + return SalAudio; + break; + case PAYLOAD_VIDEO: + return SalVideo; + break; + case PAYLOAD_TEXT: + return SalText; + break; + } + return SalOther; +} + /*this function merges the payload types from the codec default list with the list read from configuration file. * If a new codec becomes supported in Liblinphone or if the list from configuration file is empty or incomplete, all the supported codecs are added * automatically. This 'l' list is entirely destroyed and rewritten.*/ -static MSList *add_missing_codecs(const MSList *default_list, MSList *l){ +static MSList *add_missing_supported_codecs(LinphoneCore *lc, const MSList *default_list, MSList *l){ const MSList *elem; MSList *newlist; + PayloadType *last_inserted = NULL; for(elem=default_list; elem!=NULL; elem=elem->next){ MSList *elem2=ms_list_find(l,elem->data); if (!elem2){ PayloadType *pt=(PayloadType*)elem->data; /*this codec from default list should be inserted in the list*/ - if (!elem->prev){ + + if (!linphone_core_codec_supported(lc, payload_type_get_stream_type(pt), pt->mime_type)) continue; + if (!last_inserted){ l=ms_list_prepend(l,pt); }else{ - const MSList *after=ms_list_find(l,elem->prev->data); + const MSList *after=ms_list_find(l,last_inserted); l=ms_list_insert(l, after->next, pt); } + last_inserted = pt; ms_message("Supported codec %s/%i fmtp=%s automatically added to codec list.", pt->mime_type, pt->clock_rate, pt->recv_fmtp ? pt->recv_fmtp : ""); } @@ -1262,7 +1281,7 @@ static void codecs_config_read(LinphoneCore *lc) } } if( lp_config_get_int(lc->config, "misc", "add_missing_audio_codecs", 1) == 1 ){ - audio_codecs=add_missing_codecs(lc->default_audio_codecs,audio_codecs); + audio_codecs=add_missing_supported_codecs(lc, lc->default_audio_codecs,audio_codecs); } for (i=0;get_codec(lc,SalVideo,i,&pt);i++){ @@ -1271,7 +1290,7 @@ static void codecs_config_read(LinphoneCore *lc) } } if( lp_config_get_int(lc->config, "misc", "add_missing_video_codecs", 1) == 1 ){ - video_codecs=add_missing_codecs(lc->default_video_codecs,video_codecs); + video_codecs=add_missing_supported_codecs(lc, lc->default_video_codecs,video_codecs); } for (i=0;get_codec(lc,SalText,i,&pt);i++){ @@ -1279,7 +1298,7 @@ static void codecs_config_read(LinphoneCore *lc) text_codecs=codec_append_if_new(text_codecs, pt); } } - text_codecs = add_missing_codecs(lc->default_text_codecs, text_codecs); + text_codecs = add_missing_supported_codecs(lc, lc->default_text_codecs, text_codecs); linphone_core_set_audio_codecs(lc,audio_codecs); linphone_core_set_video_codecs(lc,video_codecs); @@ -1462,20 +1481,18 @@ const char * linphone_core_get_version(void){ static void linphone_core_register_payload_type(LinphoneCore *lc, const PayloadType *const_pt, const char *recv_fmtp, bool_t enabled){ MSList **codec_list = const_pt->type==PAYLOAD_VIDEO ? &lc->default_video_codecs : const_pt->type==PAYLOAD_TEXT ? &lc->default_text_codecs : &lc->default_audio_codecs; - if (linphone_core_codec_supported(lc, (const_pt->type == PAYLOAD_VIDEO) ? SalVideo : const_pt->type == PAYLOAD_TEXT ? SalText : SalAudio, const_pt->mime_type)){ - PayloadType *pt=payload_type_clone(const_pt); - int number=-1; - payload_type_set_enable(pt,enabled); - if (recv_fmtp!=NULL) payload_type_set_recv_fmtp(pt,recv_fmtp); - /*Set a number to the payload type from the statically defined (RFC3551) profile, if not static, -1 is returned - and the payload type number will be determined dynamically later, at call time.*/ - payload_type_set_number(pt, - (number=rtp_profile_find_payload_number(&av_profile, pt->mime_type, pt->clock_rate, pt->channels)) - ); - ms_message("Codec %s/%i fmtp=[%s] number=%i, enabled=%i) added to default capabilities.", pt->mime_type, pt->clock_rate, - pt->recv_fmtp ? pt->recv_fmtp : "", number, (int)payload_type_enabled(pt)); - *codec_list=ms_list_append(*codec_list,pt); - } + PayloadType *pt=payload_type_clone(const_pt); + int number=-1; + payload_type_set_enable(pt,enabled); + if (recv_fmtp!=NULL) payload_type_set_recv_fmtp(pt,recv_fmtp); + /*Set a number to the payload type from the statically defined (RFC3551) profile, if not static, -1 is returned + and the payload type number will be determined dynamically later, at call time.*/ + payload_type_set_number(pt, + (number=rtp_profile_find_payload_number(&av_profile, pt->mime_type, pt->clock_rate, pt->channels)) + ); + ms_message("Codec %s/%i fmtp=[%s] number=%i, enabled=%i) added to the list of possible codecs.", pt->mime_type, pt->clock_rate, + pt->recv_fmtp ? pt->recv_fmtp : "", number, (int)payload_type_enabled(pt)); + *codec_list=ms_list_append(*codec_list,pt); } static void linphone_core_register_static_payloads(LinphoneCore *lc){ @@ -1525,6 +1542,12 @@ static void misc_config_read(LinphoneCore *lc) { lc->user_certificates_path=ms_strdup(lp_config_get_string(config,"misc","user_certificates_path",".")); } +void linphone_core_reload_ms_plugins(LinphoneCore *lc, const char *path){ + if (path) ms_factory_set_plugins_dir(lc->factory, path); + ms_factory_init_plugins(lc->factory); + codecs_config_read(lc); +} + static void linphone_core_start(LinphoneCore * lc) { sip_setup_register_all(lc->factory); sound_config_read(lc); diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 0e7fc8100..5d9eb905e 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -3854,6 +3854,14 @@ LINPHONE_PUBLIC void linphone_core_set_user_certificates_path(LinphoneCore *lc, */ LINPHONE_PUBLIC const char *linphone_core_get_user_certificates_path(LinphoneCore *lc); +/** + * Reload mediastreamer2 plugins from specified directory. + * @param[in] lc #LinphoneCore object. + * @param[in] directory the path from where plugins are to be loaded, pass NULL to use default (compile-time determined) plugin directory. + * @ingroup initializing + */ +LINPHONE_PUBLIC void linphone_core_reload_ms_plugins(LinphoneCore *lc, const char *path); + /** * Search from the list of current calls if a remote address match uri * @ingroup call_control diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 94911a48d..48280b4d6 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -39,28 +39,18 @@ extern "C" { #ifdef ANDROID #include -extern "C" void libmsilbc_init(); -#ifdef HAVE_X264 -extern "C" void libmsx264_init(); -#endif -#ifdef HAVE_OPENH264 -extern "C" void libmsopenh264_init(); -#endif -#ifdef HAVE_AMR -extern "C" void libmsamr_init(); -#endif -#ifdef HAVE_SILK -extern "C" void libmssilk_init(); -#endif -#ifdef HAVE_G729 -extern "C" void libmsbcg729_init(); -#endif -#ifdef HAVE_WEBRTC -extern "C" void libmswebrtc_init(); -#endif -#ifdef HAVE_CODEC2 -extern "C" void libmscodec2_init(); -#endif + +/*there are declarations of the init routines of our plugins. + * Since there is no way to dlopen() installed in a non-standard place in the apk, + * we have to invoke the init routines manually*/ +extern "C" void libmsx264_init(MSFactory *factory); +extern "C" void libmsopenh264_init(MSFactory *factory); +extern "C" void libmsamr_init(MSFactory *factory); +extern "C" void libmssilk_init(MSFactory *factory); +extern "C" void libmsbcg729_init(MSFactory *factory); +extern "C" void libmswebrtc_init(MSFactory *factory); +extern "C" void libmscodec2_init(MSFactory *factory); + #include #endif /*ANDROID*/ @@ -309,6 +299,9 @@ public: subscriptionDirClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/SubscriptionDir")); subscriptionDirFromIntId = env->GetStaticMethodID(subscriptionDirClass,"fromInt","(I)Lorg/linphone/core/SubscriptionDir;"); + + msFactoryClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/mediastream/Factory")); + msFactoryCtrId = env->GetMethodID(msFactoryClass,"", "(J)V"); } void setCore(jobject c) { @@ -338,6 +331,7 @@ public: env->DeleteGlobalRef(subscriptionStateClass); env->DeleteGlobalRef(subscriptionDirClass); env->DeleteGlobalRef(logCollectionUploadStateClass); + env->DeleteGlobalRef(msFactoryClass); } jobject core; @@ -428,6 +422,9 @@ public: jmethodID logCollectionUploadStateId; jmethodID logCollectionUploadStateFromIntId; jmethodID logCollectionUploadProgressId; + + jclass msFactoryClass; + jmethodID msFactoryCtrId; }; /* @@ -1236,42 +1233,42 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_newLinphoneCore(JNIEnv* LinphoneCoreData* ldata = new LinphoneCoreData(env, thiz, vTable, jlistener, ljb); linphone_core_v_table_set_user_data(vTable, ldata); - ms_init(); // Initialize mediastreamer2 before loading the plugins - -#ifdef HAVE_ILBC - libmsilbc_init(); // requires an fpu -#endif -#ifdef HAVE_X264 - libmsx264_init(); -#endif -#ifdef HAVE_OPENH264 - libmsopenh264_init(); -#endif -#ifdef HAVE_AMR - libmsamr_init(); -#endif -#ifdef HAVE_SILK - libmssilk_init(); -#endif -#ifdef HAVE_G729 - libmsbcg729_init(); -#endif -#ifdef HAVE_WEBRTC - libmswebrtc_init(); -#endif -#ifdef HAVE_CODEC2 - libmscodec2_init(); -#endif jobject core = env->NewGlobalRef(thiz); ljb->setCore(core); LinphoneCore *lc = linphone_core_new(vTable, userConfig, factoryConfig, ljb); - jlong nativePtr = (jlong)lc; + MSFactory *factory = linphone_core_get_ms_factory(lc); + +#ifdef HAVE_X264 + libmsx264_init(factory); +#endif +#ifdef HAVE_OPENH264 + libmsopenh264_init(factory); +#endif +#ifdef HAVE_AMR + libmsamr_init(factory); +#endif +#ifdef HAVE_SILK + libmssilk_init(factory); +#endif +#ifdef HAVE_G729 + libmsbcg729_init(factory); +#endif +#ifdef HAVE_WEBRTC + libmswebrtc_init(factory); +#endif +#ifdef HAVE_CODEC2 + libmscodec2_init(factory); +#endif + linphone_core_reload_ms_plugins(lc, NULL); + + jlong nativePtr = (jlong)lc; if (userConfig) env->ReleaseStringUTFChars(juserConfig, userConfig); if (factoryConfig) env->ReleaseStringUTFChars(jfactoryConfig, factoryConfig); return nativePtr; } + extern "C" void Java_org_linphone_core_LinphoneCoreImpl_delete(JNIEnv* env, jobject thiz, jlong native_ptr) { LinphoneCore *lc=(LinphoneCore*)native_ptr; LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc); @@ -1282,7 +1279,6 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_delete(JNIEnv* env, jobj jobject wifi_lock_class = lc->wifi_lock_class; linphone_core_destroy(lc); - ms_exit(); if (wifi_lock) env->DeleteGlobalRef(wifi_lock); if (wifi_lock_class) env->DeleteGlobalRef(wifi_lock_class); @@ -1635,6 +1631,14 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_migrateCallLogs(JNIEnv* linphone_core_migrate_logs_from_rc_to_db((LinphoneCore *)lc); } +extern "C" jobject Java_org_linphone_core_LinphoneCoreImpl_getMSFactory(JNIEnv* env + ,jobject thiz + ,jlong lc){ + LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data((LinphoneCore *)lc); + MSFactory *factory = linphone_core_get_ms_factory((LinphoneCore*)lc); + return env->NewObject(ljb->msFactoryClass, ljb->msFactoryCtrId, (jlong)factory); +} + extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setMtu(JNIEnv* env ,jobject thiz ,jlong lc @@ -2153,9 +2157,11 @@ extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_startEchoCalibration(JNI } -extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_needsEchoCalibration(JNIEnv *env, jobject thiz, jlong lc) { +extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_needsEchoCalibration(JNIEnv *env, jobject thiz, jlong lcptr) { MSSndCard *sndcard; - MSSndCardManager *m = ms_snd_card_manager_get(); + LinphoneCore *lc = (LinphoneCore*) lcptr; + MSFactory * factory = linphone_core_get_ms_factory(lc); + MSSndCardManager *m = ms_factory_get_snd_card_manager(factory); const char *card = linphone_core_get_capture_device((LinphoneCore*)lc); sndcard = ms_snd_card_manager_get_card(m, card); if (sndcard == NULL) { @@ -2173,9 +2179,11 @@ extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_needsEchoCalibration return TRUE; } -extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_hasBuiltInEchoCanceler(JNIEnv *env, jobject thiz, jlong lc) { +extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_hasBuiltInEchoCanceler(JNIEnv *env, jobject thiz, jlong lcptr) { MSSndCard *sndcard; - MSSndCardManager *m = ms_snd_card_manager_get(); + LinphoneCore *lc = (LinphoneCore*) lcptr; + MSFactory * factory = linphone_core_get_ms_factory(lc); + MSSndCardManager *m = ms_factory_get_snd_card_manager(factory); const char *card = linphone_core_get_capture_device((LinphoneCore*)lc); sndcard = ms_snd_card_manager_get_card(m, card); if (sndcard == NULL) { @@ -4663,8 +4671,9 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setStaticPicture(JNIEnv env->ReleaseStringUTFChars(path, cpath); } -extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setCpuCountNative(JNIEnv *env, jobject thiz, jint count) { - ms_set_cpu_count(count); +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setCpuCountNative(JNIEnv *env, jobject thiz, jlong coreptr, jint count) { + MSFactory *factory = linphone_core_get_ms_factory((LinphoneCore*)coreptr); + ms_factory_set_cpu_count(factory, count); } extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAudioJittcomp(JNIEnv *env, jobject thiz, jlong lc, jint value) { diff --git a/java/common/org/linphone/core/LinphoneCore.java b/java/common/org/linphone/core/LinphoneCore.java index 1b69b4e04..d8083906a 100644 --- a/java/common/org/linphone/core/LinphoneCore.java +++ b/java/common/org/linphone/core/LinphoneCore.java @@ -2268,4 +2268,10 @@ public interface LinphoneCore { */ public void setMediaNetworkReachable(boolean isReachable); + /** + * Returns the mediastreamer2 (media stack) factory object used by the LinphoneCore. This may be useful to perform + * some advanced media-related configuration options. + **/ + org.linphone.mediastream.Factory getMSFactory(); + } diff --git a/java/impl/org/linphone/core/LinphoneCoreImpl.java b/java/impl/org/linphone/core/LinphoneCoreImpl.java index 2e18d9b3d..e4cabfaa2 100644 --- a/java/impl/org/linphone/core/LinphoneCoreImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreImpl.java @@ -947,10 +947,10 @@ class LinphoneCoreImpl implements LinphoneCore { setUserAgent(nativePtr,name,version); } - private native void setCpuCountNative(int count); + private native void setCpuCountNative(long nativePtr, int count); public synchronized void setCpuCount(int count) { - setCpuCountNative(count); + setCpuCountNative(nativePtr, count); } public synchronized int getMissedCallsCount() { @@ -1620,5 +1620,9 @@ class LinphoneCoreImpl implements LinphoneCore { public void setMediaNetworkReachable(boolean isReachable) { setMediaNetworkReachable(nativePtr, isReachable); } - + private native Object getMSFactory(long nativePtr); + @Override + public org.linphone.mediastream.Factory getMSFactory(){ + return (org.linphone.mediastream.Factory) getMSFactory(nativePtr); + } } diff --git a/mediastreamer2 b/mediastreamer2 index bc6574e8c..bcd3042a1 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit bc6574e8c7d5a385d89c2cb807e4fb9a6c20f612 +Subproject commit bcd3042a1984088a78a7517774300b0a6647506d