diff --git a/CMakeLists.txt b/CMakeLists.txt index caca495c3..ddf41d3ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ ############################################################################ cmake_minimum_required(VERSION 3.0) -project(linphone VERSION 3.11.1 LANGUAGES C CXX) +project(linphone VERSION 3.11.2 LANGUAGES C CXX) set(LINPHONE_MAJOR_VERSION ${PROJECT_VERSION_MAJOR}) diff --git a/configure.ac b/configure.ac index 46a0e2b85..f1180465b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT([linphone],[3.11.1],[linphone-developers@nongnu.org]) +AC_INIT([linphone],[3.11.2],[linphone-developers@nongnu.org]) AC_CANONICAL_SYSTEM AC_CONFIG_SRCDIR([coreapi/linphonecore.c]) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 3ce529cac..7444fd23b 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -1106,9 +1106,9 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, linphone_core_get_text_port_range(call->core, &min_port, &max_port); port_config_set(call,call->main_text_stream_index,min_port,max_port); - linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO], LINPHONE_CALL_STATS_AUDIO); - linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO], LINPHONE_CALL_STATS_VIDEO); - linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_TEXT], LINPHONE_CALL_STATS_TEXT); + linphone_call_init_stats(call->audio_stats, LINPHONE_CALL_STATS_AUDIO); + linphone_call_init_stats(call->video_stats, LINPHONE_CALL_STATS_VIDEO); + linphone_call_init_stats(call->text_stats, LINPHONE_CALL_STATS_TEXT); } void linphone_call_init_stats(LinphoneCallStats *stats, int type) { @@ -1307,6 +1307,9 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr call->dir=LinphoneCallOutgoing; call->core=lc; call->dest_proxy=cfg; + call->audio_stats = linphone_call_stats_new(); + call->video_stats = linphone_call_stats_new(); + call->text_stats = linphone_call_stats_new(); linphone_call_outgoing_select_ip_version(call,to,cfg); linphone_call_get_local_ip(call, to); call->params = linphone_call_params_copy(params); @@ -1489,6 +1492,9 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro LinphoneNatPolicy *nat_policy = NULL; int i; call->dir=LinphoneCallIncoming; + call->audio_stats = linphone_call_stats_new(); + call->video_stats = linphone_call_stats_new(); + call->text_stats = linphone_call_stats_new(); sal_op_set_user_pointer(op,call); call->op=op; call->core=lc; @@ -1613,9 +1619,9 @@ static void linphone_call_free_media_resources(LinphoneCall *call){ for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i){ ms_media_stream_sessions_uninit(&call->sessions[i]); } - linphone_call_stats_uninit(&call->stats[LINPHONE_CALL_STATS_AUDIO]); - linphone_call_stats_uninit(&call->stats[LINPHONE_CALL_STATS_VIDEO]); - linphone_call_stats_uninit(&call->stats[LINPHONE_CALL_STATS_TEXT]); + linphone_call_stats_uninit(call->audio_stats); + linphone_call_stats_uninit(call->video_stats); + linphone_call_stats_uninit(call->text_stats); } /* @@ -1872,6 +1878,18 @@ static void linphone_call_destroy(LinphoneCall *obj){ if (obj->audiostream || obj->videostream){ linphone_call_free_media_resources(obj); } + if (obj->audio_stats) { + linphone_call_stats_unref(obj->audio_stats); + obj->audio_stats = NULL; + } + if (obj->video_stats) { + linphone_call_stats_unref(obj->video_stats); + obj->video_stats = NULL; + } + if (obj->text_stats) { + linphone_call_stats_unref(obj->text_stats); + obj->text_stats = NULL; + } if (obj->op!=NULL) { sal_op_release(obj->op); obj->op=NULL; @@ -3907,9 +3925,9 @@ void linphone_call_delete_ice_session(LinphoneCall *call){ if (call->audiostream != NULL) call->audiostream->ms.ice_check_list = NULL; if (call->videostream != NULL) call->videostream->ms.ice_check_list = NULL; if (call->textstream != NULL) call->textstream->ms.ice_check_list = NULL; - call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateNotActivated; - call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateNotActivated; - call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateNotActivated; + call->audio_stats->ice_state = LinphoneIceStateNotActivated; + call->video_stats->ice_state = LinphoneIceStateNotActivated; + call->text_stats->ice_state = LinphoneIceStateNotActivated; } } @@ -3934,7 +3952,15 @@ static void linphone_call_log_fill_stats(LinphoneCallLog *log, MediaStream *st){ static void update_rtp_stats(LinphoneCall *call, int stream_index) { if (call->sessions[stream_index].rtp_session) { const rtp_stats_t *stats = rtp_session_get_stats(call->sessions[stream_index].rtp_session); - memcpy(&call->stats[stream_index].rtp_stats, stats, sizeof(*stats)); + LinphoneCallStats *call_stats = NULL; + if (stream_index == call->main_audio_stream_index) { + call_stats = call->audio_stats; + } else if (stream_index == call->main_video_stream_index) { + call_stats = call->video_stats; + } else { + call_stats = call->text_stats; + } + if (call_stats) memcpy(&(call_stats->rtp_stats), stats, sizeof(*stats)); } } @@ -4202,26 +4228,47 @@ static MediaStream *linphone_call_get_stream(LinphoneCall *call, LinphoneStreamT return NULL; } -const LinphoneCallStats *linphone_call_get_stats(LinphoneCall *call, LinphoneStreamType type){ +static void _linphone_call_stats_clone(LinphoneCallStats *dst, const LinphoneCallStats *src) { + /* + * Save the belle_sip_object_t part, copy the entire structure and restore the belle_sip_object_t part + */ + belle_sip_object_t tmp = dst->base; + memcpy(dst, src, sizeof(LinphoneCallStats)); + dst->base = tmp; + + dst->received_rtcp = NULL; + dst->sent_rtcp = NULL; +} + +LinphoneCallStats *linphone_call_get_stats(LinphoneCall *call, LinphoneStreamType type){ if ((int)type >=0 && type<=LinphoneStreamTypeText){ - LinphoneCallStats *stats = &call->stats[type]; + LinphoneCallStats *stats = NULL; + LinphoneCallStats *stats_copy = linphone_call_stats_new(); + if (type == LinphoneStreamTypeAudio) { + stats = call->audio_stats; + } else if (type == LinphoneStreamTypeVideo) { + stats = call->video_stats; + } else if (type == LinphoneStreamTypeText) { + stats = call->text_stats; + } MediaStream *ms = linphone_call_get_stream(call, type); - if (ms) update_local_stats(stats, ms); - return stats; + if (ms && stats) update_local_stats(stats, ms); + _linphone_call_stats_clone(stats_copy, stats); + return stats_copy; } ms_error("Invalid stream type %i", (int)type); return NULL; } -const LinphoneCallStats *linphone_call_get_audio_stats(LinphoneCall *call) { +LinphoneCallStats *linphone_call_get_audio_stats(LinphoneCall *call) { return linphone_call_get_stats(call, LinphoneStreamTypeAudio); } -const LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call) { +LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call) { return linphone_call_get_stats(call, LinphoneStreamTypeVideo); } -const LinphoneCallStats *linphone_call_get_text_stats(LinphoneCall *call) { +LinphoneCallStats *linphone_call_get_text_stats(LinphoneCall *call) { return linphone_call_get_stats(call, LinphoneStreamTypeText); } @@ -4231,12 +4278,42 @@ static bool_t ice_in_progress(LinphoneCallStats *stats){ bool_t linphone_call_media_in_progress(LinphoneCall *call){ bool_t ret=FALSE; - if (ice_in_progress(&call->stats[LINPHONE_CALL_STATS_AUDIO]) || ice_in_progress(&call->stats[LINPHONE_CALL_STATS_VIDEO]) || ice_in_progress(&call->stats[LINPHONE_CALL_STATS_TEXT])) + if (ice_in_progress(call->audio_stats) || ice_in_progress(call->video_stats) || ice_in_progress(call->text_stats)) ret=TRUE; /*TODO: could check zrtp state, upnp state*/ return ret; } +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCallStats); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallStats, belle_sip_object_t, + NULL, // destroy + _linphone_call_stats_clone, // clone + NULL, // marshal + FALSE +); + +LinphoneCallStats *linphone_call_stats_new() { + LinphoneCallStats *stats = belle_sip_object_new(LinphoneCallStats); + return stats; +} + +LinphoneCallStats* linphone_call_stats_ref(LinphoneCallStats* stats) { + return (LinphoneCallStats*) belle_sip_object_ref(stats); +} + +void linphone_call_stats_unref(LinphoneCallStats* stats) { + belle_sip_object_unref(stats); +} + +void *linphone_call_stats_get_user_data(const LinphoneCallStats *stats) { + return stats->user_data; +} + +void linphone_call_stats_set_user_data(LinphoneCallStats *stats, void *data) { + stats->user_data = data; +} + LinphoneStreamType linphone_call_stats_get_type(const LinphoneCallStats *stats) { return stats->type; } @@ -4355,6 +4432,10 @@ float linphone_call_stats_get_jitter_buffer_size_ms(const LinphoneCallStats *sta return stats->jitter_stats.jitter_buffer_size_ms; } +float linphone_call_stats_get_round_trip_delay(const LinphoneCallStats *stats) { + return stats->round_trip_delay; +} + void linphone_call_start_recording(LinphoneCall *call){ if (!call->params->record_file){ ms_error("linphone_call_start_recording(): no output file specified. Use linphone_call_params_set_record_file()."); @@ -4375,7 +4456,16 @@ void linphone_call_stop_recording(LinphoneCall *call){ static void report_bandwidth_for_stream(LinphoneCall *call, MediaStream *ms, LinphoneStreamType type){ bool_t active = ms ? (media_stream_get_state(ms) == MSStreamStarted) : FALSE; - LinphoneCallStats *stats = &call->stats[type]; + LinphoneCallStats *stats = NULL; + if (type == LinphoneStreamTypeAudio) { + stats = call->audio_stats; + } else if (type == LinphoneStreamTypeAudio) { + stats = call->video_stats; + } else if (type == LinphoneStreamTypeAudio) { + stats = call->text_stats; + } else { + return; + } stats->download_bandwidth=(active) ? (float)(media_stream_get_down_bw(ms)*1e-3) : 0.f; stats->upload_bandwidth=(active) ? (float)(media_stream_get_up_bw(ms)*1e-3) : 0.f; @@ -4401,18 +4491,18 @@ static void report_bandwidth(LinphoneCall *call, MediaStream *as, MediaStream *v "\tRTP audio=[d=%5.1f,u=%5.1f], video=[d=%5.1f,u=%5.1f], text=[d=%5.1f,u=%5.1f] kbits/sec\n" "\tRTCP audio=[d=%5.1f,u=%5.1f], video=[d=%5.1f,u=%5.1f], text=[d=%5.1f,u=%5.1f] kbits/sec", call, - call->stats[LINPHONE_CALL_STATS_AUDIO].download_bandwidth, - call->stats[LINPHONE_CALL_STATS_AUDIO].upload_bandwidth, - call->stats[LINPHONE_CALL_STATS_VIDEO].download_bandwidth, - call->stats[LINPHONE_CALL_STATS_VIDEO].upload_bandwidth, - call->stats[LINPHONE_CALL_STATS_TEXT].download_bandwidth, - call->stats[LINPHONE_CALL_STATS_TEXT].upload_bandwidth, - call->stats[LINPHONE_CALL_STATS_AUDIO].rtcp_download_bandwidth, - call->stats[LINPHONE_CALL_STATS_AUDIO].rtcp_upload_bandwidth, - call->stats[LINPHONE_CALL_STATS_VIDEO].rtcp_download_bandwidth, - call->stats[LINPHONE_CALL_STATS_VIDEO].rtcp_upload_bandwidth, - call->stats[LINPHONE_CALL_STATS_TEXT].rtcp_download_bandwidth, - call->stats[LINPHONE_CALL_STATS_TEXT].rtcp_upload_bandwidth + call->audio_stats->download_bandwidth, + call->audio_stats->upload_bandwidth, + call->video_stats->download_bandwidth, + call->video_stats->upload_bandwidth, + call->text_stats->download_bandwidth, + call->text_stats->upload_bandwidth, + call->audio_stats->rtcp_download_bandwidth, + call->audio_stats->rtcp_upload_bandwidth, + call->video_stats->rtcp_download_bandwidth, + call->video_stats->rtcp_upload_bandwidth, + call->text_stats->rtcp_download_bandwidth, + call->text_stats->rtcp_upload_bandwidth ); } @@ -4545,7 +4635,14 @@ void linphone_call_stats_uninit(LinphoneCallStats *stats){ } void linphone_call_notify_stats_updated_with_stream_index(LinphoneCall *call, int stream_index){ - LinphoneCallStats *stats = &call->stats[stream_index]; + LinphoneCallStats *stats = NULL; + if (stream_index == call->main_audio_stream_index) { + stats = call->audio_stats; + } else if (stream_index == call->main_video_stream_index) { + stats = call->video_stats; + } else { + stats = call->text_stats; + } if (stats->updated){ switch(stats->updated) { case LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE: @@ -4615,13 +4712,25 @@ void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index){ while((evq = linphone_call_get_event_queue(call, stream_index)) != NULL && NULL != (ev=ortp_ev_queue_get(evq))){ OrtpEventType evt=ortp_event_get_type(ev); OrtpEventData *evd=ortp_event_get_data(ev); - int stats_index = stream_index == call->main_audio_stream_index ? LINPHONE_CALL_STATS_AUDIO : (stream_index == call->main_video_stream_index ? LINPHONE_CALL_STATS_VIDEO : LINPHONE_CALL_STATS_TEXT); + int stats_index; + LinphoneCallStats *stats = NULL; + + if (stream_index == call->main_audio_stream_index) { + stats_index = LINPHONE_CALL_STATS_AUDIO; + stats = call->audio_stats; + } else if (stream_index == call->main_video_stream_index) { + stats_index = LINPHONE_CALL_STATS_VIDEO; + stats = call->video_stats; + } else { + stats_index = LINPHONE_CALL_STATS_TEXT; + stats = call->text_stats; + } /*and yes the MediaStream must be taken at each iteration, because it may have changed due to the handling of events * in this loop*/ ms = linphone_call_get_media_stream(call, stream_index); - if (ms) linphone_call_stats_fill(&call->stats[stats_index],ms,ev); + if (ms) linphone_call_stats_fill(stats,ms,ev); linphone_call_notify_stats_updated_with_stream_index(call,stats_index); if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){ diff --git a/coreapi/misc.c b/coreapi/misc.c index fa295f6c7..9f5f216a3 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -548,19 +548,19 @@ static void linphone_core_add_local_ice_candidates(LinphoneCall *call, int famil if ((ice_check_list_state(audio_cl) != ICL_Completed) && (ice_check_list_candidates_gathered(audio_cl) == FALSE)) { ice_add_local_candidate(audio_cl, "host", family, addr, call->media_ports[call->main_audio_stream_index].rtp_port, 1, NULL); ice_add_local_candidate(audio_cl, "host", family, addr, call->media_ports[call->main_audio_stream_index].rtcp_port, 2, NULL); - call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateInProgress; + call->audio_stats->ice_state = LinphoneIceStateInProgress; } if (linphone_core_video_enabled(call->core) && (video_cl != NULL) && (ice_check_list_state(video_cl) != ICL_Completed) && (ice_check_list_candidates_gathered(video_cl) == FALSE)) { ice_add_local_candidate(video_cl, "host", family, addr, call->media_ports[call->main_video_stream_index].rtp_port, 1, NULL); ice_add_local_candidate(video_cl, "host", family, addr, call->media_ports[call->main_video_stream_index].rtcp_port, 2, NULL); - call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateInProgress; + call->video_stats->ice_state = LinphoneIceStateInProgress; } if (call->params->realtimetext_enabled && (text_cl != NULL) && (ice_check_list_state(text_cl) != ICL_Completed) && (ice_check_list_candidates_gathered(text_cl) == FALSE)) { ice_add_local_candidate(text_cl, "host", family, addr, call->media_ports[call->main_text_stream_index].rtp_port, 1, NULL); ice_add_local_candidate(text_cl, "host", family, addr, call->media_ports[call->main_text_stream_index].rtcp_port, 2, NULL); - call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateInProgress; + call->text_stats->ice_state = LinphoneIceStateInProgress; } } @@ -697,14 +697,14 @@ void linphone_call_update_ice_state_in_call_stats(LinphoneCall *call) { if (ice_check_list_state(audio_check_list) == ICL_Completed) { switch (ice_check_list_selected_valid_candidate_type(audio_check_list)) { case ICT_HostCandidate: - call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateHostConnection; + call->audio_stats->ice_state = LinphoneIceStateHostConnection; break; case ICT_ServerReflexiveCandidate: case ICT_PeerReflexiveCandidate: - call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateReflexiveConnection; + call->audio_stats->ice_state = LinphoneIceStateReflexiveConnection; break; case ICT_RelayedCandidate: - call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateRelayConnection; + call->audio_stats->ice_state = LinphoneIceStateRelayConnection; break; case ICT_CandidateInvalid: case ICT_CandidateTypeMax: @@ -712,22 +712,22 @@ void linphone_call_update_ice_state_in_call_stats(LinphoneCall *call) { break; } } else { - call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateFailed; + call->audio_stats->ice_state = LinphoneIceStateFailed; } - }else call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateNotActivated; + }else call->audio_stats->ice_state = LinphoneIceStateNotActivated; if (call->params->has_video && (video_check_list != NULL)) { if (ice_check_list_state(video_check_list) == ICL_Completed) { switch (ice_check_list_selected_valid_candidate_type(video_check_list)) { case ICT_HostCandidate: - call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateHostConnection; + call->video_stats->ice_state = LinphoneIceStateHostConnection; break; case ICT_ServerReflexiveCandidate: case ICT_PeerReflexiveCandidate: - call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateReflexiveConnection; + call->video_stats->ice_state = LinphoneIceStateReflexiveConnection; break; case ICT_RelayedCandidate: - call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateRelayConnection; + call->video_stats->ice_state = LinphoneIceStateRelayConnection; break; case ICT_CandidateInvalid: case ICT_CandidateTypeMax: @@ -735,22 +735,22 @@ void linphone_call_update_ice_state_in_call_stats(LinphoneCall *call) { break; } } else { - call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateFailed; + call->video_stats->ice_state = LinphoneIceStateFailed; } - }else call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateNotActivated; + }else call->video_stats->ice_state = LinphoneIceStateNotActivated; if (call->params->realtimetext_enabled && (text_check_list != NULL)) { if (ice_check_list_state(text_check_list) == ICL_Completed) { switch (ice_check_list_selected_valid_candidate_type(text_check_list)) { case ICT_HostCandidate: - call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateHostConnection; + call->text_stats->ice_state = LinphoneIceStateHostConnection; break; case ICT_ServerReflexiveCandidate: case ICT_PeerReflexiveCandidate: - call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateReflexiveConnection; + call->text_stats->ice_state = LinphoneIceStateReflexiveConnection; break; case ICT_RelayedCandidate: - call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateRelayConnection; + call->text_stats->ice_state = LinphoneIceStateRelayConnection; break; case ICT_CandidateInvalid: case ICT_CandidateTypeMax: @@ -758,28 +758,28 @@ void linphone_call_update_ice_state_in_call_stats(LinphoneCall *call) { break; } } else { - call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateFailed; + call->text_stats->ice_state = LinphoneIceStateFailed; } - }else call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateNotActivated; + }else call->text_stats->ice_state = LinphoneIceStateNotActivated; } else if (session_state == IS_Running) { - call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateInProgress; + call->audio_stats->ice_state = LinphoneIceStateInProgress; if (call->params->has_video && (video_check_list != NULL)) { - call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateInProgress; + call->video_stats->ice_state = LinphoneIceStateInProgress; } if (call->params->realtimetext_enabled && (text_check_list != NULL)) { - call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateInProgress; + call->text_stats->ice_state = LinphoneIceStateInProgress; } } else { - call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateFailed; + call->audio_stats->ice_state = LinphoneIceStateFailed; if (call->params->has_video && (video_check_list != NULL)) { - call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateFailed; + call->video_stats->ice_state = LinphoneIceStateFailed; } if (call->params->realtimetext_enabled && (text_check_list != NULL)) { - call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateFailed; + call->text_stats->ice_state = LinphoneIceStateFailed; } } ms_message("Call [%p] New ICE state: audio: [%s] video: [%s] text: [%s]", call, - linphone_ice_state_to_string(call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state), linphone_ice_state_to_string(call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state), linphone_ice_state_to_string(call->stats[LINPHONE_CALL_STATS_TEXT].ice_state)); + linphone_ice_state_to_string(call->audio_stats->ice_state), linphone_ice_state_to_string(call->video_stats->ice_state), linphone_ice_state_to_string(call->text_stats->ice_state)); } void linphone_call_stop_ice_for_inactive_streams(LinphoneCall *call, SalMediaDescription *desc) { diff --git a/coreapi/private.h b/coreapi/private.h index 023acc490..1d4a0b08e 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -351,7 +351,9 @@ struct _LinphoneCall{ OrtpEvQueue *videostream_app_evq; OrtpEvQueue *textstream_app_evq; CallCallbackObj nextVideoFrameDecoded; - LinphoneCallStats stats[3]; /* audio, video, text */ + LinphoneCallStats *audio_stats; + LinphoneCallStats *video_stats; + LinphoneCallStats *text_stats; #ifdef BUILD_UPNP UpnpSession *upnp_session; #endif //BUILD_UPNP @@ -1761,6 +1763,41 @@ BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneVideoActivationPolicy); LinphoneVideoActivationPolicy *linphone_video_activation_policy_new(void); +/** + * The LinphoneCallStats objects carries various statistic informations regarding quality of audio or video streams. + * + * To receive these informations periodically and as soon as they are computed, the application is invited to place a #LinphoneCoreCallStatsUpdatedCb callback in the LinphoneCoreVTable structure + * it passes for instantiating the LinphoneCore object (see linphone_core_new() ). + * + * At any time, the application can access last computed statistics using linphone_call_get_audio_stats() or linphone_call_get_video_stats(). +**/ +struct _LinphoneCallStats { + belle_sip_object_t base; + void *user_data; + LinphoneStreamType type; /**< Type of the stream which the stats refer to */ + jitter_stats_t jitter_stats; /**log->reporting.reports[stats_type]; reporting_content_metrics_t * metrics = NULL; - LinphoneCallStats stats = call->stats[stats_type]; + LinphoneCallStats *stats = NULL; mblk_t *block = NULL; int report_interval; + if (stats_type == 0) { + stats = call->audio_stats; + } else if (stats_type == 1) { + stats = call->video_stats; + } else { + stats = call->text_stats; + } + if (! media_report_enabled(call,stats_type)) return; report_interval = linphone_proxy_config_get_quality_reporting_interval(call->dest_proxy); - if (stats.updated == LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE) { + if (stats->updated == LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE) { metrics = &report->remote_metrics; - block = stats.received_rtcp; - } else if (stats.updated == LINPHONE_CALL_STATS_SENT_RTCP_UPDATE) { + block = stats->received_rtcp; + } else if (stats->updated == LINPHONE_CALL_STATS_SENT_RTCP_UPDATE) { metrics = &report->local_metrics; - block = stats.sent_rtcp; + block = stats->sent_rtcp; } do{ if (rtcp_is_XR(block) && (rtcp_XR_get_block_type(block) == RTCP_XR_VOIP_METRICS)){ @@ -617,7 +625,7 @@ void linphone_reporting_on_rtcp_update(LinphoneCall *call, SalStreamType stats_t // for local mos rating, we'll use the quality indicator directly // because rtcp XR might not be enabled - if (stats.updated == LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE){ + if (stats->updated == LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE){ metrics->quality_estimates.moslq = (rtcp_XR_voip_metrics_get_mos_lq(block)==127) ? 127 : rtcp_XR_voip_metrics_get_mos_lq(block) / 10.f; metrics->quality_estimates.moscq = (rtcp_XR_voip_metrics_get_mos_cq(block)==127) ? diff --git a/daemon/commands/audio-stream-stats.cc b/daemon/commands/audio-stream-stats.cc index 4845dbb7b..7393b2cdd 100644 --- a/daemon/commands/audio-stream-stats.cc +++ b/daemon/commands/audio-stream-stats.cc @@ -61,5 +61,5 @@ void AudioStreamStatsCommand::exec(Daemon *app, const string& args) { return; } - app->sendResponse(Response(AudioStreamStatsResponse(app, stream->stream, &stream->stats, false).getBody(), Response::Ok)); + app->sendResponse(Response(AudioStreamStatsResponse(app, stream->stream, stream->stats, false).getBody(), Response::Ok)); } diff --git a/daemon/daemon.cc b/daemon/daemon.cc index 01f44e7c4..907972976 100644 --- a/daemon/daemon.cc +++ b/daemon/daemon.cc @@ -141,13 +141,13 @@ DtmfResponse::DtmfResponse(Daemon *daemon, LinphoneCall *call, int dtmf) { } static ostream &printCallStatsHelper(ostream &ostr, const LinphoneCallStats *stats, const string &prefix) { - ostr << prefix << "ICE state: " << ice_state_str[stats->ice_state] << "\n"; - ostr << prefix << "RoundTripDelay: " << stats->round_trip_delay << "\n"; - ostr << prefix << "Jitter: " << stats->jitter_stats.jitter << "\n"; + ostr << prefix << "ICE state: " << ice_state_str[linphone_call_stats_get_ice_state(stats)] << "\n"; + ostr << prefix << "RoundTripDelay: " << linphone_call_stats_get_round_trip_delay(stats) << "\n"; +// ostr << prefix << "Jitter: " << stats->jitter_stats.jitter << "\n"; // ostr << prefix << "MaxJitter: " << stats->jitter_stats.max_jitter << "\n"; // ostr << prefix << "SumJitter: " << stats->jitter_stats.sum_jitter << "\n"; // ostr << prefix << "MaxJitterTs: " << stats->jitter_stats.max_jitter_ts << "\n"; - ostr << prefix << "JitterBufferSizeMs: " << stats->jitter_stats.jitter_buffer_size_ms << "\n"; + ostr << prefix << "JitterBufferSizeMs: " << linphone_call_stats_get_jitter_buffer_size_ms(stats) << "\n"; ostr << prefix << "Received-InterarrivalJitter: " << linphone_call_stats_get_receiver_interarrival_jitter(stats) << "\n"; ostr << prefix << "Received-FractionLost: " << linphone_call_stats_get_receiver_loss_rate(stats) << "\n"; @@ -199,14 +199,14 @@ AudioStreamStatsResponse::AudioStreamStatsResponse(Daemon* daemon, AudioStream* ostr << "Event-type: audio-stream-stats\n"; ostr << "Id: " << daemon->updateAudioStreamId(stream) << "\n"; ostr << "Type: "; - if (stats->type == LINPHONE_CALL_STATS_AUDIO) { + if (linphone_call_stats_get_type(stats) == LINPHONE_CALL_STATS_AUDIO) { ostr << "Audio"; } else { ostr << "Video"; } ostr << "\n"; } else { - prefix = ((stats->type == LINPHONE_CALL_STATS_AUDIO) ? "Audio-" : "Video-"); + prefix = ((linphone_call_stats_get_type(stats) == LINPHONE_CALL_STATS_AUDIO) ? "Audio-" : "Video-"); } printCallStatsHelper(ostr, stats, prefix); @@ -547,9 +547,9 @@ void Daemon::iterateStreamStats() { while (it->second->queue && (NULL != (ev=ortp_ev_queue_get(it->second->queue)))){ OrtpEventType evt=ortp_event_get_type(ev); if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED || evt == ORTP_EVENT_RTCP_PACKET_EMITTED) { - linphone_call_stats_fill(&it->second->stats, &it->second->stream->ms, ev); + linphone_call_stats_fill(it->second->stats, &it->second->stream->ms, ev); if (mUseStatsEvents) mEventQueue.push(new AudioStreamStatsResponse(this, - it->second->stream, &it->second->stats, true)); + it->second->stream, it->second->stats, true)); } ortp_event_destroy(ev); } diff --git a/daemon/daemon.h b/daemon/daemon.h index 7a23b5587..12a32c358 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -191,11 +191,10 @@ private: struct AudioStreamAndOther { AudioStream *stream; OrtpEvQueue *queue; - LinphoneCallStats stats; + LinphoneCallStats *stats; AudioStreamAndOther(AudioStream *as) : stream(as) { queue = ortp_ev_queue_new(); rtp_session_register_event_queue(as->ms.sessions.rtp_session, queue); - memset(&stats, 0, sizeof(stats)); } ~AudioStreamAndOther() { rtp_session_unregister_event_queue(stream->ms.sessions.rtp_session, queue); diff --git a/gtk/incall_view.c b/gtk/incall_view.c index b3055f238..6c7edd939 100644 --- a/gtk/incall_view.c +++ b/gtk/incall_view.c @@ -243,8 +243,10 @@ static const char *upnp_state_to_string(LinphoneUpnpState ice_state){ } static void _refresh_call_stats(GtkWidget *callstats, LinphoneCall *call){ - const LinphoneCallStats *as=linphone_call_get_audio_stats(call); - const LinphoneCallStats *vs=linphone_call_get_video_stats(call); + LinphoneUpnpState upnp_state; + LinphoneIceState ice_state; + LinphoneCallStats *as=linphone_call_get_audio_stats(call); + LinphoneCallStats *vs=linphone_call_get_video_stats(call); const char *audio_media_connectivity = _("Direct or through server"); const char *video_media_connectivity = _("Direct or through server"); const LinphoneCallParams *curparams=linphone_call_get_current_params(call); @@ -256,7 +258,7 @@ static void _refresh_call_stats(GtkWidget *callstats, LinphoneCall *call){ gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"rtp_profile")),tmp); g_free(tmp); tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"), - as->download_bandwidth,as->upload_bandwidth); + linphone_call_stats_get_download_bandwidth(as),linphone_call_stats_get_upload_bandwidth(as)); gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"audio_bandwidth_usage")),tmp); g_free(tmp); if (has_video){ @@ -267,7 +269,7 @@ static void _refresh_call_stats(GtkWidget *callstats, LinphoneCall *call){ gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_size_recv")),size_r); gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_size_sent")),size_s); - tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"),vs->download_bandwidth,vs->upload_bandwidth); + tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"),linphone_call_stats_get_download_bandwidth(vs),linphone_call_stats_get_upload_bandwidth(vs)); g_free(size_r); g_free(size_s); } else { @@ -275,27 +277,33 @@ static void _refresh_call_stats(GtkWidget *callstats, LinphoneCall *call){ } gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_bandwidth_usage")),tmp); if (tmp) g_free(tmp); - if(as->upnp_state != LinphoneUpnpStateNotAvailable && as->upnp_state != LinphoneUpnpStateIdle) { - audio_media_connectivity = upnp_state_to_string(as->upnp_state); - } else if(as->ice_state != LinphoneIceStateNotActivated) { - audio_media_connectivity = ice_state_to_string(as->ice_state); + upnp_state = linphone_call_stats_get_upnp_state(as); + ice_state = linphone_call_stats_get_ice_state(as); + if(upnp_state != LinphoneUpnpStateNotAvailable && upnp_state != LinphoneUpnpStateIdle) { + audio_media_connectivity = upnp_state_to_string(upnp_state); + } else if(ice_state != LinphoneIceStateNotActivated) { + audio_media_connectivity = ice_state_to_string(ice_state); } gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"audio_media_connectivity")),audio_media_connectivity); if (has_video){ - if(vs->upnp_state != LinphoneUpnpStateNotAvailable && vs->upnp_state != LinphoneUpnpStateIdle) { - video_media_connectivity = upnp_state_to_string(vs->upnp_state); - } else if(vs->ice_state != LinphoneIceStateNotActivated) { - video_media_connectivity = ice_state_to_string(vs->ice_state); + upnp_state = linphone_call_stats_get_upnp_state(vs); + ice_state = linphone_call_stats_get_ice_state(vs); + if(upnp_state != LinphoneUpnpStateNotAvailable && upnp_state != LinphoneUpnpStateIdle) { + video_media_connectivity = upnp_state_to_string(upnp_state); + } else if(ice_state != LinphoneIceStateNotActivated) { + video_media_connectivity = ice_state_to_string(ice_state); } }else video_media_connectivity=NULL; gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_media_connectivity")),video_media_connectivity); - if (as->round_trip_delay>0){ - tmp=g_strdup_printf(_("%.3f seconds"),as->round_trip_delay); + if (linphone_call_stats_get_round_trip_delay(as)>0){ + tmp=g_strdup_printf(_("%.3f seconds"),linphone_call_stats_get_round_trip_delay(as)); gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"round_trip_time")),tmp); g_free(tmp); } + linphone_call_stats_unref(as); + linphone_call_stats_unref(vs); } static gboolean refresh_call_stats(GtkWidget *callstats){ diff --git a/include/linphone/call.h b/include/linphone/call.h index 24d28ce5e..bbe04ae08 100644 --- a/include/linphone/call.h +++ b/include/linphone/call.h @@ -834,17 +834,17 @@ LINPHONE_PUBLIC void linphone_call_ogl_render(LinphoneCall *call, bool_t is_prev LINPHONE_PUBLIC LinphoneStatus linphone_call_send_info_message(LinphoneCall *call, const LinphoneInfoMessage *info); /** - * Return call statistics for a particular stream type. + * Return a copy of the call statistics for a particular stream type. * @param call the call * @param type the stream type **/ -LINPHONE_PUBLIC const LinphoneCallStats *linphone_call_get_stats(LinphoneCall *call, LinphoneStreamType type); +LINPHONE_PUBLIC LinphoneCallStats *linphone_call_get_stats(LinphoneCall *call, LinphoneStreamType type); -LINPHONE_PUBLIC const LinphoneCallStats *linphone_call_get_audio_stats(LinphoneCall *call); +LINPHONE_PUBLIC LinphoneCallStats *linphone_call_get_audio_stats(LinphoneCall *call); -LINPHONE_PUBLIC const LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call); +LINPHONE_PUBLIC LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call); -LINPHONE_PUBLIC const LinphoneCallStats *linphone_call_get_text_stats(LinphoneCall *call); +LINPHONE_PUBLIC LinphoneCallStats *linphone_call_get_text_stats(LinphoneCall *call); /** * Add a listener in order to be notified of LinphoneCall events. Once an event is received, registred LinphoneCallCbs are diff --git a/include/linphone/call_stats.h b/include/linphone/call_stats.h index 11044c1c6..a5bd96c48 100644 --- a/include/linphone/call_stats.h +++ b/include/linphone/call_stats.h @@ -40,33 +40,34 @@ extern "C" { #define LINPHONE_CALL_STATS_PERIODICAL_UPDATE (1 << 2) /**< Every seconds LinphoneCallStats object has been updated */ /** - * The LinphoneCallStats objects carries various statistic informations regarding quality of audio or video streams. - * - * To receive these informations periodically and as soon as they are computed, the application is invited to place a #LinphoneCoreCallStatsUpdatedCb callback in the LinphoneCoreVTable structure - * it passes for instantiating the LinphoneCore object (see linphone_core_new() ). - * - * At any time, the application can access last computed statistics using linphone_call_get_audio_stats() or linphone_call_get_video_stats(). + * Increment refcount. + * @param[in] stats LinphoneCallStats object + * @ingroup misc **/ -struct _LinphoneCallStats { - LinphoneStreamType type; /**< Type of the stream which the stats refer to */ - jitter_stats_t jitter_stats; /**lc)); BC_ASSERT_GREATER(linphone_core_manager_get_max_audio_down_bw(pauline),70,int,"%i"); - BC_ASSERT_LOWER((int)linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc))->download_bandwidth, 90, int, "%i"); + BC_ASSERT_LOWER((int)linphone_call_stats_get_download_bandwidth(stats), 90, int, "%i"); + linphone_call_stats_unref(stats); + stats = linphone_call_get_audio_stats(linphone_core_get_current_call(pauline2->lc)); BC_ASSERT_GREATER(linphone_core_manager_get_max_audio_down_bw(pauline2),70,int,"%i"); - BC_ASSERT_LOWER((int)linphone_call_get_audio_stats(linphone_core_get_current_call(pauline2->lc))->download_bandwidth,90, int, "%i"); + BC_ASSERT_LOWER((int)linphone_call_stats_get_download_bandwidth(stats),90, int, "%i"); + linphone_call_stats_unref(stats); BC_ASSERT_TRUE(linphone_call_params_audio_multicast_enabled(linphone_call_get_current_params(linphone_core_get_current_call(pauline->lc)))); BC_ASSERT_TRUE(linphone_call_params_audio_multicast_enabled(linphone_call_get_current_params(linphone_core_get_current_call(marie->lc)))); diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index 87ff0cfef..ac001c86a 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -112,13 +112,18 @@ void call_stats_updated(LinphoneCore *lc, LinphoneCall *call, const LinphoneCall if (lstats->updated & LINPHONE_CALL_STATS_PERIODICAL_UPDATE ) { int tab_size = sizeof (counters->audio_download_bandwidth)/sizeof(int); int index = (counters->current_bandwidth_index[lstats->type]++) % tab_size; + LinphoneCallStats *audio_stats, *video_stats; + audio_stats = linphone_call_get_audio_stats(call); + video_stats = linphone_call_get_video_stats(call); if (lstats->type == LINPHONE_CALL_STATS_AUDIO) { - counters->audio_download_bandwidth[index] = (int)linphone_call_get_audio_stats(call)->download_bandwidth; - counters->audio_upload_bandwidth[index] = (int)linphone_call_get_audio_stats(call)->upload_bandwidth; + counters->audio_download_bandwidth[index] = (int)audio_stats->download_bandwidth; + counters->audio_upload_bandwidth[index] = (int)audio_stats->upload_bandwidth; } else { - counters->video_download_bandwidth[index] = (int)linphone_call_get_video_stats(call)->download_bandwidth; - counters->video_upload_bandwidth[index] = (int)linphone_call_get_video_stats(call)->upload_bandwidth; + counters->video_download_bandwidth[index] = (int)video_stats->download_bandwidth; + counters->video_upload_bandwidth[index] = (int)video_stats->upload_bandwidth; } + linphone_call_stats_unref(audio_stats); + linphone_call_stats_unref(video_stats); } } @@ -179,6 +184,7 @@ void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreMana LinphoneCall *c1,*c2; MSTimeSpec ts; int max_time_to_wait; + LinphoneCallStats *audio_stats1, *video_stats1, *audio_stats2, *video_stats2; c1=linphone_core_get_current_call(caller->lc); c2=linphone_core_get_current_call(callee->lc); @@ -195,46 +201,58 @@ void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreMana max_time_to_wait = 5000; do { - if (linphone_call_get_audio_stats(c1)->round_trip_delay > 0.0 - && linphone_call_get_audio_stats(c2)->round_trip_delay > 0.0 - && (!linphone_call_log_video_enabled(linphone_call_get_call_log(c1)) || linphone_call_get_video_stats(c1)->round_trip_delay>0.0) - && (!linphone_call_log_video_enabled(linphone_call_get_call_log(c2)) || linphone_call_get_video_stats(c2)->round_trip_delay>0.0)) { + audio_stats1 = linphone_call_get_audio_stats(c1); + video_stats1 = linphone_call_get_video_stats(c1); + audio_stats2 = linphone_call_get_audio_stats(c2); + video_stats2 = linphone_call_get_video_stats(c2); + if (audio_stats1->round_trip_delay > 0.0 + && audio_stats2->round_trip_delay > 0.0 + && (!linphone_call_log_video_enabled(linphone_call_get_call_log(c1)) || video_stats1->round_trip_delay>0.0) + && (!linphone_call_log_video_enabled(linphone_call_get_call_log(c2)) || video_stats2->round_trip_delay>0.0)) { break; } + linphone_call_stats_unref(audio_stats1); + linphone_call_stats_unref(audio_stats2); + if (video_stats1) linphone_call_stats_unref(video_stats1); + if (video_stats2) linphone_call_stats_unref(video_stats2); wait_for_until(caller->lc,callee->lc,NULL,0,20); /*just to sleep while iterating*/ }while (!liblinphone_tester_clock_elapsed(&ts,max_time_to_wait)); + audio_stats1 = linphone_call_get_audio_stats(c1); + video_stats1 = linphone_call_get_video_stats(c1); + audio_stats2 = linphone_call_get_audio_stats(c2); + video_stats2 = linphone_call_get_video_stats(c2); if (linphone_core_rtcp_enabled(caller->lc) && linphone_core_rtcp_enabled(callee->lc)) { BC_ASSERT_GREATER(caller->stat.number_of_rtcp_received, 1, int, "%i"); BC_ASSERT_GREATER(callee->stat.number_of_rtcp_received, 1, int, "%i"); - BC_ASSERT_GREATER(linphone_call_get_audio_stats(c1)->round_trip_delay,0.0,float,"%f"); - BC_ASSERT_GREATER(linphone_call_get_audio_stats(c2)->round_trip_delay,0.0,float,"%f"); + BC_ASSERT_GREATER(audio_stats1->round_trip_delay,0.0,float,"%f"); + BC_ASSERT_GREATER(audio_stats2->round_trip_delay,0.0,float,"%f"); if (linphone_call_log_video_enabled(linphone_call_get_call_log(c1))) { - BC_ASSERT_GREATER(linphone_call_get_video_stats(c1)->round_trip_delay,0.0,float,"%f"); + BC_ASSERT_GREATER(video_stats1->round_trip_delay,0.0,float,"%f"); } if (linphone_call_log_video_enabled(linphone_call_get_call_log(c2))) { - BC_ASSERT_GREATER(linphone_call_get_video_stats(c2)->round_trip_delay,0.0,float,"%f"); + BC_ASSERT_GREATER(video_stats2->round_trip_delay,0.0,float,"%f"); } } else { if (linphone_core_rtcp_enabled(caller->lc)) { - BC_ASSERT_EQUAL(linphone_call_get_audio_stats(c1)->rtp_stats.sent_rtcp_packets, 0, unsigned long long, "%llu"); - BC_ASSERT_EQUAL(linphone_call_get_audio_stats(c2)->rtp_stats.recv_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(audio_stats1->rtp_stats.sent_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(audio_stats2->rtp_stats.recv_rtcp_packets, 0, unsigned long long, "%llu"); if (linphone_call_log_video_enabled(linphone_call_get_call_log(c1))) { - BC_ASSERT_EQUAL(linphone_call_get_video_stats(c1)->rtp_stats.sent_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(video_stats1->rtp_stats.sent_rtcp_packets, 0, unsigned long long, "%llu"); } if (linphone_call_log_video_enabled(linphone_call_get_call_log(c2))) { - BC_ASSERT_EQUAL(linphone_call_get_video_stats(c2)->rtp_stats.recv_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(video_stats2->rtp_stats.recv_rtcp_packets, 0, unsigned long long, "%llu"); } } if (linphone_core_rtcp_enabled(callee->lc)) { - BC_ASSERT_EQUAL(linphone_call_get_audio_stats(c2)->rtp_stats.sent_rtcp_packets, 0, unsigned long long, "%llu"); - BC_ASSERT_EQUAL(linphone_call_get_audio_stats(c1)->rtp_stats.recv_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(audio_stats2->rtp_stats.sent_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(audio_stats1->rtp_stats.recv_rtcp_packets, 0, unsigned long long, "%llu"); if (linphone_call_log_video_enabled(linphone_call_get_call_log(c1))) { - BC_ASSERT_EQUAL(linphone_call_get_video_stats(c1)->rtp_stats.recv_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(video_stats1->rtp_stats.recv_rtcp_packets, 0, unsigned long long, "%llu"); } if (linphone_call_log_video_enabled(linphone_call_get_call_log(c2))) { - BC_ASSERT_EQUAL(linphone_call_get_video_stats(c2)->rtp_stats.sent_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(video_stats2->rtp_stats.sent_rtcp_packets, 0, unsigned long long, "%llu"); } } @@ -3353,6 +3371,7 @@ void check_media_direction(LinphoneCoreManager* mgr, LinphoneCall *call, bctbx_l if (video_dir != LinphoneMediaDirectionInvalid){ int current_recv_iframe = mgr->stat.number_of_IframeDecoded; int expected_recv_iframe=0; + LinphoneCallStats *stats = linphone_call_get_video_stats(call); if (video_dir != LinphoneMediaDirectionInactive){ BC_ASSERT_TRUE(linphone_call_params_video_enabled(params)); @@ -3360,24 +3379,23 @@ void check_media_direction(LinphoneCoreManager* mgr, LinphoneCall *call, bctbx_l linphone_call_set_next_video_frame_decoded_callback(call,linphone_call_iframe_decoded_cb,mgr->lc); linphone_call_send_vfu_request(call); } - switch (video_dir) { case LinphoneMediaDirectionInactive: - BC_ASSERT_LOWER((int)linphone_call_get_video_stats(call)->upload_bandwidth, 5, int, "%i"); + BC_ASSERT_LOWER((int)stats->upload_bandwidth, 5, int, "%i"); break; case LinphoneMediaDirectionSendOnly: expected_recv_iframe = 0; - BC_ASSERT_LOWER((int)linphone_call_get_video_stats(call)->download_bandwidth, 5, int, "%i"); + BC_ASSERT_LOWER((int)stats->download_bandwidth, 5, int, "%i"); break; case LinphoneMediaDirectionRecvOnly: - BC_ASSERT_LOWER((int)linphone_call_get_video_stats(call)->upload_bandwidth, 5, int, "%i"); + BC_ASSERT_LOWER((int)stats->upload_bandwidth, 5, int, "%i"); case LinphoneMediaDirectionSendRecv: expected_recv_iframe = 1; break; default: break; } - + linphone_call_stats_unref(stats); BC_ASSERT_TRUE(wait_for_list(lcs, &mgr->stat.number_of_IframeDecoded,current_recv_iframe + expected_recv_iframe,10000)); } #endif @@ -3719,6 +3737,7 @@ static void call_with_paused_no_sdp_on_resume(void) { LinphoneCoreManager* marie; LinphoneCoreManager* pauline; LinphoneCall* call_marie = NULL; + LinphoneCallStats *stats; bool_t call_ok; marie = linphone_core_manager_new( "marie_rc"); @@ -3756,7 +3775,9 @@ static void call_with_paused_no_sdp_on_resume(void) { wait_for_until(marie->lc, pauline->lc, &dummy, 1, 3000); BC_ASSERT_GREATER(linphone_core_manager_get_max_audio_down_bw(marie),70,int,"%i"); - BC_ASSERT_TRUE(linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc))->download_bandwidth>70); + stats = linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc)); + BC_ASSERT_TRUE(stats->download_bandwidth>70); + linphone_call_stats_unref(stats); end_call(marie,pauline); end: @@ -4569,8 +4590,8 @@ static void custom_rtp_modifier(bool_t pauseResumeTest, bool_t recordTest) { // Now we want to ensure that all sent RTP packets actually go through our RTP transport modifier and thus no packet leave without being processed (by any operation we might want to do on it) { - const LinphoneCallStats *marie_stats = linphone_call_get_audio_stats(call_marie); - const LinphoneCallStats *pauline_stats = linphone_call_get_audio_stats(call_pauline); + LinphoneCallStats *marie_stats = linphone_call_get_audio_stats(call_marie); + LinphoneCallStats *pauline_stats = linphone_call_get_audio_stats(call_pauline); rtp_stats_t marie_rtp_stats = *linphone_call_stats_get_rtp_stats(marie_stats); rtp_stats_t pauline_rtp_stats = *linphone_call_stats_get_rtp_stats(pauline_stats); ms_message("Marie sent %i RTP packets and received %i (for real)", (int)marie_rtp_stats.packet_sent, (int)marie_rtp_stats.packet_recv); @@ -4580,6 +4601,8 @@ static void custom_rtp_modifier(bool_t pauseResumeTest, bool_t recordTest) { // There can be a small difference between the number of packets received in the modifier and the number processed in reception because the processing is asynchronous BC_ASSERT_TRUE(data_pauline->packetReceivedCount - pauline_rtp_stats.packet_recv < 20); BC_ASSERT_TRUE(data_pauline->packetSentCount == pauline_rtp_stats.packet_sent); + linphone_call_stats_unref(marie_stats); + linphone_call_stats_unref(pauline_stats); } end: @@ -5649,7 +5672,7 @@ static bool_t quick_call(LinphoneCoreManager *m1, LinphoneCoreManager *m2){ static void call_with_encryption_mandatory(bool_t caller_has_encryption_mandatory){ LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); - + LinphoneCallStats *marie_stats, *pauline_stats; /*marie doesn't support ZRTP at all*/ marie->lc->zrtp_not_available_simulation=1; @@ -5670,8 +5693,12 @@ static void call_with_encryption_mandatory(bool_t caller_has_encryption_mandator BC_ASSERT_EQUAL(linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc))->rtp_stats.packet_sent, 0, int, "%i"); #endif /*however we can trust packet_recv from the other party instead */ - BC_ASSERT_EQUAL((int)linphone_call_get_audio_stats(linphone_core_get_current_call(marie->lc))->rtp_stats.packet_recv, 0, int, "%i"); - BC_ASSERT_EQUAL((int)linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc))->rtp_stats.packet_recv, 0, int, "%i"); + marie_stats = linphone_call_get_audio_stats(linphone_core_get_current_call(marie->lc)); + pauline_stats = linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc)); + BC_ASSERT_EQUAL((int)marie_stats->rtp_stats.packet_recv, 0, int, "%i"); + BC_ASSERT_EQUAL((int)pauline_stats->rtp_stats.packet_recv, 0, int, "%i"); + linphone_call_stats_unref(marie_stats); + linphone_call_stats_unref(pauline_stats); end_call(marie, pauline); end: diff --git a/tester/complex_sip_case_tester.c b/tester/complex_sip_case_tester.c index 3e2a566af..f50996b5a 100644 --- a/tester/complex_sip_case_tester.c +++ b/tester/complex_sip_case_tester.c @@ -26,21 +26,30 @@ #if HAVE_SIPP void check_rtcp(LinphoneCall *call) { MSTimeSpec ts; + LinphoneCallStats *audio_stats, *video_stats; linphone_call_ref(call); liblinphone_tester_clock_start(&ts); do { - if (linphone_call_get_audio_stats(call)->round_trip_delay > 0.0 && (!linphone_call_log_video_enabled(linphone_call_get_call_log(call)) || linphone_call_get_video_stats(call)->round_trip_delay > 0.0)) { + audio_stats = linphone_call_get_audio_stats(call); + video_stats = linphone_call_get_video_stats(call); + if (linphone_call_stats_get_round_trip_delay(audio_stats) > 0.0 && (!linphone_call_log_video_enabled(linphone_call_get_call_log(call)) || linphone_call_stats_get_round_trip_delay(video_stats) > 0.0)) { break; } + linphone_call_stats_unref(audio_stats); + if (video_stats) linphone_call_stats_unref(video_stats); wait_for_until(call->core, NULL, NULL, 0, 20); /*just to sleep while iterating*/ } while (!liblinphone_tester_clock_elapsed(&ts, 15000)); - BC_ASSERT_GREATER(linphone_call_get_audio_stats(call)->round_trip_delay, 0.0, float, "%f"); + audio_stats = linphone_call_get_audio_stats(call); + BC_ASSERT_GREATER(linphone_call_stats_get_round_trip_delay(audio_stats), 0.0, float, "%f"); if (linphone_call_log_video_enabled(linphone_call_get_call_log(call))) { - BC_ASSERT_GREATER(linphone_call_get_video_stats(call)->round_trip_delay, 0.0, float, "%f"); + video_stats = linphone_call_get_video_stats(call); + BC_ASSERT_GREATER(linphone_call_stats_get_round_trip_delay(video_stats), 0.0, float, "%f"); + linphone_call_stats_unref(video_stats); } + linphone_call_stats_unref(audio_stats); linphone_call_unref(call); } diff --git a/tester/tester.c b/tester/tester.c index 363e84b4e..40f8b43b9 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -677,6 +677,7 @@ void liblinphone_tester_uninit(void) { static void check_ice_from_rtp(LinphoneCall *c1, LinphoneCall *c2, LinphoneStreamType stream_type) { MediaStream *ms; + LinphoneCallStats *stats; switch (stream_type) { case LinphoneStreamTypeAudio: ms=&c1->audiostream->ms; @@ -693,7 +694,8 @@ static void check_ice_from_rtp(LinphoneCall *c1, LinphoneCall *c2, LinphoneStrea return; } - if (linphone_call_get_audio_stats(c1)->ice_state == LinphoneIceStateHostConnection && media_stream_started(ms)) { + stats = linphone_call_get_audio_stats(c1); + if (stats->ice_state == LinphoneIceStateHostConnection && media_stream_started(ms)) { struct sockaddr_storage remaddr; socklen_t remaddrlen = sizeof(remaddr); char ip[NI_MAXHOST] = { 0 }; @@ -718,6 +720,7 @@ static void check_ice_from_rtp(LinphoneCall *c1, LinphoneCall *c2, LinphoneStrea BC_ASSERT_STRING_EQUAL(ip, expected_addr); } } + linphone_call_stats_unref(stats); } bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee, LinphoneIceState state) { @@ -747,13 +750,17 @@ bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee, Linph liblinphone_tester_clock_start(&ts); do{ if ((c1 != NULL) && (c2 != NULL)) { - if (linphone_call_get_audio_stats(c1)->ice_state==state && - linphone_call_get_audio_stats(c2)->ice_state==state ){ + LinphoneCallStats *stats1 = linphone_call_get_audio_stats(c1); + LinphoneCallStats *stats2 = linphone_call_get_audio_stats(c2); + if (stats1->ice_state==state && + stats2->ice_state==state){ audio_success=TRUE; check_ice_from_rtp(c1,c2,LinphoneStreamTypeAudio); check_ice_from_rtp(c2,c1,LinphoneStreamTypeAudio); break; } + linphone_call_stats_unref(stats1); + linphone_call_stats_unref(stats2); linphone_core_iterate(caller->lc); linphone_core_iterate(callee->lc); } @@ -765,13 +772,17 @@ bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee, Linph liblinphone_tester_clock_start(&ts); do{ if ((c1 != NULL) && (c2 != NULL)) { - if (linphone_call_get_video_stats(c1)->ice_state==state && - linphone_call_get_video_stats(c2)->ice_state==state ){ + LinphoneCallStats *stats1 = linphone_call_get_video_stats(c1); + LinphoneCallStats *stats2 = linphone_call_get_video_stats(c2); + if (stats1->ice_state==state && + stats2->ice_state==state){ video_success=TRUE; check_ice_from_rtp(c1,c2,LinphoneStreamTypeVideo); check_ice_from_rtp(c2,c1,LinphoneStreamTypeVideo); break; } + linphone_call_stats_unref(stats1); + linphone_call_stats_unref(stats2); linphone_core_iterate(caller->lc); linphone_core_iterate(callee->lc); } @@ -783,13 +794,17 @@ bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee, Linph liblinphone_tester_clock_start(&ts); do{ if ((c1 != NULL) && (c2 != NULL)) { - if (linphone_call_get_text_stats(c1)->ice_state==state && - linphone_call_get_text_stats(c2)->ice_state==state ){ + LinphoneCallStats *stats1 = linphone_call_get_text_stats(c1); + LinphoneCallStats *stats2 = linphone_call_get_text_stats(c2); + if (stats1->ice_state==state && + stats2->ice_state==state){ text_success=TRUE; check_ice_from_rtp(c1,c2,LinphoneStreamTypeText); check_ice_from_rtp(c2,c1,LinphoneStreamTypeText); break; } + linphone_call_stats_unref(stats1); + linphone_call_stats_unref(stats2); linphone_core_iterate(caller->lc); linphone_core_iterate(callee->lc); } diff --git a/tester/video_tester.c b/tester/video_tester.c index 2921d6bf7..54fccaea6 100644 --- a/tester/video_tester.c +++ b/tester/video_tester.c @@ -481,18 +481,32 @@ static void forked_outgoing_early_media_video_call_with_inactive_audio_test(void BC_ASSERT_PTR_NOT_NULL(marie2_call); if (pauline_call && marie1_call && marie2_call) { + LinphoneCallStats *pauline_audio_stats, *marie1_audio_stats, *marie2_audio_stats; + LinphoneCallStats *pauline_video_stats, *marie1_video_stats, *marie2_video_stats; linphone_call_set_next_video_frame_decoded_callback(pauline_call, linphone_call_iframe_decoded_cb, pauline->lc); /* wait a bit that streams are established */ wait_for_list(lcs, &dummy, 1, 3000); - BC_ASSERT_EQUAL(linphone_call_get_audio_stats(pauline_call)->download_bandwidth, 0, float, "%f"); - BC_ASSERT_EQUAL(linphone_call_get_audio_stats(marie1_call)->download_bandwidth, 0, float, "%f"); - BC_ASSERT_EQUAL(linphone_call_get_audio_stats(marie2_call)->download_bandwidth, 0, float, "%f"); - BC_ASSERT_LOWER(linphone_call_get_video_stats(pauline_call)->download_bandwidth, 11, float, "%f"); /* because of stun packets*/ - BC_ASSERT_GREATER(linphone_call_get_video_stats(marie1_call)->download_bandwidth, 0, float, "%f"); - BC_ASSERT_GREATER(linphone_call_get_video_stats(marie2_call)->download_bandwidth, 0, float, "%f"); + pauline_audio_stats = linphone_call_get_audio_stats(pauline_call); + marie1_audio_stats = linphone_call_get_audio_stats(marie1_call); + marie2_audio_stats = linphone_call_get_audio_stats(marie2_call); + pauline_video_stats = linphone_call_get_video_stats(pauline_call); + marie1_video_stats = linphone_call_get_video_stats(marie1_call); + marie2_video_stats = linphone_call_get_video_stats(marie2_call); + BC_ASSERT_EQUAL(pauline_audio_stats->download_bandwidth, 0, float, "%f"); + BC_ASSERT_EQUAL(marie1_audio_stats->download_bandwidth, 0, float, "%f"); + BC_ASSERT_EQUAL(marie2_audio_stats->download_bandwidth, 0, float, "%f"); + BC_ASSERT_LOWER(pauline_video_stats->download_bandwidth, 11, float, "%f"); /* because of stun packets*/ + BC_ASSERT_GREATER(marie1_video_stats->download_bandwidth, 0, float, "%f"); + BC_ASSERT_GREATER(marie2_video_stats->download_bandwidth, 0, float, "%f"); BC_ASSERT_GREATER(marie1->stat.number_of_IframeDecoded, 1, int, "%i"); BC_ASSERT_GREATER(marie2->stat.number_of_IframeDecoded, 1, int, "%i"); + linphone_call_stats_unref(pauline_audio_stats); + linphone_call_stats_unref(marie1_audio_stats); + linphone_call_stats_unref(marie2_audio_stats); + linphone_call_stats_unref(pauline_video_stats); + linphone_call_stats_unref(marie1_video_stats); + linphone_call_stats_unref(marie2_video_stats); linphone_call_params_set_audio_direction(marie1_params, LinphoneMediaDirectionSendRecv); linphone_call_accept_with_params(linphone_core_get_current_call(marie1->lc), marie1_params); @@ -504,11 +518,19 @@ static void forked_outgoing_early_media_video_call_with_inactive_audio_test(void /*wait a bit that streams are established*/ wait_for_list(lcs, &dummy, 1, 3000); - BC_ASSERT_GREATER(linphone_call_get_audio_stats(pauline_call)->download_bandwidth, 71, float, "%f"); - BC_ASSERT_GREATER(linphone_call_get_audio_stats(marie1_call)->download_bandwidth, 71, float, "%f"); - BC_ASSERT_GREATER(linphone_call_get_video_stats(pauline_call)->download_bandwidth, 0, float, "%f"); - BC_ASSERT_GREATER(linphone_call_get_video_stats(marie1_call)->download_bandwidth, 0, float, "%f"); + pauline_audio_stats = linphone_call_get_audio_stats(pauline_call); + marie1_audio_stats = linphone_call_get_audio_stats(marie1_call); + pauline_video_stats = linphone_call_get_video_stats(pauline_call); + marie1_video_stats = linphone_call_get_video_stats(marie1_call); + BC_ASSERT_GREATER(pauline_audio_stats->download_bandwidth, 71, float, "%f"); + BC_ASSERT_GREATER(marie1_audio_stats->download_bandwidth, 71, float, "%f"); + BC_ASSERT_GREATER(pauline_video_stats->download_bandwidth, 0, float, "%f"); + BC_ASSERT_GREATER(marie1_video_stats->download_bandwidth, 0, float, "%f"); BC_ASSERT_GREATER(pauline->stat.number_of_IframeDecoded, 1, int, "%i"); + linphone_call_stats_unref(pauline_audio_stats); + linphone_call_stats_unref(marie1_audio_stats); + linphone_call_stats_unref(pauline_video_stats); + linphone_call_stats_unref(marie1_video_stats); /* send an INFO in reverse side to check that dialogs are properly established */ info = linphone_core_create_info_message(marie1->lc);