static int apply_ptime(MSAudioBitrateDriver *obj,int target_ptime){ char tmp[64]; int result=-1; if (target_ptime < min_ptime || target_ptime>max_ptime) { ms_error("MSAudioBitrateDriver [%p]: cannot apply ptime value [%i] on [%p] because out of range [%i..%i]",obj,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("MSAudioBitrateDriver [%p]: ptime is now [%i ms]",obj,obj->cur_ptime); } else { ms_message("MSAudioBitrateDriver [%p]: cannot move ptime from [%i ms] to [%i ms]",obj,obj->cur_ptime,target_ptime); } return result; }
int ms_filter_call_method(MSFilter *f, unsigned int id, void *arg){ /*compatibility stuff*/ if (id==MS_AUDIO_DECODER_SET_RTP_PAYLOAD_PICKER && !ms_filter_has_method(f,MS_AUDIO_DECODER_SET_RTP_PAYLOAD_PICKER)) id=MS_FILTER_SET_RTP_PAYLOAD_PICKER; if (ms_filter_has_method(f, id)) return _ms_filter_call_method(f,id,arg); return -1; }
int video_stream_get_camera_sensor_rotation(VideoStream *stream) { int rotation = -1; if (stream->source) { if (ms_filter_has_method(stream->source, MS_VIDEO_CAPTURE_GET_CAMERA_SENSOR_ROTATION) && ms_filter_call_method(stream->source, MS_VIDEO_CAPTURE_GET_CAMERA_SENSOR_ROTATION, &rotation) == 0) return rotation; } return -1; }
static void qos_analyzer_on_action_suggested(void *user_data, int datac, const char** datav){ reporting_session_report_t *report = (reporting_session_report_t*)user_data; LinphoneCall *call = report->call; char * appendbuf; int i; int ptime = -1; int bitrate[3] = {-1, -1, -1}; int up_bw[3] = {-1, -1, -1}; int down_bw[3] = {-1, -1, -1}; MediaStream *streams[3] = { (MediaStream*) call->audiostream, (MediaStream *) call->videostream, (MediaStream *) call->textstream }; for (i = 0; i < 3; i++){ if (streams[i] != NULL){ if (streams[i]->encoder != NULL){ if (ms_filter_has_method(streams[i]->encoder,MS_FILTER_GET_BITRATE)){ ms_filter_call_method(streams[i]->encoder,MS_FILTER_GET_BITRATE,&bitrate[i]); bitrate[i] /= 1000; } } up_bw[i] = (int)(media_stream_get_up_bw(streams[i])/1000.f); down_bw[i] = (int)(media_stream_get_down_bw(streams[i])/1000.f); } } if (call->audiostream!=NULL){ if (call->audiostream->ms.encoder!=NULL){ if(ms_filter_has_method(call->audiostream->ms.encoder,MS_AUDIO_ENCODER_GET_PTIME)){ ms_filter_call_method(call->audiostream->ms.encoder,MS_AUDIO_ENCODER_GET_PTIME,&ptime); } } } appendbuf=ms_strdup_printf("%s%d;", report->qos_analyzer.timestamp?report->qos_analyzer.timestamp:"", ms_time(0)); STR_REASSIGN(report->qos_analyzer.timestamp,appendbuf); STR_REASSIGN(report->qos_analyzer.input_leg, ms_strdup_printf("%s aenc_ptime aenc_br a_dbw a_ubw venc_br v_dbw v_ubw tenc_br t_dbw t_ubw", datav[0])); appendbuf=ms_strdup_printf("%s%s %d %d %d %d %d %d %d %d %d %d;", report->qos_analyzer.input?report->qos_analyzer.input:"", datav[1], ptime, bitrate[0], down_bw[0], up_bw[0], bitrate[1], down_bw[1], up_bw[1], bitrate[2], down_bw[2], up_bw[2]); STR_REASSIGN(report->qos_analyzer.input,appendbuf); STR_REASSIGN(report->qos_analyzer.output_leg, ms_strdup(datav[2])); appendbuf=ms_strdup_printf("%s%s;", report->qos_analyzer.output?report->qos_analyzer.output:"", datav[3]); STR_REASSIGN(report->qos_analyzer.output, appendbuf); }
MSBitrateDriver *ms_audio_bitrate_driver_new(RtpSession *session, MSFilter *encoder){ MSAudioBitrateDriver *obj=ms_new0(MSAudioBitrateDriver,1); obj->parent.desc=&audio_bitrate_driver; obj->session = session; obj->encoder=encoder; obj->min_ptime=20; obj->cur_ptime=0; obj->cur_bitrate=obj->nom_bitrate=0; if (ms_filter_has_method(obj->encoder, MS_AUDIO_ENCODER_GET_CAPABILITIES)) ms_filter_call_method(obj->encoder, MS_AUDIO_ENCODER_GET_CAPABILITIES, &obj->encoder_caps); return (MSBitrateDriver*)obj; }
unsigned long video_stream_get_native_preview_window_id(VideoStream *stream){ unsigned long id=0; if (stream->output2){ if (ms_filter_call_method(stream->output2,MS_VIDEO_DISPLAY_GET_NATIVE_WINDOW_ID,&id)==0) return id; } if (stream->source){ if (ms_filter_has_method(stream->source,MS_VIDEO_DISPLAY_GET_NATIVE_WINDOW_ID) && ms_filter_call_method(stream->source,MS_VIDEO_DISPLAY_GET_NATIVE_WINDOW_ID,&id)==0) return id; } return stream->preview_window_id; }
static void cut_audio_stream_graph(MSAudioEndpoint *ep, bool_t is_remote){ AudioStream *st=ep->st; /*stop the audio graph*/ ms_ticker_detach(st->ms.sessions.ticker,st->soundread); if (!st->ec) ms_ticker_detach(st->ms.sessions.ticker,st->soundwrite); ep->in_cut_point_prev.pin=0; if (is_remote){ /*we would like to keep the volrecv (MSVolume filter) in the graph to measure the output level*/ ep->in_cut_point_prev.filter=st->volrecv; }else{ ep->in_cut_point_prev.filter=st->plc ? st->plc : st->ms.decoder; } ep->in_cut_point=just_after(ep->in_cut_point_prev.filter); ms_filter_unlink(ep->in_cut_point_prev.filter,ep->in_cut_point_prev.pin,ep->in_cut_point.filter, ep->in_cut_point.pin); ep->out_cut_point=just_before(st->ms.encoder); ms_filter_unlink(ep->out_cut_point.filter,ep->out_cut_point.pin,st->ms.encoder,0); if (ms_filter_has_method(st->ms.encoder,MS_FILTER_GET_SAMPLE_RATE)){ ms_filter_call_method(st->ms.encoder,MS_FILTER_GET_SAMPLE_RATE,&ep->samplerate); }else{ ms_filter_call_method(st->ms.rtpsend,MS_FILTER_GET_SAMPLE_RATE,&ep->samplerate); } if (is_remote){ ep->mixer_in.filter=ep->in_cut_point_prev.filter; ep->mixer_in.pin=ep->in_cut_point_prev.pin; ep->mixer_out.filter=st->ms.encoder; ep->mixer_out.pin=0; }else{ ep->mixer_in=ep->out_cut_point; ep->mixer_out=ep->in_cut_point; } }
int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char *rem_rtp_ip,int rem_rtp_port, const char *rem_rtcp_ip, int rem_rtcp_port, int payload,int jitt_comp, const char *infile, const char *outfile, MSSndCard *playcard, MSSndCard *captcard, bool_t use_ec) { RtpSession *rtps=stream->ms.session; PayloadType *pt,*tel_ev; int tmp; MSConnectionHelper h; int sample_rate; MSRtpPayloadPickerContext picker_context; bool_t has_builtin_ec=FALSE; rtp_session_set_profile(rtps,profile); if (rem_rtp_port>0) rtp_session_set_remote_addr_full(rtps,rem_rtp_ip,rem_rtp_port,rem_rtcp_ip,rem_rtcp_port); if (rem_rtcp_port<=0){ rtp_session_enable_rtcp(rtps,FALSE); } rtp_session_set_payload_type(rtps,payload); rtp_session_set_jitter_compensation(rtps,jitt_comp); if (rem_rtp_port>0) ms_filter_call_method(stream->ms.rtpsend,MS_RTP_SEND_SET_SESSION,rtps); stream->ms.rtprecv=ms_filter_new(MS_RTP_RECV_ID); ms_filter_call_method(stream->ms.rtprecv,MS_RTP_RECV_SET_SESSION,rtps); stream->ms.session=rtps; if((stream->features & AUDIO_STREAM_FEATURE_DTMF) != 0) stream->dtmfgen=ms_filter_new(MS_DTMF_GEN_ID); else stream->dtmfgen=NULL; rtp_session_signal_connect(rtps,"telephone-event",(RtpCallback)on_dtmf_received,(unsigned long)stream); rtp_session_signal_connect(rtps,"payload_type_changed",(RtpCallback)mediastream_payload_type_changed,(unsigned long)&stream->ms); /* creates the local part */ if (captcard!=NULL){ if (stream->soundread==NULL) stream->soundread=ms_snd_card_create_reader(captcard); has_builtin_ec=!!(ms_snd_card_get_capabilities(captcard) & MS_SND_CARD_CAP_BUILTIN_ECHO_CANCELLER); }else { stream->soundread=ms_filter_new(MS_FILE_PLAYER_ID); stream->read_resampler=ms_filter_new(MS_RESAMPLE_ID); if (infile!=NULL) audio_stream_play(stream,infile); } if (playcard!=NULL) { if (stream->soundwrite==NULL) stream->soundwrite=ms_snd_card_create_writer(playcard); }else { stream->soundwrite=ms_filter_new(MS_FILE_REC_ID); if (outfile!=NULL) audio_stream_record(stream,outfile); } /* creates the couple of encoder/decoder */ pt=rtp_profile_get_payload(profile,payload); if (pt==NULL){ ms_error("audiostream.c: undefined payload type."); return -1; } tel_ev=rtp_profile_get_payload_from_mime (profile,"telephone-event"); if ((stream->features & AUDIO_STREAM_FEATURE_DTMF_ECHO) != 0 && (tel_ev==NULL || ( (tel_ev->flags & PAYLOAD_TYPE_FLAG_CAN_RECV) && !(tel_ev->flags & PAYLOAD_TYPE_FLAG_CAN_SEND))) && ( strcasecmp(pt->mime_type,"pcmu")==0 || strcasecmp(pt->mime_type,"pcma")==0)){ /*if no telephone-event payload is usable and pcma or pcmu is used, we will generate inband dtmf*/ stream->dtmfgen_rtp=ms_filter_new (MS_DTMF_GEN_ID); } else { stream->dtmfgen_rtp=NULL; } if (ms_filter_call_method(stream->ms.rtpsend,MS_FILTER_GET_SAMPLE_RATE,&sample_rate)!=0){ ms_error("Sample rate is unknown for RTP side !"); return -1; } stream->ms.encoder=ms_filter_create_encoder(pt->mime_type); stream->ms.decoder=ms_filter_create_decoder(pt->mime_type); if ((stream->ms.encoder==NULL) || (stream->ms.decoder==NULL)){ /* big problem: we have not a registered codec for this payload...*/ ms_error("audio_stream_start_full: No decoder or encoder available for payload %s.",pt->mime_type); return -1; } if (ms_filter_has_method(stream->ms.decoder, MS_FILTER_SET_RTP_PAYLOAD_PICKER)) { ms_message(" decoder has FEC capabilities"); picker_context.filter_graph_manager=stream; picker_context.picker=&audio_stream_payload_picker; ms_filter_call_method(stream->ms.decoder,MS_FILTER_SET_RTP_PAYLOAD_PICKER, &picker_context); } if((stream->features & AUDIO_STREAM_FEATURE_VOL_SND) != 0) stream->volsend=ms_filter_new(MS_VOLUME_ID); else stream->volsend=NULL; if((stream->features & AUDIO_STREAM_FEATURE_VOL_RCV) != 0) stream->volrecv=ms_filter_new(MS_VOLUME_ID); else stream->volrecv=NULL; audio_stream_enable_echo_limiter(stream,stream->el_type); audio_stream_enable_noise_gate(stream,stream->use_ng); if (stream->use_agc){ int tmp=1; if (stream->volsend==NULL) stream->volsend=ms_filter_new(MS_VOLUME_ID); ms_filter_call_method(stream->volsend,MS_VOLUME_ENABLE_AGC,&tmp); } if (stream->dtmfgen) { ms_filter_call_method(stream->dtmfgen,MS_FILTER_SET_SAMPLE_RATE,&sample_rate); ms_filter_call_method(stream->dtmfgen,MS_FILTER_SET_NCHANNELS,&pt->channels); } if (stream->dtmfgen_rtp) { ms_filter_call_method(stream->dtmfgen_rtp,MS_FILTER_SET_SAMPLE_RATE,&sample_rate); ms_filter_call_method(stream->dtmfgen_rtp,MS_FILTER_SET_NCHANNELS,&pt->channels); } /* give the sound filters some properties */ if (ms_filter_call_method(stream->soundread,MS_FILTER_SET_SAMPLE_RATE,&sample_rate) != 0) { /* need to add resampler*/ if (stream->read_resampler == NULL) stream->read_resampler=ms_filter_new(MS_RESAMPLE_ID); } ms_filter_call_method(stream->soundread,MS_FILTER_SET_NCHANNELS,&pt->channels); if (ms_filter_call_method(stream->soundwrite,MS_FILTER_SET_SAMPLE_RATE,&sample_rate) != 0) { /* need to add resampler*/ if (stream->write_resampler == NULL) stream->write_resampler=ms_filter_new(MS_RESAMPLE_ID); } ms_filter_call_method(stream->soundwrite,MS_FILTER_SET_NCHANNELS,&pt->channels); // Override feature if ( ((stream->features & AUDIO_STREAM_FEATURE_EC) && !use_ec) || has_builtin_ec ) stream->features &=~AUDIO_STREAM_FEATURE_EC; /*configure the echo canceller if required */ if ((stream->features & AUDIO_STREAM_FEATURE_EC) == 0 && stream->ec != NULL) { ms_filter_destroy(stream->ec); stream->ec=NULL; } if (stream->ec){ if (!stream->is_ec_delay_set){ int delay_ms=ms_snd_card_get_minimal_latency(captcard); if (delay_ms!=0){ ms_message("Setting echo canceller delay with value provided by soundcard: %i ms",delay_ms); ms_filter_call_method(stream->ec,MS_ECHO_CANCELLER_SET_DELAY,&delay_ms); } } ms_filter_call_method(stream->ec,MS_FILTER_SET_SAMPLE_RATE,&sample_rate); } if (stream->features & AUDIO_STREAM_FEATURE_MIXED_RECORDING){ int val=0; int pin=1; stream->recorder=ms_filter_new(MS_FILE_REC_ID); stream->recorder_mixer=ms_filter_new(MS_AUDIO_MIXER_ID); stream->recv_tee=ms_filter_new(MS_TEE_ID); stream->send_tee=ms_filter_new(MS_TEE_ID); ms_filter_call_method(stream->recorder_mixer,MS_AUDIO_MIXER_ENABLE_CONFERENCE_MODE,&val); ms_filter_call_method(stream->recorder_mixer,MS_FILTER_SET_SAMPLE_RATE,&sample_rate); ms_filter_call_method(stream->recorder_mixer,MS_FILTER_SET_NCHANNELS,&pt->channels); ms_filter_call_method(stream->recv_tee,MS_TEE_MUTE,&pin); ms_filter_call_method(stream->send_tee,MS_TEE_MUTE,&pin); ms_filter_call_method(stream->recorder,MS_FILTER_SET_SAMPLE_RATE,&sample_rate); ms_filter_call_method(stream->recorder,MS_FILTER_SET_NCHANNELS,&pt->channels); } /* give the encoder/decoder some parameters*/ ms_filter_call_method(stream->ms.encoder,MS_FILTER_SET_SAMPLE_RATE,&sample_rate); ms_message("Payload's bitrate is %i",pt->normal_bitrate); if (pt->normal_bitrate>0){ ms_message("Setting audio encoder network bitrate to %i",pt->normal_bitrate); ms_filter_call_method(stream->ms.encoder,MS_FILTER_SET_BITRATE,&pt->normal_bitrate); } ms_filter_call_method(stream->ms.encoder,MS_FILTER_SET_NCHANNELS,&pt->channels); ms_filter_call_method(stream->ms.decoder,MS_FILTER_SET_SAMPLE_RATE,&sample_rate); ms_filter_call_method(stream->ms.decoder,MS_FILTER_SET_NCHANNELS,&pt->channels); if (pt->send_fmtp!=NULL) { char value[16]={0}; int ptime; if (ms_filter_has_method(stream->ms.encoder,MS_AUDIO_ENCODER_SET_PTIME)){ if (fmtp_get_value(pt->send_fmtp,"ptime",value,sizeof(value)-1)){ ptime=atoi(value); ms_filter_call_method(stream->ms.encoder,MS_AUDIO_ENCODER_SET_PTIME,&ptime); } } ms_filter_call_method(stream->ms.encoder,MS_FILTER_ADD_FMTP, (void*)pt->send_fmtp); } if (pt->recv_fmtp!=NULL) ms_filter_call_method(stream->ms.decoder,MS_FILTER_ADD_FMTP,(void*)pt->recv_fmtp); /*create the equalizer*/ if ((stream->features & AUDIO_STREAM_FEATURE_EQUALIZER) != 0){ stream->equalizer=ms_filter_new(MS_EQUALIZER_ID); if(stream->equalizer) { tmp=stream->eq_active; ms_filter_call_method(stream->equalizer,MS_EQUALIZER_SET_ACTIVE,&tmp); } }else stream->equalizer=NULL; /*configure resampler if needed*/ ms_filter_call_method(stream->ms.rtpsend, MS_FILTER_SET_NCHANNELS, &pt->channels); ms_filter_call_method(stream->ms.rtprecv, MS_FILTER_SET_NCHANNELS, &pt->channels); if (stream->read_resampler){ audio_stream_configure_resampler(stream->read_resampler,stream->soundread,stream->ms.rtpsend); } if (stream->write_resampler){ audio_stream_configure_resampler(stream->write_resampler,stream->ms.rtprecv,stream->soundwrite); } if (stream->ms.use_rc){ stream->ms.rc=ms_audio_bitrate_controller_new(stream->ms.session,stream->ms.encoder,0); } /* Create PLC */ if ((stream->features & AUDIO_STREAM_FEATURE_PLC) != 0) { int decoder_have_plc = 0; if (ms_filter_has_method(stream->ms.decoder, MS_AUDIO_DECODER_HAVE_PLC)) { if (ms_filter_call_method(stream->ms.decoder, MS_AUDIO_DECODER_HAVE_PLC, &decoder_have_plc) != 0) { ms_warning("MS_AUDIO_DECODER_HAVE_PLC function error: enable default plc"); } } else { ms_warning("MS_DECODER_HAVE_PLC function not implemented by the decoder: enable default plc"); } if (decoder_have_plc == 0) { stream->plc = ms_filter_new(MS_GENERIC_PLC_ID); } if (stream->plc) { ms_filter_call_method(stream->plc, MS_FILTER_SET_NCHANNELS, &pt->channels); ms_filter_call_method(stream->plc, MS_FILTER_SET_SAMPLE_RATE, &sample_rate); } } else { stream->plc = NULL; } /* create ticker */ if (stream->ms.ticker==NULL) start_ticker(&stream->ms); else{ /*we were using the dummy preload graph, destroy it*/ if (stream->dummy) stop_preload_graph(stream); } /* and then connect all */ /* tip: draw yourself the picture if you don't understand */ /*sending graph*/ ms_connection_helper_start(&h); ms_connection_helper_link(&h,stream->soundread,-1,0); if (stream->read_resampler) ms_connection_helper_link(&h,stream->read_resampler,0,0); if (stream->ec) ms_connection_helper_link(&h,stream->ec,1,1); if (stream->volsend) ms_connection_helper_link(&h,stream->volsend,0,0); if (stream->dtmfgen_rtp) ms_connection_helper_link(&h,stream->dtmfgen_rtp,0,0); if (stream->send_tee) ms_connection_helper_link(&h,stream->send_tee,0,0); ms_connection_helper_link(&h,stream->ms.encoder,0,0); ms_connection_helper_link(&h,stream->ms.rtpsend,0,-1); /*receiving graph*/ ms_connection_helper_start(&h); ms_connection_helper_link(&h,stream->ms.rtprecv,-1,0); ms_connection_helper_link(&h,stream->ms.decoder,0,0); if (stream->plc) ms_connection_helper_link(&h,stream->plc,0,0); if (stream->dtmfgen) ms_connection_helper_link(&h,stream->dtmfgen,0,0); if (stream->volrecv) ms_connection_helper_link(&h,stream->volrecv,0,0); if (stream->recv_tee) ms_connection_helper_link(&h,stream->recv_tee,0,0); if (stream->equalizer) ms_connection_helper_link(&h,stream->equalizer,0,0); if (stream->ec) ms_connection_helper_link(&h,stream->ec,0,0); if (stream->write_resampler) ms_connection_helper_link(&h,stream->write_resampler,0,0); ms_connection_helper_link(&h,stream->soundwrite,0,-1); /*call recording part, attached to both outgoing and incoming graphs*/ if (stream->recorder){ ms_filter_link(stream->send_tee,1,stream->recorder_mixer,0); ms_filter_link(stream->recv_tee,1,stream->recorder_mixer,1); ms_filter_link(stream->recorder_mixer,0,stream->recorder,0); } /*to make sure all preprocess are done before befre processing audio*/ ms_ticker_attach_multiple(stream->ms.ticker ,stream->soundread ,stream->ms.rtprecv ,NULL); stream->ms.start_time=ms_time(NULL); stream->ms.is_beginning=TRUE; return 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; }