1 /*
2 mediastreamer2 library - modular sound and video processing and streaming
3 
4  * Copyright (C) 2011  Belledonne Communications, Grenoble, France
5 
6 	 Author: Simon Morlat <simon.morlat@linphone.org>
7 
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21  */
22 
23 #include "mediastreamer2/bitratecontrol.h"
24 
25 #include <bctoolbox/defs.h>
26 
27 static const int probing_up_interval=10;
28 
29 enum state_t{
30 	Init,
31 	Probing,
32 	Stable,
33 	ProbingUp
34 };
35 
state_name(enum state_t st)36 const char *state_name(enum state_t st){
37 	switch(st){
38 		case Init: return "Init";
39 		case Probing: return "Probing";
40 		case Stable: return "Stable";
41 		case ProbingUp: return "ProbingUp";
42 	}
43 	return "bad state";
44 }
45 
46 struct _MSBitrateController{
47 	MSQosAnalyzer *analyzer;
48 	MSBitrateDriver *driver;
49 	enum state_t state;
50 	int stable_count;
51 	int probing_up_count;
52 
53 };
54 
ms_bitrate_controller_new(MSQosAnalyzer * qosanalyzer,MSBitrateDriver * driver)55 MSBitrateController *ms_bitrate_controller_new(MSQosAnalyzer *qosanalyzer, MSBitrateDriver *driver){
56 	MSBitrateController *obj=ms_new0(MSBitrateController,1);
57 	obj->analyzer=ms_qos_analyzer_ref(qosanalyzer);
58 	obj->driver=ms_bitrate_driver_ref(driver);
59 	return obj;
60 }
61 
execute_action(MSBitrateController * obj,const MSRateControlAction * action)62 static int execute_action(MSBitrateController *obj, const MSRateControlAction *action){
63 	return ms_bitrate_driver_execute_action(obj->driver,action);
64 }
65 
state_machine(MSBitrateController * obj)66 static void state_machine(MSBitrateController *obj){
67 	MSRateControlAction action = {0};
68 	switch(obj->state){
69 		case Stable:
70 			obj->stable_count++;
71 			BCTBX_NO_BREAK; /*intentionally no break*/
72 		case Init:
73 			ms_qos_analyzer_suggest_action(obj->analyzer,&action);
74 			if (action.type!=MSRateControlActionDoNothing){
75 				execute_action(obj,&action);
76 				obj->state=Probing;
77 			}else if (obj->stable_count>=probing_up_interval){
78 				action.type=MSRateControlActionIncreaseQuality;
79 				action.value=10;
80 				execute_action(obj,&action);
81 				obj->state=ProbingUp;
82 				obj->probing_up_count=0;
83 			}
84 		break;
85 		case Probing:
86 			obj->stable_count=0;
87 			if (ms_qos_analyzer_has_improved(obj->analyzer)){
88 				obj->state=Stable;
89 			}else{
90 				ms_qos_analyzer_suggest_action(obj->analyzer,&action);
91 				if (action.type!=MSRateControlActionDoNothing){
92 					execute_action(obj,&action);
93 				}
94 			}
95 		break;
96 		case ProbingUp:
97 			obj->stable_count=0;
98 			obj->probing_up_count++;
99 			ms_qos_analyzer_suggest_action(obj->analyzer,&action);
100 			if (action.type!=MSRateControlActionDoNothing){
101 				execute_action(obj,&action);
102 				obj->state=Probing;
103 			}else{
104 				/*continue with slow ramp up*/
105 				if (obj->probing_up_count==2){
106 					action.type=MSRateControlActionIncreaseQuality;
107 					action.value=10;
108 					if (execute_action(obj,&action)==-1){
109 						/* we reached the maximum*/
110 						obj->state=Init;
111 					}
112 					obj->probing_up_count=0;
113 				}
114 			}
115 		break;
116 		default:
117 		break;
118 	}
119 	ms_message("MSBitrateController: current state is %s",state_name(obj->state));
120 }
121 
122 
123 
ms_bitrate_controller_process_rtcp(MSBitrateController * obj,mblk_t * rtcp)124 void ms_bitrate_controller_process_rtcp(MSBitrateController *obj, mblk_t *rtcp){
125 	if (ms_qos_analyzer_process_rtcp(obj->analyzer,rtcp)){
126 		state_machine(obj);
127 	}
128 }
129 
ms_bitrate_controller_update(MSBitrateController * obj)130 void ms_bitrate_controller_update(MSBitrateController *obj){
131 	ms_qos_analyzer_update(obj->analyzer);
132 }
133 
ms_bitrate_controller_get_qos_analyzer(MSBitrateController * obj)134 MSQosAnalyzer * ms_bitrate_controller_get_qos_analyzer(MSBitrateController *obj){
135 	return obj->analyzer;
136 }
137 
ms_bitrate_controller_destroy(MSBitrateController * obj)138 void ms_bitrate_controller_destroy(MSBitrateController *obj){
139 	ms_qos_analyzer_unref(obj->analyzer);
140 	ms_bitrate_driver_unref(obj->driver);
141 	ms_free(obj);
142 }
143 
ms_audio_bitrate_controller_new(RtpSession * session,MSFilter * encoder,unsigned int flags)144 MSBitrateController *ms_audio_bitrate_controller_new(RtpSession *session, MSFilter *encoder, unsigned int flags){
145 	return ms_bitrate_controller_new(
146 	                                 ms_simple_qos_analyzer_new(session),
147 	                                 ms_audio_bitrate_driver_new(session, encoder));
148 }
149 
ms_av_bitrate_controller_new(RtpSession * asession,MSFilter * aenc,RtpSession * vsession,MSFilter * venc)150 MSBitrateController *ms_av_bitrate_controller_new(RtpSession *asession, MSFilter *aenc, RtpSession *vsession, MSFilter *venc){
151 	return ms_bitrate_controller_new(
152 	                                 ms_simple_qos_analyzer_new(vsession),
153 	                                 ms_av_bitrate_driver_new(asession, aenc, vsession, venc));
154 }
155 
ms_bandwidth_bitrate_controller_new(RtpSession * asession,MSFilter * aenc,RtpSession * vsession,MSFilter * venc)156 MSBitrateController *ms_bandwidth_bitrate_controller_new(RtpSession *asession, MSFilter *aenc, RtpSession *vsession, MSFilter *venc){
157 	return ms_bitrate_controller_new(
158 	                                 ms_stateful_qos_analyzer_new(vsession?vsession:asession),
159 	                                 ms_bandwidth_bitrate_driver_new(asession, aenc, vsession, venc));
160 }
161