Started rework of streams' indexes for RTT

This commit is contained in:
Sylvain Berfini 2015-09-15 17:13:30 +02:00
parent e141a5ea38
commit 15b6353e30
10 changed files with 439 additions and 123 deletions

View file

@ -739,6 +739,8 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md,
stream->type=SalAudio;
} else if ( strcasecmp ( "video", mtype ) == 0 ) {
stream->type=SalVideo;
} else if ( strcasecmp ( "text", mtype ) == 0 ) {
stream->type=SalText;
} else {
stream->type=SalOther;
strncpy ( stream->typeother,mtype,sizeof ( stream->typeother )-1 );

View file

@ -118,6 +118,11 @@ static bool_t linphone_call_all_streams_encrypted(const LinphoneCall *call) {
if (media_stream_secured((MediaStream *)call->videostream))
number_of_encrypted_stream++;
}
if (call->textstream && media_stream_get_state((MediaStream *)call->textstream) == MSStreamStarted) {
number_of_active_stream++;
if (media_stream_secured((MediaStream *)call->textstream))
number_of_encrypted_stream++;
}
}
return number_of_active_stream>0 && number_of_active_stream==number_of_encrypted_stream;
}
@ -401,20 +406,22 @@ static MSList *make_codec_list(LinphoneCore *lc, CodecConstraints * hints, SalSt
return l;
}
static void update_media_description_from_stun(SalMediaDescription *md, const StunCandidate *ac, const StunCandidate *vc){
static void update_media_description_from_stun(SalMediaDescription *md, const StunCandidate *ac, const StunCandidate *vc, const StunCandidate *tc){
int i;
for (i = 0; i < md->nb_streams; i++) {
if (!sal_stream_description_active(&md->streams[i])) continue;
if ((md->streams[i].type == SalAudio) && (ac->port != 0)) {
strcpy(md->streams[0].rtp_addr,ac->addr);
md->streams[0].rtp_port=ac->port;
strcpy(md->streams[i].rtp_addr,ac->addr);
md->streams[i].rtp_port=ac->port;
if ((ac->addr[0]!='\0' && vc->addr[0]!='\0' && strcmp(ac->addr,vc->addr)==0) || sal_media_description_get_nb_active_streams(md)==1){
strcpy(md->addr,ac->addr);
}
}
if ((md->streams[i].type == SalVideo) && (vc->port != 0)) {
strcpy(md->streams[1].rtp_addr,vc->addr);
md->streams[1].rtp_port=vc->port;
} else if ((md->streams[i].type == SalVideo) && (vc->port != 0)) {
strcpy(md->streams[i].rtp_addr,vc->addr);
md->streams[i].rtp_port=vc->port;
} else if ((md->streams[i].type == SalText) && (tc->port != 0)) {
strcpy(md->streams[i].rtp_addr,tc->addr);
md->streams[i].rtp_port=tc->port;
}
}
}
@ -594,7 +601,7 @@ static void force_streams_dir_according_to_state(LinphoneCall *call, SalMediaDes
break;
}
for (i=0; i<2; ++i){
for (i=0; i<md->nb_streams; ++i){
SalStreamDescription *sd = &md->streams[i];
sd->dir = SalStreamSendOnly;
if (sd->type == SalVideo){
@ -617,16 +624,15 @@ void linphone_call_make_local_media_description(LinphoneCall *call) {
LinphoneCallParams *params = call->params;
LinphoneCore *lc = call->core;
/*multicast is only set in case of outgoing call*/
if (call->dir == LinphoneCallOutgoing && linphone_call_params_audio_multicast_enabled(params)) {
md->streams[0].ttl=linphone_core_get_audio_multicast_ttl(lc);
md->streams[0].multicast_role = SalMulticastSender;
md->streams[call->main_audio_stream_index].ttl=linphone_core_get_audio_multicast_ttl(lc);
md->streams[call->main_audio_stream_index].multicast_role = SalMulticastSender;
}
if (call->dir == LinphoneCallOutgoing && linphone_call_params_video_multicast_enabled(params)) {
md->streams[1].ttl=linphone_core_get_video_multicast_ttl(lc);
md->streams[1].multicast_role = SalMulticastSender;
md->streams[call->main_video_stream_index].ttl=linphone_core_get_video_multicast_ttl(lc);
md->streams[call->main_video_stream_index].multicast_role = SalMulticastSender;
}
subject=linphone_call_params_get_session_name(params);
@ -655,28 +661,28 @@ void linphone_call_make_local_media_description(LinphoneCall *call) {
else md->bandwidth=linphone_core_get_download_bandwidth(lc);
/*set audio capabilities */
strncpy(md->streams[0].rtp_addr,linphone_call_get_public_ip_for_stream(call,0),sizeof(md->streams[0].rtp_addr));
strncpy(md->streams[0].rtcp_addr,linphone_call_get_public_ip_for_stream(call,0),sizeof(md->streams[0].rtcp_addr));
strncpy(md->streams[0].name,"Audio",sizeof(md->streams[0].name)-1);
md->streams[0].rtp_port=call->media_ports[0].rtp_port;
md->streams[0].rtcp_port=call->media_ports[0].rtcp_port;
md->streams[0].proto=get_proto_from_call_params(params);
md->streams[0].dir=get_audio_dir_from_call_params(params);
md->streams[0].type=SalAudio;
strncpy(md->streams[call->main_audio_stream_index].rtp_addr,linphone_call_get_public_ip_for_stream(call,call->main_audio_stream_index),sizeof(md->streams[call->main_audio_stream_index].rtp_addr));
strncpy(md->streams[call->main_audio_stream_index].rtcp_addr,linphone_call_get_public_ip_for_stream(call,call->main_audio_stream_index),sizeof(md->streams[call->main_audio_stream_index].rtcp_addr));
strncpy(md->streams[call->main_audio_stream_index].name,"Audio",sizeof(md->streams[call->main_audio_stream_index].name)-1);
md->streams[call->main_audio_stream_index].rtp_port=call->media_ports[call->main_audio_stream_index].rtp_port;
md->streams[call->main_audio_stream_index].rtcp_port=call->media_ports[call->main_audio_stream_index].rtcp_port;
md->streams[call->main_audio_stream_index].proto=get_proto_from_call_params(params);
md->streams[call->main_audio_stream_index].dir=get_audio_dir_from_call_params(params);
md->streams[call->main_audio_stream_index].type=SalAudio;
if (params->down_ptime)
md->streams[0].ptime=params->down_ptime;
md->streams[call->main_audio_stream_index].ptime=params->down_ptime;
else
md->streams[0].ptime=linphone_core_get_download_ptime(lc);
md->streams[call->main_audio_stream_index].ptime=linphone_core_get_download_ptime(lc);
codec_hints.bandwidth_limit=params->audio_bw;
codec_hints.max_codecs=-1;
codec_hints.previously_used=old_md ? old_md->streams[0].already_assigned_payloads : NULL;
codec_hints.previously_used=old_md ? old_md->streams[call->main_audio_stream_index].already_assigned_payloads : NULL;
l=make_codec_list(lc, &codec_hints, SalAudio, lc->codecs_conf.audio_codecs);
md->streams[0].max_rate=get_max_codec_sample_rate(l);
md->streams[0].payloads=l;
md->streams[call->main_audio_stream_index].max_rate=get_max_codec_sample_rate(l);
md->streams[call->main_audio_stream_index].payloads=l;
if (call->audiostream && call->audiostream->ms.sessions.rtp_session) {
char* me = linphone_address_as_string_uri_only(call->me);
md->streams[0].rtp_ssrc=rtp_session_get_send_ssrc(call->audiostream->ms.sessions.rtp_session);
strncpy(md->streams[0].rtcp_cname,me,sizeof(md->streams[0].rtcp_cname));
md->streams[call->main_audio_stream_index].rtp_ssrc=rtp_session_get_send_ssrc(call->audiostream->ms.sessions.rtp_session);
strncpy(md->streams[call->main_audio_stream_index].rtcp_cname,me,sizeof(md->streams[call->main_audio_stream_index].rtcp_cname));
ms_free(me);
}
else
@ -684,23 +690,23 @@ void linphone_call_make_local_media_description(LinphoneCall *call) {
nb_active_streams++;
if (params->has_video && (!params->internal_call_update || !call->current_params->video_declined)){
strncpy(md->streams[1].rtp_addr,linphone_call_get_public_ip_for_stream(call,1),sizeof(md->streams[1].rtp_addr));
strncpy(md->streams[1].rtcp_addr,linphone_call_get_public_ip_for_stream(call,1),sizeof(md->streams[1].rtcp_addr));
strncpy(md->streams[1].name,"Video",sizeof(md->streams[1].name)-1);
md->streams[1].rtp_port=call->media_ports[1].rtp_port;
md->streams[1].rtcp_port=call->media_ports[1].rtcp_port;
md->streams[1].proto=md->streams[0].proto;
md->streams[1].dir=get_video_dir_from_call_params(params);
md->streams[1].type=SalVideo;
strncpy(md->streams[call->main_video_stream_index].rtp_addr,linphone_call_get_public_ip_for_stream(call,call->main_video_stream_index),sizeof(md->streams[call->main_video_stream_index].rtp_addr));
strncpy(md->streams[call->main_video_stream_index].rtcp_addr,linphone_call_get_public_ip_for_stream(call,call->main_video_stream_index),sizeof(md->streams[call->main_video_stream_index].rtcp_addr));
strncpy(md->streams[call->main_video_stream_index].name,"Video",sizeof(md->streams[call->main_video_stream_index].name)-1);
md->streams[call->main_video_stream_index].rtp_port=call->media_ports[call->main_video_stream_index].rtp_port;
md->streams[call->main_video_stream_index].rtcp_port=call->media_ports[call->main_video_stream_index].rtcp_port;
md->streams[call->main_video_stream_index].proto=md->streams[call->main_video_stream_index].proto;
md->streams[call->main_video_stream_index].dir=get_video_dir_from_call_params(params);
md->streams[call->main_video_stream_index].type=SalVideo;
codec_hints.bandwidth_limit=0;
codec_hints.max_codecs=-1;
codec_hints.previously_used=old_md ? old_md->streams[1].already_assigned_payloads : NULL;
codec_hints.previously_used=old_md ? old_md->streams[call->main_video_stream_index].already_assigned_payloads : NULL;
l=make_codec_list(lc, &codec_hints, SalVideo, lc->codecs_conf.video_codecs);
md->streams[1].payloads=l;
md->streams[call->main_video_stream_index].payloads=l;
if (call->videostream && call->videostream->ms.sessions.rtp_session) {
char* me = linphone_address_as_string_uri_only(call->me);
md->streams[1].rtp_ssrc=rtp_session_get_send_ssrc(call->videostream->ms.sessions.rtp_session);
strncpy(md->streams[1].rtcp_cname,me,sizeof(md->streams[1].rtcp_cname));
md->streams[call->main_video_stream_index].rtp_ssrc=rtp_session_get_send_ssrc(call->videostream->ms.sessions.rtp_session);
strncpy(md->streams[call->main_video_stream_index].rtcp_cname,me,sizeof(md->streams[call->main_video_stream_index].rtcp_cname));
ms_free(me);
}
else
@ -709,6 +715,33 @@ void linphone_call_make_local_media_description(LinphoneCall *call) {
} else {
ms_message("Don't put video stream on local offer for call [%p]",call);
}
if (params->realtimetext_enabled) {
strncpy(md->streams[call->main_text_stream_index].rtp_addr,linphone_call_get_public_ip_for_stream(call,call->main_text_stream_index),sizeof(md->streams[call->main_text_stream_index].rtp_addr));
strncpy(md->streams[call->main_text_stream_index].rtcp_addr,linphone_call_get_public_ip_for_stream(call,call->main_text_stream_index),sizeof(md->streams[call->main_text_stream_index].rtcp_addr));
strncpy(md->streams[call->main_text_stream_index].name,"Text",sizeof(md->streams[call->main_text_stream_index].name)-1);
md->streams[call->main_text_stream_index].rtp_port=call->media_ports[call->main_text_stream_index].rtp_port;
md->streams[call->main_text_stream_index].rtcp_port=call->media_ports[call->main_text_stream_index].rtcp_port;
md->streams[call->main_text_stream_index].proto=md->streams[call->main_text_stream_index].proto;
md->streams[call->main_text_stream_index].dir=SalStreamSendRecv;
md->streams[call->main_text_stream_index].type=SalText;
codec_hints.bandwidth_limit=0;
codec_hints.max_codecs=-1;
codec_hints.previously_used=old_md ? old_md->streams[call->main_text_stream_index].already_assigned_payloads : NULL;
l=make_codec_list(lc, &codec_hints, SalText, lc->codecs_conf.text_codecs);
md->streams[call->main_text_stream_index].payloads=l;
if (call->textstream && call->textstream->ms.sessions.rtp_session) {
char* me = linphone_address_as_string_uri_only(call->me);
md->streams[call->main_text_stream_index].rtp_ssrc=rtp_session_get_send_ssrc(call->textstream->ms.sessions.rtp_session);
strncpy(md->streams[call->main_text_stream_index].rtcp_cname,me,sizeof(md->streams[call->main_text_stream_index].rtcp_cname));
ms_free(me);
}
else
ms_warning("Cannot get text local ssrc for call [%p]",call);
nb_active_streams++;
} else {
ms_message("Don't put text stream on local offer for call [%p]",call);
}
if (md->nb_streams < nb_active_streams)
md->nb_streams = nb_active_streams;
@ -731,7 +764,7 @@ void linphone_call_make_local_media_description(LinphoneCall *call) {
setup_rtcp_fb(call, md);
setup_rtcp_xr(call, md);
update_media_description_from_stun(md,&call->ac,&call->vc);
update_media_description_from_stun(md, &call->ac, &call->vc, &call->tc);
call->localdesc=md;
linphone_call_update_local_media_description_from_ice_or_upnp(call);
linphone_address_destroy(addr);
@ -838,13 +871,17 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from,
linphone_address_ref(call->me);
linphone_core_get_audio_port_range(call->core, &min_port, &max_port);
port_config_set(call,0,min_port,max_port);
port_config_set(call,call->main_audio_stream_index,min_port,max_port);
linphone_core_get_video_port_range(call->core, &min_port, &max_port);
port_config_set(call,1,min_port,max_port);
port_config_set(call,call->main_video_stream_index,min_port,max_port);
linphone_core_get_text_port_range(call->core, &min_port, &max_port);
port_config_set(call,call->main_text_stream_index,min_port,max_port);
linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO], LINPHONE_CALL_STATS_AUDIO);
linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO], LINPHONE_CALL_STATS_VIDEO);
linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_TEXT], LINPHONE_CALL_STATS_TEXT);
}
void linphone_call_init_stats(LinphoneCallStats *stats, int type) {
@ -961,21 +998,25 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphoneCall, belle_sip_object_t,
);
void linphone_call_fill_media_multicast_addr(LinphoneCall *call) {
if (linphone_call_params_audio_multicast_enabled(call->params)){
strncpy(call->media_ports[0].multicast_ip,
linphone_core_get_audio_multicast_addr(call->core), sizeof(call->media_ports[0].multicast_ip));
strncpy(call->media_ports[call->main_audio_stream_index].multicast_ip,
linphone_core_get_audio_multicast_addr(call->core), sizeof(call->media_ports[call->main_audio_stream_index].multicast_ip));
} else
call->media_ports[0].multicast_ip[0]='\0';
call->media_ports[call->main_audio_stream_index].multicast_ip[0]='\0';
if (linphone_call_params_video_multicast_enabled(call->params)){
strncpy(call->media_ports[1].multicast_ip,
linphone_core_get_video_multicast_addr(call->core), sizeof(call->media_ports[1].multicast_ip));
strncpy(call->media_ports[call->main_video_stream_index].multicast_ip,
linphone_core_get_video_multicast_addr(call->core), sizeof(call->media_ports[call->main_video_stream_index].multicast_ip));
} else
call->media_ports[1].multicast_ip[0]='\0';
call->media_ports[call->main_video_stream_index].multicast_ip[0]='\0';
}
LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg){
LinphoneCall *call = belle_sip_object_new(LinphoneCall);
call->main_audio_stream_index = LINPHONE_CALL_STATS_AUDIO;
call->main_video_stream_index = LINPHONE_CALL_STATS_VIDEO;
call->main_text_stream_index = LINPHONE_CALL_STATS_TEXT;
call->dir=LinphoneCallOutgoing;
call->core=lc;
linphone_call_outgoing_select_ip_version(call,to,cfg);
@ -1045,6 +1086,10 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
SalMediaDescription *md;
LinphoneFirewallPolicy fpol;
int i;
call->main_audio_stream_index = LINPHONE_CALL_STATS_AUDIO;
call->main_video_stream_index = LINPHONE_CALL_STATS_VIDEO;
call->main_text_stream_index = LINPHONE_CALL_STATS_TEXT;
call->dir=LinphoneCallIncoming;
sal_op_set_user_pointer(op,call);
@ -1102,6 +1147,16 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
if (md->streams[i].rtp_addr[0]!='\0' && ms_is_multicast(md->streams[i].rtp_addr)){
md->streams[i].multicast_role = SalMulticastReceiver;
strncpy(call->media_ports[i].multicast_ip,md->streams[i].rtp_addr,sizeof(call->media_ports[i].multicast_ip));
if (sal_stream_description_active(&md->streams[i])) {
if (md->streams[i].type == SalAudio) {
call->main_audio_stream_index = i;
} else if (md->streams[i].type == SalVideo) {
call->main_video_stream_index = i;
} else if (md->streams[i].type == SalText) {
call->main_text_stream_index = i;
}
}
}
}
}
@ -1163,12 +1218,14 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
*/
void linphone_call_free_media_resources(LinphoneCall *call){
linphone_call_stop_media_streams(call);
ms_media_stream_sessions_uninit(&call->sessions[0]);
ms_media_stream_sessions_uninit(&call->sessions[1]);
ms_media_stream_sessions_uninit(&call->sessions[call->main_audio_stream_index]);
ms_media_stream_sessions_uninit(&call->sessions[call->main_video_stream_index]);
ms_media_stream_sessions_uninit(&call->sessions[call->main_text_stream_index]);
linphone_call_delete_upnp_session(call);
linphone_call_delete_ice_session(call);
linphone_call_stats_uninit(&call->stats[0]);
linphone_call_stats_uninit(&call->stats[1]);
linphone_call_stats_uninit(&call->stats[call->main_audio_stream_index]);
linphone_call_stats_uninit(&call->stats[call->main_video_stream_index]);
linphone_call_stats_uninit(&call->stats[call->main_text_stream_index]);
}
/*
@ -1458,7 +1515,7 @@ static unsigned int linphone_call_get_n_active_streams(const LinphoneCall *call)
md = sal_call_get_remote_media_description(call->op);
if (!md)
return 0;
return sal_media_description_nb_active_streams_of_type(md, SalAudio) + sal_media_description_nb_active_streams_of_type(md, SalVideo);
return sal_media_description_nb_active_streams_of_type(md, SalAudio) + sal_media_description_nb_active_streams_of_type(md, SalVideo) + sal_media_description_nb_active_streams_of_type(md, SalText);
}
/**
@ -1535,6 +1592,8 @@ const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call){
call->current_params->video_multicast_enabled = ms_is_multicast(rtp_addr);
} else
call->current_params->video_multicast_enabled = FALSE;
sd=sal_media_description_find_best_stream(md,SalText);
}
return call->current_params;
@ -1558,6 +1617,7 @@ const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call){
unsigned int i;
unsigned int nb_audio_streams = sal_media_description_nb_active_streams_of_type(md, SalAudio);
unsigned int nb_video_streams = sal_media_description_nb_active_streams_of_type(md, SalVideo);
unsigned int nb_text_streams = sal_media_description_nb_active_streams_of_type(md, SalText);
for (i = 0; i < nb_video_streams; i++) {
sd = sal_media_description_get_active_stream_of_type(md, SalVideo, i);
@ -1568,6 +1628,10 @@ const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call){
sd = sal_media_description_get_active_stream_of_type(md, SalAudio, i);
if (sal_stream_description_has_srtp(sd) == TRUE) cp->media_encryption = LinphoneMediaEncryptionSRTP;
}
for (i = 0; i < nb_text_streams; i++) {
sd = sal_media_description_get_active_stream_of_type(md, SalText, i);
if (sal_stream_description_has_srtp(sd) == TRUE) cp->media_encryption = LinphoneMediaEncryptionSRTP;
}
if (!cp->has_video){
if (md->bandwidth>0 && md->bandwidth<=linphone_core_get_edge_bw(call->core)){
cp->low_bandwidth=TRUE;
@ -1926,8 +1990,9 @@ int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){
has_video=linphone_core_video_enabled(call->core) && linphone_core_media_description_contains_video_stream(remote);
}else has_video=call->params->has_video;
_linphone_call_prepare_ice_for_stream(call,0,TRUE);
if (has_video) _linphone_call_prepare_ice_for_stream(call,1,TRUE);
_linphone_call_prepare_ice_for_stream(call,call->main_audio_stream_index,TRUE);
if (has_video) _linphone_call_prepare_ice_for_stream(call,call->main_video_stream_index,TRUE);
if (call->params->realtimetext_enabled) _linphone_call_prepare_ice_for_stream(call,call->main_text_stream_index,TRUE);
/*start ICE gathering*/
if (incoming_offer)
linphone_call_update_ice_from_remote_media_description(call,remote); /*this may delete the ice session*/
@ -2024,7 +2089,7 @@ void linphone_call_init_audio_stream(LinphoneCall *call){
snprintf(rtcp_tool,sizeof(rtcp_tool)-1,"%s-%s",linphone_core_get_user_agent_name(),linphone_core_get_user_agent_version());
if (call->audiostream != NULL) return;
if (call->sessions[0].rtp_session==NULL){
if (call->sessions[call->main_audio_stream_index].rtp_session==NULL){
SalMulticastRole multicast_role = linphone_call_get_multicast_role(call,SalAudio);
SalMediaDescription *remotedesc=NULL;
SalStreamDescription *stream_desc = NULL;
@ -2032,24 +2097,24 @@ void linphone_call_init_audio_stream(LinphoneCall *call){
if (remotedesc)
stream_desc = sal_media_description_find_best_stream(remotedesc, SalAudio);
call->audiostream=audiostream=audio_stream_new2(linphone_call_get_bind_ip_for_stream(call,0),
multicast_role == SalMulticastReceiver ? stream_desc->rtp_port : call->media_ports[0].rtp_port,
multicast_role == SalMulticastReceiver ? 0 /*disabled for now*/ : call->media_ports[0].rtcp_port);
call->audiostream=audiostream=audio_stream_new2(linphone_call_get_bind_ip_for_stream(call,call->main_audio_stream_index),
multicast_role == SalMulticastReceiver ? stream_desc->rtp_port : call->media_ports[call->main_audio_stream_index].rtp_port,
multicast_role == SalMulticastReceiver ? 0 /*disabled for now*/ : call->media_ports[call->main_audio_stream_index].rtcp_port);
if (multicast_role == SalMulticastReceiver)
linphone_call_join_multicast_group(call, 0, &audiostream->ms);
linphone_call_join_multicast_group(call, call->main_audio_stream_index, &audiostream->ms);
rtp_session_enable_network_simulation(call->audiostream->ms.sessions.rtp_session, &lc->net_conf.netsim_params);
cname = linphone_address_as_string_uri_only(call->me);
audio_stream_set_rtcp_information(call->audiostream, cname, rtcp_tool);
ms_free(cname);
rtp_session_set_symmetric_rtp(audiostream->ms.sessions.rtp_session,linphone_core_symmetric_rtp_enabled(lc));
setup_dtls_params(call, &audiostream->ms);
media_stream_reclaim_sessions(&audiostream->ms, &call->sessions[0]);
media_stream_reclaim_sessions(&audiostream->ms, &call->sessions[call->main_audio_stream_index]);
}else{
call->audiostream=audio_stream_new_with_sessions(&call->sessions[0]);
call->audiostream=audio_stream_new_with_sessions(&call->sessions[call->main_audio_stream_index]);
}
audiostream=call->audiostream;
if (call->media_ports[0].rtp_port==-1){
port_config_set_random_choosed(call,0,audiostream->ms.sessions.rtp_session);
if (call->media_ports[call->main_audio_stream_index].rtp_port==-1){
port_config_set_random_choosed(call,call->main_audio_stream_index,audiostream->ms.sessions.rtp_session);
}
dscp=linphone_core_get_audio_dscp(lc);
if (dscp!=-1)
@ -2098,17 +2163,17 @@ void linphone_call_init_audio_stream(LinphoneCall *call){
rtp_session_get_transports(audiostream->ms.sessions.rtp_session,&meta_rtp,&meta_rtcp);
if (meta_rtp_transport_get_endpoint(meta_rtp) == NULL) {
meta_rtp_transport_set_endpoint(meta_rtp,lc->rtptf->audio_rtp_func(lc->rtptf->audio_rtp_func_data, call->media_ports[0].rtp_port));
meta_rtp_transport_set_endpoint(meta_rtp,lc->rtptf->audio_rtp_func(lc->rtptf->audio_rtp_func_data, call->media_ports[call->main_audio_stream_index].rtp_port));
}
if (meta_rtp_transport_get_endpoint(meta_rtcp) == NULL) {
meta_rtp_transport_set_endpoint(meta_rtcp,lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->media_ports[0].rtcp_port));
meta_rtp_transport_set_endpoint(meta_rtcp,lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->media_ports[call->main_audio_stream_index].rtcp_port));
}
}
call->audiostream_app_evq = ortp_ev_queue_new();
rtp_session_register_event_queue(audiostream->ms.sessions.rtp_session,call->audiostream_app_evq);
_linphone_call_prepare_ice_for_stream(call,0,FALSE);
_linphone_call_prepare_ice_for_stream(call,call->main_audio_stream_index,FALSE);
}
void linphone_call_init_video_stream(LinphoneCall *call){
@ -2125,7 +2190,7 @@ void linphone_call_init_video_stream(LinphoneCall *call){
int dscp=linphone_core_get_video_dscp(lc);
const char *display_filter=linphone_core_get_video_display_filter(lc);
if (call->sessions[1].rtp_session==NULL){
if (call->sessions[call->main_video_stream_index].rtp_session==NULL){
SalMulticastRole multicast_role = linphone_call_get_multicast_role(call,SalVideo);
SalMediaDescription *remotedesc=NULL;
SalStreamDescription *stream_desc = NULL;
@ -2133,24 +2198,24 @@ void linphone_call_init_video_stream(LinphoneCall *call){
if (remotedesc)
stream_desc = sal_media_description_find_best_stream(remotedesc, SalVideo);
call->videostream=video_stream_new2(linphone_call_get_bind_ip_for_stream(call,1),
multicast_role == SalMulticastReceiver ? stream_desc->rtp_port : call->media_ports[1].rtp_port,
multicast_role == SalMulticastReceiver ? 0 /*disabled for now*/ : call->media_ports[1].rtcp_port);
call->videostream=video_stream_new2(linphone_call_get_bind_ip_for_stream(call,call->main_video_stream_index),
multicast_role == SalMulticastReceiver ? stream_desc->rtp_port : call->media_ports[call->main_video_stream_index].rtp_port,
multicast_role == SalMulticastReceiver ? 0 /*disabled for now*/ : call->media_ports[call->main_video_stream_index].rtcp_port);
if (multicast_role == SalMulticastReceiver)
linphone_call_join_multicast_group(call, 1, &call->videostream->ms);
linphone_call_join_multicast_group(call, call->main_video_stream_index, &call->videostream->ms);
rtp_session_enable_network_simulation(call->videostream->ms.sessions.rtp_session, &lc->net_conf.netsim_params);
cname = linphone_address_as_string_uri_only(call->me);
video_stream_set_rtcp_information(call->videostream, cname, rtcp_tool);
ms_free(cname);
rtp_session_set_symmetric_rtp(call->videostream->ms.sessions.rtp_session,linphone_core_symmetric_rtp_enabled(lc));
setup_dtls_params(call, &call->videostream->ms);
media_stream_reclaim_sessions(&call->videostream->ms, &call->sessions[1]);
media_stream_reclaim_sessions(&call->videostream->ms, &call->sessions[call->main_video_stream_index]);
}else{
call->videostream=video_stream_new_with_sessions(&call->sessions[1]);
call->videostream=video_stream_new_with_sessions(&call->sessions[call->main_video_stream_index]);
}
if (call->media_ports[1].rtp_port==-1){
port_config_set_random_choosed(call,1,call->videostream->ms.sessions.rtp_session);
if (call->media_ports[call->main_video_stream_index].rtp_port==-1){
port_config_set_random_choosed(call,call->main_video_stream_index,call->videostream->ms.sessions.rtp_session);
}
if (dscp!=-1)
video_stream_set_dscp(call->videostream,dscp);
@ -2167,15 +2232,15 @@ void linphone_call_init_video_stream(LinphoneCall *call){
rtp_session_get_transports(call->videostream->ms.sessions.rtp_session,&meta_rtp,&meta_rtcp);
if (meta_rtp_transport_get_endpoint(meta_rtp) == NULL) {
meta_rtp_transport_set_endpoint(meta_rtp,lc->rtptf->video_rtp_func(lc->rtptf->video_rtp_func_data, call->media_ports[1].rtp_port));
meta_rtp_transport_set_endpoint(meta_rtp,lc->rtptf->video_rtp_func(lc->rtptf->video_rtp_func_data, call->media_ports[call->main_video_stream_index].rtp_port));
}
if (meta_rtp_transport_get_endpoint(meta_rtcp) == NULL) {
meta_rtp_transport_set_endpoint(meta_rtcp,lc->rtptf->video_rtcp_func(lc->rtptf->video_rtcp_func_data, call->media_ports[1].rtcp_port));
meta_rtp_transport_set_endpoint(meta_rtcp,lc->rtptf->video_rtcp_func(lc->rtptf->video_rtcp_func_data, call->media_ports[call->main_video_stream_index].rtcp_port));
}
}
call->videostream_app_evq = ortp_ev_queue_new();
rtp_session_register_event_queue(call->videostream->ms.sessions.rtp_session,call->videostream_app_evq);
_linphone_call_prepare_ice_for_stream(call,1,FALSE);
_linphone_call_prepare_ice_for_stream(call,call->main_video_stream_index,FALSE);
#ifdef TEST_EXT_RENDERER
video_stream_set_render_callback(call->videostream,rendercb,NULL);
#endif
@ -2185,9 +2250,61 @@ void linphone_call_init_video_stream(LinphoneCall *call){
#endif
}
void linphone_call_init_text_stream(LinphoneCall *call){
TextStream *textstream;
LinphoneCore *lc=call->core;
char* cname;
if (call->textstream != NULL) return;
if (call->sessions[call->main_text_stream_index].rtp_session == NULL) {
SalMulticastRole multicast_role = linphone_call_get_multicast_role(call, SalText);
SalMediaDescription *remotedesc = NULL;
SalStreamDescription *stream_desc = NULL;
if (call->op) remotedesc = sal_call_get_remote_media_description(call->op);
if (remotedesc) stream_desc = sal_media_description_find_best_stream(remotedesc, SalText);
call->textstream = textstream = text_stream_new2(linphone_call_get_bind_ip_for_stream(call,call->main_text_stream_index),
multicast_role == SalMulticastReceiver ? stream_desc->rtp_port : call->media_ports[call->main_text_stream_index].rtp_port,
multicast_role == SalMulticastReceiver ? 0 /*disabled for now*/ : call->media_ports[call->main_text_stream_index].rtcp_port);
if (multicast_role == SalMulticastReceiver)
linphone_call_join_multicast_group(call, call->main_text_stream_index, &textstream->ms);
rtp_session_enable_network_simulation(call->textstream->ms.sessions.rtp_session, &lc->net_conf.netsim_params);
cname = linphone_address_as_string_uri_only(call->me);
ms_free(cname);
rtp_session_set_symmetric_rtp(textstream->ms.sessions.rtp_session,linphone_core_symmetric_rtp_enabled(lc));
setup_dtls_params(call, &textstream->ms);
media_stream_reclaim_sessions(&textstream->ms, &call->sessions[call->main_text_stream_index]);
} else {
call->textstream = text_stream_new_with_sessions(&call->sessions[call->main_text_stream_index]);
}
textstream = call->textstream;
if (call->media_ports[call->main_text_stream_index].rtp_port == -1) {
port_config_set_random_choosed(call, call->main_text_stream_index, textstream->ms.sessions.rtp_session);
}
if (lc->rtptf){
RtpTransport *meta_rtp;
RtpTransport *meta_rtcp;
rtp_session_get_transports(textstream->ms.sessions.rtp_session, &meta_rtp, &meta_rtcp);
if (meta_rtp_transport_get_endpoint(meta_rtp) == NULL) {
meta_rtp_transport_set_endpoint(meta_rtp,lc->rtptf->audio_rtp_func(lc->rtptf->audio_rtp_func_data, call->media_ports[call->main_text_stream_index].rtp_port));
}
if (meta_rtp_transport_get_endpoint(meta_rtcp) == NULL) {
meta_rtp_transport_set_endpoint(meta_rtcp,lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->media_ports[call->main_text_stream_index].rtcp_port));
}
}
call->textstream_app_evq = ortp_ev_queue_new();
rtp_session_register_event_queue(textstream->ms.sessions.rtp_session, call->textstream_app_evq);
_linphone_call_prepare_ice_for_stream(call, call->main_text_stream_index, FALSE);
}
void linphone_call_init_media_streams(LinphoneCall *call){
linphone_call_init_audio_stream(call);
linphone_call_init_video_stream(call);
linphone_call_init_text_stream(call);
}
@ -2364,6 +2481,8 @@ static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *m
bw=get_ideal_audio_bw(call,md,desc);
else if (desc->type==SalVideo)
bw=get_video_bw(call,md,desc);
//else if (desc->type== SalText)
for(elem=desc->payloads;elem!=NULL;elem=elem->next){
PayloadType *pt=(PayloadType*)elem->data;
@ -2452,7 +2571,7 @@ static void configure_rtp_session_for_rtcp_fb(LinphoneCall *call, const SalStrea
}
static void configure_rtp_session_for_rtcp_xr(LinphoneCore *lc, LinphoneCall *call, SalStreamType type) {
RtpSession *session;
RtpSession *session = NULL;
const OrtpRtcpXrConfiguration *localconfig;
const OrtpRtcpXrConfiguration *remoteconfig;
OrtpRtcpXrConfiguration currentconfig;
@ -2480,8 +2599,10 @@ static void configure_rtp_session_for_rtcp_xr(LinphoneCore *lc, LinphoneCall *ca
}
if (type == SalAudio) {
session = call->audiostream->ms.sessions.rtp_session;
} else {
} else if (type == SalVideo) {
session = call->videostream->ms.sessions.rtp_session;
} else if (type == SalText) {
session = call->textstream->ms.sessions.rtp_session;
}
rtp_session_configure_rtcp_xr(session, &currentconfig);
}
@ -2517,6 +2638,10 @@ void static start_dtls_on_all_streams(LinphoneCall *call) {
,sal_media_description_find_best_stream(result_desc,SalVideo)
,sal_media_description_find_best_stream(remote_desc,SalVideo));
#endif
if (call->textstream && (media_stream_get_state((const MediaStream *)call->textstream) == MSStreamStarted))/*dtls must start at the end of ice*/
start_dtls(&call->textstream->ms.sessions
,sal_media_description_find_best_stream(result_desc,SalText)
,sal_media_description_find_best_stream(remote_desc,SalText));
return;
}
@ -2552,6 +2677,10 @@ void static set_dtls_fingerprint_on_all_streams(LinphoneCall *call) {
,sal_media_description_find_best_stream(result_desc,SalVideo)
,sal_media_description_find_best_stream(remote_desc,SalVideo));
#endif
if (call->textstream && (media_stream_get_state((const MediaStream *)call->textstream) == MSStreamStarted))/*dtls must start at the end of ice*/
set_dtls_fingerprint(&call->textstream->ms.sessions
,sal_media_description_find_best_stream(result_desc,SalText)
,sal_media_description_find_best_stream(remote_desc,SalText));
return;
}
@ -2906,6 +3035,10 @@ static void linphone_call_start_video_stream(LinphoneCall *call, LinphoneCallSta
#endif
}
static void linphone_call_start_text_stream(LinphoneCall *call) {
//TODO textstream
}
static void setZrtpCryptoTypesParameters(MSZrtpParams *params, LinphoneCore *lc)
{
int i;
@ -2986,6 +3119,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, LinphoneCallState nex
call->current_params->audio_codec = NULL;
call->current_params->video_codec = NULL;
call->current_params->text_codec = NULL;
if ((call->audiostream == NULL) && (call->videostream == NULL)) {
ms_fatal("start_media_stream() called without prior init !");
@ -3030,6 +3164,10 @@ void linphone_call_start_media_streams(LinphoneCall *call, LinphoneCallState nex
}
#endif
}
if (call->params->realtimetext_enabled) {
linphone_call_start_text_stream(call);
}
set_dtls_fingerprint_on_all_streams(call);
@ -3077,6 +3215,13 @@ void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescript
if (call->audiostream && local_st_desc && old_stream && new_stream &&
update_stream_crypto_params(call,local_st_desc,old_stream,new_stream,&call->audiostream->ms)){
}
local_st_desc = sal_media_description_find_secure_stream_of_type(call->localdesc, SalText);
old_stream = sal_media_description_find_secure_stream_of_type(old_md, SalText);
new_stream = sal_media_description_find_secure_stream_of_type(new_md, SalText);
if (call->textstream && local_st_desc && old_stream && new_stream &&
update_stream_crypto_params(call,local_st_desc,old_stream,new_stream,&call->textstream->ms)){
}
start_dtls_on_all_streams(call);
@ -3104,8 +3249,10 @@ void linphone_call_delete_ice_session(LinphoneCall *call){
call->ice_session = NULL;
if (call->audiostream != NULL) call->audiostream->ms.ice_check_list = NULL;
if (call->videostream != NULL) call->videostream->ms.ice_check_list = NULL;
if (call->textstream != NULL) call->textstream->ms.ice_check_list = NULL;
call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateNotActivated;
call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateNotActivated;
call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateNotActivated;
}
}
@ -3143,7 +3290,7 @@ static void update_rtp_stats(LinphoneCall *call, int stream_index) {
static void linphone_call_stop_audio_stream(LinphoneCall *call) {
if (call->audiostream!=NULL) {
linphone_reporting_update_media_info(call, LINPHONE_CALL_STATS_AUDIO);
media_stream_reclaim_sessions(&call->audiostream->ms,&call->sessions[0]);
media_stream_reclaim_sessions(&call->audiostream->ms,&call->sessions[call->main_audio_stream_index]);
if (call->audiostream->ec){
const char *state_str=NULL;
@ -3159,8 +3306,8 @@ static void linphone_call_stop_audio_stream(LinphoneCall *call) {
linphone_call_remove_from_conf(call);
}
audio_stream_stop(call->audiostream);
update_rtp_stats(call, 0);
rtp_session_unregister_event_queue(call->sessions[0].rtp_session, call->audiostream_app_evq);
update_rtp_stats(call, call->main_audio_stream_index);
rtp_session_unregister_event_queue(call->sessions[call->main_audio_stream_index].rtp_session, call->audiostream_app_evq);
ortp_ev_queue_flush(call->audiostream_app_evq);
ortp_ev_queue_destroy(call->audiostream_app_evq);
call->audiostream_app_evq=NULL;
@ -3173,12 +3320,12 @@ static void linphone_call_stop_video_stream(LinphoneCall *call) {
#ifdef VIDEO_ENABLED
if (call->videostream!=NULL){
linphone_reporting_update_media_info(call, LINPHONE_CALL_STATS_VIDEO);
media_stream_reclaim_sessions(&call->videostream->ms,&call->sessions[1]);
media_stream_reclaim_sessions(&call->videostream->ms,&call->sessions[call->main_video_stream_index]);
linphone_call_log_fill_stats(call->log,(MediaStream*)call->videostream);
video_stream_stop(call->videostream);
call->videostream=NULL;
update_rtp_stats(call, 1);
rtp_session_unregister_event_queue(call->sessions[1].rtp_session, call->videostream_app_evq);
update_rtp_stats(call, call->main_video_stream_index);
rtp_session_unregister_event_queue(call->sessions[call->main_video_stream_index].rtp_session, call->videostream_app_evq);
ortp_ev_queue_flush(call->videostream_app_evq);
ortp_ev_queue_destroy(call->videostream_app_evq);
call->videostream_app_evq=NULL;
@ -3192,12 +3339,29 @@ static void unset_rtp_profile(LinphoneCall *call, int i){
rtp_session_set_profile(call->sessions[i].rtp_session,&av_profile);
}
static void linphone_call_stop_text_stream(LinphoneCall *call) {
if (call->textstream != NULL) {
linphone_reporting_update_media_info(call, LINPHONE_CALL_STATS_TEXT);
media_stream_reclaim_sessions(&call->textstream->ms, &call->sessions[call->main_text_stream_index]);
linphone_call_log_fill_stats(call->log, (MediaStream*)call->textstream);
text_stream_stop(call->textstream);
call->textstream = NULL;
update_rtp_stats(call, call->main_text_stream_index);
rtp_session_unregister_event_queue(call->sessions[call->main_text_stream_index].rtp_session, call->textstream_app_evq);
ortp_ev_queue_flush(call->textstream_app_evq);
ortp_ev_queue_destroy(call->textstream_app_evq);
call->textstream_app_evq = NULL;
call->current_params->text_codec = NULL;
}
}
void linphone_call_stop_media_streams(LinphoneCall *call){
if (call->audiostream || call->videostream) {
if (call->audiostream && call->videostream)
audio_stream_unlink_video(call->audiostream, call->videostream);
linphone_call_stop_audio_stream(call);
linphone_call_stop_video_stream(call);
linphone_call_stop_text_stream(call);
if (call->core->msevq != NULL) {
ms_event_queue_skip(call->core->msevq);
@ -3417,7 +3581,7 @@ static bool_t ice_in_progress(LinphoneCallStats *stats){
**/
bool_t linphone_call_media_in_progress(LinphoneCall *call){
bool_t ret=FALSE;
if (ice_in_progress(&call->stats[LINPHONE_CALL_STATS_AUDIO]) || ice_in_progress(&call->stats[LINPHONE_CALL_STATS_VIDEO]))
if (ice_in_progress(&call->stats[LINPHONE_CALL_STATS_AUDIO]) || ice_in_progress(&call->stats[LINPHONE_CALL_STATS_VIDEO]) || ice_in_progress(&call->stats[LINPHONE_CALL_STATS_TEXT]))
ret=TRUE;
/*TODO: could check zrtp state, upnp state*/
return ret;
@ -3682,8 +3846,8 @@ static void change_ice_media_destinations(LinphoneCall *call) {
int rtcp_port;
bool_t result;
if (call->audiostream && ice_session_check_list(call->ice_session, 0)) {
result = ice_check_list_selected_valid_remote_candidate(ice_session_check_list(call->ice_session, 0), &rtp_addr, &rtp_port, &rtcp_addr, &rtcp_port);
if (call->audiostream && ice_session_check_list(call->ice_session, call->main_audio_stream_index)) {
result = ice_check_list_selected_valid_remote_candidate(ice_session_check_list(call->ice_session, call->main_audio_stream_index), &rtp_addr, &rtp_port, &rtcp_addr, &rtcp_port);
if (result == TRUE) {
ms_message("Change audio stream destination: RTP=%s:%d RTCP=%s:%d", rtp_addr, rtp_port, rtcp_addr, rtcp_port);
rtp_session_set_symmetric_rtp(call->audiostream->ms.sessions.rtp_session, FALSE);
@ -3691,8 +3855,8 @@ static void change_ice_media_destinations(LinphoneCall *call) {
}
}
#ifdef VIDEO_ENABLED
if (call->videostream && ice_session_check_list(call->ice_session, 1)) {
result = ice_check_list_selected_valid_remote_candidate(ice_session_check_list(call->ice_session, 1), &rtp_addr, &rtp_port, &rtcp_addr, &rtcp_port);
if (call->videostream && ice_session_check_list(call->ice_session, call->main_video_stream_index)) {
result = ice_check_list_selected_valid_remote_candidate(ice_session_check_list(call->ice_session, call->main_video_stream_index), &rtp_addr, &rtp_port, &rtcp_addr, &rtcp_port);
if (result == TRUE) {
ms_message("Change video stream destination: RTP=%s:%d RTCP=%s:%d", rtp_addr, rtp_port, rtcp_addr, rtcp_port);
rtp_session_set_symmetric_rtp(call->videostream->ms.sessions.rtp_session, FALSE);
@ -3700,6 +3864,14 @@ static void change_ice_media_destinations(LinphoneCall *call) {
}
}
#endif
if (call->textstream && ice_session_check_list(call->ice_session, call->main_text_stream_index)) {
result = ice_check_list_selected_valid_remote_candidate(ice_session_check_list(call->ice_session, call->main_text_stream_index), &rtp_addr, &rtp_port, &rtcp_addr, &rtcp_port);
if (result == TRUE) {
ms_message("Change text stream destination: RTP=%s:%d RTCP=%s:%d", rtp_addr, rtp_port, rtcp_addr, rtcp_port);
rtp_session_set_symmetric_rtp(call->textstream->ms.sessions.rtp_session, FALSE);
rtp_session_set_remote_addr_full(call->textstream->ms.sessions.rtp_session, rtp_addr, rtp_port, rtcp_addr, rtcp_port);
}
}
}
static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
@ -3846,7 +4018,7 @@ void linphone_call_notify_stats_updated(LinphoneCall *call, int stream_index){
}
void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index){
MediaStream *ms=stream_index==0 ? (MediaStream *)call->audiostream : (MediaStream *)call->videostream; /*assumption to remove*/
MediaStream *ms = stream_index == call->main_audio_stream_index ? (MediaStream *)call->audiostream : (stream_index == call->main_video_stream_index ? (MediaStream *)call->videostream : (MediaStream *)call->textstream);
OrtpEvQueue *evq;
OrtpEvent *ev;
@ -3863,13 +4035,16 @@ void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index){
video_stream_iterate((VideoStream*)ms);
#endif
break;
case MSText:
text_stream_iterate((TextStream*)ms);
break;
default:
ms_error("linphone_call_handle_stream_events(): unsupported stream type.");
return;
break;
}
/*yes the event queue has to be taken at each iteration, because ice events may perform operations re-creating the streams*/
while ((evq=stream_index==0 ? call->audiostream_app_evq : call->videostream_app_evq) && (NULL != (ev=ortp_ev_queue_get(evq)))){
while ((evq = stream_index == call->main_audio_stream_index ? call->audiostream_app_evq : (stream_index == call->main_video_stream_index ? call->videostream_app_evq : call->textstream_app_evq)) && (NULL != (ev=ortp_ev_queue_get(evq)))){
OrtpEventType evt=ortp_event_get_type(ev);
OrtpEventData *evd=ortp_event_get_data(ev);
@ -3894,6 +4069,8 @@ void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index){
handle_ice_events(call, ev);
} else if (evt==ORTP_EVENT_TELEPHONE_EVENT){
linphone_core_dtmf_received(call,evd->info.telephone_event);
} else if (evt == ORTP_EVENT_RTT_CHARACTER_RECEIVED) {
//TODO
}
ortp_event_destroy(ev);
}
@ -3932,8 +4109,9 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
linphone_upnp_call_process(call);
#endif //BUILD_UPNP
linphone_call_handle_stream_events(call,0);
linphone_call_handle_stream_events(call,1);
linphone_call_handle_stream_events(call, call->main_audio_stream_index);
linphone_call_handle_stream_events(call, call->main_video_stream_index);
linphone_call_handle_stream_events(call, call->main_text_stream_index);
if (call->state==LinphoneCallStreamsRunning && one_second_elapsed && call->audiostream!=NULL
&& call->audiostream->ms.state==MSStreamStarted && disconnect_timeout>0 )
disconnected=!audio_stream_alive(call->audiostream,disconnect_timeout);
@ -4218,18 +4396,26 @@ LinphoneChatRoom * linphone_call_get_chat_room(LinphoneCall *call) {
int linphone_call_get_stream_count(LinphoneCall *call) {
// Revisit when multiple media streams will be implemented
#ifdef VIDEO_ENABLED
if (linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(call))) {
return 3;
}
return 2;
#else
if (linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(call))) {
return 2;
}
return 1;
#endif
}
MSFormatType linphone_call_get_stream_type(LinphoneCall *call, int stream_index) {
// Revisit when multiple media streams will be implemented
if (stream_index == 0) {
return MSAudio;
if (stream_index == call->main_video_stream_index) {
return MSVideo;
} else if (stream_index == call->main_text_stream_index) {
return MSText;
}
return MSVideo;
return MSAudio;
}
RtpTransport* linphone_call_get_meta_rtp_transport(LinphoneCall *call, int stream_index) {

View file

@ -1027,6 +1027,15 @@ static void rtp_config_read(LinphoneCore *lc)
linphone_core_set_video_port(lc, min_port);
}
if (lp_config_get_range(lc->config, "rtp", "text_rtp_port", &min_port, &max_port, 11078, 11078) == TRUE) {
if (min_port <= 0) min_port = 1;
if (max_port > 65535) max_port = 65535;
linphone_core_set_text_port_range(lc, min_port, max_port);
} else {
min_port = lp_config_get_int(lc->config, "rtp", "text_rtp_port", 11078);
linphone_core_set_text_port(lc, min_port);
}
jitt_comp=lp_config_get_int(lc->config,"rtp","audio_jitt_comp",60);
linphone_core_set_audio_jittcomp(lc,jitt_comp);
jitt_comp=lp_config_get_int(lc->config,"rtp","video_jitt_comp",60);
@ -1121,7 +1130,7 @@ static bool_t get_codec(LinphoneCore *lc, SalStreamType type, int index, Payload
LpConfig *config=lc->config;
*ret=NULL;
snprintf(codeckey,50,"%s_codec_%i",type==SalAudio ? "audio" : "video", index);
snprintf(codeckey,50,"%s_codec_%i",type == SalAudio ? "audio" : type == SalVideo ? "video" : "text", index);
mime=lp_config_get_string(config,codeckey,"mime",NULL);
if (mime==NULL || strlen(mime)==0 ) return FALSE;
@ -1133,15 +1142,17 @@ static bool_t get_codec(LinphoneCore *lc, SalStreamType type, int index, Payload
ms_warning("Codec %s/%i read from conf is not supported by mediastreamer2, ignored.",mime,rate);
return TRUE;
}
pt=find_payload(type==SalAudio ? lc->default_audio_codecs : lc->default_video_codecs,mime,rate,channels,fmtp);
pt = find_payload(type == SalAudio ? lc->default_audio_codecs : type == SalVideo ? lc->default_video_codecs : lc->default_text_codecs ,mime,rate,channels,fmtp);
if (!pt){
MSList **default_list=(type==SalAudio) ? &lc->default_audio_codecs : &lc->default_video_codecs;
if (type==SalAudio)
MSList **default_list = (type==SalAudio) ? &lc->default_audio_codecs : type == SalVideo ? &lc->default_video_codecs : &lc->default_text_codecs;
if (type == SalAudio)
ms_warning("Codec %s/%i/%i read from conf is not in the default list.",mime,rate,channels);
else
else if (type == SalVideo)
ms_warning("Codec %s/%i read from conf is not in the default list.",mime,rate);
else
ms_warning("Codec %s read from conf is not in the default list.",mime);
pt=payload_type_new();
pt->type=(type==SalAudio) ? PAYLOAD_AUDIO_PACKETIZED : PAYLOAD_VIDEO;
pt->type=(type==SalAudio) ? PAYLOAD_AUDIO_PACKETIZED : type == SalVideo ? PAYLOAD_VIDEO : PAYLOAD_TEXT;
pt->mime_type=ortp_strdup(mime);
pt->clock_rate=rate;
pt->channels=channels;
@ -1199,6 +1210,7 @@ static void codecs_config_read(LinphoneCore *lc)
PayloadType *pt;
MSList *audio_codecs=NULL;
MSList *video_codecs=NULL;
MSList *text_codecs=NULL;
lc->codecs_conf.dyn_pt=96;
lc->codecs_conf.telephone_event_pt=lp_config_get_int(lc->config,"misc","telephone_event_pt",101);
@ -1220,8 +1232,17 @@ static void codecs_config_read(LinphoneCore *lc)
if( lp_config_get_int(lc->config, "misc", "add_missing_video_codecs", 1) == 1 ){
video_codecs=add_missing_codecs(lc->default_video_codecs,video_codecs);
}
for (i=0;get_codec(lc,SalText,i,&pt);i++){
if (pt){
text_codecs=codec_append_if_new(text_codecs, pt);
}
}
text_codecs = add_missing_codecs(lc->default_text_codecs, text_codecs);
linphone_core_set_audio_codecs(lc,audio_codecs);
linphone_core_set_video_codecs(lc,video_codecs);
linphone_core_set_text_codecs(lc, text_codecs);
linphone_core_update_allocated_audio_bandwidth(lc);
}
@ -1402,7 +1423,7 @@ const char * linphone_core_get_version(void){
static void linphone_core_register_payload_type(LinphoneCore *lc, const PayloadType *const_pt, const char *recv_fmtp, bool_t enabled){
MSList **codec_list=const_pt->type==PAYLOAD_VIDEO ? &lc->default_video_codecs : &lc->default_audio_codecs;
if (linphone_core_codec_supported(lc, (const_pt->type == PAYLOAD_VIDEO) ? SalVideo : SalAudio, const_pt->mime_type)){
if (linphone_core_codec_supported(lc, (const_pt->type == PAYLOAD_VIDEO) ? SalVideo : const_pt->type == PAYLOAD_TEXT ? SalText : SalAudio, const_pt->mime_type)){
PayloadType *pt=payload_type_clone(const_pt);
int number=-1;
payload_type_set_enable(pt,enabled);
@ -1428,8 +1449,8 @@ static void linphone_core_register_static_payloads(LinphoneCore *lc){
if (pt->type==PAYLOAD_VIDEO) continue;
#endif
if (find_payload_type_from_list(
pt->mime_type, pt->clock_rate, pt->type!=PAYLOAD_VIDEO ? pt->channels : LINPHONE_FIND_PAYLOAD_IGNORE_CHANNELS,
pt->type==PAYLOAD_VIDEO ? lc->default_video_codecs : lc->default_audio_codecs)==NULL){
pt->mime_type, pt->clock_rate, pt->type == PAYLOAD_VIDEO || pt->type == PAYLOAD_TEXT ? LINPHONE_FIND_PAYLOAD_IGNORE_CHANNELS : pt->channels,
pt->type == PAYLOAD_VIDEO ? lc->default_video_codecs : pt->type == PAYLOAD_TEXT ? lc->default_text_codecs : lc->default_audio_codecs)==NULL){
linphone_core_register_payload_type(lc,pt,NULL,FALSE);
}
}
@ -1569,7 +1590,8 @@ static void linphone_core_register_default_codecs(LinphoneCore *lc){
linphone_core_register_payload_type(lc,&payload_type_aal2_g726_40,NULL,FALSE);
linphone_core_register_payload_type(lc,&payload_type_codec2,NULL,FALSE);
linphone_core_register_payload_type(lc,&payload_type_t140,NULL,TRUE);
linphone_core_register_payload_type(lc,&payload_type_t140_red,NULL,TRUE);
#ifdef VIDEO_ENABLED
@ -1659,6 +1681,11 @@ const MSList *linphone_core_get_video_codecs(const LinphoneCore *lc)
return lc->codecs_conf.video_codecs;
}
const MSList *linphone_core_get_text_codecs(const LinphoneCore *lc)
{
return lc->codecs_conf.text_codecs;
}
int linphone_core_set_primary_contact(LinphoneCore *lc, const char *contact)
{
LinphoneAddress *ctt;
@ -1788,6 +1815,15 @@ int linphone_core_set_video_codecs(LinphoneCore *lc, MSList *codecs){
return 0;
}
int linphone_core_set_text_codecs(LinphoneCore *lc, MSList *codecs) {
if (lc->codecs_conf.text_codecs != NULL)
ms_list_free(lc->codecs_conf.text_codecs);
lc->codecs_conf.text_codecs = codecs;
_linphone_core_codec_config_write(lc);
return 0;
}
/**
* Enable RFC3389 generic confort noise algorithm (CN payload type).
* It is disabled by default, because this algorithm is only relevant for legacy codecs (PCMU, PCMA, G722).
@ -1893,6 +1929,24 @@ void linphone_core_get_video_port_range(const LinphoneCore *lc, int *min_port, i
*max_port = lc->rtp_conf.video_rtp_max_port;
}
/**
* Returns the UDP port used for text streaming.
*
* @ingroup network_parameters
**/
int linphone_core_get_text_port(const LinphoneCore *lc) {
return lc->rtp_conf.text_rtp_min_port;
}
/**
* Get the video port range from which is randomly chosen the UDP port used for text streaming.
*
* @ingroup network_parameters
*/
void linphone_core_get_text_port_range(const LinphoneCore *lc, int *min_port, int *max_port) {
*min_port = lc->rtp_conf.text_rtp_min_port;
*max_port = lc->rtp_conf.text_rtp_max_port;
}
/**
* Returns the value in seconds of the no-rtp timeout.
@ -1992,6 +2046,26 @@ void linphone_core_set_video_port_range(LinphoneCore *lc, int min_port, int max_
lc->rtp_conf.video_rtp_min_port=min_port;
lc->rtp_conf.video_rtp_max_port=max_port;
}
/**
* Sets the UDP port used for text streaming.
* A value if -1 will request the system to allocate the local port randomly.
* This is recommended in order to avoid firewall warnings.
*
* @ingroup network_parameters
**/
void linphone_core_set_text_port(LinphoneCore *lc, int port) {
lc->rtp_conf.text_rtp_min_port = lc->rtp_conf.text_rtp_max_port = port;
}
/**
* Sets the UDP port range from which to randomly select the port used for text streaming.
* @ingroup media_parameters
*/
void linphone_core_set_text_port_range(LinphoneCore *lc, int min_port, int max_port) {
lc->rtp_conf.text_rtp_min_port = min_port;
lc->rtp_conf.text_rtp_max_port = max_port;
}
/**
* Sets the no-rtp timeout value in seconds.
@ -3843,7 +3917,7 @@ int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call){
}
lc->current_call=NULL;
linphone_core_notify_display_status(lc,_("Pausing the current call..."));
if (call->audiostream || call->videostream)
if (call->audiostream || call->videostream || call->textstream)
linphone_call_stop_media_streams (call);
call->paused_by_app=FALSE;
return 0;
@ -6850,6 +6924,7 @@ void linphone_core_init_default_params(LinphoneCore*lc, LinphoneCallParams *para
params->has_video=linphone_core_video_enabled(lc) && lc->video_policy.automatically_initiate;
params->media_encryption=linphone_core_get_media_encryption(lc);
params->in_conference=FALSE;
params->realtimetext_enabled = linphone_core_realtime_text_enabled(lc);
params->privacy=LinphonePrivacyDefault;
params->avpf_enabled=FALSE;
params->audio_dir=LinphoneMediaDirectionSendRecv;
@ -7184,3 +7259,7 @@ LINPHONE_PUBLIC const char *linphone_core_log_collection_upload_state_to_string(
}
return "UNKNOWN";
}
bool_t linphone_core_realtime_text_enabled(LinphoneCore *lc) {
return lc->text_conf.enabled;
}

View file

@ -469,6 +469,7 @@ typedef struct _LinphoneVideoPolicy LinphoneVideoPolicy;
#define LINPHONE_CALL_STATS_AUDIO 0
#define LINPHONE_CALL_STATS_VIDEO 1
#define LINPHONE_CALL_STATS_TEXT 2
/**
* Enum describing ICE states.
@ -2683,6 +2684,22 @@ LINPHONE_PUBLIC const MSList *linphone_core_get_video_codecs(const LinphoneCore
LINPHONE_PUBLIC int linphone_core_set_video_codecs(LinphoneCore *lc, MSList *codecs);
/**
* Returns the list of available text codecs.
* @param[in] lc The LinphoneCore object
* @return \mslist{PayloadType}
*
* This list is unmodifiable. The ->data field of the MSList points a PayloadType
* structure holding the codec information.
* It is possible to make copy of the list with ms_list_copy() in order to modify it
* (such as the order of codecs).
* @ingroup media_parameters
**/
LINPHONE_PUBLIC const MSList *linphone_core_get_text_codecs(const LinphoneCore *lc);
LINPHONE_PUBLIC int linphone_core_set_text_codecs(LinphoneCore *lc, MSList *codecs);
LINPHONE_PUBLIC void linphone_core_enable_generic_confort_noise(LinphoneCore *lc, bool_t enabled);
LINPHONE_PUBLIC bool_t linphone_core_generic_confort_noise_enabled(const LinphoneCore *lc);
@ -2931,6 +2948,10 @@ LINPHONE_PUBLIC int linphone_core_get_video_port(const LinphoneCore *lc);
LINPHONE_PUBLIC void linphone_core_get_video_port_range(const LinphoneCore *lc, int *min_port, int *max_port);
LINPHONE_PUBLIC int linphone_core_get_text_port(const LinphoneCore *lc);
LINPHONE_PUBLIC void linphone_core_get_text_port_range(const LinphoneCore *lc, int *min_port, int *max_port);
LINPHONE_PUBLIC int linphone_core_get_nortp_timeout(const LinphoneCore *lc);
LINPHONE_PUBLIC void linphone_core_set_audio_port(LinphoneCore *lc, int port);
@ -2941,6 +2962,10 @@ LINPHONE_PUBLIC void linphone_core_set_video_port(LinphoneCore *lc, int port);
LINPHONE_PUBLIC void linphone_core_set_video_port_range(LinphoneCore *lc, int min_port, int max_port);
LINPHONE_PUBLIC void linphone_core_set_text_port(LinphoneCore *lc, int port);
LINPHONE_PUBLIC void linphone_core_set_text_port_range(LinphoneCore *lc, int min_port, int max_port);
LINPHONE_PUBLIC void linphone_core_set_nortp_timeout(LinphoneCore *lc, int port);
LINPHONE_PUBLIC void linphone_core_set_use_info_for_dtmf(LinphoneCore *lc, bool_t use_info);
@ -4092,6 +4117,13 @@ LINPHONE_PUBLIC void linphone_core_set_video_preset(LinphoneCore *lc, const char
*/
LINPHONE_PUBLIC const char * linphone_core_get_video_preset(const LinphoneCore *lc);
/**
* Gets if realtime text is enabled or not
* @param[in] lc LinphoneCore object
* @return true if realtime text is enabled, false otherwise
*/
LINPHONE_PUBLIC bool_t linphone_core_realtime_text_enabled(LinphoneCore *lc);
#ifdef __cplusplus
}
#endif

View file

@ -62,7 +62,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
static void clear_ice_check_list(LinphoneCall *call, IceCheckList *removed);
bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const LinphonePayloadType *pt){
if (ms_list_find(lc->codecs_conf.audio_codecs, (PayloadType*) pt) || ms_list_find(lc->codecs_conf.video_codecs, (PayloadType*)pt)){
if (ms_list_find(lc->codecs_conf.audio_codecs, (PayloadType*) pt) || ms_list_find(lc->codecs_conf.video_codecs, (PayloadType*)pt) || ms_list_find(lc->codecs_conf.text_codecs, (PayloadType*)pt)){
return payload_type_enabled(pt);
}
ms_error("Getting enablement status of codec not in audio or video list of PayloadType !");
@ -75,7 +75,7 @@ bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const LinphonePayload
}
int linphone_core_enable_payload_type(LinphoneCore *lc, LinphonePayloadType *pt, bool_t enabled){
if (ms_list_find(lc->codecs_conf.audio_codecs,pt) || ms_list_find(lc->codecs_conf.video_codecs,pt)){
if (ms_list_find(lc->codecs_conf.audio_codecs,pt) || ms_list_find(lc->codecs_conf.video_codecs,pt) || ms_list_find(lc->codecs_conf.text_codecs,pt)){
payload_type_set_enable(pt,enabled);
_linphone_core_codec_config_write(lc);
linphone_core_update_allocated_audio_bandwidth(lc);
@ -106,7 +106,7 @@ const char *linphone_core_get_payload_type_description(LinphoneCore *lc, Payload
}
void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, LinphonePayloadType *pt, int bitrate){
if (ms_list_find(lc->codecs_conf.audio_codecs, (PayloadType*) pt) || ms_list_find(lc->codecs_conf.video_codecs, (PayloadType*)pt)){
if (ms_list_find(lc->codecs_conf.audio_codecs, (PayloadType*) pt) || ms_list_find(lc->codecs_conf.video_codecs, (PayloadType*)pt) || ms_list_find(lc->codecs_conf.text_codecs, (PayloadType*)pt)){
if (pt->type==PAYLOAD_VIDEO || pt->flags & PAYLOAD_TYPE_IS_VBR){
pt->normal_bitrate=bitrate*1000;
pt->flags|=PAYLOAD_TYPE_BITRATE_OVERRIDE;

View file

@ -117,6 +117,7 @@ struct _LinphoneCallParams{
LinphoneMediaEncryption media_encryption;
PayloadType *audio_codec; /*audio codec currently in use */
PayloadType *video_codec; /*video codec currently in use */
PayloadType *text_codec; /*text codec currently in use */
MSVideoSize sent_vsize; /* Size of the video currently being sent */
MSVideoSize recv_vsize; /* Size of the video currently being received */
float received_fps,sent_fps;
@ -251,6 +252,7 @@ struct _LinphoneCall{
SalMediaDescription *resultdesc;
struct _RtpProfile *audio_profile;
struct _RtpProfile *video_profile;
struct _RtpProfile *text_profile;
struct _RtpProfile *rtp_io_audio_profile;
struct _RtpProfile *rtp_io_video_profile;
struct _LinphoneCallLog *log;
@ -262,11 +264,13 @@ struct _LinphoneCall{
LinphoneCallState prevstate;
LinphoneCallState transfer_state; /*idle if no transfer*/
LinphoneProxyConfig *dest_proxy;
PortConfig media_ports[2];
MSMediaStreamSessions sessions[2]; /*the rtp, srtp, zrtp contexts for each stream*/
StunCandidate ac,vc; /*audio video ip/port discovered by STUN*/
int main_audio_stream_index, main_video_stream_index, main_text_stream_index;
PortConfig media_ports[SAL_MEDIA_DESCRIPTION_MAX_STREAMS];
MSMediaStreamSessions sessions[SAL_MEDIA_DESCRIPTION_MAX_STREAMS]; /*the rtp, srtp, zrtp contexts for each stream*/
StunCandidate ac, vc, tc; /*audio video text ip/port discovered by STUN*/
struct _AudioStream *audiostream; /**/
struct _VideoStream *videostream;
struct _TextStream *textstream;
void *video_window_id;
MSAudioEndpoint *endpoint; /*used for conferencing*/
char *refer_to;
@ -278,8 +282,9 @@ struct _LinphoneCall{
OrtpEvQueue *audiostream_app_evq;
char *auth_token;
OrtpEvQueue *videostream_app_evq;
OrtpEvQueue *textstream_app_evq;
CallCallbackObj nextVideoFrameDecoded;
LinphoneCallStats stats[2];
LinphoneCallStats stats[3]; /* audio, video, text */
#ifdef BUILD_UPNP
UpnpSession *upnp_session;
#endif //BUILD_UPNP
@ -453,6 +458,7 @@ void linphone_call_init_stats(LinphoneCallStats *stats, int type);
void linphone_call_fix_call_parameters(LinphoneCall *call);
void linphone_call_init_audio_stream(LinphoneCall *call);
void linphone_call_init_video_stream(LinphoneCall *call);
void linphone_call_init_text_stream(LinphoneCall *call);
void linphone_call_init_media_streams(LinphoneCall *call);
void linphone_call_start_media_streams(LinphoneCall *call, LinphoneCallState target_state);
void linphone_call_start_media_streams_for_ice_gathering(LinphoneCall *call);
@ -656,6 +662,8 @@ typedef struct rtp_config
char* video_multicast_addr;
int video_multicast_ttl;
bool_t video_multicast_enabled;
int text_rtp_min_port;
int text_rtp_max_port;
}rtp_config_t;
@ -701,6 +709,7 @@ typedef struct codecs_config
{
MSList *audio_codecs; /* list of audio codecs in order of preference*/
MSList *video_codecs;
MSList *text_codecs;
int dyn_pt;
int telephone_event_pt;
}codecs_config_t;
@ -718,6 +727,10 @@ typedef struct video_config{
bool_t reuse_preview_source;
}video_config_t;
typedef struct text_config{
bool_t enabled;
}text_config_t;
typedef struct ui_config
{
int is_daemon;
@ -781,11 +794,13 @@ struct _LinphoneCore
struct _LpConfig *config;
MSList *default_audio_codecs;
MSList *default_video_codecs;
MSList *default_text_codecs;
net_config_t net_conf;
sip_config_t sip_conf;
rtp_config_t rtp_conf;
sound_config_t sound_conf;
video_config_t video_conf;
text_config_t text_conf;
codecs_config_t codecs_conf;
ui_config_t ui_conf;
autoreplier_config_t autoreplier_conf;

View file

@ -617,8 +617,9 @@ void sal_auth_info_delete(SalAuthInfo* auth_info) {
const char* sal_stream_type_to_string(SalStreamType type) {
switch (type) {
case SalAudio:return "audio";
case SalVideo:return "video";
case SalAudio: return "audio";
case SalVideo: return "video";
case SalText: return "text";
default: return "other";
}
}

View file

@ -126,6 +126,7 @@ void *sal_get_user_pointer(const Sal *sal);
typedef enum {
SalAudio,
SalVideo,
SalText,
SalOther
} SalStreamType;
const char* sal_stream_type_to_string(SalStreamType type);

@ -1 +1 @@
Subproject commit 93cf916ac44dea93db7744b1d66ea3655c8345d9
Subproject commit 2df927914113b54610e9174d6c1f8615d22cb304

2
oRTP

@ -1 +1 @@
Subproject commit bb95930a77e8a1432e5c31dc170f05ecd15518e5
Subproject commit c3b24c490a1f1f22dda6a88d2d2e428ff610b915