static void stateful_analyzer_suggest_action(MSQosAnalyzer *objbase, MSRateControlAction *action){
	MSStatefulQosAnalyzer *obj=(MSStatefulQosAnalyzer*)objbase;

	float curbw = obj->latest ? obj->latest->bandwidth : 0.f;
	float bw = compute_available_bw(obj);

	/*try a burst every 50 seconds (10 RTCP packets)*/
	if (obj->curindex % 10 == 0){
		ms_debug("MSQosStatefulAnalyzer[%p]: try burst!", obj);
		obj->burst_state = MSStatefulQosAnalyzerBurstEnable;
	}
	/*test a min burst to avoid overestimation of available bandwidth*/
	else if (obj->curindex % 10 == 2 || obj->curindex % 10 == 3){
		ms_debug("MSQosStatefulAnalyzer[%p]: try minimal burst!", obj);
		bw *= .33;
	}

	/*no bandwidth estimation computed*/
	if (bw <= 0 || curbw <= 0){
		action->type=MSRateControlActionDoNothing;
		action->value=0;
	}else if (bw > curbw){
		action->type=MSRateControlActionIncreaseQuality;
		action->value=MAX(0, 100. * (bw / curbw - 1));
	}else{
		action->type=MSRateControlActionDecreaseBitrate;
		action->value=MAX(10, -100. * (bw / curbw - 1));
	}

	ms_debug("MSQosStatefulAnalyzer[%p]: %s of value %d",
		obj, ms_rate_control_action_type_name(action->type), action->value);
}
static int audio_bitrate_driver_execute_action(MSBitrateDriver *objbase, const MSRateControlAction *action){
	MSAudioBitrateDriver *obj=(MSAudioBitrateDriver*)objbase;
	ms_message("MSAudioBitrateDriver: executing action of type %s, value=%i",ms_rate_control_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;
}
Esempio n. 3
0
static void simple_analyzer_suggest_action(MSQosAnalyzer *objbase, MSRateControlAction *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=(int)MIN(cur->lost_percentage,50);
		ms_message("MSSimpleQosAnalyzer: loss rate unacceptable and big jitter");
	}else if (simple_rt_prop_increased(obj)){
		action->type=MSRateControlActionDecreaseBitrate;
		action->value=20;
		ms_message("MSSimpleQosAnalyzer: 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=MSRateControlActionDecreaseBitrate;
		action->value=(int)MIN(cur->lost_percentage,50);
		ms_message("MSSimpleQosAnalyzer: loss rate unacceptable.");
	}else{
		action->type=MSRateControlActionDoNothing;
		ms_message("MSSimpleQosAnalyzer: everything is fine.");
	}

	if (objbase->on_action_suggested!=NULL){
		int i;
		char *data[4];
		int datac = sizeof(data) / sizeof(data[0]);
		data[0]=ms_strdup("%loss rt_prop_increased int_jitter_ms rt_prop_ms");
		data[1]=ms_strdup_printf("%d %d %d %d"
			, (int)cur->lost_percentage
			, (simple_rt_prop_increased(obj)==TRUE)
			, (int)cur->int_jitter
			, (int)(1000*cur->rt_prop));
		data[2]=ms_strdup("action_type action_value");
		data[3]=ms_strdup_printf("%s %d"
			, ms_rate_control_action_type_name(action->type)
			, action->value);

		objbase->on_action_suggested(objbase->on_action_suggested_user_pointer, datac, (const char**)data);

		for (i=0;i<datac;++i){
			ms_free(data[i]);
		}
	}
}
Esempio n. 4
0
static int bandwidth_driver_execute_action(MSBitrateDriver *objbase, const MSRateControlAction *action){
	MSBandwidthBitrateDriver *obj=(MSBandwidthBitrateDriver*)objbase;
	int ret=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.");
			return -1;
		}
	}

	if (!obj->venc){
		ret=1;
	}
	switch(action->type){
		case MSRateControlActionDecreaseBitrate:
			if (obj->venc){
				ret=bandwidth_change_video_bitrate(obj,action);
			}
			if (ret!=0 && obj->audio_driver){
				ret=ms_bitrate_driver_execute_action(obj->audio_driver,action);
			}
		break;
		case MSRateControlActionDecreasePacketRate:
			if (obj->audio_driver){
				ret=bandwidth_change_ptime((MSAudioBitrateDriver*) obj->audio_driver, 100);
			}else{
				ret=1;
			}
		break;
		case MSRateControlActionIncreaseQuality:
			if (obj->venc){
				ret=bandwidth_change_video_bitrate(obj,action);
			}
			if (ret!=0 && obj->audio_driver){
				ret=ms_bitrate_driver_execute_action(obj->audio_driver,action);
			}
		break;
		case MSRateControlActionDoNothing:
		break;
	}
	ms_message("MSBandwidthBitrateDriver: Action %s %s", ms_rate_control_action_type_name(action->type), ret == 0 ? "succeeded" : "failed");
	return ret;
}
Esempio n. 5
0
static void stateful_analyzer_suggest_action(MSQosAnalyzer *objbase, MSRateControlAction *action){
	MSStatefulQosAnalyzer *obj=(MSStatefulQosAnalyzer*)objbase;

	float curbw = 0;
	float bw = 0;
	rtcpstatspoint_t* greatest_pt = NULL;
	/*if this is the first measure, there is not enough reliable data to use; we
	assume loss rate is due to non congestionned network. This is mainly useful
	in the case loss rate is high (>30%), to reduce quality even before the second
	RTCP report which can be really used.
	*/
	if (obj->curindex==1){
		if (obj->network_loss_rate!=0.f){
			action->type=MSRateControlActionDecreaseBitrate;
			action->value=obj->network_loss_rate;
		}
	}else {
		curbw = obj->latest ? obj->latest->bandwidth : 0.f;
		bw = compute_available_bw(obj);
		greatest_pt = ms_list_size(obj->rtcpstatspoint) ?
			(rtcpstatspoint_t*)ms_list_nth_data(obj->rtcpstatspoint, ms_list_size(obj->rtcpstatspoint)-1)
			: NULL;

		/*try a burst every 50 seconds (10 RTCP packets)*/
		if (obj->curindex % 10 == 6){
			ms_message("MSStatefulQosAnalyzer[%p]: try burst!", obj);
			obj->burst_state = MSStatefulQosAnalyzerBurstEnable;
		}
		/*test a min burst to avoid overestimation of available bandwidth but only
		if there is some loss*/
		else if (greatest_pt!=NULL && greatest_pt->loss_percent>1
				&& (obj->curindex % 10 == 2 || obj->curindex % 10 == 3)){
			ms_message("MSStatefulQosAnalyzer[%p]: try minimal burst!", obj);
			bw *= .33;
		}

		/*no bandwidth estimation computed*/
		if (bw <= 0 || curbw <= 0){
			action->type=MSRateControlActionDoNothing;
			action->value=0;
		}else if (bw > curbw){
			action->type=MSRateControlActionIncreaseQuality;
			action->value=MAX(0, 100. * (bw / curbw - 1));
		}else{
			action->type=MSRateControlActionDecreaseBitrate;
			action->value=MAX(10, -100. * (bw / curbw - 1));
		}
	}

	ms_message("MSStatefulQosAnalyzer[%p]: %s of value %d",
		obj, ms_rate_control_action_type_name(action->type), action->value);


	if (objbase->on_action_suggested!=NULL){
		int i;
		char *data[4];
		int datac = sizeof(data) / sizeof(data[0]);
		data[0]=ms_strdup("%loss rtt_ms cur_bw");
		data[1]=ms_strdup_printf("%d %d %d"
			, obj->latest?(int)obj->latest->loss_percent:0
			, obj->latest?(int)obj->latest->rtt:0
			, obj->latest?(int)obj->latest->bandwidth:0
			);
		data[2]=ms_strdup("action_type action_value est_bw");
		data[3]=ms_strdup_printf("%s %d %d"
			, ms_rate_control_action_type_name(action->type)
			, action->value
			, (int)bw
			);

		objbase->on_action_suggested(objbase->on_action_suggested_user_pointer, datac, (const char**)data);

		for (i=0;i<datac;++i){
			ms_free(data[i]);
		}
	}
}
Esempio n. 6
0
static int audio_bitrate_driver_execute_action(MSBitrateDriver *objbase, const MSRateControlAction *action){
	MSAudioBitrateDriver *obj=(MSAudioBitrateDriver*)objbase;
	ms_message("MSAudioBitrateDriver: executing action of type %s, value=%i",ms_rate_control_action_type_name(action->type),action->value);

	if (obj->nom_bitrate==0){
		ms_filter_call_method(obj->encoder,MS_FILTER_GET_BITRATE,&obj->nom_bitrate);
		if (obj->nom_bitrate==0){
			ms_warning("MSAudioBitrateDriver: Not doing bitrate control on audio encoder, it does not seem to support that. Controlling ptime only.");
			obj->nom_bitrate=-1;
		}else 
			obj->cur_bitrate=obj->nom_bitrate;
	}
	if (obj->cur_ptime==0){
		ms_filter_call_method(obj->encoder,MS_AUDIO_ENCODER_GET_PTIME,&obj->cur_ptime);
		if (obj->cur_ptime==0){
			ms_warning("MSAudioBitrateDriver: encoder %s does not implement MS_AUDIO_ENCODER_GET_PTIME. Consider to implement this method for better accuracy of rate control.",obj->encoder->desc->name);
			obj->cur_ptime=obj->min_ptime;
		}
	}

	if (action->type==MSRateControlActionDecreaseBitrate){
		/*reducing bitrate of the codec isn't sufficient. Increasing ptime is much more efficient*/
		if (inc_ptime(obj)==-1){
			if (obj->nom_bitrate>0){
				int cur_br=0;
				int new_br;

				/*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("MSAudioBitrateDriver: GET_BITRATE failed");
					return 0;
				}
				obj->cur_bitrate=cur_br;
				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->nom_bitrate>0){
			if (ms_filter_call_method(obj->encoder,MS_FILTER_GET_BITRATE,&obj->cur_bitrate)==0){
				if (obj->cur_bitrate > 0  && obj->cur_bitrate<obj->nom_bitrate){
				obj->cur_bitrate=(obj->cur_bitrate*140)/100;
				if (obj->cur_bitrate> obj->nom_bitrate) obj->cur_bitrate=obj->nom_bitrate;
				ms_message("MSAudioBitrateDriver: increasing bitrate of codec to %i",obj->cur_bitrate);
				if (ms_filter_call_method(obj->encoder,MS_FILTER_SET_BITRATE,&obj->cur_bitrate)!=0){
					ms_message("MSAudioBitrateDriver: could not set codec bitrate to %i",obj->cur_bitrate);
				}else obj->cur_bitrate=obj->nom_bitrate; /* so that we do not attempt this anymore*/
				return 0;
			}
			}else ms_warning("MSAudioBitrateDriver: MS_FILTER_GET_BITRATE failed.");
			
		}
		if (obj->cur_ptime>obj->min_ptime){
			obj->cur_ptime-=obj->min_ptime;
			apply_ptime(obj);
		}else return -1;
	}
	return 0;
}
Esempio n. 7
0
static int audio_bitrate_driver_execute_action(MSBitrateDriver *objbase, const MSRateControlAction *action){
	MSAudioBitrateDriver *obj=(MSAudioBitrateDriver*)objbase;
	ms_message("MSAudioBitrateDriver: executing action of type %s, value=%i",ms_rate_control_action_type_name(action->type),action->value);

	if (obj->nom_bitrate==0){
		ms_filter_call_method(obj->encoder,MS_FILTER_GET_BITRATE,&obj->nom_bitrate);
		if (obj->nom_bitrate==0){
			ms_warning("MSAudioBitrateDriver: Not doing bitrate control on audio encoder, it does not seem to support that. Controlling ptime only.");
			obj->nom_bitrate=-1;
		}else
			obj->cur_bitrate=obj->nom_bitrate;
	}
	if (obj->cur_ptime==0 || ms_filter_has_method(obj->encoder,MS_AUDIO_ENCODER_GET_PTIME)){ /*always sync current ptime if possible*/
		ms_filter_call_method(obj->encoder,MS_AUDIO_ENCODER_GET_PTIME,&obj->cur_ptime);
		if (obj->cur_ptime==0){
			ms_warning("MSAudioBitrateDriver: encoder %s does not implement MS_AUDIO_ENCODER_GET_PTIME. Consider to implement this method for better accuracy of rate control.",obj->encoder->desc->name);
			obj->cur_ptime=obj->min_ptime;
		}
	}

	if (action->type==MSRateControlActionDecreaseBitrate){
		
		/*reducing bitrate of the codec isn't sufficient. Increasing ptime is much more efficient*/
		if ((obj->encoder_caps & MS_AUDIO_ENCODER_CAP_AUTO_PTIME) || inc_ptime(obj)){
			if (obj->nom_bitrate>0){
				int cur_br=0;
				int new_br;

				/*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("MSAudioBitrateDriver: GET_BITRATE failed");
					return 0;
				}
				obj->cur_bitrate=cur_br;
				new_br=cur_br-((cur_br*action->value)/100);

				ms_message("MSAudioBitrateDriver: Attempting to reduce audio bitrate from %i to %i",cur_br,new_br);
				if (ms_filter_call_method(obj->encoder,MS_FILTER_SET_BITRATE,&new_br)!=0){
					ms_message("MSAudioBitrateDriver: SET_BITRATE failed, incrementing ptime");
					return inc_ptime(obj);
				} else {
					rtp_session_set_target_upload_bandwidth(obj->session, new_br);
				}
				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){
		return inc_ptime(obj);
	}else if (action->type==MSRateControlActionIncreaseQuality){
		int ret=0;
		if (!(obj->encoder_caps & MS_AUDIO_ENCODER_CAP_AUTO_PTIME)){
			if (obj->cur_ptime>obj->min_ptime){
				ret=dec_ptime(obj);
			}
		}
		if (obj->nom_bitrate>0){
			int cur_bitrate=0;
			if (ms_filter_call_method(obj->encoder,MS_FILTER_GET_BITRATE,&cur_bitrate)==0){
				if (cur_bitrate > 0  && cur_bitrate<obj->nom_bitrate){
					obj->cur_bitrate=(obj->cur_bitrate*140)/100;
					if (obj->cur_bitrate>= obj->nom_bitrate) {
						obj->cur_bitrate=obj->nom_bitrate;
						ret=-1;/*we reached the nominal value*/
					}
					ms_message("MSAudioBitrateDriver: increasing bitrate of codec to %i",obj->cur_bitrate);
					if (ms_filter_call_method(obj->encoder,MS_FILTER_SET_BITRATE,&obj->cur_bitrate)!=0){
						ms_message("MSAudioBitrateDriver: could not set codec bitrate to %i",obj->cur_bitrate);
					}else {
						rtp_session_set_target_upload_bandwidth(obj->session, obj->cur_bitrate);
					}
				}
			}else ms_warning("MSAudioBitrateDriver: MS_FILTER_GET_BITRATE failed.");
		}
		return ret;
	}
	return 0;
}