/*this function makes a special case for speex/8000. This codec is variable bitrate. The 8kbit/s mode is interesting when having a low upload bandwidth, but its quality is not very good. We 'd better use its 15kbt/s mode when we have enough bandwidth*/ static int get_codec_bitrate(LinphoneCore *lc, const PayloadType *pt){ int upload_bw=linphone_core_get_upload_bandwidth(lc); if (bandwidth_is_greater(upload_bw,129) || (bandwidth_is_greater(upload_bw,33) && !linphone_core_video_enabled(lc)) ) { if (strcmp(pt->mime_type,"speex")==0 && pt->clock_rate==8000){ return 15000; } } return pt->normal_bitrate; }
static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *md, const SalStreamDescription *desc, int *used_pt){ int bw; const MSList *elem; RtpProfile *prof=rtp_profile_new("Call profile"); bool_t first=TRUE; int remote_bw=0; LinphoneCore *lc=call->core; int up_ptime=0; *used_pt=-1; for(elem=desc->payloads;elem!=NULL;elem=elem->next){ PayloadType *pt=(PayloadType*)elem->data; int number; if ((pt->flags & PAYLOAD_TYPE_FLAG_CAN_SEND) && first) { if (desc->type==SalAudio){ linphone_core_update_allocated_audio_bandwidth_in_call(call,pt); up_ptime=linphone_core_get_upload_ptime(lc); } *used_pt=payload_type_get_number(pt); first=FALSE; } if (desc->bandwidth>0) remote_bw=desc->bandwidth; else if (md->bandwidth>0) { /*case where b=AS is given globally, not per stream*/ remote_bw=md->bandwidth; if (desc->type==SalVideo){ remote_bw=get_video_bandwidth(remote_bw,call->audio_bw); } } if (desc->type==SalAudio){ bw=get_min_bandwidth(call->audio_bw,remote_bw); }else bw=get_min_bandwidth(get_video_bandwidth(linphone_core_get_upload_bandwidth (lc),call->audio_bw),remote_bw); if (bw>0) pt->normal_bitrate=bw*1000; else if (desc->type==SalAudio){ pt->normal_bitrate=-1; } if (desc->ptime>0){ up_ptime=desc->ptime; } if (up_ptime>0){ char tmp[40]; snprintf(tmp,sizeof(tmp),"ptime=%i",up_ptime); payload_type_append_send_fmtp(pt,tmp); } number=payload_type_get_number(pt); if (rtp_profile_get_payload(prof,number)!=NULL){ ms_warning("A payload type with number %i already exists in profile !",number); }else rtp_profile_set_payload(prof,number,pt); } return prof; }
/* return TRUE if codec can be used with bandwidth, FALSE else*/ bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, PayloadType *pt) { double codec_band; int allowed_bw,video_bw; bool_t ret=FALSE; linphone_core_update_allocated_audio_bandwidth(lc); allowed_bw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc), linphone_core_get_upload_bandwidth(lc)); if (allowed_bw==0) { allowed_bw=-1; video_bw=1500; /*around 1.5 Mbit/s*/ }else video_bw=get_video_bandwidth(allowed_bw,lc->audio_bw); switch (pt->type){ case PAYLOAD_AUDIO_CONTINUOUS: case PAYLOAD_AUDIO_PACKETIZED: codec_band=get_audio_payload_bandwidth(lc,pt); ret=bandwidth_is_greater(allowed_bw*1000,codec_band); /*hack to avoid using uwb codecs when having low bitrate and video*/ if (bandwidth_is_greater(199,allowed_bw)){ if (linphone_core_video_enabled(lc) && pt->clock_rate>16000){ ret=FALSE; } } //ms_message("Payload %s: %g",pt->mime_type,codec_band); break; case PAYLOAD_VIDEO: if (video_bw>0){ pt->normal_bitrate=video_bw*1000; ret=TRUE; } else ret=FALSE; break; } return ret; }
void linphone_gtk_show_login_frame(LinphoneProxyConfig *cfg){ GtkWidget *mw=linphone_gtk_get_main_window(); GtkWidget *label=linphone_gtk_get_widget(mw,"login_label"); const LinphoneAuthInfo *ai; gchar *str; LinphoneAddress *from; LinphoneCore *lc=linphone_gtk_get_core(); int nettype; const char *passwd=NULL; if (linphone_core_get_download_bandwidth(lc)==512 && linphone_core_get_upload_bandwidth(lc)==512) nettype=NetworkKindOpticalFiber; else nettype=NetworkKindAdsl; gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(mw,"login_internet_kind")),nettype); gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(mw,"internet_kind")),nettype); if (linphone_gtk_get_ui_config_int("automatic_login",0) ){ g_timeout_add(250,(GSourceFunc)do_login_noprompt,cfg); return; } { const char *login_image=linphone_gtk_get_ui_config("login_image",NULL); if (login_image){ GdkPixbuf *pbuf=create_pixbuf (login_image); gtk_image_set_from_pixbuf (GTK_IMAGE(linphone_gtk_get_widget(mw,"login_image")), pbuf); g_object_unref(G_OBJECT(pbuf)); } } gtk_widget_hide(linphone_gtk_get_widget(mw,"disconnect_item")); gtk_widget_hide(linphone_gtk_get_widget(mw,"main_frame")); gtk_widget_show(linphone_gtk_get_widget(mw,"login_frame")); gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"main_menu"),FALSE); gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"options_menu"),FALSE); str=g_strdup_printf(_("Please enter login information for %s"),linphone_proxy_config_get_domain(cfg)); gtk_label_set_text(GTK_LABEL(label),str); g_object_set_data(G_OBJECT(mw),"login_proxy_config",cfg); g_free(str); from=linphone_address_new(linphone_proxy_config_get_identity(cfg)); if (linphone_address_get_username(from)[0]=='?'){ const char *username=linphone_gtk_get_ui_config ("login_username",NULL); if (username) linphone_address_set_username(from,username); } ai=linphone_core_find_auth_info(lc,linphone_proxy_config_get_domain(cfg),linphone_address_get_username(from)); /*display the last entered username, if not '?????'*/ if (linphone_address_get_username(from)[0]!='?') gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(mw,"login_username")), linphone_address_get_username(from)); if (ai) passwd=linphone_auth_info_get_passwd(ai); gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(mw,"login_password")), passwd!=NULL ? passwd : ""); linphone_address_destroy(from); }
static int media_parameters_changed(LinphoneCall *call, SalMediaDescription *oldmd, SalMediaDescription *newmd) { if (call->params.in_conference != call->current_params.in_conference) return SAL_MEDIA_DESCRIPTION_CHANGED; if (call->up_bw != linphone_core_get_upload_bandwidth(call->core)) return SAL_MEDIA_DESCRIPTION_CHANGED; if (call->localdesc_changed) ms_message("Local description has changed: %i", call->localdesc_changed); return call->localdesc_changed | sal_media_description_equals(oldmd, newmd); }
static bool_t media_parameters_changed(LinphoneCall *call, SalMediaDescription *oldmd, SalMediaDescription *newmd){ return !sal_media_description_equals(oldmd,newmd) || call->up_bw!=linphone_core_get_upload_bandwidth(call->core); }
void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_muted, bool_t send_ringbacktone){ LinphoneCore *lc=call->core; LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc); const char *tool="linphone-" LINPHONE_VERSION; char *cname; int used_pt=-1; #ifdef VIDEO_ENABLED const SalStreamDescription *vstream=sal_media_description_find_stream(call->resultdesc, SalProtoRtpAvp,SalVideo); #endif bool_t use_arc=linphone_core_adaptive_rate_control_enabled(lc); if(call->audiostream == NULL) { ms_fatal("start_media_stream() called without prior init !"); return; } call->current_params = call->params; /* adjust rtp jitter compensation. It must be at least the latency of the sound card */ int jitt_comp=MAX(lc->sound_conf.latency,lc->rtp_conf.audio_jitt_comp); if (call->media_start_time==0) call->media_start_time=time(NULL); cname=linphone_address_as_string_uri_only(me); { const SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc, SalProtoRtpAvp,SalAudio); if (stream && stream->dir!=SalStreamInactive && stream->port!=0){ MSSndCard *playcard=lc->sound_conf.lsd_card ? lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard; MSSndCard *captcard=lc->sound_conf.capt_sndcard; const char *playfile=lc->play_file; const char *recfile=lc->rec_file; call->audio_profile=make_profile(call,call->resultdesc,stream,&used_pt); bool_t use_ec,use_arc_audio=use_arc; if (used_pt!=-1){ if (playcard==NULL) { ms_warning("No card defined for playback !"); } if (captcard==NULL) { ms_warning("No card defined for capture !"); } /*Replace soundcard filters by inactive file players or recorders when placed in recvonly or sendonly mode*/ if (stream->port==0 || stream->dir==SalStreamRecvOnly){ captcard=NULL; playfile=NULL; }else if (stream->dir==SalStreamSendOnly){ playcard=NULL; captcard=NULL; recfile=NULL; /*And we will eventually play "playfile" if set by the user*/ /*playfile=NULL;*/ } if (send_ringbacktone){ captcard=NULL; playfile=NULL;/* it is setup later*/ } /*if playfile are supplied don't use soundcards*/ if (lc->use_files) { captcard=NULL; playcard=NULL; } use_ec=captcard==NULL ? FALSE : linphone_core_echo_cancellation_enabled(lc); #if defined(VIDEO_ENABLED) if (vstream && vstream->dir!=SalStreamInactive && vstream->payloads!=NULL){ /*when video is used, do not make adaptive rate control on audio, it is stupid.*/ use_arc_audio=FALSE; #if defined(ANDROID) /*On android we have to disable the echo canceller to preserve CPU for video codecs */ use_ec=FALSE; #endif } #endif audio_stream_enable_adaptive_bitrate_control(call->audiostream,use_arc_audio); audio_stream_start_full( call->audiostream, call->audio_profile, stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr, stream->port, stream->port+1, used_pt, jitt_comp, playfile, recfile, playcard, captcard, use_ec ); post_configure_audio_streams(call); if (all_inputs_muted && !send_ringbacktone){ audio_stream_set_mic_gain(call->audiostream,0); } if (stream->dir==SalStreamSendOnly && playfile!=NULL){ int pause_time=500; ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time); } if (send_ringbacktone){ setup_ring_player(lc,call); } audio_stream_set_rtcp_information(call->audiostream, cname, tool); }else ms_warning("No audio stream accepted ?"); } } #ifdef VIDEO_ENABLED { used_pt=-1; /* shutdown preview */ if (lc->previewstream!=NULL) { video_preview_stop(lc->previewstream); lc->previewstream=NULL; } call->current_params.has_video=FALSE; if (vstream && vstream->dir!=SalStreamInactive && vstream->port!=0) { const char *addr=vstream->addr[0]!='\0' ? vstream->addr : call->resultdesc->addr; call->video_profile=make_profile(call,call->resultdesc,vstream,&used_pt); if (used_pt!=-1){ VideoStreamDir dir=VideoStreamSendRecv; MSWebCam *cam=lc->video_conf.device; bool_t is_inactive=FALSE; call->current_params.has_video=TRUE; video_stream_set_sent_video_size(call->videostream,linphone_core_get_preferred_video_size(lc)); video_stream_enable_self_view(call->videostream,lc->video_conf.selfview); if (lc->video_window_id!=0) video_stream_set_native_window_id(call->videostream,lc->video_window_id); if (lc->preview_window_id!=0) video_stream_set_native_preview_window_id (call->videostream,lc->preview_window_id); video_stream_use_preview_video_window (call->videostream,lc->use_preview_window); if (vstream->dir==SalStreamSendOnly && lc->video_conf.capture ){ cam=get_nowebcam_device(); dir=VideoStreamSendOnly; }else if (vstream->dir==SalStreamRecvOnly && lc->video_conf.display ){ dir=VideoStreamRecvOnly; }else if (vstream->dir==SalStreamSendRecv){ if (lc->video_conf.display && lc->video_conf.capture) dir=VideoStreamSendRecv; else if (lc->video_conf.display) dir=VideoStreamRecvOnly; else dir=VideoStreamSendOnly; }else{ ms_warning("video stream is inactive."); /*either inactive or incompatible with local capabilities*/ is_inactive=TRUE; } if (call->camera_active==FALSE || all_inputs_muted){ cam=get_nowebcam_device(); } if (!is_inactive){ video_stream_set_direction (call->videostream, dir); video_stream_start(call->videostream, call->video_profile, addr, vstream->port, vstream->port+1, used_pt, jitt_comp, cam); video_stream_set_rtcp_information(call->videostream, cname,tool); } }else ms_warning("No video stream accepted."); }else{ ms_warning("No valid video stream defined."); } } #endif call->all_muted=all_inputs_muted; call->playing_ringbacktone=send_ringbacktone; call->up_bw=linphone_core_get_upload_bandwidth(lc); if (ortp_zrtp_available()) { OrtpZrtpParams params; params.zid=get_hexa_zrtp_identifier(lc); params.zid_file=lc->zrtp_secrets_cache; audio_stream_enable_zrtp(call->audiostream,¶ms); } goto end; end: ms_free(cname); linphone_address_destroy(me); }