Commit abf2a7ec authored by Simon Morlat's avatar Simon Morlat

factorize code related to call quality indicator.

add accessors to loss and late rates.
parent d9ce543d
......@@ -86,10 +86,15 @@ struct _MediaStream {
MSFilter *decoder;
MSFilter *voidsink;
MSBitrateController *rc;
MSQualityIndicator *qi;
IceCheckList *ice_check_list;
OrtpZrtpContext *zrtp_context;
srtp_t srtp_session;
time_t start_time;
time_t last_iterate_time;
bool_t use_rc;
bool_t is_beginning;
bool_t pad[2];
};
typedef struct _MediaStream MediaStream;
......@@ -106,7 +111,14 @@ MS2_PUBLIC void media_stream_enable_adaptive_jittcomp(MediaStream *stream, bool_
MS2_PUBLIC bool_t media_stream_enable_srtp(MediaStream* stream, enum ortp_srtp_crypto_suite_t suite, const char* snd_key, const char* rcv_key);
MS2_PUBLIC const MSQualityIndicator *media_stream_get_quality_indicator(MediaStream *stream);
MS2_PUBLIC float media_stream_get_quality_rating(MediaStream *stream);
MS2_PUBLIC float media_stream_get_average_quality_rating(MediaStream *stream);
/*shall only called internally*/
void media_stream_iterate(MediaStream * stream);
/**
* @addtogroup audio_stream_api
* @{
......@@ -140,16 +152,12 @@ struct _AudioStream
uint64_t last_packet_count;
time_t last_packet_time;
EchoLimiterType el_type; /*use echo limiter: two MSVolume, measured input level controlling local output level*/
MSQualityIndicator *qi;
time_t start_time;
time_t last_iterate_time;
uint32_t features;
bool_t play_dtmfs;
bool_t use_gc;
bool_t use_agc;
bool_t eq_active;
bool_t use_ng;/*noise gate*/
bool_t is_beginning;
bool_t is_ec_delay_set;
};
......
......@@ -30,17 +30,51 @@ typedef struct _MSQualityIndicator MSQualityIndicator;
extern "C"{
#endif
MSQualityIndicator *ms_quality_indicator_new(RtpSession *session);
/**
* Creates a quality indicator object.
* @param session the RtpSession being monitored.
**/
MS2_PUBLIC MSQualityIndicator *ms_quality_indicator_new(RtpSession *session);
/**
* Updates quality indicator based on a received RTCP packet.
**/
MS2_PUBLIC void ms_quality_indicator_update_from_feedback(MSQualityIndicator *qi, mblk_t *rtcp);
/**
* Updates quality indicator based on the local statistics directly computed by the RtpSession used when creating the indicator.
* This function must be called typically every second.
**/
MS2_PUBLIC void ms_quality_indicator_update_local(MSQualityIndicator *qi);
/**
* Return the real time rating of the session. Its value is between 0 (worse) and 5.0 (best).
**/
MS2_PUBLIC float ms_quality_indicator_get_rating(MSQualityIndicator *qi);
/**
* Returns the average rating of the session, that is the rating for all the duration of the session.
**/
MS2_PUBLIC float ms_quality_indicator_get_average_rating(MSQualityIndicator *qi);
/**
* Returns the local loss rate, as computed internally by ms_quality_indicator_update_local().
* This method is for advanced usage.
**/
MS2_PUBLIC float ms_quality_indicator_get_local_loss_rate(const MSQualityIndicator *qi);
/**
* Returns the local late rate, as computed internally by ms_quality_indicator_update_local().
* This method is for advanced usage.
**/
MS2_PUBLIC float ms_quality_indicator_get_local_late_rate(const MSQualityIndicator *qi);
/**
* Destroys the quality indicator object.
**/
MS2_PUBLIC void ms_quality_indicator_destroy(MSQualityIndicator *qi);
float ms_quality_indicator_get_rating(MSQualityIndicator *qi);
float ms_quality_indicator_get_average_rating(MSQualityIndicator *qi);
void ms_quality_indicator_update_from_feedback(MSQualityIndicator *qi, mblk_t *rtcp);
void ms_quality_indicator_update_local(MSQualityIndicator *qi);
void ms_quality_indicator_destroy(MSQualityIndicator *qi);
#ifdef __cplusplus
}
......
......@@ -63,7 +63,6 @@ static void audio_stream_free(AudioStream *stream) {
if (stream->recorder) ms_filter_destroy(stream->recorder);
if (stream->recorder_mixer) ms_filter_destroy(stream->recorder_mixer);
if (stream->recorder_file) ms_free(stream->recorder_file);
if (stream->qi) ms_quality_indicator_destroy(stream->qi);
ms_free(stream);
}
......@@ -122,17 +121,12 @@ static void audio_stream_process_rtcp(AudioStream *stream, mblk_t *m){
ms_message("audio_stream_iterate(): remote statistics available\n\tremote's interarrival jitter=%u\n"
"\tremote's lost packets percentage since last report=%f\n\tround trip time=%f seconds",ij,flost,rt);
if (stream->ms.rc) ms_bitrate_controller_process_rtcp(stream->ms.rc,m);
if (stream->qi) ms_quality_indicator_update_from_feedback(stream->qi,m);
if (stream->ms.qi) ms_quality_indicator_update_from_feedback(stream->ms.qi,m);
}
}while(rtcp_next_packet(m));
}
void audio_stream_iterate(AudioStream *stream){
time_t curtime=time(NULL);
if (stream->is_beginning && ms_time(NULL)-stream->start_time>15){
rtp_session_set_rtcp_report_interval(stream->ms.session,5000);
stream->is_beginning=FALSE;
}
if (stream->ms.evq){
OrtpEvent *ev=ortp_ev_queue_get(stream->ms.evq);
if (ev!=NULL){
......@@ -148,10 +142,7 @@ void audio_stream_iterate(AudioStream *stream){
ortp_event_destroy(ev);
}
}
if (stream->ms.ice_check_list) ice_check_list_process(stream->ms.ice_check_list,stream->ms.session);
/*we choose to update the quality indicator as much as possible, since local statistics can be computed realtime. */
if (stream->qi && curtime>stream->last_iterate_time) ms_quality_indicator_update_local(stream->qi);
stream->last_iterate_time=curtime;
media_stream_iterate(&stream->ms);
}
bool_t audio_stream_alive(AudioStream * stream, int timeout){
......@@ -191,7 +182,7 @@ static void stop_preload_graph(AudioStream *stream){
}
bool_t audio_stream_started(AudioStream *stream){
return stream->start_time!=0;
return stream->ms.start_time!=0;
}
/* This function is used either on IOS to workaround the long time to initialize the Audio Unit or for ICE candidates gathering. */
......@@ -261,7 +252,7 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
else
stream->dtmfgen=NULL;
rtp_session_signal_connect(rtps,"telephone-event",(RtpCallback)on_dtmf_received,(unsigned long)stream);
rtp_session_signal_connect(rtps,"payload_type_changed",(RtpCallback)payload_type_changed,(unsigned long)&stream->ms);
rtp_session_signal_connect(rtps,"payload_type_changed",(RtpCallback)mediastream_payload_type_changed,(unsigned long)&stream->ms);
/* creates the local part */
if (captcard!=NULL){
if (stream->soundread==NULL)
......@@ -440,7 +431,6 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
if (stream->ms.use_rc){
stream->ms.rc=ms_audio_bitrate_controller_new(stream->ms.session,stream->ms.encoder,0);
}
stream->qi=ms_quality_indicator_new(stream->ms.session);
/* Create PLC */
if ((stream->features & AUDIO_STREAM_FEATURE_PLC) != 0) {
......@@ -523,8 +513,8 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
,stream->ms.rtprecv
,NULL);
stream->start_time=ms_time(NULL);
stream->is_beginning=TRUE;
stream->ms.start_time=ms_time(NULL);
stream->ms.is_beginning=TRUE;
return 0;
}
......@@ -664,6 +654,7 @@ AudioStream *audio_stream_new(int loc_rtp_port, int loc_rtcp_port, bool_t ipv6){
/*some filters are created right now to allow configuration by the application before start() */
stream->ms.rtpsend=ms_filter_new(MS_RTP_SEND_ID);
stream->ms.ice_check_list=NULL;
stream->ms.qi=ms_quality_indicator_new(stream->ms.session);
if (ec_desc!=NULL)
stream->ec=ms_filter_new_from_desc(ec_desc);
......@@ -770,7 +761,7 @@ void audio_stream_stop(AudioStream * stream)
if (stream->dummy){
stop_preload_graph(stream);
}else if (stream->start_time!=0){
}else if (stream->ms.start_time!=0){
ms_ticker_detach(stream->ms.ticker,stream->soundread);
ms_ticker_detach(stream->ms.ticker,stream->ms.rtprecv);
......@@ -850,17 +841,11 @@ void audio_stream_mute_rtp(AudioStream *stream, bool_t val)
}
float audio_stream_get_quality_rating(AudioStream *stream){
if (stream->qi){
return ms_quality_indicator_get_rating(stream->qi);
}
return 0;
return media_stream_get_quality_rating(&stream->ms);
}
float audio_stream_get_average_quality_rating(AudioStream *stream){
if (stream->qi){
return ms_quality_indicator_get_average_rating(stream->qi);
}
return 0;
return media_stream_get_average_quality_rating(&stream->ms);
}
void audio_stream_enable_zrtp(AudioStream *stream, OrtpZrtpParams *params){
......
......@@ -173,6 +173,7 @@ void media_stream_free(MediaStream *stream) {
if (stream->decoder != NULL) ms_filter_destroy(stream->decoder);
if (stream->voidsink != NULL) ms_filter_destroy(stream->voidsink);
if (stream->ticker != NULL) ms_ticker_destroy(stream->ticker);
if (stream->qi) ms_quality_indicator_destroy(stream->qi);
}
void media_stream_set_rtcp_information(MediaStream *stream, const char *cname, const char *tool) {
......@@ -220,6 +221,10 @@ bool_t media_stream_enable_srtp(MediaStream *stream, enum ortp_srtp_crypto_suite
return TRUE;
}
const MSQualityIndicator *media_stream_get_quality_indicator(MediaStream *stream){
return stream->qi;
}
bool_t ms_is_ipv6(const char *remote) {
bool_t ret = FALSE;
#ifdef INET6
......@@ -240,8 +245,37 @@ bool_t ms_is_ipv6(const char *remote) {
return ret;
}
void payload_type_changed(RtpSession *session, unsigned long data) {
void mediastream_payload_type_changed(RtpSession *session, unsigned long data) {
MediaStream *stream = (MediaStream *)data;
int pt = rtp_session_get_recv_payload_type(stream->session);
media_stream_change_decoder(stream, pt);
}
void media_stream_iterate(MediaStream *stream){
time_t curtime=ms_time(NULL);
if (stream->is_beginning && (curtime-stream->start_time>15)){
rtp_session_set_rtcp_report_interval(stream->session,5000);
stream->is_beginning=FALSE;
}
if (stream->ice_check_list) ice_check_list_process(stream->ice_check_list,stream->session);
/*we choose to update the quality indicator as much as possible, since local statistics can be computed realtime. */
if (stream->qi && curtime>stream->last_iterate_time) ms_quality_indicator_update_local(stream->qi);
stream->last_iterate_time=curtime;
}
float media_stream_get_quality_rating(MediaStream *stream){
if (stream->qi){
return ms_quality_indicator_get_rating(stream->qi);
}
return -1;
}
float media_stream_get_average_quality_rating(MediaStream *stream){
if (stream->qi){
return ms_quality_indicator_get_average_rating(stream->qi);
}
return -1;
}
......@@ -47,7 +47,7 @@ MEDIASTREAMER2_INTERNAL_EXPORT RtpSession * create_duplex_rtpsession(int loc_rtp
void start_ticker(MediaStream *stream);
void payload_type_changed(RtpSession *session, unsigned long data);
void mediastream_payload_type_changed(RtpSession *session, unsigned long data);
const char * media_stream_type_str(MediaStream *stream);
......
......@@ -39,6 +39,8 @@ struct _MSQualityIndicator{
uint32_t last_ext_seq;
uint32_t last_late;
int count;
float cur_late_rate;
float cur_loss_rate;
};
MSQualityIndicator *ms_quality_indicator_new(RtpSession *session){
......@@ -140,8 +142,8 @@ void ms_quality_indicator_update_local(MSQualityIndicator *qi){
if (lost<0) lost=0; /* will be the case at least the first time, because we don't know the initial sequence number*/
if (late<0) late=0;
loss_rate=(float)lost/(float)recvcnt;
late_rate=(float)late/(float)recvcnt;
qi->cur_loss_rate=loss_rate=(float)lost/(float)recvcnt;
qi->cur_late_rate=late_rate=(float)late/(float)recvcnt;
qi->local_rating=compute_rating(loss_rate,0,late_rate,rtp_session_get_round_trip_propagation(qi->session));
update_global_rating(qi);
......@@ -152,6 +154,14 @@ float ms_quality_indicator_get_average_rating(MSQualityIndicator *qi){
return (float)(qi->sum_ratings/(double)qi->count);
}
float ms_quality_indicator_get_local_loss_rate(const MSQualityIndicator *qi){
return qi->cur_loss_rate;
}
float ms_quality_indicator_get_local_late_rate(const MSQualityIndicator *qi){
return qi->cur_late_rate;
}
void ms_quality_indicator_destroy(MSQualityIndicator *qi){
ms_free(qi);
}
......
......@@ -113,7 +113,7 @@ void video_stream_iterate(VideoStream *stream){
ortp_event_destroy(ev);
}
}
if (stream->ms.ice_check_list) ice_check_list_process(stream->ms.ice_check_list,stream->ms.session);
media_stream_iterate(&stream->ms);
}
static void choose_display_name(VideoStream *stream){
......@@ -138,6 +138,7 @@ VideoStream *video_stream_new(int loc_rtp_port, int loc_rtcp_port, bool_t use_ip
VideoStream *stream = (VideoStream *)ms_new0 (VideoStream, 1);
stream->ms.type = VideoStreamType;
stream->ms.session=create_duplex_rtpsession(loc_rtp_port,loc_rtcp_port,use_ipv6);
stream->ms.qi=ms_quality_indicator_new(stream->ms.session);
stream->ms.evq=ortp_ev_queue_new();
stream->ms.rtpsend=ms_filter_new(MS_RTP_SEND_ID);
stream->ms.ice_check_list=NULL;
......@@ -316,7 +317,7 @@ int video_stream_start (VideoStream *stream, RtpProfile *profile, const char *re
rtp_session_set_jitter_compensation(rtps,jitt_comp);
rtp_session_signal_connect(stream->ms.session,"payload_type_changed",
(RtpCallback)payload_type_changed,(unsigned long)&stream->ms);
(RtpCallback)mediastream_payload_type_changed,(unsigned long)&stream->ms);
rtp_session_get_jitter_buffer_params(stream->ms.session,&jbp);
jbp.max_packets=1000;//needed for high resolution video
......@@ -454,6 +455,9 @@ int video_stream_start (VideoStream *stream, RtpProfile *profile, const char *re
/* create the ticker */
if (stream->ms.ticker==NULL) start_ticker(&stream->ms);
stream->ms.start_time=ms_time(NULL);
stream->ms.is_beginning=TRUE;
/* attach the graphs */
if (stream->source)
......
......@@ -766,7 +766,7 @@ void setup_media_streams(MediastreamDatas* args) {
}
static void mediastream_iterate(MediastreamDatas* args) {
static void mediastream_tool_iterate(MediastreamDatas* args) {
#ifndef WIN32
struct pollfd pfd;
int err;
......@@ -844,7 +844,7 @@ void mediastream_run_loop(MediastreamDatas* args) {
{
int n;
for(n=0;n<100;++n){
mediastream_iterate(args);
mediastream_tool_iterate(args);
#if defined(VIDEO_ENABLED)
if (args->video) video_stream_iterate(args->video);
#endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment