bitratecontrol.c 4.73 KB
Newer Older
1 2 3 4 5
/*
mediastreamer2 library - modular sound and video processing and streaming

 * Copyright (C) 2011  Belledonne Communications, Grenoble, France

6 7
	 Author: Simon Morlat <simon.morlat@linphone.org>

8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
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"

25
static const int probing_up_interval=10;
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

enum state_t{
	Init,
	Probing,
	Stable,
	ProbingUp
};

const char *state_name(enum state_t st){
	switch(st){
		case Init: return "Init";
		case Probing: return "Probing";
		case Stable: return "Stable";
		case ProbingUp: return "ProbingUp";
	}
	return "bad state";
}

44
struct _MSBitrateController{
45
	MSQosAnalyzer *analyzer;
46
	MSBitrateDriver *driver;
47 48
	enum state_t state;
	int stable_count;
49
	int probing_up_count;
50

51 52
};

53
MSBitrateController *ms_bitrate_controller_new(MSQosAnalyzer *qosanalyzer, MSBitrateDriver *driver){
54
	MSBitrateController *obj=ms_new0(MSBitrateController,1);
55
	obj->analyzer=ms_qos_analyzer_ref(qosanalyzer);
56 57 58 59 60 61
	obj->driver=ms_bitrate_driver_ref(driver);
	return obj;
}

static int execute_action(MSBitrateController *obj, const MSRateControlAction *action){
	return ms_bitrate_driver_execute_action(obj->driver,action);
62 63
}

64
static void state_machine(MSBitrateController *obj){
65
	MSRateControlAction action = {0};
66 67 68 69
	switch(obj->state){
		case Stable:
			obj->stable_count++;
		case Init:
70
			ms_qos_analyzer_suggest_action(obj->analyzer,&action);
71
			if (action.type!=MSRateControlActionDoNothing){
72 73
				execute_action(obj,&action);
				obj->state=Probing;
74
			}else if (obj->stable_count>=probing_up_interval){
75
				action.type=MSRateControlActionIncreaseQuality;
76
				action.value=10;
77 78
				execute_action(obj,&action);
				obj->state=ProbingUp;
79
				obj->probing_up_count=0;
80 81 82 83
			}
		break;
		case Probing:
			obj->stable_count=0;
84
			if (ms_qos_analyzer_has_improved(obj->analyzer)){
85
				obj->state=Stable;
86
			}else{
87
				ms_qos_analyzer_suggest_action(obj->analyzer,&action);
88
				if (action.type!=MSRateControlActionDoNothing){
89 90 91 92 93 94
					execute_action(obj,&action);
				}
			}
		break;
		case ProbingUp:
			obj->stable_count=0;
95
			obj->probing_up_count++;
96
			ms_qos_analyzer_suggest_action(obj->analyzer,&action);
97
			if (action.type!=MSRateControlActionDoNothing){
98 99 100
				execute_action(obj,&action);
				obj->state=Probing;
			}else{
101 102
				/*continue with slow ramp up*/
				if (obj->probing_up_count==2){
103
					action.type=MSRateControlActionIncreaseQuality;
104
					action.value=10;
105 106 107 108 109
					if (execute_action(obj,&action)==-1){
						/* we reached the maximum*/
						obj->state=Init;
					}
					obj->probing_up_count=0;
110 111 112 113 114 115
				}
			}
		break;
		default:
		break;
	}
116
	ms_message("MSBitrateController: current state is %s",state_name(obj->state));
117 118 119 120
}



121
void ms_bitrate_controller_process_rtcp(MSBitrateController *obj, mblk_t *rtcp){
122
	if (ms_qos_analyzer_process_rtcp(obj->analyzer,rtcp)){
123 124 125 126
		state_machine(obj);
	}
}

127
void ms_bitrate_controller_update(MSBitrateController *obj){
128
	ms_qos_analyzer_update(obj->analyzer);
129 130
}

131
MSQosAnalyzer * ms_bitrate_controller_get_qos_analyzer(MSBitrateController *obj){
132
	return obj->analyzer;
133 134
}

135
void ms_bitrate_controller_destroy(MSBitrateController *obj){
136
	ms_qos_analyzer_unref(obj->analyzer);
137
	ms_bitrate_driver_unref(obj->driver);
138 139 140
	ms_free(obj);
}

141 142
MSBitrateController *ms_audio_bitrate_controller_new(RtpSession *session, MSFilter *encoder, unsigned int flags){
	return ms_bitrate_controller_new(
143
	                                 ms_simple_qos_analyzer_new(session),
144
	                                 ms_audio_bitrate_driver_new(session, encoder));
145
}
146

147 148
MSBitrateController *ms_av_bitrate_controller_new(RtpSession *asession, MSFilter *aenc, RtpSession *vsession, MSFilter *venc){
	return ms_bitrate_controller_new(
149
	                                 ms_simple_qos_analyzer_new(vsession),
150
	                                 ms_av_bitrate_driver_new(asession, aenc, vsession, venc));
151 152
}

153 154
MSBitrateController *ms_bandwidth_bitrate_controller_new(RtpSession *asession, MSFilter *aenc, RtpSession *vsession, MSFilter *venc){
	return ms_bitrate_controller_new(
155
	                                 ms_stateful_qos_analyzer_new(vsession?vsession:asession),
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
156
	                                 ms_bandwidth_bitrate_driver_new(asession, aenc, vsession, venc));
157
}
158