LinphoneCallStats is now a belle_sip_object. BREAKS BINARY COMPATIBILITY

This commit is contained in:
Sylvain Berfini 2017-04-19 15:31:20 +02:00
parent 1dcd17198e
commit 83b94af9a4
17 changed files with 426 additions and 178 deletions

View file

@ -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})

View file

@ -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])

View file

@ -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){

View file

@ -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) {

View file

@ -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; /**<jitter buffer statistics, see oRTP documentation for details */
mblk_t *received_rtcp; /**<Last RTCP packet received, as a mblk_t structure. See oRTP documentation for details how to extract information from it*/
mblk_t *sent_rtcp;/**<Last RTCP packet sent, as a mblk_t structure. See oRTP documentation for details how to extract information from it*/
float round_trip_delay; /**<Round trip propagation time in seconds if known, -1 if unknown.*/
LinphoneIceState ice_state; /**< State of ICE processing. */
LinphoneUpnpState upnp_state; /**< State of uPnP processing. */
float download_bandwidth; /**<Download bandwidth measurement of received stream, expressed in kbit/s, including IP/UDP/RTP headers*/
float upload_bandwidth; /**<Download bandwidth measurement of sent stream, expressed in kbit/s, including IP/UDP/RTP headers*/
float local_late_rate; /**<percentage of packet received too late over last second*/
float local_loss_rate; /**<percentage of lost packet over last second*/
int updated; /**< Tell which RTCP packet has been updated (received_rtcp or sent_rtcp). Can be either LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE or LINPHONE_CALL_STATS_SENT_RTCP_UPDATE */
float rtcp_download_bandwidth; /**<RTCP download bandwidth measurement of received stream, expressed in kbit/s, including IP/UDP/RTP headers*/
float rtcp_upload_bandwidth; /**<RTCP download bandwidth measurement of sent stream, expressed in kbit/s, including IP/UDP/RTP headers*/
rtp_stats_t rtp_stats; /**< RTP stats */
int rtp_remote_family; /**< Ip adress family of the remote destination */
int clockrate; /*RTP clockrate of the stream, provided here for easily converting timestamp units expressed in RTCP packets in milliseconds*/
bool_t rtcp_received_via_mux; /*private flag, for non-regression test only*/
};
BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneCallStats);
LinphoneCallStats *linphone_call_stats_new(void);
/** Belle Sip-based objects need unique ids
*/
@ -1814,7 +1851,8 @@ BELLE_SIP_TYPE_ID(LinphonePayloadType),
BELLE_SIP_TYPE_ID(LinphoneRange),
BELLE_SIP_TYPE_ID(LinphoneVideoDefinition),
BELLE_SIP_TYPE_ID(LinphoneTransports),
BELLE_SIP_TYPE_ID(LinphoneVideoActivationPolicy)
BELLE_SIP_TYPE_ID(LinphoneVideoActivationPolicy),
BELLE_SIP_TYPE_ID(LinphoneCallStats)
BELLE_SIP_DECLARE_TYPES_END

View file

@ -592,21 +592,29 @@ static float reporting_rand(float t){
void linphone_reporting_on_rtcp_update(LinphoneCall *call, SalStreamType stats_type) {
reporting_session_report_t * report = call->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) ?

View file

@ -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));
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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){

View file

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

View file

@ -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; /**<jitter buffer statistics, see oRTP documentation for details */
mblk_t *received_rtcp; /**<Last RTCP packet received, as a mblk_t structure. See oRTP documentation for details how to extract information from it*/
mblk_t *sent_rtcp;/**<Last RTCP packet sent, as a mblk_t structure. See oRTP documentation for details how to extract information from it*/
float round_trip_delay; /**<Round trip propagation time in seconds if known, -1 if unknown.*/
LinphoneIceState ice_state; /**< State of ICE processing. */
LinphoneUpnpState upnp_state; /**< State of uPnP processing. */
float download_bandwidth; /**<Download bandwidth measurement of received stream, expressed in kbit/s, including IP/UDP/RTP headers*/
float upload_bandwidth; /**<Download bandwidth measurement of sent stream, expressed in kbit/s, including IP/UDP/RTP headers*/
float local_late_rate; /**<percentage of packet received too late over last second*/
float local_loss_rate; /**<percentage of lost packet over last second*/
int updated; /**< Tell which RTCP packet has been updated (received_rtcp or sent_rtcp). Can be either LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE or LINPHONE_CALL_STATS_SENT_RTCP_UPDATE */
float rtcp_download_bandwidth; /**<RTCP download bandwidth measurement of received stream, expressed in kbit/s, including IP/UDP/RTP headers*/
float rtcp_upload_bandwidth; /**<RTCP download bandwidth measurement of sent stream, expressed in kbit/s, including IP/UDP/RTP headers*/
rtp_stats_t rtp_stats; /**< RTP stats */
int rtp_remote_family; /**< Ip adress family of the remote destination */
int clockrate; /*RTP clockrate of the stream, provided here for easily converting timestamp units expressed in RTCP packets in milliseconds*/
bool_t rtcp_received_via_mux; /*private flag, for non-regression test only*/
};
LINPHONE_PUBLIC LinphoneCallStats *linphone_call_stats_ref(LinphoneCallStats *stats);
/**
* Decrement refcount and possibly free the object.
* @param[in] stats LinphoneCallStats object
* @ingroup misc
**/
LINPHONE_PUBLIC void linphone_call_stats_unref(LinphoneCallStats *stats);
/**
* Gets the user data in the LinphoneCallStats object
* @param[in] stats the LinphoneCallStats
* @return the user data
* @ingroup misc
*/
LINPHONE_PUBLIC void *linphone_call_stats_get_user_data(const LinphoneCallStats *stats);
/**
* Sets the user data in the LinphoneCallStats object
* @param[in] stats the LinphoneCallStats object
* @param[in] data the user data
* @ingroup misc
*/
LINPHONE_PUBLIC void linphone_call_stats_set_user_data(LinphoneCallStats *stats, void *data);
/**
* Get the type of the stream the stats refer to.
@ -152,6 +153,13 @@ LINPHONE_PUBLIC LinphoneAddressFamily linphone_call_stats_get_ip_family_of_remot
*/
LINPHONE_PUBLIC float linphone_call_stats_get_jitter_buffer_size_ms(const LinphoneCallStats *stats);
/**
* Get the round trip delay in s.
* @param[in] stats LinphoneCallStats object
* @return The round trip delay in s.
*/
LINPHONE_PUBLIC float linphone_call_stats_get_round_trip_delay(const LinphoneCallStats *stats);
/**
* @}
*/

View file

@ -83,6 +83,7 @@ static void early_media_with_multicast_base(bool_t video) {
LinphoneVideoPolicy marie_policy, pauline_policy;
LpConfig *marie_lp;
LinphoneCallParams *params;
LinphoneCallStats *stats = NULL;
marie = linphone_core_manager_new("marie_rc");
pauline = linphone_core_manager_new("pauline_tcp_rc");
@ -167,11 +168,15 @@ static void early_media_with_multicast_base(bool_t video) {
wait_for_list(lcs, &dummy, 1, 3000);
stats = linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->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))));

View file

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

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);