From c31c49bef36fae9c767df513b22970df1c8d6817 Mon Sep 17 00:00:00 2001 From: Simon Morlat <simon.morlat@linphone.org> Date: Fri, 6 Oct 2023 16:10:53 +0200 Subject: [PATCH] Add new video codec priority policy, that gives preference to hardware codecs on mobile platforms, in order to preserve battery and improve framerate. --- coreapi/linphonecore.c | 130 +++++++++------ coreapi/quality_reporting.c | 33 ++-- coreapi/tester_utils.h | 2 + coreapi/update_check.c | 6 +- daemon/commands/audio-codec-get.cc | 14 +- daemon/commands/audio-codec-move.cc | 22 +-- daemon/commands/audio-codec-set.cc | 42 +++-- daemon/commands/audio-codec-toggle.cc | 15 +- daemon/daemon.cc | 55 ++++--- daemon/daemon.h | 9 +- include/CMakeLists.txt | 1 + include/linphone/api/c-alert.h | 3 +- include/linphone/api/c-payload-type.h | 10 ++ include/linphone/api/c-signal-information.h | 3 +- include/linphone/api/c-types.h | 96 +---------- include/linphone/call_params.h | 37 +---- include/linphone/core.h | 46 ++++-- include/linphone/enums/c-enums.h | 139 ++++++++++++++++ src/c-wrapper/api/c-account.cpp | 4 +- src/c-wrapper/api/c-call-params.cpp | 27 +-- src/c-wrapper/api/c-chat-message.cpp | 2 +- src/c-wrapper/api/c-core.cpp | 40 +++-- src/c-wrapper/api/c-payload-type.cpp | 10 ++ src/c-wrapper/c-wrapper.h | 2 - .../params/media-session-params-p.h | 18 +- .../params/media-session-params.cpp | 24 +-- src/conference/params/media-session-params.h | 14 +- src/conference/session/audio-mixer.cpp | 5 +- src/conference/session/ms2-stream.cpp | 6 +- src/conference/session/streams-group.cpp | 2 +- src/conference/session/streams.h | 2 +- src/conference/session/video-mixer.cpp | 4 +- src/core/core-p.h | 3 + src/core/core.cpp | 65 ++++++++ src/core/core.h | 3 + src/payload-type/payload-type.cpp | 11 ++ src/payload-type/payload-type.h | 2 + src/sal/offeranswer.cpp | 9 + src/signal-information/signal-information.h | 1 + src/utils/payload-type-handler.h | 1 + tester/audio_bypass_tester.c | 5 +- tester/call_single_tester.c | 4 +- tester/local_conference_tester_functions.cpp | 14 +- tester/offeranswer_tester.cpp | 154 ++++++++++++++++-- tester/session_timers_tester.c | 4 +- 45 files changed, 719 insertions(+), 380 deletions(-) create mode 100644 include/linphone/enums/c-enums.h diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index c190f2f50a..26795f7053 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1943,7 +1943,10 @@ static void sip_config_read(LinphoneCore *lc) { lc->sal->useDates(!!linphone_config_get_int(lc->config, "sip", "put_date", 0)); lc->sal->enableSipUpdateMethod(!!linphone_config_get_int(lc->config, "sip", "sip_update", 1)); lc->sip_conf.vfu_with_info = !!linphone_config_get_int(lc->config, "sip", "vfu_with_info", 1); - linphone_core_set_sip_transport_timeout(lc, linphone_config_get_int(lc->config, "sip", "transport_timeout", 63000)); + /* The linux kernel TCP connection timeout is 63 seconds, which is fairly long. + * We decide that 15 seconds is long enough to connect to a single node, given that we want + * to switch to alternate nodes provided in the SRV records within a reasonnable timeframe.*/ + linphone_core_set_sip_transport_timeout(lc, linphone_config_get_int(lc->config, "sip", "transport_timeout", 15000)); lc->sal->setSupportedTags( linphone_config_get_string(lc->config, "sip", "supported", "replaces, outbound, gruu, path")); LinphoneSupportLevel level_100rel = linphone_core_get_tag_100rel_support_level(lc); @@ -2038,14 +2041,14 @@ static void rtp_config_read(LinphoneCore *lc) { linphone_core_enable_video_multicast(lc, !!tmp_int); } -static PayloadType *find_payload( +static OrtpPayloadType *find_payload( const bctbx_list_t *default_list, const char *mime_type, int clock_rate, int channels, const char *recv_fmtp) { - PayloadType *candidate = NULL; - PayloadType *it; + OrtpPayloadType *candidate = NULL; + OrtpPayloadType *it; const bctbx_list_t *elem; for (elem = default_list; elem != NULL; elem = elem->next) { - it = (PayloadType *)elem->data; + it = (OrtpPayloadType *)elem->data; if (it != NULL && strcasecmp(mime_type, it->mime_type) == 0 && (clock_rate == it->clock_rate || clock_rate <= 0) && (channels == it->channels || channels <= 0)) { if ((recv_fmtp && it->recv_fmtp && strstr(recv_fmtp, it->recv_fmtp) != NULL) || @@ -2066,10 +2069,11 @@ static PayloadType *find_payload( return candidate; } -static PayloadType *find_payload_type_from_list(const char *type, int rate, int channels, const bctbx_list_t *from) { +static OrtpPayloadType * +find_payload_type_from_list(const char *type, int rate, int channels, const bctbx_list_t *from) { const bctbx_list_t *elem; for (elem = from; elem != NULL; elem = elem->next) { - PayloadType *pt = (PayloadType *)elem->data; + OrtpPayloadType *pt = (OrtpPayloadType *)elem->data; if ((strcasecmp(type, payload_type_get_mime(pt)) == 0) && (rate == LINPHONE_FIND_PAYLOAD_IGNORE_RATE || rate == pt->clock_rate) && (channels == LINPHONE_FIND_PAYLOAD_IGNORE_CHANNELS || channels == pt->channels)) { @@ -2098,11 +2102,11 @@ static bool_t linphone_core_codec_supported(LinphoneCore *lc, SalStreamType type return ms_factory_codec_supported(lc->factory, mime); } -static bool_t get_codec(LinphoneCore *lc, SalStreamType type, int index, PayloadType **ret) { +static bool_t get_codec(LinphoneCore *lc, SalStreamType type, int index, OrtpPayloadType **ret) { char codeckey[50]; const char *mime, *fmtp; int rate, channels, enabled, bitrate; - PayloadType *pt; + OrtpPayloadType *pt; LpConfig *config = lc->config; *ret = NULL; @@ -2151,7 +2155,7 @@ static bool_t get_codec(LinphoneCore *lc, SalStreamType type, int index, Payload return TRUE; } -static SalStreamType payload_type_get_stream_type(const PayloadType *pt) { +static SalStreamType payload_type_get_stream_type(const OrtpPayloadType *pt) { switch (pt->type) { case PAYLOAD_AUDIO_PACKETIZED: case PAYLOAD_AUDIO_CONTINUOUS: @@ -2172,12 +2176,12 @@ static SalStreamType payload_type_get_stream_type(const PayloadType *pt) { * the supported codecs are added automatically. This 'l' list is entirely rewritten.*/ static bctbx_list_t *add_missing_supported_codecs(LinphoneCore *lc, const bctbx_list_t *default_list, bctbx_list_t *l) { const bctbx_list_t *elem; - ::PayloadType *last_seen = NULL; + OrtpPayloadType *last_seen = NULL; for (elem = default_list; elem != NULL; elem = elem->next) { bctbx_list_t *elem2 = bctbx_list_find(l, elem->data); if (!elem2) { - PayloadType *pt = (PayloadType *)elem->data; + OrtpPayloadType *pt = (OrtpPayloadType *)elem->data; /*this codec from default list should be inserted in the list, with respect to the default_list order*/ if (!linphone_core_codec_supported(lc, payload_type_get_stream_type(pt), pt->mime_type)) continue; @@ -2191,7 +2195,7 @@ static bctbx_list_t *add_missing_supported_codecs(LinphoneCore *lc, const bctbx_ 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 : ""); } else { - last_seen = (PayloadType *)elem2->data; + last_seen = (OrtpPayloadType *)elem2->data; } } return l; @@ -2223,10 +2227,10 @@ handle_missing_codecs(LinphoneCore *lc, const bctbx_list_t *default_list, bctbx_ return l; } -static bctbx_list_t *codec_append_if_new(bctbx_list_t *l, PayloadType *pt) { +static bctbx_list_t *codec_append_if_new(bctbx_list_t *l, OrtpPayloadType *pt) { bctbx_list_t *elem; for (elem = l; elem != NULL; elem = elem->next) { - PayloadType *ept = (PayloadType *)elem->data; + OrtpPayloadType *ept = (OrtpPayloadType *)elem->data; if (pt == ept) return l; } l = bctbx_list_append(l, pt); @@ -2235,10 +2239,12 @@ static bctbx_list_t *codec_append_if_new(bctbx_list_t *l, PayloadType *pt) { static void codecs_config_read(LinphoneCore *lc) { int i; - PayloadType *pt; + OrtpPayloadType *pt; bctbx_list_t *audio_codecs = NULL; bctbx_list_t *video_codecs = NULL; bctbx_list_t *text_codecs = NULL; + int videoCodecsPriorityPolicy = + linphone_config_get_int(linphone_core_get_config(lc), "video", "codec_priority_policy", -1); lc->codecs_conf.dyn_pt = 96; @@ -2261,6 +2267,17 @@ static void codecs_config_read(LinphoneCore *lc) { video_codecs = codec_append_if_new(video_codecs, pt); } } + if (videoCodecsPriorityPolicy == -1) { + if (video_codecs != NULL) { + /* videoCodecsPriorityPolicy is unset, but there are video codecs listed in the configuration. + * For backward compatibility, then force the priority policy to be LinphoneCodecPriorityPolicyBasic. + */ + videoCodecsPriorityPolicy = LinphoneCodecPriorityPolicyBasic; + } else { + /* Otherwise, the default is LinphoneCodecPriorityPolicyAuto */ + videoCodecsPriorityPolicy = LinphoneCodecPriorityPolicyAuto; + } + } video_codecs = handle_missing_codecs(lc, lc->default_video_codecs, video_codecs, MSVideo); @@ -2275,6 +2292,7 @@ static void codecs_config_read(LinphoneCore *lc) { linphone_core_set_video_codecs(lc, video_codecs); linphone_core_set_text_codecs(lc, text_codecs); linphone_core_update_allocated_audio_bandwidth(lc); + linphone_core_set_video_codec_priority_policy(lc, (LinphoneCodecPriorityPolicy)videoCodecsPriorityPolicy); } static void build_video_devices_table(LinphoneCore *lc) { @@ -2485,13 +2503,13 @@ const char *linphone_core_get_version(void) { } static void linphone_core_register_payload_type(LinphoneCore *lc, - const PayloadType *const_pt, + const OrtpPayloadType *const_pt, const char *recv_fmtp, bool_t enabled) { bctbx_list_t **codec_list = const_pt->type == PAYLOAD_VIDEO ? &lc->default_video_codecs : const_pt->type == PAYLOAD_TEXT ? &lc->default_text_codecs : &lc->default_audio_codecs; - PayloadType *pt = payload_type_clone(const_pt); + OrtpPayloadType *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); @@ -2509,7 +2527,7 @@ static void linphone_core_register_static_payloads(LinphoneCore *lc) { RtpProfile *prof = &av_profile; int i; for (i = 0; i < RTP_PROFILE_MAX_PAYLOADS; ++i) { - PayloadType *pt = rtp_profile_get_payload(prof, i); + OrtpPayloadType *pt = rtp_profile_get_payload(prof, i); if (pt) { #ifndef VIDEO_ENABLED if (pt->type == PAYLOAD_VIDEO) continue; @@ -7772,43 +7790,47 @@ int linphone_core_get_current_call_stats(LinphoneCore *lc, rtp_stats_t *local, r } void _linphone_core_codec_config_write(LinphoneCore *lc) { - if (linphone_core_ready(lc)) { - PayloadType *pt; - codecs_config_t *config = &lc->codecs_conf; - bctbx_list_t *node; - char key[50]; - int index; - index = 0; - for (node = config->audio_codecs; node != NULL; node = bctbx_list_next(node)) { - pt = (PayloadType *)(node->data); - sprintf(key, "audio_codec_%i", index); - linphone_config_set_string(lc->config, key, "mime", pt->mime_type); - linphone_config_set_int(lc->config, key, "rate", pt->clock_rate); - if (pt->flags & PAYLOAD_TYPE_BITRATE_OVERRIDE) - linphone_config_set_int(lc->config, key, "bitrate", pt->normal_bitrate); - linphone_config_set_int(lc->config, key, "channels", pt->channels); - linphone_config_set_int(lc->config, key, "enabled", payload_type_enabled(pt)); - linphone_config_set_string(lc->config, key, "recv_fmtp", pt->recv_fmtp); - index++; - } + OrtpPayloadType *pt; + codecs_config_t *config = &lc->codecs_conf; + bctbx_list_t *node; + char key[50]; + int index; + + if (!linphone_core_ready(lc)) return; + + linphone_config_set_int(lc->config, "video", "codec_priority_policy", + linphone_core_get_video_codec_priority_policy(lc)); + + index = 0; + for (node = config->audio_codecs; node != NULL; node = bctbx_list_next(node)) { + pt = (OrtpPayloadType *)(node->data); sprintf(key, "audio_codec_%i", index); - linphone_config_clean_section(lc->config, key); - - index = 0; - for (node = config->video_codecs; node != NULL; node = bctbx_list_next(node)) { - pt = (PayloadType *)(node->data); - sprintf(key, "video_codec_%i", index); - linphone_config_set_string(lc->config, key, "mime", pt->mime_type); - linphone_config_set_int(lc->config, key, "rate", pt->clock_rate); - if (pt->flags & PAYLOAD_TYPE_BITRATE_OVERRIDE) - linphone_config_set_int(lc->config, key, "bitrate", pt->normal_bitrate); - linphone_config_set_int(lc->config, key, "enabled", payload_type_enabled(pt)); - linphone_config_set_string(lc->config, key, "recv_fmtp", pt->recv_fmtp); - index++; - } + linphone_config_set_string(lc->config, key, "mime", pt->mime_type); + linphone_config_set_int(lc->config, key, "rate", pt->clock_rate); + if (pt->flags & PAYLOAD_TYPE_BITRATE_OVERRIDE) + linphone_config_set_int(lc->config, key, "bitrate", pt->normal_bitrate); + linphone_config_set_int(lc->config, key, "channels", pt->channels); + linphone_config_set_int(lc->config, key, "enabled", payload_type_enabled(pt)); + linphone_config_set_string(lc->config, key, "recv_fmtp", pt->recv_fmtp); + index++; + } + sprintf(key, "audio_codec_%i", index); + linphone_config_clean_section(lc->config, key); + + index = 0; + for (node = config->video_codecs; node != NULL; node = bctbx_list_next(node)) { + pt = (OrtpPayloadType *)(node->data); sprintf(key, "video_codec_%i", index); - linphone_config_clean_section(lc->config, key); - } + linphone_config_set_string(lc->config, key, "mime", pt->mime_type); + linphone_config_set_int(lc->config, key, "rate", pt->clock_rate); + if (pt->flags & PAYLOAD_TYPE_BITRATE_OVERRIDE) + linphone_config_set_int(lc->config, key, "bitrate", pt->normal_bitrate); + linphone_config_set_int(lc->config, key, "enabled", payload_type_enabled(pt)); + linphone_config_set_string(lc->config, key, "recv_fmtp", pt->recv_fmtp); + index++; + } + sprintf(key, "video_codec_%i", index); + linphone_config_clean_section(lc->config, key); } static void codecs_config_uninit(LinphoneCore *lc) { diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 44b85ed0a8..fe434f4089 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -547,8 +547,8 @@ void linphone_reporting_update_ip(LinphoneCall *call) { void linphone_reporting_update_media_info(LinphoneCall *call, int stats_type) { MediaStream *stream = NULL; - const ::PayloadType *local_payload = NULL; - const ::PayloadType *remote_payload = NULL; + const LinphonePayloadType *local_payload = NULL; + const LinphonePayloadType *remote_payload = NULL; const LinphoneCallParams *current_params = linphone_call_get_current_params(call); std::shared_ptr<CallLog> log = Call::toCpp(call)->getLog(); reporting_session_report_t *report = log->getQualityReporting()->reports[stats_type]; @@ -595,15 +595,15 @@ void linphone_reporting_update_media_info(LinphoneCall *call, int stats_type) { /*yet we use the same payload config for local and remote, since this is the largest use case*/ if (stats_type == LINPHONE_CALL_STATS_AUDIO && Call::toCpp(call)->getMediaStream(LinphoneStreamTypeAudio)) { stream = Call::toCpp(call)->getMediaStream(LinphoneStreamTypeAudio); - local_payload = linphone_call_params_get_used_audio_codec(current_params); + local_payload = linphone_call_params_get_used_audio_payload_type(current_params); remote_payload = local_payload; } else if (stats_type == LINPHONE_CALL_STATS_VIDEO && Call::toCpp(call)->getMediaStream(LinphoneStreamTypeVideo)) { stream = Call::toCpp(call)->getMediaStream(LinphoneStreamTypeVideo); - local_payload = linphone_call_params_get_used_video_codec(current_params); + local_payload = linphone_call_params_get_used_video_payload_type(current_params); remote_payload = local_payload; } else if (stats_type == LINPHONE_CALL_STATS_TEXT && Call::toCpp(call)->getMediaStream(LinphoneStreamTypeText)) { stream = Call::toCpp(call)->getMediaStream(LinphoneStreamTypeText); - local_payload = linphone_call_params_get_used_text_codec(current_params); + local_payload = linphone_call_params_get_used_text_payload_type(current_params); remote_payload = local_payload; } @@ -628,19 +628,22 @@ void linphone_reporting_update_media_info(LinphoneCall *call, int stats_type) { STR_REASSIGN(report->dialog_id, ms_strdup_printf("%s;%u", dialogId.c_str(), report->info.local_addr.ssrc)); if (local_payload != NULL) { - report->local_metrics.session_description.payload_type = local_payload->type; - if (local_payload->mime_type != NULL) - STR_REASSIGN(report->local_metrics.session_description.payload_desc, ms_strdup(local_payload->mime_type)); - report->local_metrics.session_description.sample_rate = local_payload->clock_rate; - if (local_payload->recv_fmtp != NULL) - STR_REASSIGN(report->local_metrics.session_description.fmtp, ms_strdup(local_payload->recv_fmtp)); + report->local_metrics.session_description.payload_type = linphone_payload_type_get_type(local_payload); + STR_REASSIGN(report->local_metrics.session_description.payload_desc, + ms_strdup(linphone_payload_type_get_mime_type(local_payload))); + report->local_metrics.session_description.sample_rate = linphone_payload_type_get_clock_rate(local_payload); + if (linphone_payload_type_get_recv_fmtp(local_payload) != NULL) + STR_REASSIGN(report->local_metrics.session_description.fmtp, + ms_strdup(linphone_payload_type_get_recv_fmtp(local_payload))); } if (remote_payload != NULL) { - report->remote_metrics.session_description.payload_type = remote_payload->type; - STR_REASSIGN(report->remote_metrics.session_description.payload_desc, ms_strdup(remote_payload->mime_type)); - report->remote_metrics.session_description.sample_rate = remote_payload->clock_rate; - STR_REASSIGN(report->remote_metrics.session_description.fmtp, ms_strdup(remote_payload->recv_fmtp)); + report->remote_metrics.session_description.payload_type = linphone_payload_type_get_type(remote_payload); + STR_REASSIGN(report->remote_metrics.session_description.payload_desc, + ms_strdup(linphone_payload_type_get_mime_type(remote_payload))); + report->remote_metrics.session_description.sample_rate = linphone_payload_type_get_clock_rate(remote_payload); + STR_REASSIGN(report->remote_metrics.session_description.fmtp, + ms_strdup(linphone_payload_type_get_recv_fmtp(remote_payload))); } } diff --git a/coreapi/tester_utils.h b/coreapi/tester_utils.h index 537ed2bfb4..8a127130bf 100644 --- a/coreapi/tester_utils.h +++ b/coreapi/tester_utils.h @@ -391,6 +391,8 @@ LINPHONE_PUBLIC bool_t linphone_tunnel_is_tunnel_rtp_transport(const LinphoneTun LINPHONE_PUBLIC void linphone_config_simulate_crash_during_sync(LinphoneConfig *lpconfig, bool_t value); LINPHONE_PUBLIC void linphone_config_simulate_read_failure(bool_t value); +LINPHONE_PUBLIC void linphone_payload_type_set_priority_bonus(LinphonePayloadType *pt, bool_t value); + #ifdef __cplusplus } #endif diff --git a/coreapi/update_check.c b/coreapi/update_check.c index 3862076058..ae65f9a944 100644 --- a/coreapi/update_check.c +++ b/coreapi/update_check.c @@ -129,10 +129,10 @@ void linphone_core_check_for_update(LinphoneCore *lc, const char *current_versio belle_generic_uri_t *uri; char *version_check_url; LinphoneUpdateCheck *update; - MSList *item; - MSList *platform_tags = ms_factory_get_platform_tags(linphone_core_get_ms_factory(lc)); + bctbx_list_t *item; + bctbx_list_t *platform_tags = ms_factory_get_platform_tags(linphone_core_get_ms_factory(lc)); - for (item = platform_tags; item != NULL; item = ms_list_next(item)) { + for (item = platform_tags; item != NULL; item = item->next) { const char *tag = (const char *)item->data; if (strcmp(tag, "win32") == 0) platform = "windows"; else if (strcmp(tag, "apple") == 0) platform = "macosx"; diff --git a/daemon/commands/audio-codec-get.cc b/daemon/commands/audio-codec-get.cc index 03cc045a29..d6f66416c3 100644 --- a/daemon/commands/audio-codec-get.cc +++ b/daemon/commands/audio-codec-get.cc @@ -56,7 +56,7 @@ void AudioCodecGetCommand::exec(Daemon *app, const string &args) { bool found = false; istringstream ist(args); ostringstream ost; - PayloadType *pt = NULL; + LinphonePayloadType *pt = NULL; if (ist.peek() == EOF) { found = list = true; @@ -68,26 +68,28 @@ void AudioCodecGetCommand::exec(Daemon *app, const string &args) { app->sendResponse(Response("Incorrect mime type format.", Response::Error)); return; } - pt = parser.getPayloadType(); + if (parser.getPayloadType()) pt = linphone_payload_type_ref(parser.getPayloadType()); } int index = 0; - for (const bctbx_list_t *node = linphone_core_get_audio_codecs(app->getCore()); node != NULL; - node = bctbx_list_next(node)) { - PayloadType *payload = reinterpret_cast<PayloadType *>(node->data); + bctbx_list_t *payloadTypes = linphone_core_get_audio_payload_types(app->getCore()); + for (const bctbx_list_t *node = payloadTypes; node != NULL; node = bctbx_list_next(node)) { + LinphonePayloadType *payload = static_cast<LinphonePayloadType *>(node->data); if (list) { ost << PayloadTypeResponse(app->getCore(), payload, index).getBody() << "\n"; - } else if (pt == payload) { + } else if (pt && linphone_payload_type_weak_equals(pt, payload)) { ost << PayloadTypeResponse(app->getCore(), payload, index).getBody(); found = true; break; } ++index; } + bctbx_list_free_with_data(payloadTypes, (bctbx_list_free_func)linphone_payload_type_unref); if (!found) { app->sendResponse(Response("Audio codec not found.", Response::Error)); } else { app->sendResponse(Response(ost.str(), Response::Ok)); } + if (pt) linphone_payload_type_unref(pt); } diff --git a/daemon/commands/audio-codec-move.cc b/daemon/commands/audio-codec-move.cc index 556e179fd0..4c8aa7af99 100644 --- a/daemon/commands/audio-codec-move.cc +++ b/daemon/commands/audio-codec-move.cc @@ -68,7 +68,7 @@ void AudioCodecMoveCommand::exec(Daemon *app, const string &args) { app->sendResponse(Response("Incorrect mime type format.", Response::Error)); return; } - PayloadType *selected_payload = NULL; + LinphonePayloadType *selected_payload = NULL; selected_payload = parser.getPayloadType(); if (selected_payload == NULL) { @@ -84,24 +84,26 @@ void AudioCodecMoveCommand::exec(Daemon *app, const string &args) { } int i = 0; - bctbx_list_t *mslist = NULL; - for (const bctbx_list_t *node = linphone_core_get_audio_codecs(app->getCore()); node != NULL; - node = bctbx_list_next(node)) { - PayloadType *payload = reinterpret_cast<PayloadType *>(node->data); + bctbx_list_t *orig_list = linphone_core_get_audio_payload_types(app->getCore()); + bctbx_list_t *new_list = NULL; + for (bctbx_list_t *node = orig_list; node != NULL; node = bctbx_list_next(node)) { + LinphonePayloadType *payload = reinterpret_cast<LinphonePayloadType *>(node->data); if (i == index) { - mslist = bctbx_list_append(mslist, selected_payload); + new_list = bctbx_list_append(new_list, linphone_payload_type_ref(selected_payload)); ++i; } - if (selected_payload != payload) { - mslist = bctbx_list_append(mslist, payload); + if (!linphone_payload_type_weak_equals(selected_payload, linphone_payload_type_ref(payload))) { + new_list = bctbx_list_append(new_list, payload); ++i; } } if (i <= index) { index = i; - mslist = bctbx_list_append(mslist, selected_payload); + new_list = bctbx_list_append(new_list, linphone_payload_type_ref(selected_payload)); } - linphone_core_set_audio_codecs(app->getCore(), mslist); + linphone_core_set_audio_payload_types(app->getCore(), new_list); + bctbx_list_free_with_data(orig_list, (bctbx_list_free_func)linphone_payload_type_unref); + bctbx_list_free_with_data(new_list, (bctbx_list_free_func)linphone_payload_type_unref); app->sendResponse(PayloadTypeResponse(app->getCore(), selected_payload, index)); } diff --git a/daemon/commands/audio-codec-set.cc b/daemon/commands/audio-codec-set.cc index 3b40f839a4..eb868b150b 100644 --- a/daemon/commands/audio-codec-set.cc +++ b/daemon/commands/audio-codec-set.cc @@ -67,16 +67,20 @@ AudioCodecSetCommand::AudioCodecSetCommand() "Enabled: false")); } -static PayloadType *findPayload(LinphoneCore *lc, int payload_type, int *index) { +static LinphonePayloadType *findPayload(LinphoneCore *lc, int payload_type, int *index) { + bctbx_list_t *payloadTypes = linphone_core_get_audio_payload_types(lc); + LinphonePayloadType *ret = nullptr; if (index) *index = 0; - for (const bctbx_list_t *node = linphone_core_get_audio_codecs(lc); node != NULL; node = bctbx_list_next(node)) { - PayloadType *payload = reinterpret_cast<PayloadType *>(node->data); + for (const bctbx_list_t *node = payloadTypes; node != NULL; node = bctbx_list_next(node)) { + LinphonePayloadType *payload = static_cast<LinphonePayloadType *>(node->data); if (index) (*index)++; - if (payload_type == payload_type_get_number(payload)) { - return payload; + if (payload_type == linphone_payload_type_get_number(payload)) { + ret = linphone_payload_type_ref(payload); + break; } } - return NULL; + bctbx_list_free_with_data(payloadTypes, (bctbx_list_free_func)linphone_payload_type_unref); + return ret; } void AudioCodecSetCommand::exec(Daemon *app, const string &args) { @@ -104,37 +108,46 @@ void AudioCodecSetCommand::exec(Daemon *app, const string &args) { ist >> value; if (value.length() > 255) value.resize(255); - PayloadType *payload = parser.getPayloadType(); + LinphonePayloadType *payload = nullptr; + if (parser.getPayloadType()) { + payload = + linphone_core_get_payload_type(app->getCore(), linphone_payload_type_get_mime_type(parser.getPayloadType()), + linphone_payload_type_get_clock_rate(parser.getPayloadType()), + linphone_payload_type_get_channels(parser.getPayloadType())); + } if (payload) { bool handled = false; if (param.compare("clock_rate") == 0) { if (value.length() > 0) { - payload->clock_rate = atoi(value.c_str()); - handled = true; + // setting the clock rate is not supported by liblinphone. What's the purpose of doing this ?' + // linphone_payload_type_set_clock_rate(payload, atoi(value.c_str())); + handled = false; } } else if (param.compare("recv_fmtp") == 0) { - payload_type_set_recv_fmtp(payload, value.c_str()); + linphone_payload_type_set_recv_fmtp(payload, value.c_str()); handled = true; } else if (param.compare("send_fmtp") == 0) { - payload_type_set_send_fmtp(payload, value.c_str()); + linphone_payload_type_set_send_fmtp(payload, value.c_str()); handled = true; } else if (param.compare("number") == 0) { if (value.length() > 0) { int idx = atoi(value.c_str()); - PayloadType *conflict = NULL; + LinphonePayloadType *conflict = NULL; if (idx != -1) { conflict = findPayload(app->getCore(), atoi(value.c_str()), NULL); } if (conflict) { app->sendResponse(Response("New payload type number is already used.", Response::Error)); + linphone_payload_type_unref(conflict); } else { - payload_type_set_number(payload, idx); + linphone_payload_type_set_number(payload, idx); app->sendResponse(PayloadTypeResponse(app->getCore(), payload, parser.getPosition())); } + linphone_payload_type_unref(payload); return; } } else if (param.compare("bitrate") == 0) { - linphone_core_set_payload_type_bitrate(app->getCore(), payload, atoi(value.c_str())); + linphone_payload_type_set_normal_bitrate(payload, atoi(value.c_str())); handled = true; } if (handled) { @@ -142,6 +155,7 @@ void AudioCodecSetCommand::exec(Daemon *app, const string &args) { } else { app->sendResponse(Response("Invalid codec parameter.", Response::Error)); } + linphone_payload_type_unref(payload); return; } app->sendResponse(Response("Audio codec not found.", Response::Error)); diff --git a/daemon/commands/audio-codec-toggle.cc b/daemon/commands/audio-codec-toggle.cc index 35653cc28f..c5c891ef3a 100644 --- a/daemon/commands/audio-codec-toggle.cc +++ b/daemon/commands/audio-codec-toggle.cc @@ -34,7 +34,7 @@ void AudioCodecToggleCommand::exec(Daemon *app, const string &args) { app->sendResponse(Response("Missing parameter.", Response::Error)); } else { string mime_type; - PayloadType *pt = NULL; + LinphonePayloadType *pt = NULL; ist >> mime_type; PayloadTypeParser parser(app->getCore(), mime_type, true); if (!parser.successful()) { @@ -44,20 +44,21 @@ void AudioCodecToggleCommand::exec(Daemon *app, const string &args) { if (!parser.all()) pt = parser.getPayloadType(); int index = 0; - for (const bctbx_list_t *node = linphone_core_get_audio_codecs(app->getCore()); node != NULL; - node = bctbx_list_next(node)) { - PayloadType *payload = reinterpret_cast<PayloadType *>(node->data); + bctbx_list_t *l = linphone_core_get_audio_payload_types(app->getCore()); + for (const bctbx_list_t *node = l; node != NULL; node = bctbx_list_next(node)) { + LinphonePayloadType *payload = static_cast<LinphonePayloadType *>(node->data); if (parser.all()) { - linphone_core_enable_payload_type(app->getCore(), payload, mEnable); + linphone_payload_type_enable(payload, mEnable); } else { - if (pt == payload) { - linphone_core_enable_payload_type(app->getCore(), payload, mEnable); + if (linphone_payload_type_weak_equals(payload, pt)) { + linphone_payload_type_enable(payload, mEnable); app->sendResponse(PayloadTypeResponse(app->getCore(), payload, index)); return; } } ++index; } + bctbx_list_free_with_data(l, (bctbx_list_free_func)linphone_payload_type_unref); if (parser.all()) { AudioCodecGetCommand getCommand; getCommand.exec(app, ""); diff --git a/daemon/daemon.cc b/daemon/daemon.cc index c4dd918ca9..eaaf9deadc 100644 --- a/daemon/daemon.cc +++ b/daemon/daemon.cc @@ -190,10 +190,10 @@ CallStatsEvent::CallStatsEvent(Daemon *daemon, LinphoneCall *call, const Linphon printCallStatsHelper(ostr, stats, prefix); if (linphone_call_stats_get_type(stats) == LINPHONE_CALL_STATS_AUDIO) { - const PayloadType *audioCodec = linphone_call_params_get_used_audio_codec(callParams); + const LinphonePayloadType *audioCodec = linphone_call_params_get_used_audio_payload_type(callParams); ostr << PayloadTypeResponse(linphone_call_get_core(call), audioCodec, -1, prefix, false).getBody() << "\n"; } else { - const PayloadType *videoCodec = linphone_call_params_get_used_video_codec(callParams); + const LinphonePayloadType *videoCodec = linphone_call_params_get_used_video_payload_type(callParams); ostr << PayloadTypeResponse(linphone_call_get_core(call), videoCodec, -1, prefix, false).getBody() << "\n"; } @@ -227,21 +227,25 @@ CallPlayingStatsEvent::CallPlayingStatsEvent(BCTBX_UNUSED(Daemon *daemon), int i setBody(ostr.str()); } -PayloadTypeResponse::PayloadTypeResponse( - LinphoneCore *core, const PayloadType *payloadType, int index, const string &prefix, bool enabled_status) { +PayloadTypeResponse::PayloadTypeResponse(BCTBX_UNUSED(LinphoneCore *core), + const LinphonePayloadType *payloadType, + int index, + const string &prefix, + bool enabled_status) { ostringstream ostr; if (payloadType != NULL) { if (index >= 0) ostr << prefix << "Index: " << index << "\n"; - ostr << prefix << "Payload-type-number: " << payload_type_get_number(payloadType) << "\n"; - ostr << prefix << "Clock-rate: " << payloadType->clock_rate << "\n"; - ostr << prefix << "Bitrate: " << payloadType->normal_bitrate << "\n"; - ostr << prefix << "Mime: " << payloadType->mime_type << "\n"; - ostr << prefix << "Channels: " << payloadType->channels << "\n"; - ostr << prefix << "Recv-fmtp: " << ((payloadType->recv_fmtp) ? payloadType->recv_fmtp : "") << "\n"; - ostr << prefix << "Send-fmtp: " << ((payloadType->send_fmtp) ? payloadType->send_fmtp : "") << "\n"; + const char *recv_fmtp = linphone_payload_type_get_recv_fmtp(payloadType); + const char *send_fmtp = linphone_payload_type_get_send_fmtp(payloadType); + ostr << prefix << "Payload-type-number: " << linphone_payload_type_get_number(payloadType) << "\n"; + ostr << prefix << "Clock-rate: " << linphone_payload_type_get_clock_rate(payloadType) << "\n"; + ostr << prefix << "Bitrate: " << linphone_payload_type_get_normal_bitrate(payloadType) << "\n"; + ostr << prefix << "Mime: " << linphone_payload_type_get_mime_type(payloadType) << "\n"; + ostr << prefix << "Channels: " << linphone_payload_type_get_channels(payloadType) << "\n"; + ostr << prefix << "Recv-fmtp: " << (recv_fmtp ? recv_fmtp : "") << "\n"; + ostr << prefix << "Send-fmtp: " << (send_fmtp ? send_fmtp : "") << "\n"; if (enabled_status) - ostr << prefix - << "Enabled: " << (linphone_core_payload_type_enabled(core, payloadType) == TRUE ? "true" : "false") + ostr << prefix << "Enabled: " << (linphone_payload_type_enabled(payloadType) == TRUE ? "true" : "false") << "\n"; setBody(ostr.str().c_str()); } @@ -263,16 +267,29 @@ PayloadTypeParser::PayloadTypeParser(LinphoneCore *core, const string &mime_type mSuccesful = false; return; } - mPayloadType = linphone_core_find_payload_type(core, type, rate, channels); - if (mPayloadType) mPosition = bctbx_list_index(linphone_core_get_audio_codecs(core), mPayloadType); + mPayloadType = linphone_core_get_payload_type(core, type, rate, channels); + if (mPayloadType) { + bctbx_list_t *codecs = linphone_core_get_audio_payload_types(core); + bctbx_list_t *elem; + int index = 0; + for (elem = codecs; elem != NULL; elem = elem->next, ++index) { + if (linphone_payload_type_weak_equals((LinphonePayloadType *)elem->data, mPayloadType)) { + mPosition = index; + break; + } + } + bctbx_list_free_with_data(codecs, (bctbx_list_free_func)linphone_payload_type_unref); + } } else if (number != -1) { - const bctbx_list_t *elem; - for (elem = linphone_core_get_audio_codecs(core); elem != NULL; elem = elem->next) { - if (number == payload_type_get_number((PayloadType *)elem->data)) { - mPayloadType = (PayloadType *)elem->data; + bctbx_list_t *codecs = linphone_core_get_audio_payload_types(core); + bctbx_list_t *elem; + for (elem = codecs; elem != NULL; elem = elem->next) { + if (number == linphone_payload_type_get_number((LinphonePayloadType *)elem->data)) { + mPayloadType = linphone_payload_type_ref((LinphonePayloadType *)elem->data); break; } } + bctbx_list_free_with_data(codecs, (bctbx_list_free_func)linphone_payload_type_unref); } } diff --git a/daemon/daemon.h b/daemon/daemon.h index 808b4f3f9d..aa98fb5af3 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -203,7 +203,7 @@ public: class PayloadTypeResponse : public Response { public: PayloadTypeResponse(LinphoneCore *core, - const PayloadType *payloadType, + const LinphonePayloadType *payloadType, int index = -1, const std::string &prefix = std::string(), bool enabled_status = true); @@ -212,13 +212,16 @@ public: class PayloadTypeParser { public: PayloadTypeParser(LinphoneCore *core, const std::string &mime_type, bool accept_all = false); + ~PayloadTypeParser() { + if (mPayloadType) linphone_payload_type_unref(mPayloadType); + } inline bool all() { return mAll; } inline bool successful() { return mSuccesful; } - inline PayloadType *getPayloadType() const { + inline LinphonePayloadType *getPayloadType() const { return mPayloadType; } inline int getPosition() const { @@ -228,7 +231,7 @@ public: private: bool mAll; bool mSuccesful; - PayloadType *mPayloadType; + LinphonePayloadType *mPayloadType; int mPosition; }; diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 575238b1ce..a4cfce8998 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -125,6 +125,7 @@ set(C_API_HEADER_FILES ) set(ENUMS_HEADER_FILES + c-enums.h call-enums.h chat-message-enums.h chat-room-enums.h diff --git a/include/linphone/api/c-alert.h b/include/linphone/api/c-alert.h index 0564085178..8e8ebc57de 100644 --- a/include/linphone/api/c-alert.h +++ b/include/linphone/api/c-alert.h @@ -21,6 +21,7 @@ #define _L_C_ALERT_H_ #include "linphone/api/c-types.h" +#include "linphone/enums/c-enums.h" #ifdef __cplusplus extern "C" { @@ -124,4 +125,4 @@ LINPHONE_PUBLIC void linphone_alert_notify_on_terminated(LinphoneAlert *alert); } #endif -#endif //_L_C_ALERT_H_ \ No newline at end of file +#endif //_L_C_ALERT_H_ diff --git a/include/linphone/api/c-payload-type.h b/include/linphone/api/c-payload-type.h index 2b5197a022..ba13dd013f 100644 --- a/include/linphone/api/c-payload-type.h +++ b/include/linphone/api/c-payload-type.h @@ -181,6 +181,16 @@ LINPHONE_PUBLIC bool_t linphone_payload_type_is_vbr(const LinphonePayloadType *p */ LINPHONE_PUBLIC bool_t linphone_payload_type_is_usable(const LinphonePayloadType *payload_type); +/** + * Compare two payload types, and returns true if they are equal. + * Parameters (fmtp strings) are not compared, hence the name 'weak equals'. + * @param payload_type the #LinphonePayloadType object @notnil + * @param other_payload_type another #LinphonePayloadType object @notnil + * @return TRUE if the payload types are "almost" equals. + */ +LINPHONE_PUBLIC bool_t linphone_payload_type_weak_equals(const LinphonePayloadType *payload_type, + const LinphonePayloadType *other_payload_type); + #ifdef __cplusplus } #endif diff --git a/include/linphone/api/c-signal-information.h b/include/linphone/api/c-signal-information.h index 0abd1c1477..18fa1e46b3 100644 --- a/include/linphone/api/c-signal-information.h +++ b/include/linphone/api/c-signal-information.h @@ -21,6 +21,7 @@ #define _L_C_SIGNAL_INFORMATION_H_ #include "linphone/api/c-types.h" +#include "linphone/enums/c-enums.h" #ifdef __cplusplus extern "C" { @@ -98,4 +99,4 @@ LINPHONE_PUBLIC void linphone_signal_information_set_signal_unit(LinphoneSignalI } #endif -#endif //_L_C_SIGNAL_INFORMATION_H_ \ No newline at end of file +#endif //_L_C_SIGNAL_INFORMATION_H_ diff --git a/include/linphone/api/c-types.h b/include/linphone/api/c-types.h index 2d96128cc7..b52e4136f3 100644 --- a/include/linphone/api/c-types.h +++ b/include/linphone/api/c-types.h @@ -661,107 +661,15 @@ typedef struct _LinphoneAlert LinphoneAlert; * @ingroup alert */ typedef struct _LinphoneAlertCbs LinphoneAlertCbs; -/** - * @brief All kinds of alerts - * @ingroup alert - */ -typedef enum _LinphoneAlertTypes { - - /** Camera is not working. No other information - * @note Use the key "camera_misfunction_interval" in the section "alerts::camera" to set the interval - * at which the problem is checked in a #LinphoneConfig. - */ - LinphoneAlertQoSCameraMisfunction, - /** Camera is capturing low framerate. Information supplied : float framerate; - * @note Use the key "low_framerate_interval" in the section "alerts::camera" to set or get the interval at which - * the problem is checked in a #LinphoneConfig. - */ - LinphoneAlertQoSCameraLowFramerate, - /** Video decoding has stopped for a given period (10 s by default). No other information. - * @note Use the key "video_stalled_interval" in the section "alerts::camera" to set or get the interval at which - * the problem is checked in a #LinphoneConfig. - */ - LinphoneAlertQoSVideoStalled, - /** A received media stream suffers from high loss or late rate. Information provided is: - * - loss-rate (float) - * - late-rate (float) - * - media-type (string) with values {audio, video, text} - * @note Use the key "loss_rate_interval" in the section "alerts::network" to set or get the interval at which - the problem is checked in a #LinphoneConfig. - */ - LinphoneAlertQoSHighLossLateRate, - /** A report of high loss rate is received from remote party. Information provided: loss-rate (float). - * @note Use the key "remote_loss_rate_interval" in the section "alerts::network" to set or get the interval at - * which the problem is checked in a #LinphoneConfig. - */ - LinphoneAlertQoSHighRemoteLossRate, - /** Packet Burst phenomenon - * @note Use the key "burst_occured_interval" in the section "alerts::network" to set or get the interval at which - * the problem is checked in a #LinphoneConfig. - */ - LinphoneAlertQoSBurstOccured, - /** Loss rate is significant but retransmissions fail to arrive on time. - * Information provided: nack-performance (float) the fraction of lost packets recovered thanks to nack-triggered - * retransmissions. - * @note Use the key "nack_check_interval" in the section "alerts::network" to set or get the interval at which the - * problem is checked in a #LinphoneConfig. - */ - LinphoneAlertQoSRetransmissionFailures, - /** Low bandwidth detected. Information provided: bandwidth (float) in kbit/s. - * @note Use the key "download_bandwidth_interval" in the section "alerts::video" to set or get the interval at - * which the problem is checked in a #LinphoneConfig. - */ - LinphoneAlertQoSLowDownloadBandwidthEstimation, - /** Low quality (bitrate) video received. Information provided: bitrate (float) in kbit/s, width (integer), int - * height (integer). - * @note Use the key "low_quality_received_interval" in the section "alerts::video" to set or get the interval at - * which the problem is checked in a #LinphoneConfig. - */ - LinphoneAlertQoSLowQualityReceivedVideo, - /** Low quality video is being sent. Information provided: bitrate (float)in kbit/s, width (integer), height - * (integer). - * @note Use the key "quality_sent_interval" in the section "alerts::camera" to set or get the interval at which - * the problem is checked in a #LinphoneConfig. - */ - LinphoneAlertQoSLowQualitySentVideo, - /** The operating system reports a low radio signal (wifi or mobile) - * @note Use the key "low_signal_interval" in the section "alerts::network" to set or get the interval at which the - * problem is checked in a #LinphoneConfig. - */ - LinphoneAlertQoSLowSignal, - /** The operating system reports a loss of radio signal (wifi or mobile). - * Information provided: rssi-value (float), signal-type (string) with values {"wifi", "mobile", "other"}. - * @note Use the key "lost_signal_interval" in the section "alerts::network" to set or get the interval at which - * the problem is checked in a #LinphoneConfig. - */ - LinphoneAlertQoSLostSignal - -} LinphoneAlertType; + // ----------------------------------------------------------------------------- // SignalInformation // ----------------------------------------------------------------------------- /** * @brief Object to get signal (wifi/4G etc...) informations. - * @ingroup signalInformation + * @ingroup alert */ typedef struct _LinphoneSignalInformation LinphoneSignalInformation; -/** - * All signal types that a device can use. - * @ingroup signalInformation - */ -typedef enum _LinphoneSignalType { - LinphoneSignalTypeWifi = 0, - LinphoneSignalTypeMobile = 1, - LinphoneSignalTypeOther = 2 -} LinphoneSignalType; -/** - * All signal units that a device can use. - * @ingroup signalInformation - */ -typedef enum _LinphoneSignalStrengthUnit { - LinphoneSignalStrengthUnitRssi = 0, - LinphoneSignalStrengthUnitDbm = 1, -} LinphoneSignalStrengthUnit; #ifdef __cplusplus } diff --git a/include/linphone/call_params.h b/include/linphone/call_params.h index 344a27874b..3b643e6501 100644 --- a/include/linphone/call_params.h +++ b/include/linphone/call_params.h @@ -331,7 +331,7 @@ LINPHONE_PUBLIC const char *linphone_call_params_get_session_name(const Linphone * @return The selected #LinphonePayloadType. NULL is returned if no audio payload type has been selected by the call. *@maybenil **/ -LINPHONE_PUBLIC LinphonePayloadType * +LINPHONE_PUBLIC const LinphonePayloadType * linphone_call_params_get_used_audio_payload_type(const LinphoneCallParams *call_params); /** @@ -340,17 +340,16 @@ linphone_call_params_get_used_audio_payload_type(const LinphoneCallParams *call_ * @return The selected #LinphonePayloadType. NULL is returned if no video payload type has been selected by the call. *@maybenil **/ -LINPHONE_PUBLIC LinphonePayloadType * +LINPHONE_PUBLIC const LinphonePayloadType * linphone_call_params_get_used_video_payload_type(const LinphoneCallParams *call_params); -LINPHONE_PUBLIC const OrtpPayloadType *linphone_call_params_get_used_fec_codec(const LinphoneCallParams *call_params); /** * Get the text payload type that has been selected by a call. * @param call_params The #LinphoneCallParams object. @notnil * @return The selected #LinphonePayloadType. NULL is returned if no text payload type has been selected by the call. *@maybenil **/ -LINPHONE_PUBLIC LinphonePayloadType * +LINPHONE_PUBLIC const LinphonePayloadType * linphone_call_params_get_used_text_payload_type(const LinphoneCallParams *call_params); /** @@ -835,36 +834,6 @@ linphone_call_params_get_received_video_size(const LinphoneCallParams *call_para LINPHONE_PUBLIC LINPHONE_DEPRECATED MSVideoSize linphone_call_params_get_sent_video_size(const LinphoneCallParams *call_params); -/** - * Get the audio payload type that has been selected by a call. - * @param call_params The #LinphoneCallParams object. @notnil - * @return The selected payload type. NULL is returned if no audio payload type has been seleced by the call. - * @deprecated 31/03/2017 Use linphone_call_params_get_used_audio_payload_type() instead. - * @donotwrap - **/ -LINPHONE_PUBLIC LINPHONE_DEPRECATED const OrtpPayloadType * -linphone_call_params_get_used_audio_codec(const LinphoneCallParams *call_params); - -/** - * Get the video payload type that has been selected by a call. - * @param call_params The #LinphoneCallParams object. @notnil - * @return The selected payload type. NULL is returned if no video payload type has been seleced by the call. - * @deprecated 31/03/2017 Use linphone_call_params_get_used_video_payload_type() instead. - * @donotwrap - **/ -LINPHONE_PUBLIC LINPHONE_DEPRECATED const OrtpPayloadType * -linphone_call_params_get_used_video_codec(const LinphoneCallParams *call_params); - -/** - * Get the text payload type that has been selected by a call. - * @param call_params The #LinphoneCallParams object. @notnil - * @return The selected payload type. NULL is returned if no text payload type has been seleced by the call. - * @deprecated 31/03/2017 Use linphone_call_params_get_used_text_payload_type() instead. - * @donotwrap - **/ -LINPHONE_PUBLIC LINPHONE_DEPRECATED const OrtpPayloadType * -linphone_call_params_get_used_text_codec(const LinphoneCallParams *call_params); - /** * Set the #LinphoneProxyConfig to use for the call * diff --git a/include/linphone/core.h b/include/linphone/core.h index ea26994ce4..af424cd09c 100644 --- a/include/linphone/core.h +++ b/include/linphone/core.h @@ -66,6 +66,8 @@ // For migration purpose. #include "linphone/api/c-api.h" +#include "linphone/enums/c-enums.h" + #ifdef __cplusplus extern "C" { #endif @@ -2044,7 +2046,8 @@ LINPHONE_PUBLIC void linphone_core_set_upload_ptime(LinphoneCore *core, int ptim LINPHONE_PUBLIC int linphone_core_get_upload_ptime(LinphoneCore *core); /** - * Set the SIP transport timeout. + * Set the SIP transport timeout, which represents the maximum time permitted to establish a + * connection to a SIP server. * @param core #LinphoneCore object. @notnil * @param timeout_ms The SIP transport timeout in milliseconds. * @ingroup media_parameters @@ -2052,7 +2055,8 @@ LINPHONE_PUBLIC int linphone_core_get_upload_ptime(LinphoneCore *core); LINPHONE_PUBLIC void linphone_core_set_sip_transport_timeout(LinphoneCore *core, int timeout_ms); /** - * Get the SIP transport timeout. + * Get the SIP transport timeout, which represents the maximum time permitted to establish a + * connection to a SIP server. * @param core #LinphoneCore object. @notnil * @return The SIP transport timeout in milliseconds. * @ingroup media_parameters @@ -2123,8 +2127,7 @@ LINPHONE_PUBLIC void linphone_core_set_dns_servers(LinphoneCore *core, const bct /** * Return the list of the available audio payload types. * @param core The core. @notnil - * @return A freshly allocated list of the available payload types. The list - * must be destroyed with bctbx_list_free() after usage. The elements of the list haven't to be unref. + * @return A freshly allocated list of the available payload types. * @bctbx_list{LinphonePayloadType} @maybenil @tobefreed * @ingroup media_parameters */ @@ -2142,15 +2145,18 @@ LINPHONE_PUBLIC void linphone_core_set_audio_payload_types(LinphoneCore *core, c /** * Return the list of the available video payload types. * @param core The core. @notnil - * @return A freshly allocated list of the available payload types. The list - * must be destroyed with bctbx_list_free() after usage. The elements of the - * list haven't to be unref. @bctbx_list{LinphonePayloadType} @maybenil + * @return A freshly allocated list of the available payload types. @bctbx_list{LinphonePayloadType} @maybenil + * @tobefreed * @ingroup media_parameters */ LINPHONE_PUBLIC bctbx_list_t *linphone_core_get_video_payload_types(LinphoneCore *core); /** * Redefine the list of the available video payload types. + * Calling this function if the video codec priority policy is LinphoneCodecPriorityPolicyAuto + * turns video codec priority policy to basic scheme, since application is not supposed to control + * the order of video codecs when LinphoneCodecPriorityPolicyAuto is selected, by definition. + * (see linphone_core_set_video_codec_priority_policy() ) * @param core The core. @notnil * @param payload_types The new list of codecs. The core does not take * ownership on it. \bctbx_list{LinphonePayloadType} @maybenil @@ -2158,6 +2164,28 @@ LINPHONE_PUBLIC bctbx_list_t *linphone_core_get_video_payload_types(LinphoneCore */ LINPHONE_PUBLIC void linphone_core_set_video_payload_types(LinphoneCore *core, const bctbx_list_t *payload_types); +/** + * Set the priority policy for video codecs (payload types). + * Since version 5.3, the default value is #LinphoneCodecPriorityPolicyAuto unless the core's + * configuration file describes a list of video payload type to use. + * This is to preserve backward compatibility for upgrading applications. + * See #LinphoneCodecPriorityPolicy for more details. + * @param core, the core @notnil + * @param policy the #LinphoneCodecPriorityPolicy to apply + * @ingroup media_parameters + */ +LINPHONE_PUBLIC void linphone_core_set_video_codec_priority_policy(LinphoneCore *core, + LinphoneCodecPriorityPolicy policy); + +/** + * Get the current priority policy for video codecs (payload types). + * + * See #LinphoneCodecPriorityPolicy for more details. + * @param core, the core @notnil + * @return the current #LinphoneCodecPriorityPolicy + **/ +LINPHONE_PUBLIC LinphoneCodecPriorityPolicy linphone_core_get_video_codec_priority_policy(const LinphoneCore *core); + /** * Return the list of the available text payload types. * @param core The core. @notnil @@ -2206,9 +2234,7 @@ LINPHONE_PUBLIC bool_t linphone_core_generic_comfort_noise_enabled(const Linphon * @param rate can be #LINPHONE_FIND_PAYLOAD_IGNORE_RATE * @param channels number of channels, can be #LINPHONE_FIND_PAYLOAD_IGNORE_CHANNELS * @return Returns NULL if not found. If a #LinphonePayloadType is returned, it must be released with - * linphone_payload_type_unref() after using it. @maybenil - * @warning The returned payload type is allocated as a floating reference i.e. the reference counter is initialized to - * 0. + * linphone_payload_type_unref() after using it. @maybenil @tobefreed */ LINPHONE_PUBLIC LinphonePayloadType * linphone_core_get_payload_type(LinphoneCore *core, const char *type, int rate, int channels); diff --git a/include/linphone/enums/c-enums.h b/include/linphone/enums/c-enums.h new file mode 100644 index 0000000000..aaa7a588a7 --- /dev/null +++ b/include/linphone/enums/c-enums.h @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2010-2022 Belledonne Communications SARL. + * + * This file is part of Liblinphone + * (see https://gitlab.linphone.org/BC/public/liblinphone). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _L_C_ENUMS_H_ +#define _L_C_ENUMS_H_ + +/* + * Global enums, not bound to any object. + */ + +/** + * @brief All kinds of alerts + * @ingroup alert + */ +typedef enum _LinphoneAlertTypes { + + /** Camera is not working. No other information + * @note Use the key "camera_misfunction_interval" in the section "alerts::camera" to set the interval + * at which the problem is checked in a #LinphoneConfig. + */ + LinphoneAlertQoSCameraMisfunction, + /** Camera is capturing low framerate. Information supplied : float framerate; + * @note Use the key "low_framerate_interval" in the section "alerts::camera" to set or get the interval at which + * the problem is checked in a #LinphoneConfig. + */ + LinphoneAlertQoSCameraLowFramerate, + /** Video decoding has stopped for a given period (10 s by default). No other information. + * @note Use the key "video_stalled_interval" in the section "alerts::camera" to set or get the interval at which + * the problem is checked in a #LinphoneConfig. + */ + LinphoneAlertQoSVideoStalled, + /** A received media stream suffers from high loss or late rate. Information provided is: + * - loss-rate (float) + * - late-rate (float) + * - media-type (string) with values {audio, video, text} + * @note Use the key "loss_rate_interval" in the section "alerts::network" to set or get the interval at which + the problem is checked in a #LinphoneConfig. + */ + LinphoneAlertQoSHighLossLateRate, + /** A report of high loss rate is received from remote party. Information provided: loss-rate (float). + * @note Use the key "remote_loss_rate_interval" in the section "alerts::network" to set or get the interval at + * which the problem is checked in a #LinphoneConfig. + */ + LinphoneAlertQoSHighRemoteLossRate, + /** Packet Burst phenomenon + * @note Use the key "burst_occured_interval" in the section "alerts::network" to set or get the interval at which + * the problem is checked in a #LinphoneConfig. + */ + LinphoneAlertQoSBurstOccured, + /** Loss rate is significant but retransmissions fail to arrive on time. + * Information provided: nack-performance (float) the fraction of lost packets recovered thanks to nack-triggered + * retransmissions. + * @note Use the key "nack_check_interval" in the section "alerts::network" to set or get the interval at which the + * problem is checked in a #LinphoneConfig. + */ + LinphoneAlertQoSRetransmissionFailures, + /** Low bandwidth detected. Information provided: bandwidth (float) in kbit/s. + * @note Use the key "download_bandwidth_interval" in the section "alerts::video" to set or get the interval at + * which the problem is checked in a #LinphoneConfig. + */ + LinphoneAlertQoSLowDownloadBandwidthEstimation, + /** Low quality (bitrate) video received. Information provided: bitrate (float) in kbit/s, width (integer), int + * height (integer). + * @note Use the key "low_quality_received_interval" in the section "alerts::video" to set or get the interval at + * which the problem is checked in a #LinphoneConfig. + */ + LinphoneAlertQoSLowQualityReceivedVideo, + /** Low quality video is being sent. Information provided: bitrate (float)in kbit/s, width (integer), height + * (integer). + * @note Use the key "quality_sent_interval" in the section "alerts::camera" to set or get the interval at which + * the problem is checked in a #LinphoneConfig. + */ + LinphoneAlertQoSLowQualitySentVideo, + /** The operating system reports a low radio signal (wifi or mobile) + * @note Use the key "low_signal_interval" in the section "alerts::network" to set or get the interval at which the + * problem is checked in a #LinphoneConfig. + */ + LinphoneAlertQoSLowSignal, + /** The operating system reports a loss of radio signal (wifi or mobile). + * Information provided: rssi-value (float), signal-type (string) with values {"wifi", "mobile", "other"}. + * @note Use the key "lost_signal_interval" in the section "alerts::network" to set or get the interval at which + * the problem is checked in a #LinphoneConfig. + */ + LinphoneAlertQoSLostSignal + +} LinphoneAlertType; + +/** + * All signal types that a device can use. + * @ingroup signalInformation + */ +typedef enum _LinphoneSignalType { + LinphoneSignalTypeWifi = 0, + LinphoneSignalTypeMobile = 1, + LinphoneSignalTypeOther = 2 +} LinphoneSignalType; +/** + * All signal units that a device can use. + * @ingroup signalInformation + */ +typedef enum _LinphoneSignalStrengthUnit { + LinphoneSignalStrengthUnitRssi = 0, + LinphoneSignalStrengthUnitDbm = 1, +} LinphoneSignalStrengthUnit; + +/** + * Codec priority policies. + * This enum represents different policies for managing offered codec lists during calls, as well as the offer-answer + * logic. Currently, policies can be applied only for video codecs. + * @ingroup media_parameters + */ +typedef enum _LinphoneCodecPriorityPolicy { + LinphoneCodecPriorityPolicyBasic = + 0, /**< In this mode, codecs have initial default ordering, that can be changed by the application + The answerer of a call accepts codecs with the order given in the offer. */ + LinphoneCodecPriorityPolicyAuto = + 1 /**< In this mode, the codec list is managed by the #LinphoneCore according to hardware capabilities + in the goal of optimizing video quality and user experience. The answerer of call + may re-order the offerer's list in its answer in order to give preference to certain codecs.*/ +} LinphoneCodecPriorityPolicy; + +#endif diff --git a/src/c-wrapper/api/c-account.cpp b/src/c-wrapper/api/c-account.cpp index e1facbcc24..7e9a5d89c5 100644 --- a/src/c-wrapper/api/c-account.cpp +++ b/src/c-wrapper/api/c-account.cpp @@ -316,11 +316,11 @@ char *linphone_account_normalize_phone_number(const LinphoneAccount *account, co if (account) { const LinphoneAccountParams *accountParams = linphone_account_get_params(account); dial_prefix = linphone_account_params_get_international_prefix(accountParams); - dial_escape_plus = linphone_account_params_get_dial_escape_plus_enabled(accountParams); + dial_escape_plus = linphone_account_params_dial_escape_plus_enabled(accountParams); } else { LinphoneAccountParams *accountParams = linphone_account_params_new(NULL); dial_prefix = linphone_account_params_get_international_prefix(accountParams); - dial_escape_plus = linphone_account_params_get_dial_escape_plus_enabled(accountParams); + dial_escape_plus = linphone_account_params_dial_escape_plus_enabled(accountParams); linphone_account_params_unref(accountParams); } diff --git a/src/c-wrapper/api/c-call-params.cpp b/src/c-wrapper/api/c-call-params.cpp index 5d9cc9d290..2fa745243d 100644 --- a/src/c-wrapper/api/c-call-params.cpp +++ b/src/c-wrapper/api/c-call-params.cpp @@ -344,45 +344,30 @@ const char *linphone_call_params_get_session_name(const LinphoneCallParams *para return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(params)->getSessionName()); } -LinphonePayloadType *linphone_call_params_get_used_audio_payload_type(const LinphoneCallParams *params) { - return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getUsedAudioPayloadType(); +const LinphonePayloadType *linphone_call_params_get_used_audio_payload_type(const LinphoneCallParams *params) { + return bellesip::toC(L_GET_CPP_PTR_FROM_C_OBJECT(params)->getUsedAudioPayloadType()); } -LinphonePayloadType *linphone_call_params_get_used_video_payload_type(const LinphoneCallParams *params) { - return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getUsedVideoPayloadType(); +const LinphonePayloadType *linphone_call_params_get_used_video_payload_type(const LinphoneCallParams *params) { + return bellesip::toC(L_GET_CPP_PTR_FROM_C_OBJECT(params)->getUsedVideoPayloadType()); } -LinphonePayloadType *linphone_call_params_get_used_text_payload_type(const LinphoneCallParams *params) { - return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getUsedRealtimeTextPayloadType(); -} - -const OrtpPayloadType *linphone_call_params_get_used_audio_codec(const LinphoneCallParams *params) { - return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getUsedAudioCodec(); +const LinphonePayloadType *linphone_call_params_get_used_text_payload_type(const LinphoneCallParams *params) { + return bellesip::toC(L_GET_CPP_PTR_FROM_C_OBJECT(params)->getUsedRealtimeTextPayloadType()); } void linphone_call_params_set_used_audio_codec(LinphoneCallParams *params, OrtpPayloadType *codec) { L_GET_PRIVATE_FROM_C_OBJECT(params)->setUsedAudioCodec(codec); } -const OrtpPayloadType *linphone_call_params_get_used_video_codec(const LinphoneCallParams *params) { - return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getUsedVideoCodec(); -} - void linphone_call_params_set_used_video_codec(LinphoneCallParams *params, OrtpPayloadType *codec) { L_GET_PRIVATE_FROM_C_OBJECT(params)->setUsedVideoCodec(codec); } -const OrtpPayloadType *linphone_call_params_get_used_fec_codec(const LinphoneCallParams *params) { - return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getUsedFecCodec(); -} void linphone_call_params_set_used_fec_codec(LinphoneCallParams *params, OrtpPayloadType *codec) { L_GET_PRIVATE_FROM_C_OBJECT(params)->setUsedFecCodec(codec); } -const OrtpPayloadType *linphone_call_params_get_used_text_codec(const LinphoneCallParams *params) { - return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getUsedRealtimeTextCodec(); -} - void linphone_call_params_set_used_text_codec(LinphoneCallParams *params, OrtpPayloadType *codec) { L_GET_PRIVATE_FROM_C_OBJECT(params)->setUsedRealtimeTextCodec(codec); } diff --git a/src/c-wrapper/api/c-chat-message.cpp b/src/c-wrapper/api/c-chat-message.cpp index 895a936b39..4480f9f7b8 100644 --- a/src/c-wrapper/api/c-chat-message.cpp +++ b/src/c-wrapper/api/c-chat-message.cpp @@ -621,7 +621,7 @@ void linphone_chat_message_start_file_download(LinphoneChatMessage *msg, void *ud) { msg->message_state_changed_cb = status_cb; msg->message_state_changed_user_data = ud; - linphone_chat_message_download_file(msg); + L_GET_PRIVATE_FROM_C_OBJECT(msg)->downloadFile(); } const char *linphone_chat_message_get_call_id(const LinphoneChatMessage *msg) { diff --git a/src/c-wrapper/api/c-core.cpp b/src/c-wrapper/api/c-core.cpp index 14bc66cd9a..8caa9e1284 100644 --- a/src/c-wrapper/api/c-core.cpp +++ b/src/c-wrapper/api/c-core.cpp @@ -102,8 +102,8 @@ const char *linphone_core_get_linphone_specs(const LinphoneCore *lc) { return linphone_config_get_string(linphone_core_get_config(lc), "sip", "linphone_specs", NULL); } -//Deprecated -void linphone_core_set_linphone_specs (LinphoneCore *lc, const char *specs) { +// Deprecated +void linphone_core_set_linphone_specs(LinphoneCore *lc, const char *specs) { L_GET_CPP_PTR_FROM_C_OBJECT(lc)->setSpecs(L_C_TO_STRING(specs)); } @@ -111,15 +111,15 @@ void linphone_core_set_linphone_specs_list(LinphoneCore *lc, const bctbx_list_t L_GET_CPP_PTR_FROM_C_OBJECT(lc)->setSpecs(L_GET_CPP_LIST_FROM_C_LIST(specs, const char *, string)); } -void linphone_core_add_linphone_spec (LinphoneCore *lc, const char *spec) { +void linphone_core_add_linphone_spec(LinphoneCore *lc, const char *spec) { L_GET_CPP_PTR_FROM_C_OBJECT(lc)->addSpec(L_C_TO_STRING(spec)); } -void linphone_core_remove_linphone_spec (LinphoneCore *lc, const char *spec) { +void linphone_core_remove_linphone_spec(LinphoneCore *lc, const char *spec) { L_GET_CPP_PTR_FROM_C_OBJECT(lc)->removeSpec(L_C_TO_STRING(spec)); } -bctbx_list_t *linphone_core_get_linphone_specs_list (LinphoneCore *lc) { +bctbx_list_t *linphone_core_get_linphone_specs_list(LinphoneCore *lc) { return L_GET_C_LIST_FROM_CPP_LIST(L_GET_CPP_PTR_FROM_C_OBJECT(lc)->getSpecsList()); } @@ -140,10 +140,12 @@ void linphone_core_ensure_registered(LinphoneCore *lc) { } void linphone_core_process_push_notification(LinphoneCore *lc, const char *call_id) { + CoreLogContextualizer logContextualizer(lc); L_GET_CPP_PTR_FROM_C_OBJECT(lc)->pushNotificationReceived(call_id, "", false); } void linphone_core_push_notification_received(LinphoneCore *lc, const char *payload, const char *call_id) { + CoreLogContextualizer logContextualizer(lc); L_GET_CPP_PTR_FROM_C_OBJECT(lc)->pushNotificationReceived(call_id, payload, false); } @@ -151,11 +153,13 @@ void linphone_core_push_notification_received_2(LinphoneCore *lc, const char *payload, const char *call_id, bool_t is_core_starting) { + CoreLogContextualizer logContextualizer(lc); L_GET_CPP_PTR_FROM_C_OBJECT(lc)->pushNotificationReceived(call_id, payload, is_core_starting); } -LinphonePushNotificationMessage * linphone_core_get_new_message_from_callid(LinphoneCore *lc, const char *call_id) { - std::shared_ptr<PushNotificationMessage> cppMsg = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->getPushNotificationMessage(L_C_TO_STRING(call_id)); +LinphonePushNotificationMessage *linphone_core_get_new_message_from_callid(LinphoneCore *lc, const char *call_id) { + std::shared_ptr<PushNotificationMessage> cppMsg = + L_GET_CPP_PTR_FROM_C_OBJECT(lc)->getPushNotificationMessage(L_C_TO_STRING(call_id)); if (!cppMsg) return NULL; LinphonePushNotificationMessage *msg = (LinphonePushNotificationMessage *)cppMsg->toC(); @@ -167,9 +171,11 @@ LinphonePushNotificationMessage * linphone_core_get_new_message_from_callid(Linp } /* Uses the chat_room_addr instead of the call_id like linphone_core_get_new_message_from_callid to get the chatroom. -Using the call_id to get the chat room require to add a new param to chat room objects where the conference address is already here */ -LinphoneChatRoom * linphone_core_get_new_chat_room_from_conf_addr(LinphoneCore *lc , const char *chat_room_addr) { - std::shared_ptr<ChatRoom> cppChatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->getPushNotificationChatRoom(L_C_TO_STRING(chat_room_addr)); +Using the call_id to get the chat room require to add a new param to chat room objects where the conference address is +already here */ +LinphoneChatRoom *linphone_core_get_new_chat_room_from_conf_addr(LinphoneCore *lc, const char *chat_room_addr) { + std::shared_ptr<ChatRoom> cppChatRoom = + L_GET_CPP_PTR_FROM_C_OBJECT(lc)->getPushNotificationChatRoom(L_C_TO_STRING(chat_room_addr)); LinphoneChatRoom *chatRoom = L_GET_C_BACK_PTR(cppChatRoom); return chatRoom; @@ -284,6 +290,7 @@ LinphoneLdap *linphone_core_create_ldap_with_params(LinphoneCore *core, Linphone } void linphone_core_clear_ldaps(LinphoneCore *core) { + CoreLogContextualizer logContextualizer(core); auto list = L_GET_CPP_PTR_FROM_C_OBJECT(core)->getLdapList(); for (auto ldap : list) { L_GET_CPP_PTR_FROM_C_OBJECT(core)->removeLdap(ldap); @@ -291,14 +298,17 @@ void linphone_core_clear_ldaps(LinphoneCore *core) { } void linphone_core_add_ldap(LinphoneCore *core, LinphoneLdap *ldap) { + CoreLogContextualizer logContextualizer(core); L_GET_CPP_PTR_FROM_C_OBJECT(core)->addLdap(Ldap::toCpp(ldap)->getSharedFromThis()); } void linphone_core_remove_ldap(LinphoneCore *core, LinphoneLdap *ldap) { + CoreLogContextualizer logContextualizer(core); L_GET_CPP_PTR_FROM_C_OBJECT(core)->removeLdap(Ldap::toCpp(ldap)->getSharedFromThis()); } bctbx_list_t *linphone_core_get_ldap_list(LinphoneCore *lc) { + CoreLogContextualizer logContextualizer(lc); return Ldap::getCListFromCppList(L_GET_CPP_PTR_FROM_C_OBJECT(lc)->getLdapList()); } @@ -309,3 +319,13 @@ bool_t linphone_core_get_chat_messages_aggregation_enabled(LinphoneCore *core) { void linphone_core_set_chat_messages_aggregation_enabled(LinphoneCore *core, bool_t enabled) { linphone_config_set_bool(linphone_core_get_config(core), "sip", "chat_messages_aggregation", enabled); } + +void linphone_core_set_video_codec_priority_policy(LinphoneCore *core, LinphoneCodecPriorityPolicy policy) { + CoreLogContextualizer logContextualizer(core); + L_GET_CPP_PTR_FROM_C_OBJECT(core)->setVideoCodecPriorityPolicy(policy); +} + +LinphoneCodecPriorityPolicy linphone_core_get_video_codec_priority_policy(const LinphoneCore *core) { + CoreLogContextualizer logContextualizer(core); + return L_GET_CPP_PTR_FROM_C_OBJECT(core)->getVideoCodecPriorityPolicy(); +} diff --git a/src/c-wrapper/api/c-payload-type.cpp b/src/c-wrapper/api/c-payload-type.cpp index 573ce9d066..c6c0decfe1 100644 --- a/src/c-wrapper/api/c-payload-type.cpp +++ b/src/c-wrapper/api/c-payload-type.cpp @@ -112,3 +112,13 @@ bool_t linphone_payload_type_is_vbr(const LinphonePayloadType *payload_type) { bool_t linphone_payload_type_is_usable(const LinphonePayloadType *payload_type) { return LinphonePrivate::PayloadType::toCpp(payload_type)->isUsable(); } + +bool_t linphone_payload_type_weak_equals(const LinphonePayloadType *payload_type, + const LinphonePayloadType *other_payload_type) { + return LinphonePrivate::PayloadType::toCpp(payload_type) + ->weakEquals(*LinphonePrivate::PayloadType::toCpp(other_payload_type)); +} + +void linphone_payload_type_set_priority_bonus(LinphonePayloadType *payload_type, bool_t value) { + return LinphonePrivate::PayloadType::toCpp(payload_type)->setPriorityBonus(value); +} diff --git a/src/c-wrapper/c-wrapper.h b/src/c-wrapper/c-wrapper.h index f62f81d580..1ebafdab34 100644 --- a/src/c-wrapper/c-wrapper.h +++ b/src/c-wrapper/c-wrapper.h @@ -195,7 +195,6 @@ BELLE_SIP_TYPE_ID(LinphoneContactProvider), BELLE_SIP_TYPE_ID(LinphoneContactSearch), BELLE_SIP_TYPE_ID(LinphoneCoreCbs), BELLE_SIP_TYPE_ID(LinphoneErrorInfo), -BELLE_SIP_TYPE_ID(LinphoneFactory), BELLE_SIP_TYPE_ID(LinphoneFriend), BELLE_SIP_TYPE_ID(LinphoneFriendCbs), BELLE_SIP_TYPE_ID(LinphoneFriendList), @@ -212,7 +211,6 @@ BELLE_SIP_TYPE_ID(LinphoneMagicSearchCbs), BELLE_SIP_TYPE_ID(LinphoneParticipant), BELLE_SIP_TYPE_ID(LinphoneParticipantDevice), BELLE_SIP_TYPE_ID(LinphoneParticipantDeviceCbs), -BELLE_SIP_TYPE_ID(LinphonePayloadType), BELLE_SIP_TYPE_ID(LinphonePlayer), BELLE_SIP_TYPE_ID(LinphonePlayerCbs), BELLE_SIP_TYPE_ID(LinphonePresenceActivity), diff --git a/src/conference/params/media-session-params-p.h b/src/conference/params/media-session-params-p.h index 8dba90d3ff..f2013875b0 100644 --- a/src/conference/params/media-session-params-p.h +++ b/src/conference/params/media-session-params-p.h @@ -25,6 +25,8 @@ #include "media-session-params.h" +#include "payload-type/payload-type.h" + // ============================================================================= extern LinphoneCallParams *linphone_call_params_new_for_wrapper(void); @@ -96,16 +98,16 @@ public: } void setSentVideoDefinition(LinphoneVideoDefinition *value); void setUsedAudioCodec(OrtpPayloadType *pt) { - usedAudioCodec = pt; + usedAudioCodec = PayloadType::create(nullptr, pt); } void setUsedVideoCodec(OrtpPayloadType *pt) { - usedVideoCodec = pt; + usedVideoCodec = PayloadType::create(nullptr, pt); } void setUsedRealtimeTextCodec(OrtpPayloadType *pt) { - usedRealtimeTextCodec = pt; + usedRealtimeTextCodec = PayloadType::create(nullptr, pt); } void setUsedFecCodec(OrtpPayloadType *pt) { - usedFecCodec = pt; + usedFecCodec = PayloadType::create(nullptr, pt); } SalCustomSdpAttribute *getCustomSdpAttributes() const; void setCustomSdpAttributes(const SalCustomSdpAttribute *csa); @@ -117,22 +119,22 @@ public: int audioBandwidthLimit = 0; LinphoneMediaDirection audioDirection = LinphoneMediaDirectionSendRecv; bool audioMulticastEnabled = false; - ::PayloadType *usedAudioCodec = nullptr; + std::shared_ptr<PayloadType> usedAudioCodec; bool videoEnabled = false; LinphoneMediaDirection videoDirection = LinphoneMediaDirectionSendRecv; bool videoMulticastEnabled = false; - ::PayloadType *usedVideoCodec = nullptr; + std::shared_ptr<PayloadType> usedVideoCodec; float receivedFps = 0.f; LinphoneVideoDefinition *receivedVideoDefinition = nullptr; float sentFps = 0.f; LinphoneVideoDefinition *sentVideoDefinition = nullptr; bool fecEnabled = false; - ::PayloadType *usedFecCodec = nullptr; + std::shared_ptr<PayloadType> usedFecCodec; unsigned int realtimeTextKeepaliveInterval = 25000; - ::PayloadType *usedRealtimeTextCodec = nullptr; + std::shared_ptr<PayloadType> usedRealtimeTextCodec; int videoDownloadBandwidth = 0; bool realtimeTextEnabled = false; diff --git a/src/conference/params/media-session-params.cpp b/src/conference/params/media-session-params.cpp index ca049fa764..5615808e1c 100644 --- a/src/conference/params/media-session-params.cpp +++ b/src/conference/params/media-session-params.cpp @@ -339,16 +339,11 @@ LinphoneMediaDirection MediaSessionParams::getAudioDirection() const { return d->audioDirection; } -const OrtpPayloadType *MediaSessionParams::getUsedAudioCodec() const { +std::shared_ptr<const PayloadType> MediaSessionParams::getUsedAudioPayloadType() const { L_D(); return d->usedAudioCodec; } -LinphonePayloadType *MediaSessionParams::getUsedAudioPayloadType() const { - L_D(); - return d->usedAudioCodec ? linphone_payload_type_new(nullptr, d->usedAudioCodec) : nullptr; -} - void MediaSessionParams::setAudioBandwidthLimit(int value) { L_D(); d->audioBandwidthLimit = value; @@ -396,16 +391,11 @@ LinphoneVideoDefinition *MediaSessionParams::getSentVideoDefinition() const { return d->sentVideoDefinition; } -const OrtpPayloadType *MediaSessionParams::getUsedVideoCodec() const { +std::shared_ptr<const PayloadType> MediaSessionParams::getUsedVideoPayloadType() const { L_D(); return d->usedVideoCodec; } -LinphonePayloadType *MediaSessionParams::getUsedVideoPayloadType() const { - L_D(); - return d->usedVideoCodec ? linphone_payload_type_new(nullptr, d->usedVideoCodec) : nullptr; -} - LinphoneMediaDirection MediaSessionParams::getVideoDirection() const { L_D(); return d->videoDirection; @@ -441,7 +431,8 @@ bool MediaSessionParams::fecEnabled() const { L_D(); return d->fecEnabled; } -const OrtpPayloadType *MediaSessionParams::getUsedFecCodec() const { + +std::shared_ptr<const PayloadType> MediaSessionParams::getUsedFecCodec() const { L_D(); return d->usedFecCodec; } @@ -457,16 +448,11 @@ void MediaSessionParams::setRealtimeTextKeepaliveInterval(unsigned int interval) d->realtimeTextKeepaliveInterval = interval; } -const OrtpPayloadType *MediaSessionParams::getUsedRealtimeTextCodec() const { +std::shared_ptr<const PayloadType> MediaSessionParams::getUsedRealtimeTextPayloadType() const { L_D(); return d->usedRealtimeTextCodec; } -LinphonePayloadType *MediaSessionParams::getUsedRealtimeTextPayloadType() const { - L_D(); - return d->usedRealtimeTextCodec ? linphone_payload_type_new(nullptr, d->usedRealtimeTextCodec) : nullptr; -} - bool MediaSessionParams::realtimeTextEnabled() const { L_D(); return d->realtimeTextEnabled; diff --git a/src/conference/params/media-session-params.h b/src/conference/params/media-session-params.h index 599c1d8e4c..932ac6233d 100644 --- a/src/conference/params/media-session-params.h +++ b/src/conference/params/media-session-params.h @@ -21,10 +21,9 @@ #ifndef _L_MEDIA_SESSION_PARAMS_H_ #define _L_MEDIA_SESSION_PARAMS_H_ -#include <ortp/payloadtype.h> - #include "call-session-params.h" #include "call/audio-device/audio-device.h" +#include "payload-type/payload-type.h" #include "utils/general-internal.h" // ============================================================================= @@ -71,8 +70,7 @@ public: void enableAudioMulticast(bool value); int getAudioBandwidthLimit() const; LinphoneMediaDirection getAudioDirection() const; - const OrtpPayloadType *getUsedAudioCodec() const; - LinphonePayloadType *getUsedAudioPayloadType() const; + std::shared_ptr<const PayloadType> getUsedAudioPayloadType() const; void setAudioBandwidthLimit(int value); void setAudioDirection(SalStreamDir direction); void setAudioDirection(LinphoneMediaDirection direction); @@ -83,8 +81,7 @@ public: LinphoneVideoDefinition *getReceivedVideoDefinition() const; float getSentFps() const; LinphoneVideoDefinition *getSentVideoDefinition() const; - const OrtpPayloadType *getUsedVideoCodec() const; - LinphonePayloadType *getUsedVideoPayloadType() const; + std::shared_ptr<const PayloadType> getUsedVideoPayloadType() const; LinphoneMediaDirection getVideoDirection() const; void setVideoDirection(SalStreamDir direction); void setVideoDirection(LinphoneMediaDirection direction); @@ -93,12 +90,11 @@ public: void enableFec(bool value); bool fecEnabled() const; - const OrtpPayloadType *getUsedFecCodec() const; + std::shared_ptr<const PayloadType> getUsedFecCodec() const; void enableRealtimeText(bool value); void setRealtimeTextKeepaliveInterval(unsigned int interval); - const OrtpPayloadType *getUsedRealtimeTextCodec() const; - LinphonePayloadType *getUsedRealtimeTextPayloadType() const; + std::shared_ptr<const PayloadType> getUsedRealtimeTextPayloadType() const; bool realtimeTextEnabled() const; unsigned int realtimeTextKeepaliveInterval() const; diff --git a/src/conference/session/audio-mixer.cpp b/src/conference/session/audio-mixer.cpp index 86f26db58f..dc0eab8d5a 100644 --- a/src/conference/session/audio-mixer.cpp +++ b/src/conference/session/audio-mixer.cpp @@ -94,7 +94,7 @@ void MS2AudioMixer::disconnectEndpoint(BCTBX_UNUSED(Stream *as), MSAudioEndpoint RtpProfile *MS2AudioMixer::sMakeDummyProfile(int samplerate) { RtpProfile *prof = rtp_profile_new("dummy"); - PayloadType *pt = payload_type_clone(&payload_type_l16_mono); + OrtpPayloadType *pt = payload_type_clone(&payload_type_l16_mono); pt->clock_rate = samplerate; rtp_profile_set_payload(prof, 0, pt); return prof; @@ -153,7 +153,8 @@ void MS2AudioMixer::enableMic(bool value) { if (mLocalEndpoint) { bool coreMicrophoneEnabled = !!linphone_core_mic_enabled(mSession.getCore().getCCore()); if (!coreMicrophoneEnabled) { - lWarning() << "Microphone of the local participant of conference will be muted because the microphone is disabled in the core settings"; + lWarning() << "Microphone of the local participant of conference will be muted because the microphone is " + "disabled in the core settings"; } bool enabled = (value && coreMicrophoneEnabled); bctbx_message("AudioMixer[%p]: mic of local participnt is [%s].", this, enabled ? "enabled" : "disabled"); diff --git a/src/conference/session/ms2-stream.cpp b/src/conference/session/ms2-stream.cpp index 0601592bf9..9e3da2d974 100644 --- a/src/conference/session/ms2-stream.cpp +++ b/src/conference/session/ms2-stream.cpp @@ -1068,10 +1068,10 @@ void MS2Stream::updateDestinations(const OfferAnswerContext ¶ms) { bool MS2Stream::canIgnorePtimeChange(const OfferAnswerContext ¶ms) { const auto &resultStreamDesc = params.getResultStreamDescription(); - const PayloadType *pt = getMediaSessionPrivate().getCurrentParams()->getUsedAudioCodec(); - if (pt != nullptr && pt->send_fmtp != NULL) { + auto pt = getMediaSessionPrivate().getCurrentParams()->getUsedAudioPayloadType(); + if (pt && !pt->getSendFmtp().empty()) { char tmp[30]; - if (fmtp_get_value(pt->send_fmtp, "ptime", tmp, sizeof(tmp))) { + if (fmtp_get_value(pt->getSendFmtp().c_str(), "ptime", tmp, sizeof(tmp))) { return resultStreamDesc.getChosenConfiguration().ptime == atoi(tmp); } } diff --git a/src/conference/session/streams-group.cpp b/src/conference/session/streams-group.cpp index 43ed6d27ff..b91f3282b0 100644 --- a/src/conference/session/streams-group.cpp +++ b/src/conference/session/streams-group.cpp @@ -295,7 +295,7 @@ MediaSessionPrivate &StreamsGroup::getMediaSessionPrivate() const { return *getMediaSession().getPrivate(); } -int StreamsGroup::updateAllocatedAudioBandwidth(const PayloadType *pt, int maxbw) { +int StreamsGroup::updateAllocatedAudioBandwidth(const OrtpPayloadType *pt, int maxbw) { mAudioBandwidth = PayloadTypeHandler::getAudioPayloadTypeBandwidth(pt, maxbw); lInfo() << "Audio bandwidth for StreamsGroup [" << this << "] is " << mAudioBandwidth; return mAudioBandwidth; diff --git a/src/conference/session/streams.h b/src/conference/session/streams.h index 7a80e089a2..8ee753f834 100644 --- a/src/conference/session/streams.h +++ b/src/conference/session/streams.h @@ -537,7 +537,7 @@ public: Core &getCore() const; protected: - int updateAllocatedAudioBandwidth(const PayloadType *pt, int maxbw); + int updateAllocatedAudioBandwidth(const OrtpPayloadType *pt, int maxbw); int getVideoBandwidth(const std::shared_ptr<SalMediaDescription> &md, const SalStreamDescription &desc); void zrtpStarted(Stream *mainZrtpStream); void propagateEncryptionChanged(); diff --git a/src/conference/session/video-mixer.cpp b/src/conference/session/video-mixer.cpp index bce09ad094..a8a4939084 100644 --- a/src/conference/session/video-mixer.cpp +++ b/src/conference/session/video-mixer.cpp @@ -96,7 +96,7 @@ void MS2VideoMixer::setFocus(StreamsGroup *sg) { RtpProfile *MS2VideoMixer::sMakeDummyProfile() { RtpProfile *prof = rtp_profile_new("dummy video"); LinphonePayloadType *pt = linphone_core_get_payload_type(mSession.getCCore(), "VP8", 90000, -1); - PayloadType *ortp_pt = payload_type_clone(linphone_payload_type_get_ortp_pt(pt)); + OrtpPayloadType *ortp_pt = payload_type_clone(linphone_payload_type_get_ortp_pt(pt)); rtp_profile_set_payload(prof, sVP8PayloadTypeNumber, ortp_pt); linphone_payload_type_unref(pt); return prof; @@ -122,7 +122,7 @@ void MS2VideoMixer::createLocalMember(bool isThumbnail) { if (!mLocalDummyProfile) mLocalDummyProfile = sMakeDummyProfile(); MSMediaStreamIO io; int outputBandwidth = getOutputBandwidth() * 1000; - PayloadType *pt; + OrtpPayloadType *pt; memset(&io, 0, sizeof(io)); diff --git a/src/core/core-p.h b/src/core/core-p.h index e125beb206..9e2934a391 100644 --- a/src/core/core-p.h +++ b/src/core/core-p.h @@ -187,6 +187,8 @@ public: /* centralized method to write down all NatPolicy used by Accounts or Core */ void writeNatPolicyConfigurations(); + void reorderVideoCodecList(); + int getCodecPriority(const OrtpPayloadType *pt) const; static const Utils::Version conferenceProtocolVersion; static const Utils::Version groupChatProtocolVersion; static const Utils::Version ephemeralProtocolVersion; @@ -228,6 +230,7 @@ private: std::list<std::shared_ptr<Ldap>> mLdapServers; // Persistent list of LDAP servers std::string logLabel; + LinphoneCodecPriorityPolicy videoCodecPriorityPolicy = LinphoneCodecPriorityPolicyAuto; L_DECLARE_PUBLIC(Core); }; diff --git a/src/core/core.cpp b/src/core/core.cpp index 75aeecb89e..2bb5c2128c 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -81,6 +81,7 @@ // TODO: Remove me later. #include "c-wrapper/c-wrapper.h" #include "private.h" +#include <utils/payload-type-handler.h> #define LINPHONE_DB "linphone.db" #define LINPHONE_CALL_HISTORY_DB "call-history.db" @@ -630,6 +631,55 @@ void CorePrivate::updateVideoDevice() { } } +int CorePrivate::getCodecPriority(const OrtpPayloadType *pt) const { + static constexpr int priorityBonusScore = 50; + static const std::map<string, int> priorityMap = {{"AV1", 50}, {"H265", 40}, {"H264", 30}, {"VP8", 20}}; + auto it = priorityMap.find(pt->mime_type); + + if (it != priorityMap.end()) { + // lInfo() << pt->mime_type << " has priority " << it->second << " with bonus: " << ((pt->flags & + // PAYLOAD_TYPE_PRIORITY_BONUS) ? "yes" : "no"); + return it->second + ((pt->flags & PAYLOAD_TYPE_PRIORITY_BONUS) ? priorityBonusScore : 0); + } + return 1000; // return highest priority for unknown codecs, for convenience for whose who want to write plugins. +} + +void CorePrivate::reorderVideoCodecList() { + bctbx_list_t *videoCodecList = getCCore()->codecs_conf.video_codecs; + bctbx_list_t *elem; + std::list<OrtpPayloadType *> newList; + + for (elem = videoCodecList; elem != nullptr; elem = elem->next) { + OrtpPayloadType *pt = (OrtpPayloadType *)elem->data; + if (videoCodecPriorityPolicy == LinphoneCodecPriorityPolicyAuto) { +#if defined(__ANDROID__) || (defined(__APPLE__) && TARGET_OS_IPHONE) + MSFilterDesc *encoderDesc = ms_factory_get_encoder(getCCore()->factory, pt->mime_type); + if (encoderDesc && (encoderDesc->flags & MS_FILTER_IS_HW_ACCELERATED)) { + payload_type_set_flag(pt, PAYLOAD_TYPE_PRIORITY_BONUS); + } else { + payload_type_unset_flag(pt, PAYLOAD_TYPE_PRIORITY_BONUS); + } +#endif + newList.push_back(pt); + } else + payload_type_unset_flag( + pt, PAYLOAD_TYPE_PRIORITY_BONUS); // no notion of bonus in LinphoneCodecPriorityPolicyBasic. + } + if (videoCodecPriorityPolicy == LinphoneCodecPriorityPolicyAuto) { + lInfo() << "Sorting video codec list, new list is:"; + newList.sort([this](const OrtpPayloadType *pt1, const OrtpPayloadType *pt2) -> bool { + return getCodecPriority(pt1) > getCodecPriority(pt2); + }); + bctbx_list_free(videoCodecList); + videoCodecList = nullptr; + for (auto pt : newList) { + lInfo() << pt->mime_type; + videoCodecList = bctbx_list_append(videoCodecList, pt); + } + getCCore()->codecs_conf.video_codecs = videoCodecList; + } +} + // ============================================================================= Core::Core() : Object(*new CorePrivate) { @@ -2148,4 +2198,19 @@ const std::string &Core::getLabel() const { return d->logLabel; } +void Core::setVideoCodecPriorityPolicy(LinphoneCodecPriorityPolicy policy) { + L_D(); + if (linphone_core_ready(getCCore())) { + linphone_config_set_int(linphone_core_get_config(getCCore()), "video", "codec_priority_policy", (int)policy); + } + bool changed = policy != d->videoCodecPriorityPolicy; + d->videoCodecPriorityPolicy = policy; + if (changed) d->reorderVideoCodecList(); +} + +LinphoneCodecPriorityPolicy Core::getVideoCodecPriorityPolicy() const { + L_D(); + return d->videoCodecPriorityPolicy; +} + LINPHONE_END_NAMESPACE diff --git a/src/core/core.h b/src/core/core.h index 8a8b52621d..1b3a4634ed 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -381,6 +381,9 @@ public: void setLabel(const std::string &label); const std::string &getLabel() const; + void setVideoCodecPriorityPolicy(LinphoneCodecPriorityPolicy policy); + LinphoneCodecPriorityPolicy getVideoCodecPriorityPolicy() const; + private: Core(); diff --git a/src/payload-type/payload-type.cpp b/src/payload-type/payload-type.cpp index 7ea6c5c482..f62b14ac27 100644 --- a/src/payload-type/payload-type.cpp +++ b/src/payload-type/payload-type.cpp @@ -240,6 +240,11 @@ void PayloadType::setSendFmtp(const string &sendFmtp) { payload_type_set_send_fmtp(mPt, send_fmtp_c); } +void PayloadType::setPriorityBonus(bool value) { + if (value) payload_type_set_flag(mPt, PAYLOAD_TYPE_PRIORITY_BONUS); + else payload_type_unset_flag(mPt, PAYLOAD_TYPE_PRIORITY_BONUS); +} + int PayloadType::getType() const { return mPt->type; } @@ -352,4 +357,10 @@ bool PayloadType::isUsable() const { return linphone_core_is_payload_type_usable_for_bandwidth(cCore, mPt, maxbw); } +bool PayloadType::weakEquals(const PayloadType &other) const { + if (mPt == nullptr || other.mPt == nullptr) return false; + return mPt->type == other.mPt->type && mPt->clock_rate == other.mPt->clock_rate && + strcasecmp(mPt->mime_type, other.mPt->mime_type) == 0 && mPt->channels == other.mPt->channels; +} + LINPHONE_END_NAMESPACE diff --git a/src/payload-type/payload-type.h b/src/payload-type/payload-type.h index 893671f75f..02a1941153 100644 --- a/src/payload-type/payload-type.h +++ b/src/payload-type/payload-type.h @@ -72,6 +72,8 @@ public: bool isEnabled() const; bool isVbr() const; bool isUsable() const; + void setPriorityBonus(bool value); + bool weakEquals(const PayloadType &other) const; private: OrtpPayloadType *mPt; diff --git a/src/sal/offeranswer.cpp b/src/sal/offeranswer.cpp index dfed5f5893..beea448a69 100644 --- a/src/sal/offeranswer.cpp +++ b/src/sal/offeranswer.cpp @@ -305,6 +305,15 @@ std::list<OrtpPayloadType *> OfferAnswerEngine::matchPayloads(MSFactory *factory payload_type_set_flag(cloned_p1, PAYLOAD_TYPE_FROZEN_NUMBER); res.push_back(cloned_p1); } + } else { + /* case of generating an answer */ + /* resort result list to put high-priority codecs first */ + res.sort([](const PayloadType *p1, const PayloadType *p2) -> bool { + if (p1->flags & PAYLOAD_TYPE_PRIORITY_BONUS && !(p2->flags & PAYLOAD_TYPE_PRIORITY_BONUS)) { + return true; + } + return false; + }); } return res; } diff --git a/src/signal-information/signal-information.h b/src/signal-information/signal-information.h index 06ea3d5c08..4086f67749 100644 --- a/src/signal-information/signal-information.h +++ b/src/signal-information/signal-information.h @@ -21,6 +21,7 @@ #define SIGNAL_INFORMATION_H #include "linphone/api/c-types.h" +#include "linphone/enums/c-enums.h" #include <belle-sip/object++.hh> using namespace std; diff --git a/src/utils/payload-type-handler.h b/src/utils/payload-type-handler.h index 9ae211c1f6..c52f8a3812 100644 --- a/src/utils/payload-type-handler.h +++ b/src/utils/payload-type-handler.h @@ -32,6 +32,7 @@ #define PAYLOAD_TYPE_ENABLED PAYLOAD_TYPE_USER_FLAG_0 #define PAYLOAD_TYPE_BITRATE_OVERRIDE PAYLOAD_TYPE_USER_FLAG_3 #define PAYLOAD_TYPE_FROZEN_NUMBER PAYLOAD_TYPE_USER_FLAG_4 +#define PAYLOAD_TYPE_PRIORITY_BONUS PAYLOAD_TYPE_USER_FLAG_5 // Used for codec sorting and offer-answer. // ============================================================================= diff --git a/tester/audio_bypass_tester.c b/tester/audio_bypass_tester.c index a46c72fe74..0e32ddf932 100644 --- a/tester/audio_bypass_tester.c +++ b/tester/audio_bypass_tester.c @@ -487,9 +487,8 @@ static void audio_bypass(void) { BC_ASSERT_TRUE(call_ok); if (!call_ok) goto end; - BC_ASSERT_STRING_EQUAL(linphone_call_params_get_used_audio_codec( - linphone_call_get_current_params(linphone_core_get_current_call(marie_lc))) - ->mime_type, + BC_ASSERT_STRING_EQUAL(linphone_payload_type_get_mime_type(linphone_call_params_get_used_audio_payload_type( + linphone_call_get_current_params(linphone_core_get_current_call(marie_lc)))), "L16"); wait_for_until(pauline_lc, marie_lc, NULL, 0, 5000); // hello44100.wav is 4 seconds long diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index 1012ec72de..a906047c70 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -5077,9 +5077,9 @@ static void call_with_in_dialog_codec_change_base(bool_t no_sdp) { BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 2)); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallUpdatedByRemote, 1)); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 2)); - BC_ASSERT_STRING_EQUAL("PCMA", payload_type_get_mime(linphone_call_params_get_used_audio_codec( + BC_ASSERT_STRING_EQUAL("PCMA", linphone_payload_type_get_mime_type(linphone_call_params_get_used_audio_payload_type( linphone_call_get_current_params(linphone_core_get_current_call(marie->lc))))); - BC_ASSERT_STRING_EQUAL("PCMA", payload_type_get_mime(linphone_call_params_get_used_audio_codec( + BC_ASSERT_STRING_EQUAL("PCMA", linphone_payload_type_get_mime_type(linphone_call_params_get_used_audio_payload_type( linphone_call_get_current_params(linphone_core_get_current_call(pauline->lc))))); wait_for_until(marie->lc, pauline->lc, &dummy, 1, 5000); BC_ASSERT_GREATER(linphone_core_manager_get_max_audio_down_bw(marie), 70, int, "%i"); diff --git a/tester/local_conference_tester_functions.cpp b/tester/local_conference_tester_functions.cpp index c5e9726efc..52358d26b1 100644 --- a/tester/local_conference_tester_functions.cpp +++ b/tester/local_conference_tester_functions.cpp @@ -1746,18 +1746,20 @@ void update_sequence_number(bctbx_list_t **participants_info, static bool have_common_audio_payload(LinphoneCoreManager *mgr1, LinphoneCoreManager *mgr2) { bool found = false; - const bctbx_list_t *elem = linphone_core_get_audio_codecs(mgr1->lc); - for (; elem != NULL; elem = elem->next) { - PayloadType *pt1 = (PayloadType *)elem->data; - if (linphone_core_payload_type_enabled(mgr1->lc, pt1) == TRUE) { - LinphonePayloadType *pt2 = - linphone_core_get_payload_type(mgr2->lc, pt1->mime_type, pt1->clock_rate, pt1->channels); + bctbx_list_t *codecs = linphone_core_get_audio_payload_types(mgr1->lc); + for (bctbx_list_t *elem = codecs; elem != NULL; elem = elem->next) { + LinphonePayloadType *pt1 = (LinphonePayloadType *)elem->data; + if (linphone_payload_type_enabled(pt1) == TRUE) { + LinphonePayloadType *pt2 = linphone_core_get_payload_type( + mgr2->lc, linphone_payload_type_get_mime_type(pt1), linphone_payload_type_get_clock_rate(pt1), + linphone_payload_type_get_channels(pt1)); if (pt2 && linphone_payload_type_enabled(pt2)) { found = true; } linphone_payload_type_unref(pt2); } } + bctbx_list_free_with_data(codecs, (bctbx_list_free_func)linphone_payload_type_unref); return found; } diff --git a/tester/offeranswer_tester.cpp b/tester/offeranswer_tester.cpp index 346eb13e7f..d9ce61982c 100644 --- a/tester/offeranswer_tester.cpp +++ b/tester/offeranswer_tester.cpp @@ -65,16 +65,16 @@ static void start_with_no_config(void) { static void check_payload_type_numbers(LinphoneCall *call1, LinphoneCall *call2, int expected_number) { const LinphoneCallParams *params = linphone_call_get_current_params(call1); if (!BC_ASSERT_PTR_NOT_NULL(params)) return; - const PayloadType *pt = linphone_call_params_get_used_audio_codec(params); + const LinphonePayloadType *pt = linphone_call_params_get_used_audio_payload_type(params); BC_ASSERT_PTR_NOT_NULL(pt); if (pt) { - BC_ASSERT_EQUAL(payload_type_get_number(pt), expected_number, int, "%d"); + BC_ASSERT_EQUAL(linphone_payload_type_get_number(pt), expected_number, int, "%d"); } params = linphone_call_get_current_params(call2); - pt = linphone_call_params_get_used_audio_codec(params); + pt = linphone_call_params_get_used_audio_payload_type(params); BC_ASSERT_PTR_NOT_NULL(pt); if (pt) { - BC_ASSERT_EQUAL(payload_type_get_number(pt), expected_number, int, "%d"); + BC_ASSERT_EQUAL(linphone_payload_type_get_number(pt), expected_number, int, "%d"); } } @@ -144,13 +144,13 @@ static void simple_call_with_fmtps(void) { pauline_call = linphone_core_get_current_call(pauline->lc); BC_ASSERT_PTR_NOT_NULL(pauline_call); if (pauline_call) { - LinphonePayloadType *pt = + const LinphonePayloadType *pt = linphone_call_params_get_used_audio_payload_type(linphone_call_get_current_params(pauline_call)); BC_ASSERT_PTR_NOT_NULL(pt); if (pt) { BC_ASSERT_STRING_EQUAL(linphone_payload_type_get_send_fmtp(pt), "parles-plus-fort=1"); } - linphone_payload_type_unref(pt); + pt = linphone_call_params_get_used_audio_payload_type( linphone_call_get_current_params(linphone_core_get_current_call(marie->lc))); BC_ASSERT_PTR_NOT_NULL(pt); @@ -159,7 +159,6 @@ static void simple_call_with_fmtps(void) { linphone_payload_type_get_recv_fmtp(pt)); BC_ASSERT_STRING_EQUAL(linphone_payload_type_get_recv_fmtp(pt), "parles-plus-fort=1"); } - linphone_payload_type_unref(pt); } end_call(marie, pauline); @@ -228,13 +227,12 @@ static void h264_call_with_fmtps(void) { pauline_call = linphone_core_get_current_call(pauline->lc); BC_ASSERT_PTR_NOT_NULL(pauline_call); if (pauline_call) { - LinphonePayloadType *pt = + const LinphonePayloadType *pt = linphone_call_params_get_used_video_payload_type(linphone_call_get_current_params(pauline_call)); BC_ASSERT_PTR_NOT_NULL(pt); if (pt) { BC_ASSERT_PTR_NOT_NULL(strstr(linphone_payload_type_get_recv_fmtp(pt), "packetization-mode=1")); } - linphone_payload_type_unref(pt); pt = linphone_call_params_get_used_video_payload_type( linphone_call_get_current_params(linphone_core_get_current_call(marie->lc))); BC_ASSERT_PTR_NOT_NULL(pt); @@ -244,7 +242,6 @@ static void h264_call_with_fmtps(void) { BC_ASSERT_PTR_NOT_NULL(strstr(linphone_payload_type_get_recv_fmtp(pt), "packetization-mode=1")); BC_ASSERT_PTR_NOT_NULL(strstr(linphone_payload_type_get_recv_fmtp(pt), "packetization-mode=1")); } - linphone_payload_type_unref(pt); } end_call(marie, pauline); @@ -377,7 +374,7 @@ static void h264_call_receiver_with_no_h264_support(void) { pauline_call = linphone_core_get_current_call(pauline->lc); BC_ASSERT_PTR_NOT_NULL(pauline_call); if (pauline_call) { - LinphonePayloadType *pt = + const LinphonePayloadType *pt = linphone_call_params_get_used_video_payload_type(linphone_call_get_current_params(pauline_call)); BC_ASSERT_PTR_NULL(pt); pt = linphone_call_params_get_used_video_payload_type( @@ -427,13 +424,12 @@ static void h264_call_without_packetization_mode(void) { pauline_call = linphone_core_get_current_call(pauline->lc); BC_ASSERT_PTR_NOT_NULL(pauline_call); if (pauline_call) { - LinphonePayloadType *pt = + const LinphonePayloadType *pt = linphone_call_params_get_used_video_payload_type(linphone_call_get_current_params(pauline_call)); BC_ASSERT_PTR_NOT_NULL(pt); if (pt) { BC_ASSERT_PTR_NULL(strstr(linphone_payload_type_get_recv_fmtp(pt), "packetization-mode")); } - linphone_payload_type_unref(pt); pt = linphone_call_params_get_used_video_payload_type( linphone_call_get_current_params(linphone_core_get_current_call(marie->lc))); BC_ASSERT_PTR_NOT_NULL(pt); @@ -443,7 +439,6 @@ static void h264_call_without_packetization_mode(void) { BC_ASSERT_PTR_NULL(strstr(linphone_payload_type_get_recv_fmtp(pt), "packetization-mode")); BC_ASSERT_PTR_NULL(strstr(linphone_payload_type_get_recv_fmtp(pt), "packetization-mode")); } - linphone_payload_type_unref(pt); } end_call(marie, pauline); @@ -1090,6 +1085,134 @@ static void call_with_unknown_stream_accepted_2(void) { _call_with_unknown_stream(TRUE, TRUE); } +static void activate_video_and_ice(LinphoneCoreManager *m) { + LinphoneVideoActivationPolicy *pol = linphone_factory_create_video_activation_policy(linphone_factory_get()); + LinphoneNatPolicy *nat_policy; + LinphoneAccountParams *account_params; + LinphoneAccount *account; + linphone_video_activation_policy_set_automatically_initiate(pol, TRUE); + linphone_video_activation_policy_set_automatically_accept(pol, TRUE); + linphone_core_set_video_activation_policy(m->lc, pol); + linphone_video_activation_policy_unref(pol); + + linphone_core_enable_video_capture(m->lc, TRUE); + linphone_core_enable_video_display(m->lc, TRUE); + + nat_policy = linphone_core_create_nat_policy(m->lc); + linphone_nat_policy_enable_ice(nat_policy, TRUE); + + account = linphone_core_get_default_account(m->lc); + account_params = linphone_account_params_clone(linphone_account_get_params(account)); + linphone_account_params_set_nat_policy(account_params, nat_policy); + linphone_account_set_params(account, account_params); + linphone_account_params_unref(account_params); + linphone_nat_policy_unref(nat_policy); + + linphone_core_set_video_device(m->lc, liblinphone_tester_static_image_id); +} + +static bool_t codec_appears_first(LinphoneCore *lc, const char *codec) { + bctbx_list_t *codec_list = linphone_core_get_video_payload_types(lc); + LinphonePayloadType *pt = (LinphonePayloadType *)codec_list->data; + bool_t ret = strcasecmp(codec, linphone_payload_type_get_mime_type(pt)) == 0; + bctbx_list_free_with_data(codec_list, (bctbx_list_free_func)linphone_payload_type_unref); + return ret; +} + +static const char *call_selected_codec(LinphoneCall *call) { + const LinphoneCallParams *current_params = linphone_call_get_current_params(call); + const LinphonePayloadType *pt = linphone_call_params_get_used_video_payload_type(current_params); + if (BC_ASSERT_PTR_NOT_NULL(pt)) { + return linphone_payload_type_get_mime_type(pt); + } + return ""; +} + +static void check_linphonerc_config(const char *rcfile) { + char *path = bc_tester_res(rcfile); + if (BC_ASSERT_PTR_NOT_NULL(path)) { + LinphoneConfig *config = linphone_factory_create_config(linphone_factory_get(), path); + if (BC_ASSERT_PTR_NOT_NULL(config)) { + BC_ASSERT_STRING_EQUAL(linphone_config_get_string(config, "video", "codec_priority_policy", "unset"), + "unset"); + linphone_config_unref(config); + } + bc_free(path); + } +} + +static void call_with_video_codec_priority_policy(void) { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc"); + LinphonePayloadType *vp8, *av1; + LinphoneCall *marie_call, *pauline_call; + + vp8 = linphone_core_get_payload_type(pauline->lc, "VP8", 90000, -1); + av1 = linphone_core_get_payload_type(pauline->lc, "AV1", 90000, -1); + + if (!vp8 || !av1) { + ms_warning("This test requires both VP8 and AV1 video codecs, skipped."); + goto end; + } + activate_video_and_ice(marie); + activate_video_and_ice(pauline); + + /* Make sure that configuration files do not mention codec_priority_policy.*/ + check_linphonerc_config("rcfiles/marie_rc"); + check_linphonerc_config("rcfiles/pauline_tcp_rc"); + + /* PolicyAuto is the default one. However Marie has a video codec list defined, so in absence of + [video]video_priority_policy item written in its configuration file, we must assume it is using the basic policy. + */ + BC_ASSERT_TRUE(linphone_core_get_video_codec_priority_policy(marie->lc) == LinphoneCodecPriorityPolicyBasic); + BC_ASSERT_TRUE(linphone_core_get_video_codec_priority_policy(pauline->lc) == LinphoneCodecPriorityPolicyAuto); + + BC_ASSERT_TRUE(codec_appears_first(marie->lc, "AV1")); + BC_ASSERT_TRUE(codec_appears_first(pauline->lc, "AV1")); + + /* this is to force to re-compute the codec list order: */ + linphone_core_set_video_codec_priority_policy(pauline->lc, LinphoneCodecPriorityPolicyBasic); + /* AV1 is before VP8 by default. Give an artificial bonus to VP8. Normally this is done at startup*/ + linphone_payload_type_set_priority_bonus(vp8, TRUE); // this function is not public, apps should not do this. + + linphone_core_set_video_codec_priority_policy(pauline->lc, LinphoneCodecPriorityPolicyAuto); + /* now vp8 shall appear first */ + BC_ASSERT_TRUE(codec_appears_first(pauline->lc, "VP8")); + + marie_call = linphone_core_invite_address(marie->lc, pauline->identity); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallIncomingReceived, 1)); + pauline_call = linphone_core_get_current_call(pauline->lc); + if (!BC_ASSERT_PTR_NOT_NULL(pauline_call)) goto end; + linphone_call_accept(pauline_call); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1)); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1)); + BC_ASSERT_STRING_EQUAL(call_selected_codec(marie_call), "VP8"); + BC_ASSERT_STRING_EQUAL(call_selected_codec(pauline_call), "VP8"); + /* Now comes the ICE re-INVITE */ + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 2)); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 2)); + /* Assert that the ICE re-invite did not change the selected codec */ + BC_ASSERT_STRING_EQUAL(call_selected_codec(marie_call), "VP8"); + BC_ASSERT_STRING_EQUAL(call_selected_codec(pauline_call), "VP8"); + wait_for_until(marie->lc, pauline->lc, NULL, 0, 1000); + + linphone_call_terminate(pauline_call); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1)); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallEnd, 1)); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallReleased, 1)); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallReleased, 1)); + /* Assert the priority policy for pauline is now set */ + BC_ASSERT_STRING_EQUAL( + linphone_config_get_string(linphone_core_get_config(pauline->lc), "video", "codec_priority_policy", "unset"), + "1"); + +end: + if (av1) linphone_payload_type_unref(av1); + if (vp8) linphone_payload_type_unref(vp8); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + #endif static test_t offeranswer_tests[] = { @@ -1163,7 +1286,8 @@ static test_t offeranswer_tests[] = { TEST_NO_TAG("Call with unknown stream", call_with_unknown_stream), TEST_NO_TAG("Call with unknown stream, accepted", call_with_unknown_stream_accepted), TEST_NO_TAG("Call with unknown stream, accepted 2", call_with_unknown_stream_accepted_2), - TEST_NO_TAG("Call with 2 audio streams", call_with_two_audio_streams) + TEST_NO_TAG("Call with 2 audio streams", call_with_two_audio_streams), + TEST_NO_TAG("Call with video codec priority policy auto", call_with_video_codec_priority_policy) #endif }; diff --git a/tester/session_timers_tester.c b/tester/session_timers_tester.c index 5566730986..b54434b5db 100644 --- a/tester/session_timers_tester.c +++ b/tester/session_timers_tester.c @@ -616,10 +616,10 @@ static void session_timer_interval_smaller(void) { BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 3)); BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneCallUpdatedByRemote, 1)); BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 2)); - BC_ASSERT_STRING_EQUAL(payload_type_get_mime(linphone_call_params_get_used_audio_codec( + BC_ASSERT_STRING_EQUAL(linphone_payload_type_get_mime_type(linphone_call_params_get_used_audio_payload_type( linphone_call_get_current_params(linphone_core_get_current_call(marie->lc)))), "PCMA"); - BC_ASSERT_STRING_EQUAL(payload_type_get_mime(linphone_call_params_get_used_audio_codec( + BC_ASSERT_STRING_EQUAL(linphone_payload_type_get_mime_type(linphone_call_params_get_used_audio_payload_type( linphone_call_get_current_params(linphone_core_get_current_call(pauline->lc)))), "PCMA"); wait_for_until(pauline->lc, marie->lc, &dummy, 1, 5000); -- GitLab