90 changes: 81 additions & 9 deletions src/voip/bitratedriver.c
Expand Up @@ -143,6 +143,27 @@ static int audio_bitrate_driver_execute_action(MSBitrateDriver *objbase, const M
obj->cur_ptime-=obj->min_ptime;
apply_ptime(obj);
}else return -1;
}else if (action->type==MSRateControlSetBitrate){
if (obj->nom_bitrate>0){
ms_message("MSAudioBitrateDriver: setting bitrate of codec to %i",action->value);
int new_br=action->value;
if (ms_filter_call_method(obj->encoder,MS_FILTER_SET_BITRATE,&new_br)!=0){
if (ms_filter_call_method(obj->encoder,MS_FILTER_GET_BITRATE,&obj->cur_bitrate)!=0){
ms_message("MSAudioBitrateDriver: Encoder has current bitrate %i",obj->cur_bitrate);
}
if (action->value > obj->cur_bitrate){
if (obj->cur_ptime>obj->min_ptime){
obj->cur_ptime-=obj->min_ptime;
apply_ptime(obj);
}else{
return -1;
}
}else{
ms_message("MSAudioBitrateDriver: SET_BITRATE failed, incrementing ptime");
inc_ptime(obj);
}
}
}
}
return 0;
}
Expand Down Expand Up @@ -176,48 +197,93 @@ typedef struct _MSAVBitrateDriver{
MSBitrateDriver *audio_driver;
MSFilter *venc;
int nom_bitrate;
int bitrate_limit;
int cur_bitrate;
int set_hold;
}MSAVBitrateDriver;

static int dec_video_bitrate(MSAVBitrateDriver *obj, const MSRateControlAction *action){
int new_br;

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;

if(obj->nom_bitrate > obj->cur_bitrate){
obj->nom_bitrate=obj->cur_bitrate;
}
if(obj->nom_bitrate*10 < obj->cur_bitrate){
obj->nom_bitrate=obj->cur_bitrate/2;
}
new_br=((float)obj->nom_bitrate)*(100.0-(float)action->value)/100.0;
if (new_br<min_video_bitrate){
ms_message("MSAVBitrateDriver: reaching low bound.");
new_br=min_video_bitrate;
}
obj->nom_bitrate=obj->cur_bitrate=new_br;
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;
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;
ms_filter_call_method(obj->venc,MS_FILTER_GET_BITRATE,&obj->cur_bitrate);
if(obj->nom_bitrate*10 < obj->cur_bitrate){
obj->nom_bitrate=obj->cur_bitrate/2;
}
if(obj->nom_bitrate > obj->cur_bitrate*10){
obj->nom_bitrate=obj->cur_bitrate*2;
}
newbr=(float)obj->nom_bitrate*(1.0+((float)action->value/100.0));
if(newbr<min_video_bitrate){
ret=-1;
newbr=min_video_bitrate;
}
if(newbr > obj->bitrate_limit){
newbr=obj->bitrate_limit;
ret=-1;
}
obj->cur_bitrate=newbr;
obj->nom_bitrate=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;
}

static int set_video_bitrate(MSAVBitrateDriver *obj, const MSRateControlAction *action){
int ret=0;
int proposed_bitrate;

proposed_bitrate=action->value*0.9; //leave 10% for fluctuations
obj->set_hold++;
if(proposed_bitrate < min_video_bitrate){
proposed_bitrate=min_video_bitrate;
}
if(proposed_bitrate > obj->bitrate_limit){
proposed_bitrate=obj->bitrate_limit;
ret=-1;
}
if(obj->set_hold > 4 &&
((obj->cur_bitrate - proposed_bitrate > obj->cur_bitrate*0.1) ||
(proposed_bitrate - obj->cur_bitrate > obj->cur_bitrate*0.2)) ){
obj->nom_bitrate=obj->cur_bitrate=proposed_bitrate;
obj->set_hold=0;
ms_message("MSAVBitrateDriver: setting 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;
}

static int av_driver_execute_action(MSBitrateDriver *objbase, const MSRateControlAction *action){
MSAVBitrateDriver *obj=(MSAVBitrateDriver*)objbase;
int ret=0;
if (obj->nom_bitrate==0){
ms_filter_call_method(obj->venc,MS_FILTER_GET_BITRATE,&obj->nom_bitrate);
if (obj->nom_bitrate==0){
if (obj->bitrate_limit==0){
ms_filter_call_method(obj->venc,MS_FILTER_GET_BITRATE,&obj->bitrate_limit);
if (obj->bitrate_limit==0){
ms_warning("MSAVBitrateDriver: Not doing adaptive rate control on video encoder, it does not seem to support that.");
return -1;
}
obj->nom_bitrate=obj->bitrate_limit;
}

switch(action->type){
Expand All @@ -228,12 +294,17 @@ static int av_driver_execute_action(MSBitrateDriver *objbase, const MSRateContro
if (obj->audio_driver){
ret=ms_bitrate_driver_execute_action(obj->audio_driver,action);
}
ret=dec_video_bitrate(obj,action);
break;
case MSRateControlActionIncreaseQuality:
ret=inc_video_bitrate(obj,action);
break;
case MSRateControlActionDoNothing:
break;
case MSRateControlSetBitrate:
ret=set_video_bitrate(obj,action);
break;

}
return ret;
}
Expand All @@ -255,6 +326,7 @@ MSBitrateDriver *ms_av_bitrate_driver_new(MSFilter *aenc, MSFilter *venc){
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;
obj->set_hold=0;

return (MSBitrateDriver*)obj;
}
Expand Down
8 changes: 7 additions & 1 deletion src/voip/mediastream.c
Expand Up @@ -116,10 +116,16 @@ MSTickerPrio __ms_get_default_prio(bool_t is_video) {
#endif
}

RtpSession * create_duplex_rtpsession(int loc_rtp_port, int loc_rtcp_port, bool_t ipv6) {
RtpSession * create_duplex_rtpsession(int loc_rtp_port, int loc_rtcp_port, bool_t ipv6, bool_t dccp, int ccid) {
RtpSession *rtpr;

rtpr = rtp_session_new(RTP_SESSION_SENDRECV);
if(dccp){
rtp_session_set_use_dccp(rtpr,TRUE);
if(ccid > 0){
rtp_session_set_dccp_ccid(rtpr,ccid);
}
}
rtp_session_set_recv_buf_size(rtpr, ms_get_mtu());
rtp_session_set_scheduling_mode(rtpr, 0);
rtp_session_set_blocking_mode(rtpr, 0);
Expand Down
2 changes: 1 addition & 1 deletion src/voip/private.h
Expand Up @@ -43,7 +43,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

MSTickerPrio __ms_get_default_prio(bool_t is_video);

MEDIASTREAMER2_INTERNAL_EXPORT RtpSession * create_duplex_rtpsession(int loc_rtp_port, int loc_rtcp_port, bool_t ipv6);
MEDIASTREAMER2_INTERNAL_EXPORT RtpSession * create_duplex_rtpsession(int loc_rtp_port, int loc_rtcp_port, bool_t ipv6, bool_t dccp, int ccid);

void start_ticker(MediaStream *stream);

Expand Down
56 changes: 51 additions & 5 deletions src/voip/qosanalyzer.c
Expand Up @@ -34,6 +34,14 @@ bool_t ms_qos_analyser_process_rtcp(MSQosAnalyser *obj,mblk_t *msg){
return FALSE;
}

bool_t ms_qos_analyser_process_rejected_send(MSQosAnalyser *obj){
if (obj->desc->process_rejected_send){
return obj->desc->process_rejected_send(obj);
}
ms_error("Unimplemented process_rejected_send() call.");
return FALSE;
}

void ms_qos_analyser_suggest_action(MSQosAnalyser *obj, MSRateControlAction *action){
if (obj->desc->suggest_action){
obj->desc->suggest_action(obj,action);
Expand Down Expand Up @@ -75,6 +83,7 @@ typedef struct rtpstats{
float lost_percentage; /*percentage of lost packet since last report*/
float int_jitter; /*interrarrival jitter */
float rt_prop; /*round trip propagation*/
bool_t send_refused;
}rtpstats_t;


Expand All @@ -88,6 +97,8 @@ const char *ms_rate_control_action_type_name(MSRateControlActionType t){
return "DecreaseBitrate";
case MSRateControlActionDecreasePacketRate:
return "DecreasePacketRate";
case MSRateControlSetBitrate:
return "SetBitRate";
}
return "bad action type";
}
Expand All @@ -100,7 +111,8 @@ typedef struct _MSSimpleQosAnalyser{
rtpstats_t stats[STATS_HISTORY];
int curindex;
bool_t rt_prop_doubled;
bool_t pad[3];
bool_t send_was_refused;
bool_t pad[2];
}MSSimpleQosAnalyser;


Expand All @@ -127,11 +139,26 @@ static bool_t rt_prop_increased(MSSimpleQosAnalyser *obj){
return FALSE;
}

static bool_t simple_analyser_process_rejected_send(MSQosAnalyser *objbase){
MSSimpleQosAnalyser *obj=(MSSimpleQosAnalyser*)objbase;
rtpstats_t *cur;

cur=&obj->stats[obj->curindex % STATS_HISTORY];
cur->send_refused=TRUE;
obj->send_was_refused=TRUE;
return TRUE;
}


static bool_t simple_analyser_process_rtcp(MSQosAnalyser *objbase, mblk_t *rtcp){
MSSimpleQosAnalyser *obj=(MSSimpleQosAnalyser*)objbase;
rtpstats_t *cur;
const report_block_t *rb=NULL;

if(obj->session->rtp.is_dccp){
return TRUE;
}

if (rtcp_is_SR(rtcp)){
rb=rtcp_SR_get_report_block(rtcp,0);
}else if (rtcp_is_RR(rtcp)){
Expand Down Expand Up @@ -169,9 +196,15 @@ static void simple_analyser_suggest_action(MSQosAnalyser *objbase, MSRateControl
action->type=MSRateControlActionDecreaseBitrate;
action->value=20;
ms_message("MSQosAnalyser: rt_prop doubled.");
}else if (cur->send_refused){
action->type=MSRateControlActionDecreaseBitrate;
action->value=30;
ms_message("MSQosAnalyser: send refused, cut bitrate");
cur->send_refused=FALSE;
}else if (cur->lost_percentage>=unacceptable_loss_rate){
/*big loss rate but no jitter, and no big rtp_prop: pure lossy network*/
action->type=MSRateControlActionDecreasePacketRate;
action->value=20; /*For video, this is equivalent to Decreasing bitrate*/
ms_message("MSQosAnalyser: loss rate unacceptable.");
}else{
action->type=MSRateControlActionDoNothing;
Expand All @@ -184,16 +217,28 @@ static bool_t simple_analyser_has_improved(MSQosAnalyser *objbase){
rtpstats_t *cur=&obj->stats[obj->curindex % STATS_HISTORY];
rtpstats_t *prev=&obj->stats[(STATS_HISTORY+obj->curindex-1) % STATS_HISTORY];

if(cur->send_refused==TRUE){
goto end;
}
if (prev->lost_percentage>=unacceptable_loss_rate){
if (cur->lost_percentage<prev->lost_percentage){
ms_message("MSQosAnalyser: lost percentage has improved");
return TRUE;
}else goto end;
}
if (obj->rt_prop_doubled && cur->rt_prop<prev->rt_prop){
ms_message("MSQosAnalyser: rt prop decrased");
obj->rt_prop_doubled=FALSE;
return TRUE;
if (obj->rt_prop_doubled){
if(cur->rt_prop<prev->rt_prop){
ms_message("MSQosAnalyser: rt prop decrased");
obj->rt_prop_doubled=FALSE;
return TRUE;
}else goto end;
}

if (obj->send_was_refused){
if(cur->send_refused==FALSE){
obj->send_was_refused=FALSE;
return TRUE;
}else goto end;
}

end:
Expand All @@ -202,6 +247,7 @@ static bool_t simple_analyser_has_improved(MSQosAnalyser *objbase){
}

static MSQosAnalyserDesc simple_analyser_desc={
simple_analyser_process_rejected_send,
simple_analyser_process_rtcp,
simple_analyser_suggest_action,
simple_analyser_has_improved
Expand Down
10 changes: 7 additions & 3 deletions src/voip/videostream.c
Expand Up @@ -32,7 +32,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

#include <ortp/zrtp.h>


void video_stream_free(VideoStream *stream) {
/* Prevent filters from being destroyed two times */
if (stream->source_performs_encoding == TRUE) {
Expand Down Expand Up @@ -118,6 +117,11 @@ void video_stream_iterate(VideoStream *stream){
video_steam_process_rtcp(stream,evd->packet);
}else if ((evt == ORTP_EVENT_STUN_PACKET_RECEIVED) && (stream->ms.ice_check_list)) {
ice_handle_stun_packet(stream->ms.ice_check_list,stream->ms.session,ortp_event_get_data(ev));
}else if(evt==ORTP_EVENT_SEND_REJECTED && stream->ms.rc){
ms_bitrate_controller_process_rejected_send(stream->ms.rc);
}else if(evt==ORTP_EVENT_BANDWIDTH && stream->ms.rc){
OrtpEventData *evd=ortp_event_get_data(ev);
ms_bitrate_controler_process_bandwidth_update(stream->ms.rc, evd->info.bandwidth);
}
ortp_event_destroy(ev);
}
Expand All @@ -143,10 +147,10 @@ static void choose_display_name(VideoStream *stream){
#endif
}

VideoStream *video_stream_new(int loc_rtp_port, int loc_rtcp_port, bool_t use_ipv6){
VideoStream *video_stream_new(int loc_rtp_port, int loc_rtcp_port, bool_t use_ipv6, bool_t dccp, int ccid){
VideoStream *stream = (VideoStream *)ms_new0 (VideoStream, 1);
stream->ms.type = VideoStreamType;
stream->ms.session=create_duplex_rtpsession(loc_rtp_port,loc_rtcp_port,use_ipv6);
stream->ms.session=create_duplex_rtpsession(loc_rtp_port,loc_rtcp_port,use_ipv6, dccp, ccid);
stream->ms.qi=ms_quality_indicator_new(stream->ms.session);
stream->ms.evq=ortp_ev_queue_new();
stream->ms.rtpsend=ms_filter_new(MS_RTP_SEND_ID);
Expand Down
4 changes: 2 additions & 2 deletions tools/mediastream.c
Expand Up @@ -613,7 +613,7 @@ void setup_media_streams(MediastreamDatas* args) {
ms_snd_card_manager_get_card(manager,args->capture_card);
MSSndCard *play= args->playback_card==NULL ? ms_snd_card_manager_get_default_playback_card(manager) :
ms_snd_card_manager_get_card(manager,args->playback_card);
args->audio=audio_stream_new(args->localport,args->localport+1,ms_is_ipv6(args->ip));
args->audio=audio_stream_new(args->localport,args->localport+1,ms_is_ipv6(args->ip),FALSE,0);
audio_stream_enable_automatic_gain_control(args->audio,args->agc);
audio_stream_enable_noise_gate(args->audio,args->use_ng);
audio_stream_set_echo_canceller_params(args->audio,args->ec_len_ms,args->ec_delay_ms,args->ec_framesize);
Expand Down Expand Up @@ -706,7 +706,7 @@ void setup_media_streams(MediastreamDatas* args) {
exit(-1);
}
ms_message("Starting video stream.\n");
args->video=video_stream_new(args->localport, args->localport+1, ms_is_ipv6(args->ip));
args->video=video_stream_new(args->localport, args->localport+1, ms_is_ipv6(args->ip),FALSE,0);
#ifdef ANDROID
if (args->device_rotation >= 0)
video_stream_set_device_rotation(args->video, args->device_rotation);
Expand Down