Commit fe3455c6 authored by Gautier Pelloux-Prayer's avatar Gautier Pelloux-Prayer
Browse files

first try to handle congestion state and some test refactoring

parent 31e2602a
...@@ -86,7 +86,7 @@ struct _MSQosAnalyserDesc{ ...@@ -86,7 +86,7 @@ struct _MSQosAnalyserDesc{
}; };
/** /**
* A MSQosAnalyzer is responsible to analyze RTCP feedback and suggest actions on bitrate or packet rate accordingly. * A MSQosAnalyser is responsible to analyze RTCP feedback and suggest actions on bitrate or packet rate accordingly.
* This is an abstract interface. * This is an abstract interface.
**/ **/
struct _MSQosAnalyser{ struct _MSQosAnalyser{
...@@ -94,15 +94,19 @@ struct _MSQosAnalyser{ ...@@ -94,15 +94,19 @@ struct _MSQosAnalyser{
int refcnt; int refcnt;
}; };
#define MS_QOS_ANALYSER_NETWORK_FINE 0
#define MS_QOS_ANALYSER_NETWORK_UNSTABLE 1
#define MS_QOS_ANALYSER_NETWORK_CONGESTED 2
MSQosAnalyser * ms_qos_analyser_ref(MSQosAnalyser *obj); MSQosAnalyser * ms_qos_analyser_ref(MSQosAnalyser *obj);
void ms_qos_analyser_unref(MSQosAnalyser *obj); void ms_qos_analyser_unref(MSQosAnalyser *obj);
void ms_qos_analyser_suggest_action(MSQosAnalyser *obj, MSRateControlAction *action); void ms_qos_analyser_suggest_action(MSQosAnalyser *obj, MSRateControlAction *action);
bool_t ms_qos_analyser_has_improved(MSQosAnalyser *obj); bool_t ms_qos_analyser_has_improved(MSQosAnalyser *obj);
bool_t ms_qos_analyser_is_network_stable(const MSQosAnalyser *obj); uint32_t ms_qos_analyser_get_network_state(const MSQosAnalyser *obj);
bool_t ms_qos_analyser_process_rtcp(MSQosAnalyser *obj, mblk_t *rtcp); bool_t ms_qos_analyser_process_rtcp(MSQosAnalyser *obj, mblk_t *rtcp);
/** /**
* The simple qos analyzer is an implementation of MSQosAnalyser that performs analysis for single stream. * The simple qos analyser is an implementation of MSQosAnalyser that performs analysis for single stream.
**/ **/
MSQosAnalyser * ms_simple_qos_analyser_new(RtpSession *session); MSQosAnalyser * ms_simple_qos_analyser_new(RtpSession *session);
......
...@@ -288,11 +288,11 @@ MS2_PUBLIC int audio_stream_start_with_files (AudioStream * stream, RtpProfile * ...@@ -288,11 +288,11 @@ MS2_PUBLIC int audio_stream_start_with_files (AudioStream * stream, RtpProfile *
/** /**
* Starts an audio stream from/to local wav files or soundcards. * Starts an audio stream from/to local wav files or soundcards.
* *
* This method starts the processing of the audio stream, that is playing from wav file or soundcard, voice processing, encoding, * This method starts the processing of the audio stream, that is playing from wav file or soundcard, voice processing, encoding,
* sending through RTP, receiving from RTP, decoding, voice processing and wav file recording or soundcard playback. * sending through RTP, receiving from RTP, decoding, voice processing and wav file recording or soundcard playback.
* *
* *
* @param stream an AudioStream previously created with audio_stream_new(). * @param stream an AudioStream previously created with audio_stream_new().
* @param prof a RtpProfile containing all PayloadType possible during the audio session. * @param prof a RtpProfile containing all PayloadType possible during the audio session.
* @param rem_rtp_ip remote IP address where to send the encoded audio. * @param rem_rtp_ip remote IP address where to send the encoded audio.
...@@ -362,16 +362,16 @@ MS2_PUBLIC AudioStream *audio_stream_new_with_sessions(const MSMediaStreamSessio ...@@ -362,16 +362,16 @@ MS2_PUBLIC AudioStream *audio_stream_new_with_sessions(const MSMediaStreamSessio
MS2_PUBLIC uint32_t audio_stream_get_features(AudioStream *st); MS2_PUBLIC uint32_t audio_stream_get_features(AudioStream *st);
MS2_PUBLIC void audio_stream_set_features(AudioStream *st, uint32_t features); MS2_PUBLIC void audio_stream_set_features(AudioStream *st, uint32_t features);
MS2_PUBLIC void audio_stream_prepare_sound(AudioStream *st, MSSndCard *playcard, MSSndCard *captcard); MS2_PUBLIC void audio_stream_prepare_sound(AudioStream *st, MSSndCard *playcard, MSSndCard *captcard);
MS2_PUBLIC void audio_stream_unprepare_sound(AudioStream *st); MS2_PUBLIC void audio_stream_unprepare_sound(AudioStream *st);
MS2_PUBLIC bool_t audio_stream_started(AudioStream *stream); MS2_PUBLIC bool_t audio_stream_started(AudioStream *stream);
/** /**
* Starts an audio stream from local soundcards. * Starts an audio stream from local soundcards.
* *
* This method starts the processing of the audio stream, that is capture from soundcard, voice processing, encoding, * This method starts the processing of the audio stream, that is capture from soundcard, voice processing, encoding,
* sending through RTP, receiving from RTP, decoding, voice processing and soundcard playback. * sending through RTP, receiving from RTP, decoding, voice processing and soundcard playback.
* *
* @param stream an AudioStream previously created with audio_stream_new(). * @param stream an AudioStream previously created with audio_stream_new().
* @param prof a RtpProfile containing all PayloadType possible during the audio session. * @param prof a RtpProfile containing all PayloadType possible during the audio session.
* @param remip remote IP address where to send the encoded audio. * @param remip remote IP address where to send the encoded audio.
......
...@@ -45,7 +45,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ...@@ -45,7 +45,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef MS_MINIMAL_MTU #ifndef MS_MINIMAL_MTU
/*this is used for determining the minimum size of recv buffers for RTP packets /*this is used for determining the minimum size of recv buffers for RTP packets
Keep 1500 for maximum interoparibility*/ Keep 1500 for maximum interoparibility*/
#define MS_MINIMAL_MTU 1500 #define MS_MINIMAL_MTU 1500
#endif #endif
...@@ -81,12 +81,12 @@ static void media_stream_change_decoder(MediaStream *stream, int payload) { ...@@ -81,12 +81,12 @@ static void media_stream_change_decoder(MediaStream *stream, int payload) {
RtpSession *session = stream->sessions.rtp_session; RtpSession *session = stream->sessions.rtp_session;
RtpProfile *prof = rtp_session_get_profile(session); RtpProfile *prof = rtp_session_get_profile(session);
PayloadType *pt = rtp_profile_get_payload(prof, payload); PayloadType *pt = rtp_profile_get_payload(prof, payload);
if (stream->decoder == NULL){ if (stream->decoder == NULL){
ms_message("media_stream_change_decoder(): ignored, no decoder."); ms_message("media_stream_change_decoder(): ignored, no decoder.");
return; return;
} }
if (pt != NULL){ if (pt != NULL){
MSFilter *dec; MSFilter *dec;
...@@ -226,7 +226,7 @@ void media_stream_free(MediaStream *stream) { ...@@ -226,7 +226,7 @@ void media_stream_free(MediaStream *stream) {
if (stream->decoder != NULL) ms_filter_destroy(stream->decoder); if (stream->decoder != NULL) ms_filter_destroy(stream->decoder);
if (stream->voidsink != NULL) ms_filter_destroy(stream->voidsink); if (stream->voidsink != NULL) ms_filter_destroy(stream->voidsink);
if (stream->qi) ms_quality_indicator_destroy(stream->qi); if (stream->qi) ms_quality_indicator_destroy(stream->qi);
} }
void media_stream_set_rtcp_information(MediaStream *stream, const char *cname, const char *tool) { void media_stream_set_rtcp_information(MediaStream *stream, const char *cname, const char *tool) {
...@@ -262,7 +262,7 @@ static int check_srtp_session_created(MediaStream *stream){ ...@@ -262,7 +262,7 @@ static int check_srtp_session_created(MediaStream *stream){
err_status_t err; err_status_t err;
srtp_t session; srtp_t session;
RtpTransport *rtp=NULL,*rtcp=NULL; RtpTransport *rtp=NULL,*rtcp=NULL;
err = ortp_srtp_create(&session, NULL); err = ortp_srtp_create(&session, NULL);
if (err != 0) { if (err != 0) {
ms_error("Failed to create srtp session (%d)", err); ms_error("Failed to create srtp session (%d)", err);
...@@ -284,9 +284,9 @@ static bool_t add_srtp_stream(srtp_t srtp, MSCryptoSuite suite, uint32_t ssrc, c ...@@ -284,9 +284,9 @@ static bool_t add_srtp_stream(srtp_t srtp, MSCryptoSuite suite, uint32_t ssrc, c
err_status_t err; err_status_t err;
unsigned b64_key_length = strlen(b64_key); unsigned b64_key_length = strlen(b64_key);
ssrc_t ssrc_conf; ssrc_t ssrc_conf;
memset(&policy,0,sizeof(policy)); memset(&policy,0,sizeof(policy));
switch(suite){ switch(suite){
case MS_AES_128_SHA1_32: case MS_AES_128_SHA1_32:
crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp); crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp);
...@@ -330,22 +330,22 @@ static bool_t add_srtp_stream(srtp_t srtp, MSCryptoSuite suite, uint32_t ssrc, c ...@@ -330,22 +330,22 @@ static bool_t add_srtp_stream(srtp_t srtp, MSCryptoSuite suite, uint32_t ssrc, c
} }
if (!inbound) if (!inbound)
policy.allow_repeat_tx=1; /*necessary for telephone-events*/ policy.allow_repeat_tx=1; /*necessary for telephone-events*/
/*ssrc_conf.type=inbound ? ssrc_any_inbound : ssrc_specific;*/ /*ssrc_conf.type=inbound ? ssrc_any_inbound : ssrc_specific;*/
ssrc_conf.type=ssrc_specific; ssrc_conf.type=ssrc_specific;
ssrc_conf.value=ssrc; ssrc_conf.value=ssrc;
policy.ssrc = ssrc_conf; policy.ssrc = ssrc_conf;
policy.key = key; policy.key = key;
policy.next = NULL; policy.next = NULL;
err = srtp_add_stream(srtp, &policy); err = srtp_add_stream(srtp, &policy);
if (err != err_status_ok) { if (err != err_status_ok) {
ortp_error("Failed to add stream to srtp session (%d)", err); ortp_error("Failed to add stream to srtp session (%d)", err);
ortp_free(key); ortp_free(key);
return -1; return -1;
} }
ortp_free(key); ortp_free(key);
return 0; return 0;
} }
...@@ -371,7 +371,7 @@ bool_t media_stream_srtp_supported(void){ ...@@ -371,7 +371,7 @@ bool_t media_stream_srtp_supported(void){
} }
int media_stream_set_srtp_recv_key(MediaStream *stream, MSCryptoSuite suite, const char* key){ int media_stream_set_srtp_recv_key(MediaStream *stream, MSCryptoSuite suite, const char* key){
if (!media_stream_srtp_supported()) { if (!media_stream_srtp_supported()) {
ms_error("ortp srtp support disabled in oRTP or mediastreamer2"); ms_error("ortp srtp support disabled in oRTP or mediastreamer2");
return -1; return -1;
...@@ -380,14 +380,14 @@ int media_stream_set_srtp_recv_key(MediaStream *stream, MSCryptoSuite suite, con ...@@ -380,14 +380,14 @@ int media_stream_set_srtp_recv_key(MediaStream *stream, MSCryptoSuite suite, con
{ {
uint32_t ssrc,send_ssrc; uint32_t ssrc,send_ssrc;
bool_t updated=FALSE; bool_t updated=FALSE;
if (check_srtp_session_created(stream)==-1) if (check_srtp_session_created(stream)==-1)
return -1; return -1;
/*check if a previous key was configured, in which case remove it*/ /*check if a previous key was configured, in which case remove it*/
send_ssrc=rtp_session_get_send_ssrc(stream->sessions.rtp_session); send_ssrc=rtp_session_get_send_ssrc(stream->sessions.rtp_session);
ssrc=find_other_ssrc(stream->sessions.srtp_session,htonl(send_ssrc)); ssrc=find_other_ssrc(stream->sessions.srtp_session,htonl(send_ssrc));
/*careful: remove_stream takes the SSRC in network byte order...*/ /*careful: remove_stream takes the SSRC in network byte order...*/
if (ortp_srtp_remove_stream(stream->sessions.srtp_session,ssrc)==0) if (ortp_srtp_remove_stream(stream->sessions.srtp_session,ssrc)==0)
updated=TRUE; updated=TRUE;
...@@ -401,20 +401,20 @@ int media_stream_set_srtp_recv_key(MediaStream *stream, MSCryptoSuite suite, con ...@@ -401,20 +401,20 @@ int media_stream_set_srtp_recv_key(MediaStream *stream, MSCryptoSuite suite, con
} }
int media_stream_set_srtp_send_key(MediaStream *stream, MSCryptoSuite suite, const char* key){ int media_stream_set_srtp_send_key(MediaStream *stream, MSCryptoSuite suite, const char* key){
if (!media_stream_srtp_supported()) { if (!media_stream_srtp_supported()) {
ms_error("ortp srtp support disabled in oRTP or mediastreamer2"); ms_error("ortp srtp support disabled in oRTP or mediastreamer2");
return -1; return -1;
} }
#ifdef ORTP_HAVE_SRTP #ifdef ORTP_HAVE_SRTP
{ {
uint32_t ssrc; uint32_t ssrc;
bool_t updated=FALSE; bool_t updated=FALSE;
if (check_srtp_session_created(stream)==-1) if (check_srtp_session_created(stream)==-1)
return -1; return -1;
/*check if a previous key was configured, in which case remove it*/ /*check if a previous key was configured, in which case remove it*/
ssrc=rtp_session_get_send_ssrc(stream->sessions.rtp_session); ssrc=rtp_session_get_send_ssrc(stream->sessions.rtp_session);
if (ssrc!=0){ if (ssrc!=0){
...@@ -465,7 +465,7 @@ void mediastream_payload_type_changed(RtpSession *session, unsigned long data) { ...@@ -465,7 +465,7 @@ void mediastream_payload_type_changed(RtpSession *session, unsigned long data) {
void media_stream_iterate(MediaStream *stream){ void media_stream_iterate(MediaStream *stream){
time_t curtime=ms_time(NULL); time_t curtime=ms_time(NULL);
if (stream->ice_check_list) ice_check_list_process(stream->ice_check_list,stream->sessions.rtp_session); if (stream->ice_check_list) ice_check_list_process(stream->ice_check_list,stream->sessions.rtp_session);
/*we choose to update the quality indicator as much as possible, since local statistics can be computed realtime. */ /*we choose to update the quality indicator as much as possible, since local statistics can be computed realtime. */
if (stream->state==MSStreamStarted){ if (stream->state==MSStreamStarted){
...@@ -483,7 +483,7 @@ void media_stream_iterate(MediaStream *stream){ ...@@ -483,7 +483,7 @@ void media_stream_iterate(MediaStream *stream){
OrtpEventType evt=ortp_event_get_type(ev); OrtpEventType evt=ortp_event_get_type(ev);
if (evt==ORTP_EVENT_RTCP_PACKET_RECEIVED){ if (evt==ORTP_EVENT_RTCP_PACKET_RECEIVED){
mblk_t *m=ortp_event_get_data(ev)->packet; mblk_t *m=ortp_event_get_data(ev)->packet;
ms_message("%s stream [%p]: receiving RTCP %s%s",media_stream_type_str(stream),stream,(rtcp_is_SR(m)?"SR":""),(rtcp_is_RR(m)?"RR":"")); ms_message("%s_stream_iterate[%p]: receiving [%p] RTCP %s%s",media_stream_type_str(stream),stream,m,(rtcp_is_SR(m)?"SR":""),(rtcp_is_RR(m)?"RR":""));
stream->process_rtcp(stream,m); stream->process_rtcp(stream,m);
}else if (evt==ORTP_EVENT_RTCP_PACKET_EMITTED){ }else if (evt==ORTP_EVENT_RTCP_PACKET_EMITTED){
ms_message("%s_stream_iterate[%p]: local statistics available\n\tLocal's current jitter buffer size:%f ms", ms_message("%s_stream_iterate[%p]: local statistics available\n\tLocal's current jitter buffer size:%f ms",
...@@ -493,7 +493,7 @@ void media_stream_iterate(MediaStream *stream){ ...@@ -493,7 +493,7 @@ void media_stream_iterate(MediaStream *stream){
} else if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED) { } else if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED) {
OrtpEventData *evd=ortp_event_get_data(ev); OrtpEventData *evd=ortp_event_get_data(ev);
stream->sessions.is_secured=evd->info.zrtp_stream_encrypted; stream->sessions.is_secured=evd->info.zrtp_stream_encrypted;
ms_message("%s stream [%p] is %s ",media_stream_type_str(stream) , stream, stream->sessions.is_secured ? "encrypted" : "not encrypted"); ms_message("%s_stream_iterate[%p]: is %s ",media_stream_type_str(stream) , stream, stream->sessions.is_secured ? "encrypted" : "not encrypted");
} }
ortp_event_destroy(ev); ortp_event_destroy(ev);
} }
......
...@@ -24,40 +24,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ...@@ -24,40 +24,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <math.h> #include <math.h>
/**
* Compute the linear interpolation y = m * x + b for a given set of points.
* m is the line slope, b the y-intercept value and x_inter the x-intrecept value
* Returns 1 if x intersection could not be calculated, 0 otherwise
**/
// static int linear_regression(int n, const double x[], const double y[], double* m, double* b, double* x_inter)
// {
// int i;
// double x_sum = 0.;
// double y_sum = 0.;
// double x_square_sum = 0.;
// double x_y_sum = 0.;
// for (i = 0; i < n; i++) {
// x_sum += x[i];
// y_sum += y[i];
// x_y_sum += x[i] * y[i];
// x_square_sum += (x[i]) * (x[i]);
// }
// x_sum /= n;
// y_sum /= n;
// *m = (x_y_sum - x_sum * y_sum * n) /
// (x_square_sum - x_sum * x_sum * n);
// *b = (y_sum - *m * x_sum);
// if (fabs(*m) > 0.000001f) {
// *x_inter = - *b / *m;
// return 0;
// }
// return 1;
// }
/** /**
* Analyses a received RTCP packet. * Analyses a received RTCP packet.
* Returns TRUE is relevant information has been found in the rtcp message, FALSE otherwise. * Returns TRUE is relevant information has been found in the rtcp message, FALSE otherwise.
...@@ -138,14 +104,14 @@ typedef struct _MSSimpleQosAnalyser{ ...@@ -138,14 +104,14 @@ typedef struct _MSSimpleQosAnalyser{
bool_t rt_prop_doubled; bool_t rt_prop_doubled;
bool_t pad[3]; bool_t pad[3];
double points[150][2]; double points[150][3];
bool_t stable_network; uint8_t network_state;
}MSSimpleQosAnalyser; }MSSimpleQosAnalyser;
static bool_t rt_prop_doubled(rtpstats_t *cur,rtpstats_t *prev){ static bool_t rt_prop_doubled(rtpstats_t *cur,rtpstats_t *prev){
//ms_message("AudioBitrateController: cur=%f, prev=%f",cur->rt_prop,prev->rt_prop); /*ms_message("AudioBitrateController: cur=%f, prev=%f",cur->rt_prop,prev->rt_prop);*/
if (cur->rt_prop>=significant_delay && prev->rt_prop>0){ if (cur->rt_prop>=significant_delay && prev->rt_prop>0){
if (cur->rt_prop>=(prev->rt_prop*2.0)){ if (cur->rt_prop>=(prev->rt_prop*2.0)){
/*propagation doubled since last report */ /*propagation doubled since last report */
...@@ -166,7 +132,6 @@ static bool_t rt_prop_increased(MSSimpleQosAnalyser *obj){ ...@@ -166,7 +132,6 @@ static bool_t rt_prop_increased(MSSimpleQosAnalyser *obj){
return FALSE; return FALSE;
} }
static bool_t simple_analyser_process_rtcp(MSQosAnalyser *objbase, mblk_t *rtcp){ static bool_t simple_analyser_process_rtcp(MSQosAnalyser *objbase, mblk_t *rtcp){
MSSimpleQosAnalyser *obj=(MSSimpleQosAnalyser*)objbase; MSSimpleQosAnalyser *obj=(MSSimpleQosAnalyser*)objbase;
rtpstats_t *cur; rtpstats_t *cur;
...@@ -191,8 +156,10 @@ static bool_t simple_analyser_process_rtcp(MSQosAnalyser *objbase, mblk_t *rtcp) ...@@ -191,8 +156,10 @@ static bool_t simple_analyser_process_rtcp(MSQosAnalyser *objbase, mblk_t *rtcp)
cur->lost_percentage=100.0*(float)report_block_get_fraction_lost(rb)/256.0; cur->lost_percentage=100.0*(float)report_block_get_fraction_lost(rb)/256.0;
cur->int_jitter=1000.0*(float)report_block_get_interarrival_jitter(rb)/(float)obj->clockrate; cur->int_jitter=1000.0*(float)report_block_get_interarrival_jitter(rb)/(float)obj->clockrate;
cur->rt_prop=rtp_session_get_round_trip_propagation(obj->session); cur->rt_prop=rtp_session_get_round_trip_propagation(obj->session);
obj->points[obj->curindex-1][0]=rtp_session_get_send_bandwidth(obj->session)/1000.0; obj->points[obj->curindex-1][0]=rtp_session_get_send_bandwidth(obj->session)/1000.0;
obj->points[obj->curindex-1][1]=(float)report_block_get_fraction_lost(rb)/256.0; obj->points[obj->curindex-1][1]=cur->lost_percentage;
obj->points[obj->curindex-1][2]=cur->rt_prop;
ms_message("MSQosAnalyser: lost_percentage=%f, int_jitter=%f ms, rt_prop=%f sec, send_bw=%f",cur->lost_percentage,cur->int_jitter,cur->rt_prop,obj->points[obj->curindex][0]); ms_message("MSQosAnalyser: lost_percentage=%f, int_jitter=%f ms, rt_prop=%f sec, send_bw=%f",cur->lost_percentage,cur->int_jitter,cur->rt_prop,obj->points[obj->curindex][0]);
if (obj->curindex>2) printf("one more %d: %f %f\n", obj->curindex-1, obj->points[obj->curindex-1][0], obj->points[obj->curindex-1][1]); if (obj->curindex>2) printf("one more %d: %f %f\n", obj->curindex-1, obj->points[obj->curindex-1][0], obj->points[obj->curindex-1][1]);
...@@ -202,74 +169,100 @@ static bool_t simple_analyser_process_rtcp(MSQosAnalyser *objbase, mblk_t *rtcp) ...@@ -202,74 +169,100 @@ static bool_t simple_analyser_process_rtcp(MSQosAnalyser *objbase, mblk_t *rtcp)
static void compute_available_bw(MSSimpleQosAnalyser *obj){ static void compute_available_bw(MSSimpleQosAnalyser *obj){
int i; int i;
double x_sum = 0.; double x_mean = 0.;
double y_sum = 0.; double y_mean = 0.;
double x_square_sum = 0.; double x_square_sum = 0.;
double x_y_sum = 0.; double x_y_sum = 0.;
int last = obj->curindex - 1; int last = obj->curindex - 1;
int f = last > 15 ? last - 13 : 2; //always skip the 2 first ones int f = last > 15 ? last - 13 : 2; //always skip the 2 first ones
int n = (last - f + 1); int n = (last - f + 1);
double mean_bw = 0.;
double mean_diff = 0.;
int x_min_ind = f;
int x_max_ind = f;
bool_t lossy_network = FALSE;
double diff, m, b;
uint8_t previous_state = obj->network_state;
obj->network_state = MS_QOS_ANALYSER_NETWORK_FINE;
if (n <= 1) { if (n <= 1) {
printf("Estimated BW is %f kbit/s\n", obj->points[0][0] * obj->points[0][1]); printf("Estimated BW is %f kbit/s\n", obj->points[0][0] * obj->points[0][1]);
return; return;
} }
int count = n;//(last - f) * (last - f + 1) / 2;
double mean_bw = 0.;
double avg_dist = 0.;
int x_min_ind = f;
int x_max_ind = f;
for (i = f; i <= last; i++) { for (i = f; i <= last; i++) {
double x = obj->points[i][0]; double x = obj->points[i][0];
double y = obj->points[i][1]; double y = obj->points[i][1];
if (x < obj->points[x_min_ind][0]) x_min_ind = i; if (x < obj->points[x_min_ind][0]) x_min_ind = i;
if (x > obj->points[x_max_ind][0]) x_max_ind = i; if (x > obj->points[x_max_ind][0]) x_max_ind = i;
double mul = 1;// (i - f + 1);
// printf("\tadding (%f;%f) of weight %f\n", x, y, mul); x_mean += x;
x_sum += x * mul; y_mean += y;
y_sum += y * mul; x_y_sum += x * y;
x_y_sum += x * y * mul * mul; x_square_sum += x * x;
x_square_sum += x * x * mul * mul;
mean_bw += x * (1 - y); mean_bw += x * (1 - y);
} }
x_sum /= count; x_mean /= n;
y_sum /= count; y_mean /= n;
mean_bw /= count; mean_bw /= n;
printf("\tEstimated BW by avg is %f kbit/s\n", mean_bw); printf("\tEstimated BW by avg is %f kbit/s\n", mean_bw);
printf("sum=%f xmin=%d xmax=%d\n", x_sum, x_min_ind, x_max_ind); printf("sum=%f xmin=%d xmax=%d\n", x_mean, x_min_ind, x_max_ind);
double diff = (obj->points[x_max_ind][0] - obj->points[x_min_ind][0]) / x_sum; diff = (obj->points[x_max_ind][0] - obj->points[x_min_ind][0]) / x_mean;
m = (x_y_sum - x_mean * y_mean * n) /
(x_square_sum - x_mean * x_mean * n);
double m = (x_y_sum - x_sum * y_sum * count) / b = (y_mean - m * x_mean);
(x_square_sum - x_sum * x_sum * count);
double b = (y_sum - m * x_sum);
for (i = f; i <= last; i++) { for (i = f; i <= last; i++) {
double x = obj->points[i][0]; double x = obj->points[i][0];
double y = obj->points[i][1]; double y = obj->points[i][1];
avg_dist += fabs(m * x + b - y); mean_diff += fabs(m * x + b - y);
} }
avg_dist /= count; mean_diff /= n;
bool_t lossy_network = avg_dist > .1; /*to compute estimated BW, we need a minimum x-axis interval size*/
// to compute estimated BW, we need a minimum sample size
if (diff > 0.05) { if (diff > 0.05) {
double avail_bw = (fabs(m) > 0.0001f) ? - b / m : mean_bw; double avail_bw = (fabs(m) > 0.0001f) ? -b/m : mean_bw;
printf("\tfor line is %f kbit/s\n", avail_bw); printf("\tfor line is %f kbit/s:\ty=%f x + %f\n", avail_bw, m, b);
printf("\t\ty=%f x + %f\n", m, b);
lossy_network |= (m < .03f && b > 0.05); lossy_network |= (m < .03f && b > 0.05);
if (!lossy_network && (m>.03f||b>0.05)){
obj->network_state = MS_QOS_ANALYSER_NETWORK_CONGESTED;
}
} else { } else {
printf("\tinsufficient difference between BW min and BW max: %f\n", diff); lossy_network |= (y_mean > 0.05);
}
if (lossy_network) {
/*since congestion may loss a high count of packets, stay in congested network while
this is not a bit more stable*/
if (previous_state == MS_QOS_ANALYSER_NETWORK_CONGESTED) {
obj->network_state = MS_QOS_ANALYSER_NETWORK_CONGESTED;
} else {
obj->network_state = MS_QOS_ANALYSER_NETWORK_UNSTABLE;
}
/*another hint for a bad network: packets drop mean difference is high*/
} else if (mean_diff > .1) {
double rtt = obj->points[last][2];
obj->network_state = (rtt > .5) ? MS_QOS_ANALYSER_NETWORK_CONGESTED : MS_QOS_ANALYSER_NETWORK_UNSTABLE;
} }
printf("\tavg_dist=%f\n", avg_dist);
printf("\t\tI think it is a %s network\n", lossy_network ? "LOSSY/UNSTABLE" : "stable"); if (obj->network_state == MS_QOS_ANALYSER_NETWORK_CONGESTED)
obj->stable_network = !lossy_network; printf("\t\tI think it is a %s network\n", "C-O-N-G-E-S-T-E-D");
else if (obj->network_state == MS_QOS_ANALYSER_NETWORK_UNSTABLE)
printf("\t\tI think it is a %s network\n", "UNSTABLE");
else
printf("\t\tI think it is a %s network\n", "stable");
} }
static void simple_analyser_suggest_action(MSQosAnalyser *objbase, MSRateControlAction *action){ static void simple_analyser_suggest_action(MSQosAnalyser *objbase, MSRateControlAction *action){
...@@ -315,9 +308,9 @@ end: ...@@ -315,9 +308,9 @@ end:
return FALSE; return FALSE;
} }
bool_t ms_qos_analyser_is_network_stable(const MSQosAnalyser *objbase){ uint32_t ms_qos_analyser_get_network_state(const MSQosAnalyser *objbase){
MSSimpleQosAnalyser *obj=(MSSimpleQosAnalyser*)objbase; MSSimpleQosAnalyser *obj=(MSSimpleQosAnalyser*)objbase;
return obj->stable_network; return obj->network_state;
}