forked from mirrors/linphone-iphone
multicast impl
This commit is contained in:
parent
ef810b108b
commit
06fc0526ec
16 changed files with 740 additions and 34 deletions
|
|
@ -210,10 +210,18 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session
|
|||
/*only add a c= line within the stream description if address are differents*/
|
||||
if (rtp_addr[0]!='\0' && strcmp(rtp_addr,md->addr)!=0){
|
||||
bool_t inet6;
|
||||
belle_sdp_connection_t *connection;
|
||||
if (strchr(rtp_addr,':')!=NULL){
|
||||
inet6=TRUE;
|
||||
}else inet6=FALSE;
|
||||
belle_sdp_media_description_set_connection(media_desc,belle_sdp_connection_create("IN", inet6 ? "IP6" : "IP4", rtp_addr));
|
||||
connection = belle_sdp_connection_create("IN", inet6 ? "IP6" : "IP4", rtp_addr);
|
||||
if (ms_is_multicast(rtp_addr)) {
|
||||
/*remove session cline in case of multicast*/
|
||||
belle_sdp_session_description_set_connection(session_desc,NULL);
|
||||
if (inet6 == FALSE)
|
||||
belle_sdp_connection_set_ttl(connection,stream->ttl);
|
||||
}
|
||||
belle_sdp_media_description_set_connection(media_desc,connection);
|
||||
}
|
||||
|
||||
if ( stream->bandwidth>0 )
|
||||
|
|
@ -706,6 +714,7 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md,
|
|||
}
|
||||
if ( ( cnx=belle_sdp_media_description_get_connection ( media_desc ) ) && belle_sdp_connection_get_address ( cnx ) ) {
|
||||
strncpy ( stream->rtp_addr,belle_sdp_connection_get_address ( cnx ), sizeof ( stream->rtp_addr ) -1 );
|
||||
stream->ttl=belle_sdp_connection_get_ttl(cnx);
|
||||
}
|
||||
|
||||
stream->rtp_port=belle_sdp_media_get_media_port ( media );
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp){
|
|||
* The management of the custom headers is not optimal. We copy everything while ref counting would be more efficient.
|
||||
*/
|
||||
if (cp->custom_headers) ncp->custom_headers=sal_custom_header_clone(cp->custom_headers);
|
||||
|
||||
return ncp;
|
||||
}
|
||||
|
||||
|
|
@ -158,6 +159,21 @@ bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp){
|
|||
return cp->has_video;
|
||||
}
|
||||
|
||||
LinphoneCallParamsMediaDirection linphone_call_params_get_audio_direction(const LinphoneCallParams *cp) {
|
||||
return cp->audio_dir;
|
||||
}
|
||||
|
||||
LinphoneCallParamsMediaDirection linphone_call_params_get_video_direction(const LinphoneCallParams *cp) {
|
||||
return cp->video_dir;
|
||||
}
|
||||
|
||||
void linphone_call_params_set_audio_direction(LinphoneCallParams *cp,LinphoneCallParamsMediaDirection dir) {
|
||||
cp->audio_dir=dir;
|
||||
}
|
||||
|
||||
void linphone_call_params_set_video_direction(LinphoneCallParams *cp,LinphoneCallParamsMediaDirection dir) {
|
||||
cp->video_dir=dir;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
|||
|
|
@ -30,6 +30,20 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
/*******************************************************************************
|
||||
* Structures and enums *
|
||||
******************************************************************************/
|
||||
/**
|
||||
* Indicates for a given media the stream direction
|
||||
* */
|
||||
enum _LinphoneCallParamsMediaDirection {
|
||||
LinphoneCallParamsMediaDirectionInactive, /** No active media not supported yet*/
|
||||
LinphoneCallParamsMediaDirectionSendOnly, /** Send only mode*/
|
||||
LinphoneCallParamsMediaDirectionRecvOnly, /** recv only mode*/
|
||||
LinphoneCallParamsMediaDirectionSendRecv, /*send receive mode not supported yet*/
|
||||
|
||||
};
|
||||
/**
|
||||
* Typedef for enum
|
||||
**/
|
||||
typedef enum _LinphoneCallParamsMediaDirection LinphoneCallParamsMediaDirection;
|
||||
|
||||
/**
|
||||
* Private structure definition for LinphoneCallParams.
|
||||
|
|
@ -247,6 +261,34 @@ LINPHONE_PUBLIC void linphone_call_params_set_session_name(LinphoneCallParams *c
|
|||
**/
|
||||
LINPHONE_PUBLIC bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp);
|
||||
|
||||
/**
|
||||
* Get the audio stream direction.
|
||||
* @param[in] cl LinphoneCallParams object
|
||||
* @return The audio stream direction associated with the call params.
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphoneCallParamsMediaDirection linphone_call_params_get_audio_direction(const LinphoneCallParams *cp);
|
||||
|
||||
/**
|
||||
* Get the video stream direction.
|
||||
* @param[in] cl LinphoneCallParams object
|
||||
* @return The video stream direction associated with the call params.
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphoneCallParamsMediaDirection linphone_call_params_get_video_direction(const LinphoneCallParams *cp);
|
||||
|
||||
/**
|
||||
* Set the audio stream direction. Only relevant for multicast
|
||||
* @param[in] cl LinphoneCallParams object
|
||||
* @param[in] The audio stream direction associated with this call params.
|
||||
**/
|
||||
/*LINPHONE_PUBLIC void linphone_call_params_set_audio_direction(LinphoneCallParams *cp, LinphoneCallParamsMediaDirection dir);*/
|
||||
|
||||
/**
|
||||
* Set the video stream direction. Only relevant for multicast
|
||||
* @param[in] cl LinphoneCallParams object
|
||||
* @param[in] The video stream direction associated with this call params.
|
||||
**/
|
||||
/*LINPHONE_PUBLIC void linphone_call_params_set_video_direction(LinphoneCallParams *cp, LinphoneCallParamsMediaDirection dir);*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Reference and user data handling functions *
|
||||
|
|
|
|||
|
|
@ -546,7 +546,24 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
|
|||
const char *me;
|
||||
SalMediaDescription *md=sal_media_description_new();
|
||||
LinphoneAddress *addr;
|
||||
char* local_ip=call->localip;
|
||||
const char* local_audio_ip;
|
||||
const char* local_video_ip;
|
||||
/*multicast is only set in case of outgoing call*/
|
||||
if (call->dir == LinphoneCallOutgoing && linphone_core_audio_multicast_enabled(lc)) {
|
||||
local_audio_ip=linphone_core_get_audio_multicast_addr(lc);
|
||||
md->streams[0].ttl=linphone_core_get_audio_multicast_ttl(lc);
|
||||
md->streams[0].multicast_role = SalMulticastRoleSender;
|
||||
} else
|
||||
local_audio_ip=call->localip;
|
||||
|
||||
if (call->dir == LinphoneCallOutgoing && linphone_core_video_multicast_enabled(lc)) {
|
||||
local_video_ip=linphone_core_get_video_multicast_addr(lc);
|
||||
md->streams[1].ttl=linphone_core_get_video_multicast_ttl(lc);
|
||||
md->streams[1].multicast_role = SalMulticastRoleSender;
|
||||
}else
|
||||
local_video_ip=call->localip;
|
||||
|
||||
|
||||
const char *subject=linphone_call_params_get_session_name(call->params);
|
||||
CodecConstraints codec_hints={0};
|
||||
|
||||
|
|
@ -562,7 +579,7 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
|
|||
md->session_ver=(old_md ? (old_md->session_ver+1) : (rand() & 0xfff));
|
||||
md->nb_streams=(call->biggestdesc ? call->biggestdesc->nb_streams : 1);
|
||||
|
||||
strncpy(md->addr,local_ip,sizeof(md->addr));
|
||||
strncpy(md->addr,call->localip,sizeof(md->addr));
|
||||
strncpy(md->username,linphone_address_get_username(addr),sizeof(md->username));
|
||||
if (subject) strncpy(md->name,subject,sizeof(md->name));
|
||||
|
||||
|
|
@ -571,8 +588,8 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
|
|||
else md->bandwidth=linphone_core_get_download_bandwidth(lc);
|
||||
|
||||
/*set audio capabilities */
|
||||
strncpy(md->streams[0].rtp_addr,local_ip,sizeof(md->streams[0].rtp_addr));
|
||||
strncpy(md->streams[0].rtcp_addr,local_ip,sizeof(md->streams[0].rtcp_addr));
|
||||
strncpy(md->streams[0].rtp_addr,local_audio_ip,sizeof(md->streams[0].rtp_addr));
|
||||
strncpy(md->streams[0].rtcp_addr,local_audio_ip,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;
|
||||
|
|
@ -599,8 +616,8 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
|
|||
nb_active_streams++;
|
||||
|
||||
if (call->params->has_video){
|
||||
strncpy(md->streams[1].rtp_addr,local_ip,sizeof(md->streams[1].rtp_addr));
|
||||
strncpy(md->streams[1].rtcp_addr,local_ip,sizeof(md->streams[1].rtcp_addr));
|
||||
strncpy(md->streams[1].rtp_addr,local_video_ip,sizeof(md->streams[1].rtp_addr));
|
||||
strncpy(md->streams[1].rtcp_addr,local_video_ip,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;
|
||||
|
|
@ -764,6 +781,9 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from,
|
|||
|
||||
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);
|
||||
/*by default local_audio_ip=local_video_ip=local_ip*/
|
||||
strncpy(call->local_audio_ip,call->localip,sizeof(call->local_audio_ip));
|
||||
strncpy(call->local_video_ip,call->localip,sizeof(call->local_video_ip));
|
||||
}
|
||||
|
||||
void linphone_call_init_stats(LinphoneCallStats *stats, int type) {
|
||||
|
|
@ -935,6 +955,20 @@ void linphone_call_set_compatible_incoming_call_parameters(LinphoneCall *call, c
|
|||
if ((sal_media_description_has_srtp(md) == TRUE) && (ms_srtp_supported() == TRUE)) {
|
||||
call->params->media_encryption = LinphoneMediaEncryptionSRTP;
|
||||
}
|
||||
|
||||
//set both local audio & video
|
||||
if (ms_is_multicast(md->streams[0].rtp_addr)) {
|
||||
strncpy(call->local_audio_ip,md->streams[0].rtp_addr,sizeof(call->local_audio_ip));
|
||||
ms_message("Disabling audio rtcp on call [%p] because of multicast",call);
|
||||
call->media_ports[0].rtp_port=md->streams[0].rtp_port;
|
||||
call->media_ports[0].rtcp_port=0;
|
||||
}
|
||||
if (ms_is_multicast(md->streams[1].rtp_addr)) {
|
||||
strncpy(call->local_video_ip,md->streams[1].rtp_addr,sizeof(call->local_video_ip));
|
||||
call->media_ports[1].rtp_port=md->streams[1].rtp_port;
|
||||
call->media_ports[1].rtcp_port=0;
|
||||
ms_message("Disabling video rtcp on call [%p] because of multicast",call);
|
||||
}
|
||||
}
|
||||
|
||||
LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op){
|
||||
|
|
@ -1767,11 +1801,12 @@ void linphone_call_init_audio_stream(LinphoneCall *call){
|
|||
int dscp;
|
||||
char rtcp_tool[128]={0};
|
||||
char* cname;
|
||||
|
||||
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){
|
||||
call->audiostream=audiostream=audio_stream_new(call->media_ports[0].rtp_port,call->media_ports[0].rtcp_port,call->af==AF_INET6);
|
||||
call->audiostream=audiostream=audio_stream_new2(call->local_audio_ip,call->media_ports[0].rtp_port,call->media_ports[0].rtcp_port);
|
||||
cname = linphone_address_as_string_uri_only(call->me);
|
||||
audio_stream_set_rtcp_information(call->audiostream, cname, rtcp_tool);
|
||||
ms_free(cname);
|
||||
|
|
@ -1876,7 +1911,7 @@ void linphone_call_init_video_stream(LinphoneCall *call){
|
|||
const char *display_filter=linphone_core_get_video_display_filter(lc);
|
||||
|
||||
if (call->sessions[1].rtp_session==NULL){
|
||||
call->videostream=video_stream_new(call->media_ports[1].rtp_port,call->media_ports[1].rtcp_port, call->af==AF_INET6);
|
||||
call->videostream=video_stream_new2(call->local_video_ip,call->media_ports[1].rtp_port,call->media_ports[1].rtcp_port);
|
||||
cname = linphone_address_as_string_uri_only(call->me);
|
||||
video_stream_set_rtcp_information(call->videostream, cname, rtcp_tool);
|
||||
ms_free(cname);
|
||||
|
|
@ -2259,7 +2294,9 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, b
|
|||
}
|
||||
/*Replace soundcard filters by inactive file players or recorders
|
||||
when placed in recvonly or sendonly mode*/
|
||||
if (stream->rtp_port==0 || stream->dir==SalStreamRecvOnly){
|
||||
if (stream->rtp_port==0
|
||||
|| stream->dir==SalStreamRecvOnly
|
||||
|| (stream->multicast_role == SalMulticastRoleReceiver && ms_is_multicast(stream->rtp_addr))){
|
||||
captcard=NULL;
|
||||
playfile=NULL;
|
||||
}else if (stream->dir==SalStreamSendOnly){
|
||||
|
|
@ -2315,13 +2352,16 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, b
|
|||
}
|
||||
}
|
||||
configure_rtp_session_for_rtcp_xr(lc, call, SalAudio);
|
||||
if (ms_is_multicast(stream->rtp_addr))
|
||||
rtp_session_set_multicast_ttl(call->audiostream->ms.sessions.rtp_session,stream->ttl);
|
||||
|
||||
audio_stream_start_full(
|
||||
call->audiostream,
|
||||
call->audio_profile,
|
||||
stream->rtp_addr[0]!='\0' ? stream->rtp_addr : call->resultdesc->addr,
|
||||
stream->rtp_port,
|
||||
stream->rtcp_addr[0]!='\0' ? stream->rtcp_addr : call->resultdesc->addr,
|
||||
linphone_core_rtcp_enabled(lc) ? (stream->rtcp_port ? stream->rtcp_port : stream->rtp_port+1) : 0,
|
||||
(linphone_core_rtcp_enabled(lc) && !ms_is_multicast(stream->rtp_addr)) ? (stream->rtcp_port ? stream->rtcp_port : stream->rtp_port+1) : 0,
|
||||
used_pt,
|
||||
linphone_core_get_audio_jittcomp(lc),
|
||||
playfile,
|
||||
|
|
@ -2402,7 +2442,12 @@ static void linphone_call_start_video_stream(LinphoneCall *call, bool_t all_inpu
|
|||
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 ){
|
||||
if (ms_is_multicast(vstream->rtp_addr)){
|
||||
if (vstream->multicast_role == SalMulticastRoleReceiver)
|
||||
dir=VideoStreamRecvOnly;
|
||||
else
|
||||
dir=VideoStreamSendOnly;
|
||||
} else if (vstream->dir==SalStreamSendOnly && lc->video_conf.capture ){
|
||||
if (local_st_desc->dir==SalStreamSendOnly){
|
||||
/* localdesc stream dir to SendOnly is when we want to put on hold, so use nowebcam in this case*/
|
||||
cam=get_nowebcam_device();
|
||||
|
|
@ -2440,6 +2485,9 @@ static void linphone_call_start_video_stream(LinphoneCall *call, bool_t all_inpu
|
|||
ms_message("%s lc rotation:%d\n", __FUNCTION__, lc->device_rotation);
|
||||
video_stream_set_device_rotation(call->videostream, lc->device_rotation);
|
||||
video_stream_set_freeze_on_error(call->videostream, lp_config_get_int(lc->config, "video", "freeze_on_error", 0));
|
||||
if (ms_is_multicast(vstream->rtp_addr))
|
||||
rtp_session_set_multicast_ttl(call->videostream->ms.sessions.rtp_session,vstream->ttl);
|
||||
|
||||
if( lc->video_conf.reuse_preview_source && source ){
|
||||
ms_message("video_stream_start_with_source kept: %p", source);
|
||||
video_stream_start_with_source(call->videostream,
|
||||
|
|
@ -2452,7 +2500,7 @@ static void linphone_call_start_video_stream(LinphoneCall *call, bool_t all_inpu
|
|||
video_stream_start(call->videostream,
|
||||
call->video_profile, rtp_addr, vstream->rtp_port,
|
||||
rtcp_addr,
|
||||
linphone_core_rtcp_enabled(lc) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0,
|
||||
(linphone_core_rtcp_enabled(lc) && !ms_is_multicast(vstream->rtp_addr)) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0,
|
||||
used_pt, linphone_core_get_video_jittcomp(lc), cam);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -947,6 +947,8 @@ static void rtp_config_read(LinphoneCore *lc)
|
|||
int nortp_timeout;
|
||||
bool_t rtp_no_xmit_on_audio_mute;
|
||||
bool_t adaptive_jitt_comp_enabled;
|
||||
const char* tmp;
|
||||
int tmp_int;
|
||||
|
||||
if (lp_config_get_range(lc->config, "rtp", "audio_rtp_port", &min_port, &max_port, 7078, 7078) == TRUE) {
|
||||
if (min_port <= 0) min_port = 1;
|
||||
|
|
@ -981,6 +983,26 @@ static void rtp_config_read(LinphoneCore *lc)
|
|||
linphone_core_enable_video_adaptive_jittcomp(lc, adaptive_jitt_comp_enabled);
|
||||
lc->rtp_conf.disable_upnp = lp_config_get_int(lc->config, "rtp", "disable_upnp", FALSE);
|
||||
linphone_core_set_avpf_mode(lc,lp_config_get_int(lc->config,"rtp","avpf",0));
|
||||
if ((tmp=lp_config_get_string(lc->config,"rtp","audio_multicast_addr",NULL)))
|
||||
linphone_core_set_audio_multicast_addr(lc,tmp);
|
||||
else
|
||||
lc->rtp_conf.audio_multicast_addr=ms_strdup("224.1.2.3");
|
||||
if ((tmp_int=lp_config_get_int(lc->config,"rtp","audio_multicast_enabled",-1)) >-1)
|
||||
linphone_core_enable_audio_multicast(lc,tmp_int);
|
||||
if ((tmp_int=lp_config_get_int(lc->config,"rtp","audio_multicast_ttl",-1))>0)
|
||||
linphone_core_set_audio_multicast_ttl(lc,tmp_int);
|
||||
else
|
||||
lc->rtp_conf.audio_multicast_ttl=1;/*local network*/
|
||||
if ((tmp=lp_config_get_string(lc->config,"rtp","video_multicast_addr",NULL)))
|
||||
linphone_core_set_video_multicast_addr(lc,tmp);
|
||||
else
|
||||
lc->rtp_conf.video_multicast_addr=ms_strdup("224.1.2.3");
|
||||
if ((tmp_int=lp_config_get_int(lc->config,"rtp","video_multicast_ttl",-1))>-1)
|
||||
linphone_core_set_video_multicast_ttl(lc,tmp_int);
|
||||
else
|
||||
lc->rtp_conf.video_multicast_ttl=1;/*local network*/
|
||||
if ((tmp_int=lp_config_get_int(lc->config,"rtp","video_multicast_enabled",-1)) >0)
|
||||
linphone_core_enable_video_multicast(lc,tmp_int);
|
||||
}
|
||||
|
||||
static PayloadType * find_payload(const MSList *default_list, const char *mime_type, int clock_rate, int channels, const char *recv_fmtp){
|
||||
|
|
@ -6123,6 +6145,8 @@ void rtp_config_uninit(LinphoneCore *lc)
|
|||
lp_config_set_int(lc->config,"rtp","nortp_timeout",config->nortp_timeout);
|
||||
lp_config_set_int(lc->config,"rtp","audio_adaptive_jitt_comp_enabled",config->audio_adaptive_jitt_comp_enabled);
|
||||
lp_config_set_int(lc->config,"rtp","video_adaptive_jitt_comp_enabled",config->video_adaptive_jitt_comp_enabled);
|
||||
ms_free(lc->rtp_conf.audio_multicast_addr);
|
||||
ms_free(lc->rtp_conf.video_multicast_addr);
|
||||
ms_free(config->srtp_suites);
|
||||
}
|
||||
|
||||
|
|
@ -6878,6 +6902,8 @@ void linphone_core_init_default_params(LinphoneCore*lc, LinphoneCallParams *para
|
|||
params->in_conference=FALSE;
|
||||
params->privacy=LinphonePrivacyDefault;
|
||||
params->avpf_enabled=FALSE;
|
||||
params->audio_dir=LinphoneCallParamsMediaDirectionSendRecv;
|
||||
params->video_dir=LinphoneCallParamsMediaDirectionSendRecv;
|
||||
}
|
||||
|
||||
void linphone_core_set_device_identifier(LinphoneCore *lc,const char* device_id) {
|
||||
|
|
@ -7216,3 +7242,81 @@ void linphone_core_remove_listener(LinphoneCore *lc, const LinphoneCoreVTable *v
|
|||
ms_message("Vtable [%p] unregistered on core [%p]",lc,vtable);
|
||||
lc->vtables=ms_list_remove(lc->vtables,(void*)vtable);
|
||||
}
|
||||
|
||||
int linphone_core_set_audio_multicast_addr(LinphoneCore *lc, const char* ip) {
|
||||
char* new_value;
|
||||
if (ip && !ms_is_multicast(ip)) {
|
||||
ms_error("Cannot set multicast audio addr to core [%p] because [%s] is not multicast",lc,ip);
|
||||
return -1;
|
||||
}
|
||||
new_value = ip?ms_strdup(ip):NULL;
|
||||
if (lc->rtp_conf.audio_multicast_addr) ms_free(lc->rtp_conf.audio_multicast_addr);
|
||||
lp_config_set_string(lc->config,"rtp","audio_multicast_addr",lc->rtp_conf.audio_multicast_addr=new_value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int linphone_core_set_video_multicast_addr(LinphoneCore *lc, const char* ip) {
|
||||
char* new_value;
|
||||
if (ip && !ms_is_multicast(ip)) {
|
||||
ms_error("Cannot set multicast video addr to core [%p] because [%s] is not multicast",lc,ip);
|
||||
return -1;
|
||||
}
|
||||
new_value = ip?ms_strdup(ip):NULL;
|
||||
if (lc->rtp_conf.video_multicast_addr) ms_free(lc->rtp_conf.video_multicast_addr);
|
||||
lp_config_set_string(lc->config,"rtp","video_multicast_addr",lc->rtp_conf.video_multicast_addr=new_value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* linphone_core_get_audio_multicast_addr(const LinphoneCore *lc) {
|
||||
return lc->rtp_conf.audio_multicast_addr;
|
||||
}
|
||||
|
||||
|
||||
const char* linphone_core_get_video_multicast_addr(const LinphoneCore *lc){
|
||||
return lc->rtp_conf.video_multicast_addr;
|
||||
}
|
||||
|
||||
int linphone_core_set_audio_multicast_ttl(LinphoneCore *lc, int ttl) {
|
||||
if (ttl>255) {
|
||||
ms_error("Cannot set multicast audio ttl to core [%p] to [%i] value must be <256",lc,ttl);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lp_config_set_int(lc->config,"rtp","audio_multicast_ttl",lc->rtp_conf.audio_multicast_ttl=ttl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int linphone_core_set_video_multicast_ttl(LinphoneCore *lc, int ttl) {
|
||||
if (ttl>255) {
|
||||
ms_error("Cannot set multicast video ttl to core [%p] to [%i] value must be <256",lc,ttl);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lp_config_set_int(lc->config,"rtp","video_multicast_ttl",lc->rtp_conf.video_multicast_ttl=ttl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int linphone_core_get_audio_multicast_ttl(const LinphoneCore *lc) {
|
||||
return lc->rtp_conf.audio_multicast_ttl;
|
||||
}
|
||||
|
||||
|
||||
int linphone_core_get_video_multicast_ttl(const LinphoneCore *lc){
|
||||
return lc->rtp_conf.video_multicast_ttl;
|
||||
}
|
||||
|
||||
void linphone_core_enable_audio_multicast(LinphoneCore *lc, bool_t yesno) {
|
||||
lp_config_set_int(lc->config,"rtp","audio_multicast_enabled",lc->rtp_conf.audio_multicast_enabled=yesno);
|
||||
}
|
||||
|
||||
bool_t linphone_core_audio_multicast_enabled(const LinphoneCore *lc) {
|
||||
return lc->rtp_conf.audio_multicast_enabled;
|
||||
}
|
||||
|
||||
void linphone_core_enable_video_multicast(LinphoneCore *lc, bool_t yesno) {
|
||||
lp_config_set_int(lc->config,"rtp","video_multicast_enabled",lc->rtp_conf.video_multicast_enabled=yesno);
|
||||
}
|
||||
|
||||
bool_t linphone_core_video_multicast_enabled(const LinphoneCore *lc) {
|
||||
return lc->rtp_conf.video_multicast_enabled;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3305,6 +3305,105 @@ LINPHONE_PUBLIC void linphone_core_set_avpf_rr_interval(LinphoneCore *lc, int in
|
|||
|
||||
LINPHONE_PUBLIC int linphone_core_get_avpf_rr_interval(const LinphoneCore *lc);
|
||||
|
||||
/**
|
||||
* Use to set multicast address to be used for audio stream.
|
||||
* @param core the core
|
||||
* @param ip an ipv4/6 multicast address
|
||||
* @return 0 in case of success
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_set_audio_multicast_addr(LinphoneCore *core, const char* ip);
|
||||
/**
|
||||
* Use to set multicast address to be used for video stream.
|
||||
* @param core the core
|
||||
* @param ip an ipv4/6 multicast address
|
||||
* @return 0 in case of success
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_set_video_multicast_addr(LinphoneCore *lc, const char *ip);
|
||||
|
||||
/**
|
||||
* Use to get multicast address to be used for audio stream.
|
||||
* @param core the core
|
||||
* @return an ipv4/6 multicast address or default value
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
LINPHONE_PUBLIC const char* linphone_core_get_audio_multicast_addr(const LinphoneCore *core);
|
||||
|
||||
/**
|
||||
* Use to get multicast address to be used for video stream.
|
||||
* @param core the core
|
||||
* @return an ipv4/6 multicast address, or default value
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
LINPHONE_PUBLIC const char* linphone_core_get_video_multicast_addr(const LinphoneCore *core);
|
||||
|
||||
/**
|
||||
* Use to set multicast ttl to be used for audio stream.
|
||||
* @param core the core
|
||||
* @param ip an ttl or -1 if not used [0..255] default value is 1
|
||||
* @return 0 in case of success
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_set_audio_multicast_ttl(LinphoneCore *core, int ttl);
|
||||
/**
|
||||
* Use to set multicast ttl to be used for video stream.
|
||||
* @param core the core
|
||||
* @param ip an ttl or -1 if not used [0..255] default value is 1
|
||||
* @return 0 in case of success
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_set_video_multicast_ttl(LinphoneCore *lc, int ttl);
|
||||
|
||||
/**
|
||||
* Use to get multicast ttl to be used for audio stream.
|
||||
* @param core the core
|
||||
* @return an time to leave value or -1 if not set
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_get_audio_multicast_ttl(const LinphoneCore *core);
|
||||
|
||||
/**
|
||||
* Use to get multicast ttl to be used for video stream.
|
||||
* @param core the core
|
||||
* @return an an time to leave value or -1 if not set
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_get_video_multicast_ttl(const LinphoneCore *core);
|
||||
|
||||
|
||||
/**
|
||||
* Use to enable multicast rtp for audio stream.
|
||||
* @param core the core
|
||||
* @param yesno if yes, subsequent calls propose multicast ip set by #linphone_core_set_audio_multicast_addr
|
||||
* @return an ipv4/6 multicast address or null
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_core_enable_audio_multicast(LinphoneCore *core, bool_t yesno);
|
||||
|
||||
/**
|
||||
* Use to get multicast state of audio stream.
|
||||
* @param core the core
|
||||
* @return true if subsequent calls propose multicast ip set by #linphone_core_set_audio_multicast_addr
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
LINPHONE_PUBLIC bool_t linphone_core_audio_multicast_enabled(const LinphoneCore *core);
|
||||
|
||||
/**
|
||||
* Use to enable multicast rtp for video stream.
|
||||
* @param core the core
|
||||
* @param yesno if yes, subsequent calls propose multicast ip set by #linphone_core_set_video_multicast_addr
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_core_enable_video_multicast(LinphoneCore *core, bool_t yesno);
|
||||
/**
|
||||
* Use to get multicast state of video stream.
|
||||
* @param core the core
|
||||
* @return true if subsequent calls propose multicast ip set by #linphone_core_set_audio_multicast_addr
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
LINPHONE_PUBLIC bool_t linphone_core_video_multicast_enabled(const LinphoneCore *core);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -296,9 +296,81 @@ static void initiate_outgoing(const SalStreamDescription *local_offer,
|
|||
SalStreamDescription *result){
|
||||
if (remote_answer->rtp_port!=0)
|
||||
result->payloads=match_payloads(local_offer->payloads,remote_answer->payloads,TRUE,FALSE);
|
||||
else {
|
||||
ms_message("Local stream description [%p] rejected by peer",local_offer);
|
||||
result->rtp_port=0;
|
||||
return;
|
||||
}
|
||||
result->proto=remote_answer->proto;
|
||||
result->type=local_offer->type;
|
||||
result->dir=compute_dir_outgoing(local_offer->dir,remote_answer->dir);
|
||||
|
||||
if (ms_is_multicast(local_offer->rtp_addr)) {
|
||||
/*6.2 Multicast Streams
|
||||
...
|
||||
If a multicast stream is accepted, the address and port information
|
||||
in the answer MUST match that of the offer. Similarly, the
|
||||
directionality information in the answer (sendonly, recvonly, or
|
||||
sendrecv) MUST equal that of the offer. This is because all
|
||||
participants in a multicast session need to have equivalent views of
|
||||
the parameters of the session, an underlying assumption of the
|
||||
multicast bias of RFC 2327.*/
|
||||
if (strcmp(local_offer->rtp_addr,remote_answer->rtp_addr) !=0 ) {
|
||||
ms_message("Remote answered IP [%s] does not match offered [%s] for local stream description [%p]"
|
||||
,remote_answer->rtp_addr
|
||||
,local_offer->rtp_addr
|
||||
,local_offer);
|
||||
result->rtp_port=0;
|
||||
return;
|
||||
}
|
||||
if (local_offer->rtp_port!=remote_answer->rtp_port) {
|
||||
ms_message("Remote answered rtp port [%i] does not match offered [%i] for local stream description [%p]"
|
||||
,remote_answer->rtp_port
|
||||
,local_offer->rtp_port
|
||||
,local_offer);
|
||||
result->rtp_port=0;
|
||||
return;
|
||||
}
|
||||
if (local_offer->dir!=remote_answer->dir) {
|
||||
ms_message("Remote answered dir [%s] does not match offered [%s] for local stream description [%p]"
|
||||
,sal_stream_dir_to_string(remote_answer->dir)
|
||||
,sal_stream_dir_to_string(local_offer->dir)
|
||||
,local_offer);
|
||||
result->rtp_port=0;
|
||||
return;
|
||||
}
|
||||
if (local_offer->bandwidth!=remote_answer->bandwidth) {
|
||||
ms_message("Remote answered bandwidth [%i] does not match offered [%i] for local stream description [%p]"
|
||||
,remote_answer->bandwidth
|
||||
,local_offer->bandwidth
|
||||
,local_offer);
|
||||
result->rtp_port=0;
|
||||
return;
|
||||
}
|
||||
if (local_offer->ptime > 0 && local_offer->ptime!=remote_answer->ptime) {
|
||||
ms_message("Remote answered ptime [%i] does not match offered [%i] for local stream description [%p]"
|
||||
,remote_answer->ptime
|
||||
,local_offer->ptime
|
||||
,local_offer);
|
||||
result->rtp_port=0;
|
||||
return;
|
||||
}
|
||||
if (local_offer->ttl > 0 && local_offer->ttl!=remote_answer->ttl) {
|
||||
ms_message("Remote answered ttl [%i] does not match offered [%i] for local stream description [%p]"
|
||||
,remote_answer->ttl
|
||||
,local_offer->ttl
|
||||
,local_offer);
|
||||
result->rtp_port=0;
|
||||
return;
|
||||
}
|
||||
result->ttl=local_offer->ttl;
|
||||
result->dir=local_offer->dir;
|
||||
result->multicast_role = SalMulticastRoleSender;
|
||||
|
||||
} else {
|
||||
result->dir=compute_dir_outgoing(local_offer->dir,remote_answer->dir);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (result->payloads && !only_telephone_event(result->payloads)){
|
||||
strcpy(result->rtp_addr,remote_answer->rtp_addr);
|
||||
|
|
@ -328,16 +400,34 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
|
|||
result->payloads=match_payloads(local_cap->payloads,remote_offer->payloads, FALSE, one_matching_codec);
|
||||
result->proto=remote_offer->proto;
|
||||
result->type=local_cap->type;
|
||||
result->dir=compute_dir_incoming(local_cap->dir,remote_offer->dir);
|
||||
if (result->payloads && !only_telephone_event(result->payloads) && (remote_offer->rtp_port!=0 || remote_offer->rtp_port==SalStreamSendOnly)){
|
||||
if (!result->payloads || only_telephone_event(result->payloads) || remote_offer->rtp_port==0 || remote_offer->rtp_port==SalStreamSendOnly){
|
||||
result->dir=compute_dir_incoming(local_cap->dir,remote_offer->dir);
|
||||
result->rtp_port=0;
|
||||
return;
|
||||
}
|
||||
if (ms_is_multicast(remote_offer->rtp_addr)) {
|
||||
if (sal_stream_description_has_srtp(result) == TRUE) {
|
||||
ms_message("SAVP not supported for multicast address for remote stream [%p]",remote_offer);
|
||||
result->rtp_port=0;
|
||||
return;
|
||||
}
|
||||
result->dir=remote_offer->dir;
|
||||
strcpy(result->rtp_addr,remote_offer->rtp_addr);
|
||||
strcpy(result->rtcp_addr,remote_offer->rtcp_addr);
|
||||
result->rtp_port=remote_offer->rtp_port;
|
||||
/*result->rtcp_port=remote_offer->rtcp_port;*/
|
||||
result->rtcp_port=0; /* rtcp not supported yet*/
|
||||
result->bandwidth=remote_offer->bandwidth;
|
||||
result->ptime=remote_offer->ptime;
|
||||
result->ttl=remote_offer->ttl;
|
||||
result->multicast_role = SalMulticastRoleReceiver;
|
||||
} else {
|
||||
strcpy(result->rtp_addr,local_cap->rtp_addr);
|
||||
strcpy(result->rtcp_addr,local_cap->rtcp_addr);
|
||||
result->rtp_port=local_cap->rtp_port;
|
||||
result->rtcp_port=local_cap->rtcp_port;
|
||||
result->bandwidth=local_cap->bandwidth;
|
||||
result->ptime=local_cap->ptime;
|
||||
}else{
|
||||
result->rtp_port=0;
|
||||
}
|
||||
if (sal_stream_description_has_srtp(result) == TRUE) {
|
||||
/* select crypto algo */
|
||||
|
|
@ -358,6 +448,7 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
|
|||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a media description to run the streams with, based on a local offer
|
||||
* and the returned response (remote).
|
||||
|
|
|
|||
|
|
@ -1796,6 +1796,8 @@ void linphone_notify_convert_presence_to_xml(SalOp *op, SalPresenceModel *presen
|
|||
return;
|
||||
}
|
||||
|
||||
xmlTextWriterSetIndent(writer,1);
|
||||
|
||||
err = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL);
|
||||
if (err >= 0) {
|
||||
err = xmlTextWriterStartElementNS(writer, NULL, (const xmlChar *)"presence", (const xmlChar *)"urn:ietf:params:xml:ns:pidf");
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ extern "C" {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
struct _LinphoneCallParams{
|
||||
belle_sip_object_t base;
|
||||
void *user_data;
|
||||
|
|
@ -105,6 +106,9 @@ struct _LinphoneCallParams{
|
|||
bool_t no_user_consent;/*when set to TRUE an UPDATE request will be used instead of reINVITE*/
|
||||
uint16_t avpf_rr_interval; /*in milliseconds*/
|
||||
LinphonePrivacyMask privacy;
|
||||
LinphoneCallParamsMediaDirection audio_dir;
|
||||
LinphoneCallParamsMediaDirection video_dir;
|
||||
|
||||
};
|
||||
|
||||
BELLE_SIP_DECLARE_VPTR(LinphoneCallParams);
|
||||
|
|
@ -217,6 +221,8 @@ struct _LinphoneCall{
|
|||
SalOp *op;
|
||||
SalOp *ping_op;
|
||||
char localip[LINPHONE_IPADDR_SIZE]; /* our best guess for local ipaddress for this call */
|
||||
char local_audio_ip[LINPHONE_IPADDR_SIZE]; /* our best guess for local ipaddress for this call or what proposed in sdp in case of multicast*/
|
||||
char local_video_ip[LINPHONE_IPADDR_SIZE]; /* our best guess for local ipaddress for this call or what proposed in sdp in case of multicast*/
|
||||
LinphoneCallState state;
|
||||
LinphoneCallState prevstate;
|
||||
LinphoneCallState transfer_state; /*idle if no transfer*/
|
||||
|
|
@ -589,6 +595,12 @@ typedef struct rtp_config
|
|||
bool_t audio_adaptive_jitt_comp_enabled;
|
||||
bool_t video_adaptive_jitt_comp_enabled;
|
||||
bool_t pad;
|
||||
char* audio_multicast_addr;
|
||||
bool_t audio_multicast_enabled;
|
||||
int audio_multicast_ttl;
|
||||
char* video_multicast_addr;
|
||||
int video_multicast_ttl;
|
||||
bool_t video_multicast_enabled;
|
||||
}rtp_config_t;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -196,6 +196,14 @@ typedef enum {
|
|||
SalDtlsRoleUnset
|
||||
} SalDtlsRole;
|
||||
|
||||
typedef enum {
|
||||
SalMulticastInative=0,
|
||||
SalMulticastRoleSender,
|
||||
SalMulticastRoleReceiver,
|
||||
SalMulticastSenderReceiver
|
||||
} SalMulticastRole;
|
||||
|
||||
|
||||
typedef struct SalStreamDescription{
|
||||
char name[16]; /*unique name of stream, in order to ease offer/answer model algorithm*/
|
||||
SalMediaProto proto;
|
||||
|
|
@ -226,6 +234,8 @@ typedef struct SalStreamDescription{
|
|||
bool_t pad[2];
|
||||
char dtls_fingerprint[256];
|
||||
SalDtlsRole dtls_role;
|
||||
int ttl; /*for multicast -1 to disable*/
|
||||
SalMulticastRole multicast_role;
|
||||
} SalStreamDescription;
|
||||
|
||||
const char *sal_stream_description_get_type_as_string(const SalStreamDescription *desc);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ liblinphonetester_la_SOURCES = tester.c \
|
|||
register_tester.c \
|
||||
message_tester.c \
|
||||
call_tester.c \
|
||||
multicast_call_tester.c \
|
||||
presence_tester.c \
|
||||
upnp_tester.c \
|
||||
eventapi_tester.c \
|
||||
|
|
|
|||
|
|
@ -127,8 +127,8 @@ void linphone_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
static void linphone_call_cb(LinphoneCall *call,void * user_data) {
|
||||
|
||||
void linphone_call_cb(LinphoneCall *call,void * user_data) {
|
||||
char* to=linphone_address_as_string(linphone_call_get_call_log(call)->to);
|
||||
char* from=linphone_address_as_string(linphone_call_get_call_log(call)->from);
|
||||
stats* counters;
|
||||
|
|
@ -139,7 +139,6 @@ static void linphone_call_cb(LinphoneCall *call,void * user_data) {
|
|||
counters = (stats*)get_stats(lc);
|
||||
counters->number_of_IframeDecoded++;
|
||||
}
|
||||
#endif
|
||||
|
||||
void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreManager* callee) {
|
||||
LinphoneCall *c1,*c2;
|
||||
|
|
@ -314,7 +313,7 @@ void end_call(LinphoneCoreManager *m1, LinphoneCoreManager *m2){
|
|||
CU_ASSERT_TRUE(wait_for(m1->lc,m2->lc,&m2->stat.number_of_LinphoneCallReleased,1));
|
||||
}
|
||||
|
||||
static void simple_call(void) {
|
||||
void simple_call_base(bool_t enable_multicast_recv_side) {
|
||||
int begin;
|
||||
int leaked_objects;
|
||||
LinphoneCoreManager* marie;
|
||||
|
|
@ -347,6 +346,8 @@ static void simple_call(void) {
|
|||
linphone_address_unref(marie_addr);
|
||||
}
|
||||
|
||||
linphone_core_enable_audio_multicast(pauline->lc,enable_multicast_recv_side);
|
||||
|
||||
CU_ASSERT_TRUE(call(marie,pauline));
|
||||
pauline_call=linphone_core_get_current_call(pauline->lc);
|
||||
CU_ASSERT_PTR_NOT_NULL(pauline_call);
|
||||
|
|
@ -375,7 +376,9 @@ static void simple_call(void) {
|
|||
belle_sip_object_dump_active_objects();
|
||||
}
|
||||
}
|
||||
|
||||
static void simple_call() {
|
||||
simple_call_base(FALSE);
|
||||
}
|
||||
static void call_with_timeouted_bye(void) {
|
||||
int begin;
|
||||
int leaked_objects;
|
||||
|
|
@ -1131,12 +1134,14 @@ static void call_with_custom_headers(void) {
|
|||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void call_paused_resumed(void) {
|
||||
void call_paused_resumed_base(bool_t multicast) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
LinphoneCall* call_pauline;
|
||||
const rtp_stats_t * stats;
|
||||
|
||||
linphone_core_enable_audio_multicast(pauline->lc,multicast);
|
||||
|
||||
CU_ASSERT_TRUE(call(pauline,marie));
|
||||
call_pauline = linphone_core_get_current_call(pauline->lc);
|
||||
|
||||
|
|
@ -1170,7 +1175,9 @@ static void call_paused_resumed(void) {
|
|||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void call_paused_resumed(void) {
|
||||
call_paused_resumed_base(FALSE);
|
||||
}
|
||||
#define CHECK_CURRENT_LOSS_RATE() \
|
||||
rtcp_count_current = pauline->stat.number_of_rtcp_sent; \
|
||||
/*wait for an RTCP packet to have an accurate cumulative lost value*/ \
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ extern test_suite_t player_test_suite;
|
|||
extern test_suite_t dtmf_test_suite;
|
||||
extern test_suite_t offeranswer_test_suite;
|
||||
extern test_suite_t video_test_suite;
|
||||
extern test_suite_t multicast_call_test_suite;
|
||||
|
||||
|
||||
extern int liblinphone_tester_nb_test_suites(void);
|
||||
|
|
@ -314,7 +315,9 @@ void liblinphone_tester_enable_ipv6(bool_t enabled);
|
|||
void cunit_android_trace_handler(int level, const char *fmt, va_list args) ;
|
||||
#endif
|
||||
int liblinphone_tester_fprintf(FILE * stream, const char * format, ...);
|
||||
|
||||
void linphone_call_cb(LinphoneCall *call,void * user_data);
|
||||
void call_paused_resumed_base(bool_t multicast);
|
||||
void simple_call_base(bool_t enable_multicast_recv_side);
|
||||
void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t enable_relay,LinphoneFirewallPolicy policy,bool_t enable_tunnel);
|
||||
#endif /* LIBLINPHONE_TESTER_H_ */
|
||||
|
||||
|
|
|
|||
198
tester/multicast_call_tester.c
Normal file
198
tester/multicast_call_tester.c
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
liblinphone_tester - liblinphone test suite
|
||||
Copyright (C) 2014 Belledonne Communications SARL
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "liblinphone_tester.h"
|
||||
#include "linphonecore.h"
|
||||
#include "belle-sip/belle-sip.h"
|
||||
|
||||
static void call_multicast_base(bool_t video) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
int begin;
|
||||
int leaked_objects;
|
||||
LinphoneVideoPolicy marie_policy, pauline_policy;
|
||||
|
||||
belle_sip_object_enable_leak_detector(TRUE);
|
||||
begin=belle_sip_object_get_object_count();
|
||||
|
||||
if (video) {
|
||||
linphone_core_enable_video_capture(marie->lc, TRUE);
|
||||
linphone_core_enable_video_display(marie->lc, TRUE);
|
||||
linphone_core_enable_video_capture(pauline->lc, TRUE);
|
||||
linphone_core_enable_video_display(pauline->lc, FALSE);
|
||||
|
||||
marie_policy.automatically_initiate=TRUE;
|
||||
marie_policy.automatically_accept=TRUE;
|
||||
pauline_policy.automatically_initiate=TRUE;
|
||||
pauline_policy.automatically_accept=TRUE;
|
||||
|
||||
linphone_core_set_video_policy(marie->lc,&marie_policy);
|
||||
linphone_core_set_video_policy(pauline->lc,&pauline_policy);
|
||||
linphone_core_set_video_multicast_addr(pauline->lc,"224.1.2.3");
|
||||
linphone_core_enable_video_multicast(pauline->lc,TRUE);
|
||||
}
|
||||
linphone_core_set_audio_multicast_addr(pauline->lc,"224.1.2.3");
|
||||
linphone_core_enable_audio_multicast(pauline->lc,TRUE);
|
||||
|
||||
CU_ASSERT_TRUE(call(pauline,marie));
|
||||
wait_for_until(marie->lc, pauline->lc, NULL, 1, 3000);
|
||||
if (linphone_core_get_current_call(marie->lc)) {
|
||||
CU_ASSERT_TRUE(linphone_call_get_audio_stats(linphone_core_get_current_call(marie->lc))->download_bandwidth>70);
|
||||
if (video) {
|
||||
/*check video path*/
|
||||
linphone_call_set_next_video_frame_decoded_callback(linphone_core_get_current_call(marie->lc),linphone_call_cb,marie->lc);
|
||||
linphone_call_send_vfu_request(linphone_core_get_current_call(marie->lc));
|
||||
CU_ASSERT_TRUE( wait_for(marie->lc,pauline->lc,&marie->stat.number_of_IframeDecoded,1));
|
||||
}
|
||||
|
||||
end_call(marie,pauline);
|
||||
}
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
|
||||
leaked_objects=belle_sip_object_get_object_count()-begin;
|
||||
CU_ASSERT_TRUE(leaked_objects==0);
|
||||
if (leaked_objects>0){
|
||||
belle_sip_object_dump_active_objects();
|
||||
}
|
||||
|
||||
}
|
||||
static void call_multicast(void) {
|
||||
call_multicast_base(FALSE);
|
||||
}
|
||||
static void multicast_audio_with_pause_resume() {
|
||||
call_paused_resumed_base(TRUE);
|
||||
}
|
||||
#ifdef VIDEO_ENABLED
|
||||
static void call_multicast_video(void) {
|
||||
call_multicast_base(TRUE);
|
||||
}
|
||||
#endif
|
||||
static void early_media_with_multicast_base(bool_t video) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new("pauline_rc");
|
||||
MSList* lcs = NULL;
|
||||
LinphoneCall* marie_call;
|
||||
int dummy=0;
|
||||
int leaked_objects;
|
||||
int begin;
|
||||
LinphoneVideoPolicy marie_policy, pauline_policy;
|
||||
|
||||
belle_sip_object_enable_leak_detector(TRUE);
|
||||
begin=belle_sip_object_get_object_count();
|
||||
|
||||
if (video) {
|
||||
linphone_core_enable_video_capture(pauline->lc, TRUE);
|
||||
linphone_core_enable_video_display(pauline->lc, TRUE);
|
||||
linphone_core_enable_video_capture(marie->lc, TRUE);
|
||||
linphone_core_enable_video_display(marie->lc, FALSE);
|
||||
|
||||
marie_policy.automatically_initiate=TRUE;
|
||||
marie_policy.automatically_accept=TRUE;
|
||||
pauline_policy.automatically_initiate=TRUE;
|
||||
pauline_policy.automatically_accept=TRUE;
|
||||
|
||||
linphone_core_set_video_policy(marie->lc,&marie_policy);
|
||||
linphone_core_set_video_policy(pauline->lc,&pauline_policy);
|
||||
linphone_core_set_video_multicast_addr(marie->lc,"224.1.2.3");
|
||||
linphone_core_enable_video_multicast(marie->lc,TRUE);
|
||||
}
|
||||
linphone_core_set_audio_multicast_addr(marie->lc,"224.1.2.3");
|
||||
linphone_core_enable_audio_multicast(marie->lc,TRUE);
|
||||
|
||||
|
||||
lcs = ms_list_append(lcs,marie->lc);
|
||||
lcs = ms_list_append(lcs,pauline->lc);
|
||||
/*
|
||||
Marie calls Pauline, and after the call has rung, transitions to an early_media session
|
||||
*/
|
||||
|
||||
marie_call = linphone_core_invite_address(marie->lc, pauline->identity);
|
||||
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingReceived,1,3000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingRinging,1,1000));
|
||||
|
||||
|
||||
if (linphone_core_inc_invite_pending(pauline->lc)) {
|
||||
/* send a 183 to initiate the early media */
|
||||
if (video) {
|
||||
/*check video path*/
|
||||
linphone_call_set_next_video_frame_decoded_callback(linphone_core_get_current_call(pauline->lc),linphone_call_cb,pauline->lc);
|
||||
}
|
||||
linphone_core_accept_early_media(pauline->lc, linphone_core_get_current_call(pauline->lc));
|
||||
|
||||
CU_ASSERT_TRUE( wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingEarlyMedia,1,2000) );
|
||||
CU_ASSERT_TRUE( wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingEarlyMedia,1,2000) );
|
||||
|
||||
wait_for_list(lcs, &dummy, 1, 3000);
|
||||
|
||||
CU_ASSERT_TRUE(linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc))->download_bandwidth>70);
|
||||
|
||||
if (video) {
|
||||
CU_ASSERT_TRUE( wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_IframeDecoded,1));
|
||||
}
|
||||
|
||||
linphone_core_accept_call(pauline->lc, linphone_core_get_current_call(pauline->lc));
|
||||
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallConnected, 1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning, 1,1000));
|
||||
|
||||
end_call(marie,pauline);
|
||||
}
|
||||
ms_free(lcs);
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
|
||||
leaked_objects=belle_sip_object_get_object_count()-begin;
|
||||
CU_ASSERT_TRUE(leaked_objects==2/*fixme jehan*/);
|
||||
if ((leaked_objects)>0){
|
||||
belle_sip_object_dump_active_objects();
|
||||
}
|
||||
}
|
||||
|
||||
static void early_media_with_multicast_audio() {
|
||||
early_media_with_multicast_base(FALSE);
|
||||
}
|
||||
static void unicast_incoming_with_multicast_audio_on() {
|
||||
simple_call_base(TRUE);
|
||||
}
|
||||
#ifdef VIDEO_ENABLED
|
||||
static void early_media_with_multicast_video() {
|
||||
early_media_with_multicast_base(TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
test_t multicast_call_tests[] = {
|
||||
{ "Multicast audio call",call_multicast},
|
||||
{ "Multicast call with pause/resume",multicast_audio_with_pause_resume},
|
||||
{ "Early media multicast audio call",early_media_with_multicast_audio},
|
||||
{ "Unicast incoming call with multicast activated",unicast_incoming_with_multicast_audio_on},
|
||||
#ifdef VIDEO_ENABLED
|
||||
{ "Multicast video call",call_multicast_video},
|
||||
{ "Early media multicast video call",early_media_with_multicast_video},
|
||||
#endif
|
||||
};
|
||||
|
||||
test_suite_t multicast_call_test_suite = {
|
||||
"Multicast Call",
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof(multicast_call_tests) / sizeof(multicast_call_tests[0]),
|
||||
multicast_call_tests
|
||||
};
|
||||
|
|
@ -347,7 +347,7 @@ static void presence_information(void) {
|
|||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
#define USE_PRESENCE_SERVER 0
|
||||
#define USE_PRESENCE_SERVER 1
|
||||
|
||||
#if USE_PRESENCE_SERVER
|
||||
static void test_subscribe_notify_publish(void) {
|
||||
|
|
@ -382,25 +382,87 @@ static void test_subscribe_notify_publish(void) {
|
|||
wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,2,2000);
|
||||
CU_ASSERT_EQUAL(LinphoneStatusOnline,linphone_friend_get_status(lf));
|
||||
|
||||
presence =linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline,NULL);
|
||||
presence =linphone_presence_model_new_with_activity(LinphonePresenceActivityBusy,NULL);
|
||||
linphone_core_set_presence_model(marie->lc,presence);
|
||||
|
||||
/*wait for new status*/
|
||||
wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,3,2000);
|
||||
CU_ASSERT_EQUAL(LinphonePresenceActivityOffline,linphone_friend_get_status(lf));
|
||||
CU_ASSERT_EQUAL(LinphoneStatusBusy,linphone_friend_get_status(lf));
|
||||
|
||||
/*wait for refresh*/
|
||||
wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,4,5000);
|
||||
CU_ASSERT_EQUAL(LinphonePresenceActivityOffline,linphone_friend_get_status(lf));
|
||||
CU_ASSERT_EQUAL(LinphoneStatusBusy,linphone_friend_get_status(lf));
|
||||
|
||||
//linphone_core_remove_friend(pauline->lc,lf);
|
||||
/*linphone_core_remove_friend(pauline->lc,lf);*/
|
||||
/*wait for final notify*/
|
||||
//wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,4,5000);
|
||||
//CU_ASSERT_EQUAL(LinphonePresenceActivityOffline,linphone_friend_get_status(lf));
|
||||
|
||||
/*wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,4,5000);
|
||||
CU_ASSERT_EQUAL(LinphonePresenceActivityOffline,linphone_friend_get_status(lf));
|
||||
*/
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
static void test_forked_subscribe_notify_publish(void) {
|
||||
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* marie2 = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
LinphoneProxyConfig* proxy;
|
||||
LinphonePresenceModel* presence;
|
||||
MSList* lcs=ms_list_append(NULL,pauline->lc);
|
||||
lcs=ms_list_append(lcs,marie->lc);
|
||||
lcs=ms_list_append(lcs,marie->lc);
|
||||
lcs=ms_list_append(lcs,marie2->lc);
|
||||
|
||||
LpConfig *pauline_lp = linphone_core_get_config(pauline->lc);
|
||||
char* lf_identity=linphone_address_as_string_uri_only(marie->identity);
|
||||
LinphoneFriend *lf = linphone_core_create_friend_with_address(pauline->lc,lf_identity);
|
||||
|
||||
lp_config_set_int(pauline_lp,"sip","subscribe_expires",5);
|
||||
|
||||
linphone_core_add_friend(pauline->lc,lf);
|
||||
|
||||
/*wait for subscribe acknowledgment*/
|
||||
wait_for_list(lcs,&pauline->stat.number_of_NotifyReceived,1,2000);
|
||||
CU_ASSERT_EQUAL(LinphoneStatusOffline,linphone_friend_get_status(lf));
|
||||
|
||||
/*enable publish*/
|
||||
|
||||
linphone_core_get_default_proxy(marie->lc,&proxy);
|
||||
linphone_proxy_config_edit(proxy);
|
||||
linphone_proxy_config_enable_publish(proxy,TRUE);
|
||||
linphone_proxy_config_set_publish_expires(proxy,3);
|
||||
linphone_proxy_config_done(proxy);
|
||||
|
||||
linphone_core_get_default_proxy(marie2->lc,&proxy);
|
||||
linphone_proxy_config_edit(proxy);
|
||||
linphone_proxy_config_enable_publish(proxy,TRUE);
|
||||
linphone_proxy_config_set_publish_expires(proxy,3);
|
||||
linphone_proxy_config_done(proxy);
|
||||
|
||||
|
||||
/*wait for marie status*/
|
||||
wait_for_list(lcs,&pauline->stat.number_of_NotifyReceived,3,2000);
|
||||
CU_ASSERT_EQUAL(LinphoneStatusOnline,linphone_friend_get_status(lf));
|
||||
|
||||
presence =linphone_presence_model_new_with_activity(LinphonePresenceActivityBusy,NULL);
|
||||
linphone_core_set_presence_model(marie->lc,presence);
|
||||
|
||||
/*wait for new status*/
|
||||
wait_for_list(lcs,&pauline->stat.number_of_NotifyReceived,4,2000);
|
||||
CU_ASSERT_EQUAL(LinphoneStatusBusy,linphone_friend_get_status(lf));
|
||||
|
||||
|
||||
presence =linphone_presence_model_new_with_activity( LinphonePresenceActivityMeeting,NULL);
|
||||
linphone_core_set_presence_model(marie2->lc,presence);
|
||||
/*wait for new status*/
|
||||
wait_for_list(lcs,&pauline->stat.number_of_NotifyReceived,5,2000);
|
||||
CU_ASSERT_EQUAL(LinphoneStatusBusy,linphone_friend_get_status(lf)); /*because liblinphone compositor is very simple for now (I.E only take first occurence)*/
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(marie2);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -414,6 +476,7 @@ test_t presence_tests[] = {
|
|||
{ "App managed presence failure", subscribe_failure_handle_by_app },
|
||||
#if USE_PRESENCE_SERVER
|
||||
{ "Subscribe with late publish", test_subscribe_notify_publish },
|
||||
{ "Forked subscribe with late publish", test_forked_subscribe_notify_publish },
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -453,6 +453,7 @@ void liblinphone_tester_init(void) {
|
|||
#if defined(VIDEO_ENABLED) && defined(HAVE_GTK)
|
||||
add_test_suite(&video_test_suite);
|
||||
#endif
|
||||
add_test_suite(&multicast_call_test_suite);
|
||||
}
|
||||
|
||||
void liblinphone_tester_uninit(void) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue