add update method in qos analyser interface for burst management/bandwidth...

add update method in qos analyser interface for burst management/bandwidth computation in stateful qos
parent f17b2640
......@@ -114,6 +114,7 @@ void ms_qos_analyser_unref(MSQosAnalyser *obj);
void ms_qos_analyser_suggest_action(MSQosAnalyser *obj, MSRateControlAction *action);
bool_t ms_qos_analyser_has_improved(MSQosAnalyser *obj);
bool_t ms_qos_analyser_process_rtcp(MSQosAnalyser *obj, mblk_t *rtcp);
void ms_qos_analyser_update(MSQosAnalyser *obj);
/**
* The simple qos analyser is an implementation of MSQosAnalyser that performs analysis for single stream.
......@@ -151,6 +152,8 @@ MSBitrateController *ms_bitrate_controller_new(MSQosAnalyser *qosanalyser, MSBit
**/
void ms_bitrate_controller_process_rtcp(MSBitrateController *obj, mblk_t *rtcp);
void ms_bitrate_controller_update(MSBitrateController *obj);
/**
* Return the QoS analyser associated to the bitrate controller
**/
......
......@@ -114,7 +114,7 @@ static void audio_stream_configure_resampler(MSFilter *resampler,MSFilter *from,
ms_filter_call_method(resampler, MS_FILTER_SET_NCHANNELS, &from_channels);
ms_filter_call_method(resampler, MS_FILTER_SET_OUTPUT_NCHANNELS, &to_channels);
ms_message("configuring %s-->%s from rate [%i] to rate [%i] and from channel [%i] to channel [%i]",
from->desc->name, to->desc->name, from_rate, to_rate, from_channels, to_channels);
from->desc->name, to->desc->name, from_rate, to_rate, from_channels, to_channels);
}
static void audio_stream_process_rtcp(MediaStream *media_stream, mblk_t *m){
......@@ -134,7 +134,7 @@ static void audio_stream_process_rtcp(MediaStream *media_stream, mblk_t *m){
ij=report_block_get_interarrival_jitter(rb);
flost=(float)(100.0*report_block_get_fraction_lost(rb)/256.0);
ms_message("audio_stream_iterate[%p]: 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",stream,ij,flost,rt);
"\tremote's lost packets percentage since last report=%f\n\tround trip time=%f seconds",stream,ij,flost,rt);
if (stream->ms.rc) ms_bitrate_controller_process_rtcp(stream->ms.rc,m);
if (stream->ms.qi) ms_quality_indicator_update_from_feedback(stream->ms.qi,m);
}
......@@ -167,7 +167,7 @@ static mblk_t* audio_stream_payload_picker(MSRtpPayloadPickerContext* context,u
static void stop_preload_graph(AudioStream *stream){
ms_ticker_detach(stream->ms.sessions.ticker,stream->dummy);
if (stream->ms.voidsink) {
ms_filter_unlink(stream->dummy,0,stream->ms.voidsink,0);
ms_filter_destroy(stream->ms.voidsink);
......@@ -248,15 +248,15 @@ static void player_callback(void *ud, MSFilter *f, unsigned int id, void *arg){
static void setup_local_player(AudioStream *stream, int samplerate, int channels){
MSConnectionHelper cnx;
int master=0;
stream->local_player=ms_filter_new(MS_FILE_PLAYER_ID);
stream->local_player_resampler=ms_filter_new(MS_RESAMPLE_ID);
ms_connection_helper_start(&cnx);
ms_connection_helper_link(&cnx,stream->local_player,-1,0);
ms_connection_helper_link(&cnx,stream->local_player_resampler,0,0);
ms_connection_helper_link(&cnx,stream->local_mixer,1,-1);
ms_filter_call_method(stream->local_player_resampler,MS_FILTER_SET_OUTPUT_SAMPLE_RATE,&samplerate);
ms_filter_call_method(stream->local_player_resampler,MS_FILTER_SET_OUTPUT_NCHANNELS,&channels);
ms_filter_call_method(stream->local_mixer,MS_FILTER_SET_SAMPLE_RATE,&samplerate);
......@@ -380,14 +380,14 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
tel_ev=rtp_profile_get_payload_from_mime (profile,"telephone-event");
if ((stream->features & AUDIO_STREAM_FEATURE_DTMF_ECHO) != 0 && (tel_ev==NULL || ( (tel_ev->flags & PAYLOAD_TYPE_FLAG_CAN_RECV) && !(tel_ev->flags & PAYLOAD_TYPE_FLAG_CAN_SEND)))
&& ( strcasecmp(pt->mime_type,"pcmu")==0 || strcasecmp(pt->mime_type,"pcma")==0)){
&& ( strcasecmp(pt->mime_type,"pcmu")==0 || strcasecmp(pt->mime_type,"pcma")==0)){
/*if no telephone-event payload is usable and pcma or pcmu is used, we will generate
inband dtmf*/
stream->dtmfgen_rtp=ms_filter_new (MS_DTMF_GEN_ID);
} else {
stream->dtmfgen_rtp=NULL;
}
if (ms_filter_call_method(stream->ms.rtpsend,MS_FILTER_GET_SAMPLE_RATE,&sample_rate)!=0){
ms_error("Sample rate is unknown for RTP side !");
return -1;
......@@ -414,7 +414,7 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
ms_error("audio_stream_start_full: No decoder or encoder available for payload %s.",pt->mime_type);
return -1;
}
/* check echo canceller max frequency and adjust sampling rate if needed when codec used is opus */
if (stream->ec!=NULL) {
if ((ms_filter_get_id(stream->ms.encoder) == MS_OPUS_ENC_ID) && (ms_filter_get_id(stream->ec) == MS_WEBRTC_AEC_ID)) { /* AECM allow 8000 or 16000 Hz or it will be bypassed */
......@@ -427,7 +427,7 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
/*hack for opus, that claims stereo all the time, but we can't support stereo yet*/
if (strcasecmp(pt->mime_type,"opus")==0)
nchannels=1;
if (ms_filter_has_method(stream->ms.decoder, MS_FILTER_SET_RTP_PAYLOAD_PICKER)) {
ms_message("Decoder has FEC capabilities");
picker_context.filter_graph_manager=stream;
......@@ -485,7 +485,7 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
}
ms_filter_call_method(stream->ec,MS_FILTER_SET_SAMPLE_RATE,&sample_rate);
}
if (stream->features & AUDIO_STREAM_FEATURE_MIXED_RECORDING){
int val=0;
int pin=1;
......@@ -500,7 +500,7 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
ms_filter_call_method(stream->send_tee,MS_TEE_MUTE,&pin);
ms_filter_call_method(stream->recorder,MS_FILTER_SET_SAMPLE_RATE,&sample_rate);
ms_filter_call_method(stream->recorder,MS_FILTER_SET_NCHANNELS,&nchannels);
}
/* give the encoder/decoder some parameters*/
......@@ -539,7 +539,7 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
}
}else
stream->equalizer=NULL;
/*configure resamplers if needed*/
if (stream->read_resampler){
audio_stream_configure_resampler(stream->read_resampler,stream->soundread,stream->ms.encoder);
......@@ -548,11 +548,11 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
if (stream->write_resampler){
audio_stream_configure_resampler(stream->write_resampler,stream->ms.decoder,stream->soundwrite);
}
if (stream->ms.use_rc){
stream->ms.rc=ms_audio_bitrate_controller_new(stream->ms.sessions.rtp_session,stream->ms.encoder,0);
stream->ms.rc=ms_bandwidth_bitrate_controller_new(stream->ms.sessions.rtp_session,stream->ms.encoder,0,0);
}
/* Create generic PLC if not handled by the decoder directly*/
if ((stream->features & AUDIO_STREAM_FEATURE_PLC) != 0) {
int decoder_have_plc = 0;
......@@ -574,7 +574,7 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
} else {
stream->plc = NULL;
}
if (stream->features & AUDIO_STREAM_FEATURE_LOCAL_PLAYING){
stream->local_mixer=ms_filter_new(MS_AUDIO_MIXER_ID);
}
......@@ -585,7 +585,7 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
/*we were using the dummy preload graph, destroy it but keep sound filters*/
_audio_stream_unprepare_sound(stream,TRUE);
}
/* and then connect all */
/* tip: draw yourself the picture if you don't understand */
......@@ -635,7 +635,7 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
ms_filter_link(stream->recv_tee,1,stream->recorder_mixer,1);
ms_filter_link(stream->recorder_mixer,0,stream->recorder,0);
}
/*to make sure all preprocess are done before befre processing audio*/
ms_ticker_attach_multiple(stream->ms.sessions.ticker
,stream->soundread
......@@ -775,7 +775,7 @@ void audio_stream_set_features(AudioStream *st, uint32_t features){
AudioStream *audio_stream_new_with_sessions(const MSMediaStreamSessions *sessions){
AudioStream *stream=(AudioStream *)ms_new0(AudioStream,1);
MSFilterDesc *ec_desc=ms_filter_lookup_by_name("MSOslec");
ms_filter_enable_statistics(TRUE);
ms_filter_reset_statistics();
......@@ -904,11 +904,11 @@ static void dismantle_local_player(AudioStream *stream){
void audio_stream_stop(AudioStream * stream){
if (stream->ms.sessions.ticker){
MSConnectionHelper h;
if (stream->ms.state==MSStreamPreparing){
audio_stream_unprepare_sound(stream);
}else if (stream->ms.state==MSStreamStarted){
ms_ticker_detach(stream->ms.sessions.ticker,stream->soundread);
ms_ticker_detach(stream->ms.sessions.ticker,stream->ms.rtprecv);
......@@ -958,7 +958,7 @@ void audio_stream_stop(AudioStream * stream){
if (stream->write_resampler!=NULL)
ms_connection_helper_unlink(&h,stream->write_resampler,0,0);
ms_connection_helper_unlink(&h,stream->soundwrite,0,-1);
/*dismantle the call recording */
if (stream->recorder){
ms_filter_unlink(stream->send_tee,1,stream->recorder_mixer,0);
......@@ -980,7 +980,7 @@ int audio_stream_send_dtmf(AudioStream *stream, char dtmf)
return 0;
}
void audio_stream_mute_rtp(AudioStream *stream, bool_t val)
void audio_stream_mute_rtp(AudioStream *stream, bool_t val)
{
if (stream->ms.rtpsend){
if (val)
......
......@@ -125,6 +125,10 @@ void ms_bitrate_controller_process_rtcp(MSBitrateController *obj, mblk_t *rtcp){
}
}
void ms_bitrate_controller_update(MSBitrateController *obj){
ms_qos_analyser_update(obj->analyser);
}
const MSQosAnalyser * ms_bitrate_controller_get_qos_analyser(MSBitrateController *obj){
return obj->analyser;
}
......@@ -149,7 +153,7 @@ MSBitrateController *ms_av_bitrate_controller_new(RtpSession *asession, MSFilter
MSBitrateController *ms_bandwidth_bitrate_controller_new(RtpSession *asession, MSFilter *aenc, RtpSession *vsession, MSFilter *venc){
return ms_bitrate_controller_new(
ms_stateful_qos_analyser_new(vsession),
ms_stateful_qos_analyser_new(vsession?vsession:asession),
ms_bandwidth_bitrate_driver_new(asession, aenc, vsession, venc));
}
......@@ -348,7 +348,7 @@ static int bandwidth_inc_video_bitrate(MSBandwidthBitrateDriver *obj, const MSRa
static int bandwidth_driver_execute_action(MSBitrateDriver *objbase, const MSRateControlAction *action){
MSBandwidthBitrateDriver *obj=(MSBandwidthBitrateDriver*)objbase;
int ret=0;
if (obj->nom_bitrate==0){
if (obj->nom_bitrate==0&&obj->venc){
ms_filter_call_method(obj->venc,MS_FILTER_GET_BITRATE,&obj->nom_bitrate);
if (obj->nom_bitrate==0){
ms_warning("MSBandwidthBitrateDriver: Not doing adaptive rate control on video encoder, it does not seem to support that.");
......@@ -358,7 +358,9 @@ static int bandwidth_driver_execute_action(MSBitrateDriver *objbase, const MSRat
switch(action->type){
case MSRateControlActionDecreaseBitrate:
ret=bandwidth_dec_video_bitrate(obj,action);
if (obj->venc){
ret=bandwidth_dec_video_bitrate(obj,action);
}
break;
case MSRateControlActionDecreasePacketRate:
if (obj->audio_driver){
......@@ -368,7 +370,11 @@ static int bandwidth_driver_execute_action(MSBitrateDriver *objbase, const MSRat
}
break;
case MSRateControlActionIncreaseQuality:
ret=bandwidth_inc_video_bitrate(obj,action);
if (obj->venc){
ret=bandwidth_inc_video_bitrate(obj,action);
}else{
ret=1;
}
if (ret != 0){
if (obj->audio_driver){
ret=ms_bitrate_driver_execute_action(obj->audio_driver,action);
......
......@@ -476,6 +476,9 @@ void media_stream_iterate(MediaStream *stream){
if (stream->qi && curtime>stream->last_iterate_time) ms_quality_indicator_update_local(stream->qi);
}
stream->last_iterate_time=curtime;
if (stream->rc) ms_bitrate_controller_update(stream->rc);
if (stream->evq){
OrtpEvent *ev=NULL;
......
......@@ -48,7 +48,12 @@ void ms_qos_analyser_suggest_action(MSQosAnalyser *obj, MSRateControlAction *act
if (obj->desc->suggest_action){
obj->desc->suggest_action(obj,action);
}
return;
}
void ms_qos_analyser_update(MSQosAnalyser *obj){
if (obj->desc->update){
obj->desc->update(obj);
}
}
bool_t ms_qos_analyser_has_improved(MSQosAnalyser *obj){
......@@ -261,6 +266,7 @@ static bool_t stateful_analyser_process_rtcp(MSQosAnalyser *objbase, mblk_t *rtc
rb=rtcp_RR_get_report_block(rtcp,0);
}
if (rb && report_block_get_ssrc(rb)==rtp_session_get_send_ssrc(obj->session)){
double up_bw = stateful_qos_analyser_upload_bandwidth(obj);
obj->curindex++;
cur=&obj->stats[obj->curindex % STATS_HISTORY];
......@@ -276,14 +282,10 @@ static bool_t stateful_analyser_process_rtcp(MSQosAnalyser *objbase, mblk_t *rtc
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);
if (obj->curindex>2){
double up_bw = stateful_qos_analyser_upload_bandwidth(obj);
int cum_loss_curr,uniq_emitted;
double loss_rate = cur->lost_percentage/100.0;
int cum_loss=report_block_get_cum_packet_loss(rb);
cum_loss=(cum_loss>>23&1) ? cum_loss-0xFFFFFF-1 : cum_loss;
cum_loss_curr=cum_loss - obj->cum_loss_prev;
uniq_emitted=report_block_get_high_ext_seq(rb) - obj->last_seq;
int cum_loss_curr=cum_loss - obj->cum_loss_prev;
int uniq_emitted=report_block_get_high_ext_seq(rb) - obj->last_seq;
if (obj->last_seq > 0){
int total_emitted=uniq_emitted * (1 + obj->session->duplication_ratio);
......@@ -297,7 +299,7 @@ static bool_t stateful_analyser_process_rtcp(MSQosAnalyser *objbase, mblk_t *rtc
P(YELLOW "SKIPPED first MIN burst %d: %f %f\n", obj->curindex-1, up_bw, loss_rate);
}else{
obj->latest=ms_new0(rtcpstatspoint_t, 1);
obj->latest->timestamp=time(0);
obj->latest->timestamp=ms_time(0);
obj->latest->bandwidth=up_bw;
obj->latest->loss_percent=loss_rate;
obj->latest->rtt=cur->rt_prop;
......@@ -312,7 +314,7 @@ static bool_t stateful_analyser_process_rtcp(MSQosAnalyser *objbase, mblk_t *rtc
if (ms_list_size(obj->rtcpstatspoint) > ESTIM_HISTORY){
P(RED "Reached list maximum capacity (count=%d)", ms_list_size(obj->rtcpstatspoint));
/*clean everything which occurred 60 sec or more ago*/
time_t clear_time = time(0) - 60;
time_t clear_time = ms_time(0) - 60;
obj->rtcpstatspoint = ms_list_remove_custom(obj->rtcpstatspoint, (MSCompareFunc)earlier_than, &clear_time);
P(RED "--> Cleaned list (count=%d)\n", ms_list_size(obj->rtcpstatspoint));
}
......@@ -533,43 +535,50 @@ static bool_t stateful_analyser_has_improved(MSQosAnalyser *objbase){
return FALSE;
}
// static void stateful_analyser_update(MSQosAnalyser *objbase){
// MSStatefulQosAnalyser *obj=(MSStatefulQosAnalyser*)objbase;
// obj->interval_count++;
// obj->upload_bandwidth_sum+=rtp_session_get_send_bandwidth(obj->session)/1000.0;
// switch (obj->burst_state){
// case MSStatefulQosAnalyserBurstEnable:{
// obj->burst_state=MSStatefulQosAnalyserBurstInProgress;
// obj->start_seq_number=obj->last_seq_number=obj->session->rtp.snd_seq;
// ortp_gettimeofday(&obj->start_time, NULL);
// rtp_session_set_duplication_ratio(obj->session, 2);
// }
// case MSStatefulQosAnalyserBurstInProgress:{
// struct timeval now;
// double elapsed;
// obj->last_seq_number=obj->session->rtp.snd_seq;
// ortp_gettimeofday(&now,NULL);
// elapsed=((now.tv_sec-obj->start_time.tv_sec)*1000.0) + ((now.tv_usec-obj->start_time.tv_usec)/1000.0);
// /*burst should last 1sec*/
// if (elapsed > 1.){
// obj->burst_state=MSStatefulQosAnalyserBurstDisable;
// rtp_session_set_duplication_ratio(obj->session, 0);
// }
// }
// case MSStatefulQosAnalyserBurstDisable:{
// }
// }
// }
static void stateful_analyser_update(MSQosAnalyser *objbase){
MSStatefulQosAnalyser *obj=(MSStatefulQosAnalyser*)objbase;
static time_t last_measure;
if (last_measure != ms_time(0)){
obj->interval_count++;
obj->upload_bandwidth_sum+=rtp_session_get_send_bandwidth(obj->session)/1000.0;
}else{
/*P(RED "already measured bw this sec\n");*/
}
last_measure = ms_time(0);
switch (obj->burst_state){
case MSStatefulQosAnalyserBurstEnable:{
obj->burst_state=MSStatefulQosAnalyserBurstInProgress;
obj->start_seq_number=obj->last_seq_number=obj->session->rtp.snd_seq;
ortp_gettimeofday(&obj->start_time, NULL);
rtp_session_set_duplication_ratio(obj->session, 2);
}
case MSStatefulQosAnalyserBurstInProgress:{
struct timeval now;
double elapsed;
obj->last_seq_number=obj->session->rtp.snd_seq;
ortp_gettimeofday(&now,NULL);
elapsed=((now.tv_sec-obj->start_time.tv_sec)*1000.0) + ((now.tv_usec-obj->start_time.tv_usec)/1000.0);
/*burst should last 1sec*/
if (elapsed > 1.){
obj->burst_state=MSStatefulQosAnalyserBurstDisable;
rtp_session_set_duplication_ratio(obj->session, 0);
}
}
case MSStatefulQosAnalyserBurstDisable:{
}
}
}
static MSQosAnalyserDesc stateful_analyser_desc={
stateful_analyser_process_rtcp,
stateful_analyser_suggest_action,
stateful_analyser_has_improved,
/*stateful_analyser_update*/
stateful_analyser_update
};
MSQosAnalyser * ms_stateful_qos_analyser_new(RtpSession *session){
......
......@@ -329,12 +329,19 @@ static void audio_stream_dtmf(int codec_payload, int initial_bitrate,int target_
#endif
static void upload_bandwidth_computation() {
bool_t supported = ms_filter_codec_supported("pcma");
if( supported ) {
adaptive_audio_stream(PCMA8_PAYLOAD_TYPE, 8000, 0, 0, 10);
}
}
static test_t tests[] = {
{ "Basic audio stream", basic_audio_stream },
{ "Adaptive audio stream [opus]", adaptive_opus_audio_stream },
{ "Adaptive audio stream [speex]", adaptive_speex16_audio_stream },
{ "Adaptive audio stream [pcma]", adaptive_pcma_audio_stream },
{ "Upload bandwidth computation", upload_bandwidth_computation },
};
test_suite_t audio_stream_test_suite = {
......
This diff is collapsed.
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