diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index a4903ed1a..70fe1656a 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -794,11 +794,13 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const if (lc->vtable.call_state_changed) lc->vtable.call_state_changed(lc,call,cstate,message); - if (cstate==LinphoneCallReleased){ + if (cstate==LinphoneCallEnd){ if (call->log->status == LinphoneCallSuccess) linphone_reporting_publish(call); + } + if (cstate==LinphoneCallReleased){ if (call->op!=NULL) { /*transfer the last error so that it can be obtained even in Released state*/ if (call->non_op_error.reason==SalReasonNone){ @@ -2718,7 +2720,7 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){ void linphone_call_stats_fill(LinphoneCallStats *stats, MediaStream *ms, OrtpEvent *ev){ OrtpEventType evt=ortp_event_get_type(ev); OrtpEventData *evd=ortp_event_get_data(ev); - + if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) { stats->round_trip_delay = rtp_session_get_round_trip_propagation(ms->sessions.rtp_session); if(stats->received_rtcp != NULL) @@ -2753,11 +2755,11 @@ void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index){ MediaStream *ms=stream_index==0 ? (MediaStream *)call->audiostream : (MediaStream *)call->videostream; /*assumption to remove*/ OrtpEvQueue *evq; OrtpEvent *ev; - + if (ms==NULL) return; /* Ensure there is no dangling ICE check list. */ if (call->ice_session == NULL) ms->ice_check_list = NULL; - + switch(ms->type){ case AudioStreamType: audio_stream_iterate((AudioStream*)ms); @@ -2776,10 +2778,10 @@ void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index){ while ((evq=stream_index==0 ? call->audiostream_app_evq : call->videostream_app_evq) && (NULL != (ev=ortp_ev_queue_get(evq)))){ OrtpEventType evt=ortp_event_get_type(ev); OrtpEventData *evd=ortp_event_get_data(ev); - + linphone_call_stats_fill(&call->stats[stream_index],ms,ev); linphone_call_notify_stats_updated(call,stream_index); - + if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){ if (ms->type==AudioStreamType) linphone_call_audiostream_encryption_changed(call, evd->info.zrtp_stream_encrypted); diff --git a/coreapi/quality_reporting.h b/coreapi/quality_reporting.h index c817feba9..c182a4210 100644 --- a/coreapi/quality_reporting.h +++ b/coreapi/quality_reporting.h @@ -26,12 +26,20 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern "C"{ #endif + +/** + * Linphone quality report sub object storing address related information (ip / port / MAC). + */ typedef struct reporting_addr { char * ip; int port; uint32_t ssrc; } reporting_addr_t; +/** + * Linphone quality report sub object storing media metrics information as required by RFC035. + */ + typedef struct reporting_content_metrics { // timestamps - mandatory struct { @@ -45,18 +53,13 @@ typedef struct reporting_content_metrics { char * payload_desc; // mime type int sample_rate; // clock rate int frame_duration; // to check (ptime?) - audio only - // int frame_ocets; - // int frames_per_sec; - // int packets_per_sec; char * fmtp; int packet_loss_concealment; // in voip metrics - audio only - // char * silence_suppression_state; } session_description; // jitter buffet - optional struct { int adaptive; // constant - // int rate; // constant int nominal; // no may vary during the call <- average? worst score? int max; // no may vary during the call <- average? int abs_max; // constant @@ -64,25 +67,14 @@ typedef struct reporting_content_metrics { // packet loss - optional struct { - float network_packet_loss_rate; // voip metrics (loss rate) + conversion - float jitter_buffer_discard_rate; //idem + float network_packet_loss_rate; + float jitter_buffer_discard_rate; } packet_loss; - // burst gap loss - optional - // (no) currently not implemented - // struct { - // int burst_loss_density; - // int burst_duration; - // float gap_loss_density; - // int gap_duration; - // int min_gap_threshold; - // } burst_gap_loss; - // delay - optional struct { int round_trip_delay; // no - vary int end_system_delay; // no - not implemented yet - // int one_way_delay; int symm_one_way_delay; // no - vary (depends on round_trip_delay) + not implemented (depends on end_system_delay) int interarrival_jitter; // no - not implemented yet int mean_abs_jitter; // to check @@ -92,7 +84,6 @@ typedef struct reporting_content_metrics { struct { int level; // no - vary int noise_level; // no - vary - // int residual_echo_return_loss; } signal; // quality estimates - optional @@ -101,20 +92,14 @@ typedef struct reporting_content_metrics { int rcq; //voip metrics R factor - no - vary or avg in [0..120] float moslq; // no - vary or avg - voip metrics - in [0..4.9] float moscq; // no - vary or avg - voip metrics - in [0..4.9] - - - // int extri; - // int extro; - // char * rlqestalg; - // char * rcqestalg; - // char * moslqestalg; - // char * moscqestalg; - // char * extriestalg; - // char * extroutestalg; - // char * qoestalg; } quality_estimates; } reporting_content_metrics_t; + +/** + * Linphone quality report main object created by function linphone_reporting_new(). + * It contains all fields required by RFC6035 + */ typedef struct reporting_session_report { struct { char * call_id; @@ -138,10 +123,40 @@ typedef struct reporting_session_report { reporting_session_report_t * linphone_reporting_new(); void linphone_reporting_destroy(reporting_session_report_t * report); + +/** + * Fill media information about a given call. This function must be called before + * stopping the media stream. + * @param call #LinphoneCall object to consider + * @param stats_type the media type (LINPHONE_CALL_STATS_AUDIO or LINPHONE_CALL_STATS_VIDEO) + * + */ void linphone_reporting_update(LinphoneCall * call, int stats_type); + +/** + * Fill IP information about a given call. This function must be called each + * time state is 'LinphoneCallStreamsRunning' since IP might be updated (if we + * found a direct route between caller and callee for example). + * @param call #LinphoneCall object to consider + * + */ void linphone_reporting_update_ip(LinphoneCall * call); + +/** + * Publish the report on the call end. + * @param call #LinphoneCall object to consider + * + */ void linphone_reporting_publish(LinphoneCall* call); + +/** + * Update publish report data with fresh RTCP stats, if needed. + * @param call #LinphoneCall object to consider + * @param stats_type the media type (LINPHONE_CALL_STATS_AUDIO or LINPHONE_CALL_STATS_VIDEO) + * + */ void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type); + #ifdef __cplusplus } #endif