Commit 85e2748d authored by Simon Morlat's avatar Simon Morlat

global rate control in development

parent 1211a897
......@@ -34,6 +34,61 @@ extern "C" {
typedef struct _MSAudioBitrateController MSAudioBitrateController;
enum MSRateControlActionType{
MSRateControlActionDoNothing,
MSRateControlActionDecreaseBitrate,
MSRateControlActionDecreasePacketRate,
MSRateControlActionIncreaseQuality
};
typedef struct _MSRateControlAction{
enum MSRateControlActionType type;
int value;
}MSRateControlAction;
typedef struct _MSBitrateDriver MSBitrateDriver;
typedef struct _MSBitrateDriverDesc MSBitrateDriverDesc;
struct _MSBitrateDriverDesc{
void (*execute_action)(MSBitrateDriver *obj, const MSRateControlAction *action);
void (*uninit)(MSBitrateDriver *obj);
};
/*
* The MSBitrateDriver has the responsability to execute rate control actions.
* This is an abstract interface.
**/
struct _MSBitrateDriver{
MSBitrateDriverDesc *desc;
};
void ms_bitrate_driver_execute_action(MSBitrateDriver *obj, const MSRateControlAction *action);
void ms_bitrate_driver_destroy(MSBitrateDriver *obj);
typedef struct _MSQosAnalyser MSQosAnalyser;
typedef struct _MSQosAnalyserDesc MSQosAnalyserDesc;
struct _MSQosAnalyserDesc{
bool_t (*process_rtcp)(MSQosAnalyzer *obj, mblk_t *rtcp);
void (*suggest_action)(MSQosAnalyzer *obj, MSRateControlAction *action);
bool_t (*has_improved)(MSQosAnalyzer *obj);
void uninit(MSQosAnalyzer);
};
/**
* A MSQosAnalyzer is responsible to analyze RTCP feedback and suggest actions on bitrate or packet rate accordingly.
* This is an abstract interface.
**/
struct _MSQosAnalyser{
MSQosAnalyserDesc *desc;
};
/**
* The simple qos analyzer is an implementation of MSQosAnalizer that performs analysis for single stream.
**/
MSQosAnalyzer * ms_simple_qos_analyser_new(RtpSession *session);
#define MS_AUDIO_RATE_CONTROL_OPTIMIZE_QUALITY (1)
#define MS_AUDIO_RATE_CONTROL_OPTIMIZE_LATENCY (1<<1)
......@@ -43,6 +98,7 @@ void ms_audio_bitrate_controller_process_rtcp(MSAudioBitrateController *obj, mbl
void ms_audio_bitrate_controller_destroy(MSAudioBitrateController *obj);
#ifdef __cplusplus
}
#endif
......
......@@ -3,6 +3,8 @@ mediastreamer2 library - modular sound and video processing and streaming
* Copyright (C) 2011 Belledonne Communications, Grenoble, France
Author: Simon Morlat <simon.morlat@linphone.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
......@@ -20,12 +22,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mediastreamer2/bitratecontrol.h"
#define STATS_HISTORY 3
static const float unacceptable_loss_rate=20;
static const int big_jitter=20; /*ms */
static const float significant_delay=0.2; /*seconds*/
static const int max_ptime=100;
enum state_t{
Init,
......@@ -44,206 +40,30 @@ const char *state_name(enum state_t st){
return "bad state";
}
typedef struct rtpstats{
uint64_t high_seq_recv; /*highest sequence number received*/
float lost_percentage; /*percentage of lost packet since last report*/
float int_jitter; /*interrarrival jitter */
float rt_prop; /*round trip propagation*/
}rtpstats_t;
enum action_type{
DoNothing,
DecreaseBitrate,
DecreasePacketRate,
IncreaseQuality
};
static const char *action_type_name(enum action_type t){
switch(t){
case DoNothing:
return "DoNothing";
case IncreaseQuality:
return "IncreaseQuality";
case DecreaseBitrate:
return "DecreaseBitrate";
case DecreasePacketRate:
return "DecreasePacketRate";
}
return "bad action type";
}
typedef struct action{
enum action_type type;
int value;
}action_t;
struct _MSAudioBitrateController{
QosAnalyser analyzer;
RtpSession *session;
MSFilter *encoder;
int clockrate;
rtpstats_t stats[STATS_HISTORY];
int curindex;
enum state_t state;
int min_ptime;
int nom_bitrate;
int cur_ptime;
int cur_bitrate;
int stable_count;
int probing_up_count;
bool_t rt_prop_doubled;
};
MSAudioBitrateController *ms_audio_bitrate_controller_new(RtpSession *session, MSFilter *encoder, unsigned int flags){
MSAudioBitrateController *rc=ms_new0(MSAudioBitrateController,1);
rc->session=session;
rc->encoder=encoder;
rc->cur_ptime=rc->min_ptime=20;
rc->cur_bitrate=rc->nom_bitrate=0;
ms_qos_analyser_init(&rc->analyser,session);
return rc;
}
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);
if (cur->rt_prop>=significant_delay && prev->rt_prop>0){
if (cur->rt_prop>=(prev->rt_prop*2.0)){
/*propagation doubled since last report */
return TRUE;
}
}
return FALSE;
}
static bool_t rt_prop_increased(MSAudioBitrateController *obj){
rtpstats_t *cur=&obj->stats[obj->curindex % STATS_HISTORY];
rtpstats_t *prev=&obj->stats[(STATS_HISTORY+obj->curindex-1) % STATS_HISTORY];
if (rt_prop_doubled(cur,prev)){
obj->rt_prop_doubled=TRUE;
return TRUE;
}
return FALSE;
}
static void analyse_quality(MSAudioBitrateController *obj, action_t *action){
rtpstats_t *cur=&obj->stats[obj->curindex % STATS_HISTORY];
/*big losses and big jitter */
if (cur->lost_percentage>=unacceptable_loss_rate && cur->int_jitter>=big_jitter){
action->type=DecreaseBitrate;
action->value=MIN(cur->lost_percentage,50);
ms_message("AudioBitrateController: analyse - loss rate unacceptable and big jitter");
}else if (rt_prop_increased(obj)){
action->type=DecreaseBitrate;
action->value=20;
ms_message("AudioBitrateController: analyse - rt_prop doubled.");
}else if (cur->lost_percentage>=unacceptable_loss_rate){
/*big loss rate but no jitter, and no big rtp_prop: pure lossy network*/
action->type=DecreasePacketRate;
ms_message("AudioBitrateController: analyse - loss rate unacceptable.");
}else{
action->type=DoNothing;
ms_message("AudioBitrateController: analyse - everything is fine.");
}
}
static bool_t has_improved(MSAudioBitrateController *obj){
rtpstats_t *cur=&obj->stats[obj->curindex % STATS_HISTORY];
rtpstats_t *prev=&obj->stats[(STATS_HISTORY+obj->curindex-1) % STATS_HISTORY];
if (prev->lost_percentage>=unacceptable_loss_rate){
if (cur->lost_percentage<prev->lost_percentage){
ms_message("AudioBitrateController: lost percentage has improved");
return TRUE;
}else goto end;
}
if (obj->rt_prop_doubled && cur->rt_prop<prev->rt_prop){
ms_message("AudioBitrateController: rt prop decrased");
obj->rt_prop_doubled=FALSE;
return TRUE;
}
end:
ms_message("AudioBitrateController: no improvements.");
return FALSE;
}
static void apply_ptime(MSAudioBitrateController *obj){
char tmp[64];
snprintf(tmp,sizeof(tmp),"ptime=%i",obj->cur_ptime);
if (ms_filter_call_method(obj->encoder,MS_FILTER_ADD_FMTP,tmp)!=0){
ms_message("AudioBitrateController: failed ptime command.");
}else ms_message("AudioBitrateController: ptime changed to %i",obj->cur_ptime);
}
static int inc_ptime(MSAudioBitrateController *obj){
if (obj->cur_ptime>=max_ptime){
ms_message("AudioBitrateController: maximum ptime reached");
return -1;
}
obj->cur_ptime+=obj->min_ptime;
apply_ptime(obj);
return 0;
}
static int execute_action(MSAudioBitrateController *obj, action_t *action){
ms_message("AudioBitrateController: executing action of type %s, value=%i",action_type_name(action->type),action->value);
if (action->type==DecreaseBitrate){
/*reducing bitrate of the codec actually doesn't work very well (not enough). Increasing ptime is much more efficient*/
if (inc_ptime(obj)==-1){
if (obj->nom_bitrate>0){
int cur_br=0;
int new_br;
if (obj->nom_bitrate==0){
if (ms_filter_call_method(obj->encoder,MS_FILTER_GET_BITRATE,&obj->nom_bitrate)!=0){
ms_message("Encoder has nominal bitrate %i",obj->nom_bitrate);
}
obj->cur_bitrate=obj->nom_bitrate;
}
/*if max ptime is reached, then try to reduce the codec bitrate if possible */
if (ms_filter_call_method(obj->encoder,MS_FILTER_GET_BITRATE,&cur_br)!=0){
ms_message("AudioBitrateController: GET_BITRATE failed");
return 0;
}
new_br=cur_br-((cur_br*action->value)/100);
ms_message("AudioBitrateController: Attempting to reduce audio bitrate to %i",new_br);
if (ms_filter_call_method(obj->encoder,MS_FILTER_SET_BITRATE,&new_br)!=0){
ms_message("AudioBitrateController: SET_BITRATE failed, incrementing ptime");
inc_ptime(obj);
return 0;
}
new_br=0;
ms_filter_call_method(obj->encoder,MS_FILTER_GET_BITRATE,&new_br);
ms_message("AudioBitrateController: bitrate actually set to %i",new_br);
obj->cur_bitrate=new_br;
}
}
}else if (action->type==DecreasePacketRate){
inc_ptime(obj);
}else if (action->type==IncreaseQuality){
if (obj->cur_bitrate<obj->nom_bitrate){
ms_message("Increasing bitrate of codec");
if (ms_filter_call_method(obj->encoder,MS_FILTER_SET_BITRATE,&obj->nom_bitrate)!=0){
ms_message("AudioBitrateController: could not restore nominal codec bitrate (%i)",obj->nom_bitrate);
}else obj->cur_bitrate=obj->nom_bitrate;
}else if (obj->cur_ptime>obj->min_ptime){
obj->cur_ptime-=obj->min_ptime;
apply_ptime(obj);
}else return -1;
}
return 0;
}
static void state_machine(MSAudioBitrateController *obj){
action_t action;
switch(obj->state){
case Stable:
obj->stable_count++;
case Init:
analyse_quality(obj,&action);
ms_qos_analyser_suggest_action(&obj->analyser,&action);
if (action.type!=DoNothing){
execute_action(obj,&action);
obj->state=Probing;
......@@ -259,7 +79,7 @@ static void state_machine(MSAudioBitrateController *obj){
if (has_improved(obj)){
obj->state=Stable;
}else{
analyse_quality(obj,&action);
ms_qos_analyser_suggest_action(&obj->analyser,&action);
if (action.type!=DoNothing){
execute_action(obj,&action);
}
......@@ -268,7 +88,7 @@ static void state_machine(MSAudioBitrateController *obj){
case ProbingUp:
obj->stable_count=0;
obj->probing_up_count++;
analyse_quality(obj,&action);
ms_qos_analyser_suggest_action(&obj->analyser,&action);
if (action.type!=DoNothing){
execute_action(obj,&action);
obj->state=Probing;
......@@ -290,34 +110,10 @@ static void state_machine(MSAudioBitrateController *obj){
ms_message("AudioBitrateController: current state is %s",state_name(obj->state));
}
static void read_report(MSAudioBitrateController *obj, const report_block_t *rb){
rtpstats_t *cur;
obj->curindex++;
cur=&obj->stats[obj->curindex % STATS_HISTORY];
if (obj->clockrate==0){
PayloadType *pt=rtp_profile_get_payload(rtp_session_get_send_profile(obj->session),rtp_session_get_send_payload_type(obj->session));
if (pt!=NULL) obj->clockrate=pt->clock_rate;
else return;
}
cur->high_seq_recv=report_block_get_high_ext_seq(rb);
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->rt_prop=rtp_session_get_round_trip_propagation(obj->session);
ms_message("AudioBitrateController: lost_percentage=%f, int_jitter=%f ms, rt_prop=%f sec",cur->lost_percentage,cur->int_jitter,cur->rt_prop);
}
void ms_audio_bitrate_controller_process_rtcp(MSAudioBitrateController *obj, mblk_t *rtcp){
const report_block_t *rb=NULL;
if (rtcp_is_SR(rtcp)){
rb=rtcp_SR_get_report_block(rtcp,0);
}else if (rtcp_is_RR(rtcp)){
rb=rtcp_RR_get_report_block(rtcp,0);
}
if (rb){
read_report(obj,rb);
if (ms_qos_analyser_process_rtcp(&obj->analyser,rtcp)){
state_machine(obj);
}
}
......
/*
mediastreamer2 library - modular sound and video processing and streaming
* Copyright (C) 2011 Belledonne Communications, Grenoble, France
Author: Simon Morlat <simon.morlat@linphone.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "mediastreamer2/bitratecontrol.h"
void ms_bitrate_driver_execute_action(MSBitrateDriver *obj, const MSRateControlAction *action){
if (obj->desc->execute_action)
obj->desc->execute_action(obj,action);
else ms_error("Driver does not implement execute_action");
}
void ms_bitrate_driver_destroy(MSBitrateDriver *obj){
if (obj->desc->uninit)
obj->desc->uninit(obj);
ms_free(obj);
}
struct _MSAudioBitrateDriver{
MSBitrateDriver parent;
int min_ptime;
int nom_bitrate;
int cur_ptime;
int cur_bitrate;
};
typedef struct _MSAudioBitrateDriver MSAudioBitrateDriver;
static void apply_ptime(MSAudioBitrateDriver *obj){
char tmp[64];
snprintf(tmp,sizeof(tmp),"ptime=%i",obj->cur_ptime);
if (ms_filter_call_method(obj->encoder,MS_FILTER_ADD_FMTP,tmp)!=0){
ms_message("AudioBitrateController: failed ptime command.");
}else ms_message("AudioBitrateController: ptime changed to %i",obj->cur_ptime);
}
static int inc_ptime(MSAudioBitrateDriver *obj){
if (obj->cur_ptime>=max_ptime){
ms_message("AudioBitrateController: maximum ptime reached");
return -1;
}
obj->cur_ptime+=obj->min_ptime;
apply_ptime(obj);
return 0;
}
static int audio_bitrate_driver_execute_action(MSBitrateDriver *objbase, MSRateControlAction *action){
MSAudioBitrateDriver *obj=(MSBitrateDriver*)objbase;
ms_message("MSAudioBitrateDriver: executing action of type %s, value=%i",action_type_name(action->type),action->value);
if (action->type==MSRateControlActionDecreaseBitrate){
/*reducing bitrate of the codec actually doesn't work very well (not enough). Increasing ptime is much more efficient*/
if (inc_ptime(obj)==-1){
if (obj->nom_bitrate>0){
int cur_br=0;
int new_br;
if (obj->nom_bitrate==0){
if (ms_filter_call_method(obj->encoder,MS_FILTER_GET_BITRATE,&obj->nom_bitrate)!=0){
ms_message("MSAudioBitrateDriver: Encoder has nominal bitrate %i",obj->nom_bitrate);
}
obj->cur_bitrate=obj->nom_bitrate;
}
/*if max ptime is reached, then try to reduce the codec bitrate if possible */
if (ms_filter_call_method(obj->encoder,MS_FILTER_GET_BITRATE,&cur_br)!=0){
ms_message("AudioBitrateController: GET_BITRATE failed");
return 0;
}
new_br=cur_br-((cur_br*action->value)/100);
ms_message("MSAudioBitrateDriver: Attempting to reduce audio bitrate to %i",new_br);
if (ms_filter_call_method(obj->encoder,MS_FILTER_SET_BITRATE,&new_br)!=0){
ms_message("MSAudioBitrateDriver: SET_BITRATE failed, incrementing ptime");
inc_ptime(obj);
return 0;
}
new_br=0;
ms_filter_call_method(obj->encoder,MS_FILTER_GET_BITRATE,&new_br);
ms_message("MSAudioBitrateDriver: bitrate actually set to %i",new_br);
obj->cur_bitrate=new_br;
}
}
}else if (action->type==MSRateControlActionDecreasePacketRate){
inc_ptime(obj);
}else if (action->type==MSRateControlActionIncreaseQuality){
if (obj->cur_bitrate<obj->nom_bitrate){
ms_message("MSAudioBitrateDriver: increasing bitrate of codec");
if (ms_filter_call_method(obj->encoder,MS_FILTER_SET_BITRATE,&obj->nom_bitrate)!=0){
ms_message("MSAudioBitrateDriver: could not restore nominal codec bitrate (%i)",obj->nom_bitrate);
}else obj->cur_bitrate=obj->nom_bitrate;
}else if (obj->cur_ptime>obj->min_ptime){
obj->cur_ptime-=obj->min_ptime;
apply_ptime(obj);
}else return -1;
}
return 0;
}
static void audio_bitrate_driver_uninit(MSBitrateDriver *objbase){
//MSAudioBitrateDriver *obj=(MSBitrateDriver*)objbase;
}
static MSBitrateDriverDesc audio_bitrate_driver={
audio_bitrate_driver_execute_action,
audio_bitrate_driver_uninit
};
MSBitrateDriver *ms_audio_bitrate_driver_new(MSFilter *encoder){
MSAudioBitrateDriver *obj=ms_new0(MSAudioBitrateDriver,1);
obj->encoder=encoder;
obj->cur_ptime=obj->min_ptime=20;
obj->cur_bitrate=obj->nom_bitrate=0;
return obj;
}
/*
mediastreamer2 library - modular sound and video processing and streaming
* Copyright (C) 2011 Belledonne Communications, Grenoble, France
Author: Simon Morlat <simon.morlat@linphone.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "mediastreamer2/bitratecontrol.h"
/**
* Analyses a received RTCP packet.
* Returns TRUE is relevant information has been found in the rtcp message, FALSE otherwise.
**/
bool_t ms_qos_analyzer_process_rtcp(MSQosAnalyzer *obj,mblk_t *msg){
if (obj->desc->process_rtcp){
return obj->desc->process_rtcp(obj,msg);
}
ms_error("Unimplemented process_rtcp() call.");
return FALSE;
}
void ms_qos_analyser_suggest_action(MSQosAnalyzer *obj, MSRateControlActionType *action){
if (obj->desc->suggest_action){
obj->desc->suggest_action(obj,action);
}
return;
}
bool_t ms_qos_analyzer_has_improved(MSQosAnalyzer *obj){
if (obj->desc->has_improved){
return obj->desc->has_improved(obj,action);
}
ms_error("Unimplemented has_improved() call.");
return TRUE;
}
void ms_qos_analyzer_destroy(MSQosAnalyzer *obj){
if (obj->desc->uninit)
obj->desc->uninit(obj);
ms_free(obj);
}
#define STATS_HISTORY 3
static const float unacceptable_loss_rate=20;
static const int big_jitter=20; /*ms */
static const float significant_delay=0.2; /*seconds*/
static const int max_ptime=100;
typedef struct rtpstats{
uint64_t high_seq_recv; /*highest sequence number received*/
float lost_percentage; /*percentage of lost packet since last report*/
float int_jitter; /*interrarrival jitter */
float rt_prop; /*round trip propagation*/
}rtpstats_t;
static const char *action_type_name(enum MSRateControlActionType t){
switch(t){
case MSRateControlActionDoNothing:
return "DoNothing";
case MSRateControlActionIncreaseQuality:
return "IncreaseQuality";
case MSRateControlActionDecreaseBitrate:
return "DecreaseBitrate";
case MSRateControlActionDecreasePacketRate:
return "DecreasePacketRate";
}
return "bad action type";
}
typedef struct _MSSimpleQosAnalyser{
MSQosAnalyzer parent;
RtpSession *session;
int clockrate;
rtpstats_t stats[STATS_HISTORY];
int curindex;
bool_t rt_prop_doubled;
bool_t pad[3];
}MSQosAnalyser;
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);
if (cur->rt_prop>=significant_delay && prev->rt_prop>0){
if (cur->rt_prop>=(prev->rt_prop*2.0)){
/*propagation doubled since last report */
return TRUE;
}
}
return FALSE;
}
static bool_t rt_prop_increased(MSSimpleQosAnalyzer *obj){
rtpstats_t *cur=&obj->stats[obj->curindex % STATS_HISTORY];
rtpstats_t *prev=&obj->stats[(STATS_HISTORY+obj->curindex-1) % STATS_HISTORY];
if (rt_prop_doubled(cur,prev)){
obj->rt_prop_doubled=TRUE;
return TRUE;
}
return FALSE;
}
static bool_t simple_analyser_process_rtcp(MSQosAnalyser *objbase, mblk_t *rtcp){
MSSimpleQosAnalyzer *obj=(MSSimpleQosAnalyzer*)objbase;
rtpstats_t *cur;
const report_block_t *rb=NULL;
if (rtcp_is_SR(rtcp)){
rb=rtcp_SR_get_report_block(rtcp,0);
}else if (rtcp_is_RR(rtcp)){
rb=rtcp_RR_get_report_block(rtcp,0);
}
if (rb){
obj->curindex++;
cur=&obj->stats[obj->curindex % STATS_HISTORY];
if (obj->clockrate==0){
PayloadType *pt=rtp_profile_get_payload(rtp_session_get_send_profile(obj->session),rtp_session_get_send_payload_type(obj->session));
if (pt!=NULL) obj->clockrate=pt->clock_rate;
else return FALSE;
}
cur->high_seq_recv=report_block_get_high_ext_seq(rb);
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->rt_prop=rtp_session_get_round_trip_propagation(obj->session);
ms_message("MSQosAnalyser: lost_percentage=%f, int_jitter=%f ms, rt_prop=%f sec",cur->lost_percentage,cur->int_jitter,cur->rt_prop);
}
return rb!=NULL;
}
static void simple_analyser_suggest_action(MSQosAnalyser *objbase, MSRateControlActionType *action){
MSSimpleQosAnalyzer *obj=(MSSimpleQosAnalyzer*)objbase;
rtpstats_t *cur=&obj->stats[obj->curindex % STATS_HISTORY];
/*big losses and big jitter */
if (cur->lost_percentage>=unacceptable_loss_rate && cur->int_jitter>=big_jitter){
action->type=MSRateControlActionDecreaseBitrate;
action->value=MIN(cur->lost_percentage,50);
ms_message("MSQosAnalyser: loss rate unacceptable and big jitter");
}else if (rt_prop_increased(obj)){
action->type=MSRateControlActionDecreaseBitrate;
action->value=20;
ms_message("MSQosAnalyser: rt_prop doubled.");
}else if (cur->lost_percentage>=unacceptable_loss_rate){
/*big loss rate but no jitter, and no big rtp_prop: pure lossy network*/
action->type=MSRateControlActionDecreasePacketRate;
ms_message("MSQosAnalyser: loss rate unacceptable.");
}else{
action->type=MSRateControlActionDoNothing;
ms_message("MSQosAnalyser: everything is fine.");
}
}
static bool_t simple_analyser_has_improved(MSQosAnalyser *objbase){
MSSimpleQosAnalyzer *obj=(MSSimpleQosAnalyzer*)objbase;
rtpstats_t *cur=&obj->stats[obj->curindex % STATS_HISTORY];
rtpstats_t *prev=&obj->stats[(STATS_HISTORY+obj->curindex-1) % STATS_HISTORY];
if (prev->lost_percentage>=unacceptable_loss_rate){
if (cur->lost_percentage<prev->lost_percentage){
ms_message("MSQosAnalyser: lost percentage has improved");
return TRUE;
}else goto end;
}
if (obj->rt_prop_doubled && cur->rt_prop<prev->rt_prop){
ms_message("MSQosAnalyser: rt prop decrased");
obj->rt_prop_doubled=FALSE;
return TRUE;
}
end:
ms_message("MSQosAnalyser: no improvements.");
return FALSE;
}
static MSQosAnalyzerDesc simple_analyzer_desc={
simple_analyser_process_rtcp,
simple_analyser_suggest_action,
simple_analyzer_has_improved
};
MSQosAnalyzer * ms_simple_qos_analyser_new(RtpSession *session){
MSSimpleQosAnalyzer *obj=ms_new0(MSSimpleQosAnalyzer,1);
obj->session=session;
obj->parent.desc=&simple_analyzer_desc;
return (MSQosAnalyzer*)obj;
}
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