bitratedriver.c 9.36 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/*
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"

25
static const int max_ptime=100;
jehan's avatar
jehan committed
26
static const int min_ptime=10;
27 28

int ms_bitrate_driver_execute_action(MSBitrateDriver *obj, const MSRateControlAction *action){
29
	if (obj->desc->execute_action)
30
		return obj->desc->execute_action(obj,action);
31
	else ms_error("Driver does not implement execute_action");
32 33 34 35 36 37
	return -1;
}

MSBitrateDriver * ms_bitrate_driver_ref(MSBitrateDriver *obj){
	obj->refcnt++;
	return obj;
38 39
}

40 41 42 43 44 45 46
void ms_bitrate_driver_unref(MSBitrateDriver *obj){
	obj->refcnt--;
	if (obj->refcnt<=0){
		if (obj->desc->uninit)
			obj->desc->uninit(obj);
		ms_free(obj);
	}
47 48 49 50
}

struct _MSAudioBitrateDriver{
	MSBitrateDriver parent;
Simon Morlat's avatar
Simon Morlat committed
51
	MSFilter *encoder;
52 53 54 55 56 57 58 59
	int min_ptime;
	int nom_bitrate;
	int cur_ptime;
	int cur_bitrate;
};

typedef struct _MSAudioBitrateDriver MSAudioBitrateDriver;

jehan's avatar
jehan committed
60
static int apply_ptime(MSAudioBitrateDriver *obj,int target_ptime){
61
	char tmp[64];
Simon Morlat's avatar
Simon Morlat committed
62 63 64
	int result=-1;
	
	if (target_ptime < min_ptime || target_ptime>max_ptime) {
jehan's avatar
jehan committed
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
		ms_error("cannot apply ptime value [%i] on [%p] because out of range [%i..%i]",target_ptime,obj,min_ptime,max_ptime);
		return -1;
	}

	if (ms_filter_has_method(obj->encoder,MS_AUDIO_ENCODER_SET_PTIME)) {
		result = ms_filter_call_method(obj->encoder,MS_AUDIO_ENCODER_SET_PTIME,&target_ptime);
	} else {
		/*legacy*/
		snprintf(tmp,sizeof(tmp),"ptime=%i",target_ptime);
		result = ms_filter_call_method(obj->encoder,MS_FILTER_ADD_FMTP,tmp);
	}

	if (ms_filter_has_method(obj->encoder,MS_AUDIO_ENCODER_GET_PTIME)) {
		ms_filter_call_method(obj->encoder,MS_AUDIO_ENCODER_GET_PTIME,&obj->cur_ptime);
	} else {
		/*legacy*/
		if (result==0) {
			obj->cur_ptime=target_ptime;
		} /*else ptime remain unchanged*/
	}
	if (result == 0) {
		ms_message("AudioBitrateController [%p]: ptime is now  [%i ms]",obj,obj->cur_ptime);
	} else {
		ms_message("AudioBitrateController [%p]: cannot move ptime from [%i ms] to [%i ms]",obj,obj->cur_ptime,target_ptime);
	}


	return result;
93 94 95
}

static int inc_ptime(MSAudioBitrateDriver *obj){
jehan's avatar
jehan committed
96 97 98 99 100
	return apply_ptime(obj,obj->cur_ptime+obj->min_ptime);
}

static int dec_ptime(MSAudioBitrateDriver *obj){
	return apply_ptime(obj,obj->cur_ptime-obj->min_ptime);
101 102
}

103 104 105
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);
Simon Morlat's avatar
Simon Morlat committed
106 107 108 109

	if (obj->nom_bitrate==0){
		ms_filter_call_method(obj->encoder,MS_FILTER_GET_BITRATE,&obj->nom_bitrate);
		if (obj->nom_bitrate==0){
110
			ms_warning("MSAudioBitrateDriver: Not doing bitrate control on audio encoder, it does not seem to support that. Controlling ptime only.");
Simon Morlat's avatar
Simon Morlat committed
111
			obj->nom_bitrate=-1;
112 113
		}else 
			obj->cur_bitrate=obj->nom_bitrate;
Simon Morlat's avatar
Simon Morlat committed
114
	}
jehan's avatar
jehan committed
115
	if (obj->cur_ptime==0 || ms_filter_has_method(obj->encoder,MS_AUDIO_ENCODER_GET_PTIME)){ /*always sync current ptime if possible*/
116 117 118 119 120 121
		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;
		}
	}
Simon Morlat's avatar
Simon Morlat committed
122

123
	if (action->type==MSRateControlActionDecreaseBitrate){
Simon Morlat's avatar
Simon Morlat committed
124
		/*reducing bitrate of the codec isn't sufficient. Increasing ptime is much more efficient*/
jehan's avatar
jehan committed
125
		if (inc_ptime(obj)){
126 127 128 129 130 131 132 133 134 135
			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;
				}
136
				obj->cur_bitrate=cur_br;
137 138 139 140 141
				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");
jehan's avatar
jehan committed
142
					return inc_ptime(obj);
143 144 145 146 147
				}
				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;
Simon Morlat's avatar
Simon Morlat committed
148
			}
149 150
		}
	}else if (action->type==MSRateControlActionDecreasePacketRate){
jehan's avatar
jehan committed
151
		return inc_ptime(obj);
152
	}else if (action->type==MSRateControlActionIncreaseQuality){
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
		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){
jehan's avatar
jehan committed
168
			return dec_ptime(obj);
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
		}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);
187
	obj->parent.desc=&audio_bitrate_driver;
188
	obj->encoder=encoder;
189 190
	obj->min_ptime=20;
	obj->cur_ptime=0;
191
	obj->cur_bitrate=obj->nom_bitrate=0;
192
	return (MSBitrateDriver*)obj;
193
}
194 195 196 197 198 199 200 201 202 203 204 205 206 207

static const int min_video_bitrate=64000;
static const float increase_ramp=1.1;

typedef struct _MSAVBitrateDriver{
	MSBitrateDriver parent;
	MSBitrateDriver *audio_driver;
	MSFilter *venc;
	int nom_bitrate;
	int cur_bitrate;
}MSAVBitrateDriver;

static int dec_video_bitrate(MSAVBitrateDriver *obj, const MSRateControlAction *action){
	int new_br;
208
	
209 210
	ms_filter_call_method(obj->venc,MS_FILTER_GET_BITRATE,&obj->cur_bitrate);
	new_br=((float)obj->cur_bitrate)*(100.0-(float)action->value)/100.0;
211 212 213 214
	if (new_br<min_video_bitrate){
		ms_message("MSAVBitrateDriver: reaching low bound.");
		new_br=min_video_bitrate;
	}
215 216 217
	ms_message("MSAVBitrateDriver: targeting %i bps for video encoder.",new_br);
	ms_filter_call_method(obj->venc,MS_FILTER_SET_BITRATE,&new_br);
	obj->cur_bitrate=new_br;
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
	return new_br==min_video_bitrate ? -1 : 0;
}

static int inc_video_bitrate(MSAVBitrateDriver *obj, const MSRateControlAction *action){
	int newbr;
	int ret=0;
	
	newbr=(float)obj->cur_bitrate*(1.0+((float)action->value/100.0));
	if (newbr>obj->nom_bitrate){
		newbr=obj->nom_bitrate;
		ret=-1;
	}
	obj->cur_bitrate=newbr;
	ms_message("MSAVBitrateDriver: increasing bitrate to %i bps for video encoder.",obj->cur_bitrate);
	ms_filter_call_method(obj->venc,MS_FILTER_SET_BITRATE,&obj->cur_bitrate);
	return ret;
234 235 236 237 238
}

static int av_driver_execute_action(MSBitrateDriver *objbase, const MSRateControlAction *action){
	MSAVBitrateDriver *obj=(MSAVBitrateDriver*)objbase;
	int ret=0;
239 240 241 242 243 244 245 246
	if (obj->nom_bitrate==0){
		ms_filter_call_method(obj->venc,MS_FILTER_GET_BITRATE,&obj->nom_bitrate);
		if (obj->nom_bitrate==0){
			ms_warning("MSAVBitrateDriver: Not doing adaptive rate control on video encoder, it does not seem to support that.");
			return -1;
		}
	}
	
247 248 249 250 251 252 253 254 255 256
	switch(action->type){
		case MSRateControlActionDecreaseBitrate:
			ret=dec_video_bitrate(obj,action);
		break;
		case MSRateControlActionDecreasePacketRate:
			if (obj->audio_driver){
				ret=ms_bitrate_driver_execute_action(obj->audio_driver,action);
			}
		break;
		case MSRateControlActionIncreaseQuality:
257
			ret=inc_video_bitrate(obj,action);
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
		break;
		case MSRateControlActionDoNothing:
		break;
	}
	return ret;
}

static void av_bitrate_driver_uninit(MSBitrateDriver *objbase){
	MSAVBitrateDriver *obj=(MSAVBitrateDriver*)objbase;
	if (obj->audio_driver)
		ms_bitrate_driver_unref(obj->audio_driver);
	
}

static MSBitrateDriverDesc av_bitrate_driver={
	av_driver_execute_action,
	av_bitrate_driver_uninit
};

MSBitrateDriver *ms_av_bitrate_driver_new(MSFilter *aenc, MSFilter *venc){
	MSAVBitrateDriver *obj=ms_new0(MSAVBitrateDriver,1);
	obj->parent.desc=&av_bitrate_driver;
	obj->audio_driver=(aenc!=NULL) ? ms_bitrate_driver_ref(ms_audio_bitrate_driver_new(aenc)) : NULL;
	obj->venc=venc;
	
	return (MSBitrateDriver*)obj;
}