From: Simon Morlat Date: Wed, 24 Nov 2010 21:37:20 +0000 (+0100) Subject: support early media sending for outgoing calls X-Git-Url: http://sjero.net/git/?p=linphone;a=commitdiff_plain;h=f55a93216d34d1ac7eb6bf5fdae35a71e2763564 support early media sending for outgoing calls --- diff --git a/console/commands.c b/console/commands.c index a7aa22f7..ab67569b 100644 --- a/console/commands.c +++ b/console/commands.c @@ -144,7 +144,10 @@ static LPC_COMMAND commands[] = { }, { "call", lpc_cmd_call, "Call a SIP uri or number", #ifdef VIDEO_ENABLED - "'call [--audio-only]' \t: initiate a call to the specified destination.\n" + "'call [options]' \t: initiate a call to the specified destination.\n" + "Options can be:\n" + "--audio-only : initiate the call without video.\n" + "--early-media : sends audio and video stream immediately when remote proposes early media.\n" #else "'call ' \t: initiate a call to the specified destination.\n" #endif @@ -542,17 +545,22 @@ lpc_cmd_call(LinphoneCore *lc, char *args) { LinphoneCall *call; LinphoneCallParams *cp=linphone_core_create_default_call_parameters (lc); - char *opt; + char *opt1,*opt2; if ( linphone_core_in_call(lc) ) { linphonec_out("Terminate or hold on the current call first.\n"); return 1; } - opt=strstr(args,"--audio-only"); - if (opt){ - opt[0]='\0'; + opt1=strstr(args,"--audio-only"); + opt2=strstr(args,"--early-media"); + if (opt1){ + opt1[0]='\0'; linphone_call_params_enable_video (cp,FALSE); } + if (opt2){ + opt2[0]='\0'; + linphone_call_params_enable_early_media_sending(cp,TRUE); + } if ( NULL == (call=linphone_core_invite_with_params(lc, args,cp)) ) { linphonec_out("Error from linphone_core_invite.\n"); diff --git a/console/linphonec.c b/console/linphonec.c index 41b70a81..8373f1f6 100644 --- a/console/linphonec.c +++ b/console/linphonec.c @@ -356,10 +356,28 @@ static void linphonec_call_state_changed(LinphoneCore *lc, LinphoneCall *call, L break; case LinphoneCallOutgoingInit: linphonec_call_identify(call); + id=(long)linphone_call_get_user_pointer (call); + from=linphone_call_get_remote_address_as_string(call); + linphonec_out("Establishing call id to %s, assigned id %i\n", from,id); break; case LinphoneCallUpdatedByRemote: linphonec_call_updated(call); break; + case LinphoneCallOutgoingProgress: + linphonec_out("Call %i to %s in progress.\n", id, from); + break; + case LinphoneCallOutgoingRinging: + linphonec_out("Call %i to %s ringing.\n", id, from); + break; + case LinphoneCallConnected: + linphonec_out("Call %i with %s connected.\n", id, from); + break; + case LinphoneCallOutgoingEarlyMedia: + linphonec_out("Call %i with %s early media.\n", id, from); + break; + case LinphoneCallError: + linphonec_out("Call %i with %s error.\n", id, from); + break; default: break; } diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index d4f5193f..13f00a99 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -27,12 +27,60 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. static void register_failure(SalOp *op, SalError error, SalReason reason, const char *details); -static void linphone_connect_incoming(LinphoneCore *lc, LinphoneCall *call){ +void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md){ + SalMediaDescription *oldmd=call->resultdesc; + if (lc->ringstream!=NULL){ ring_stop(lc->ringstream); lc->ringstream=NULL; } - linphone_call_start_media_streams(call); + if (new_md!=NULL){ + sal_media_description_ref(new_md); + call->media_pending=FALSE; + }else{ + call->media_pending=TRUE; + } + call->resultdesc=new_md; + if (call->audiostream && call->audiostream->ticker){ + /* we already started media: check if we really need to restart it*/ + if (oldmd){ + if (sal_media_description_equals(oldmd,new_md)){ + sal_media_description_unref(oldmd); + if (call->all_muted){ + ms_message("Early media finished, unmuting inputs..."); + /*we were in early media, now we want to enable real media */ + linphone_call_enable_camera (call,linphone_call_camera_enabled (call)); + if (call->audiostream) + linphone_core_mute_mic (lc, linphone_core_is_mic_muted(lc)); + } + ms_message("No need to restart streams, SDP is unchanged."); + return; + }else{ + ms_message("Media descriptions are different, need to restart the streams."); + } + } + linphone_call_stop_media_streams (call); + linphone_call_init_media_streams (call); + } + if (oldmd) + sal_media_description_unref(oldmd); + + if (new_md) { + bool_t all_muted=FALSE; + bool_t send_ringbacktone=FALSE; + + if (call->audiostream==NULL){ + /*this happens after pausing the call locally. The streams is destroyed and then we wait the 200Ok to recreate it*/ + linphone_call_init_media_streams (call); + } + if (call->state==LinphoneCallIncomingEarlyMedia || + (call->state==LinphoneCallOutgoingEarlyMedia && !call->params.real_early_media)){ + all_muted=TRUE; + }else if (call->state==LinphoneCallIncomingEarlyMedia && linphone_core_get_remote_ringback_tone (lc)!=NULL){ + send_ringbacktone=TRUE; + } + linphone_call_start_media_streams(call,all_muted,send_ringbacktone); + } } static bool_t is_duplicate_call(LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to){ @@ -55,7 +103,9 @@ static void call_received(SalOp *h){ char *tmp; LinphoneAddress *from_parsed; LinphoneAddress *from_addr, *to_addr; - const char * early_media=linphone_core_get_remote_ringback_tone (lc); + SalMediaDescription *md; + bool_t propose_early_media=lp_config_get_int(lc->config,"sip","incoming_calls_early_media",FALSE); + const char *ringback_tone=linphone_core_get_remote_ringback_tone (lc); /* first check if we can answer successfully to this invite */ if (lc->presence_mode==LinphoneStatusBusy || @@ -93,16 +143,14 @@ static void call_received(SalOp *h){ call=linphone_call_new_incoming(lc,from_addr,to_addr,h); sal_call_set_local_media_description(h,call->localdesc); - call->resultdesc=sal_call_get_final_media_description(h); - if (call->resultdesc) - sal_media_description_ref(call->resultdesc); - if (call->resultdesc && sal_media_description_empty(call->resultdesc)){ + md=sal_call_get_final_media_description(h); + + if (md && sal_media_description_empty(md)){ sal_call_decline(h,SalReasonMedia,NULL); linphone_call_unref(call); return; } - /* the call is acceptable so we can now add it to our list */ linphone_core_add_call(lc,call); @@ -136,17 +184,18 @@ static void call_received(SalOp *h){ }else{ /*TODO : play a tone within the context of the current call */ } - sal_call_notify_ringing(h,early_media!=NULL); -#if !(__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000) - linphone_call_init_media_streams(call); - if (early_media!=NULL){ - linphone_call_start_early_media (call); + linphone_call_set_state(call,LinphoneCallIncomingReceived,"Incoming call"); + + sal_call_notify_ringing(h,propose_early_media || ringback_tone!=NULL); + + if (propose_early_media || ringback_tone!=NULL){ + linphone_call_set_state(call,LinphoneCallIncomingEarlyMedia,"Incoming call early media"); + linphone_core_update_streams(lc,call,md); } -#endif ms_free(barmesg); ms_free(tmp); - linphone_call_set_state(call,LinphoneCallIncomingReceived,"Incoming call"); + if (sal_call_get_replaces(call->op)!=NULL && lp_config_get_int(lc->config,"sip","auto_answer_replacing_calls",1)){ linphone_core_accept_call(lc,call); } @@ -183,8 +232,6 @@ static void call_ringing(SalOp *h){ ms_message("Early media already started."); return; } - sal_media_description_ref(md); - call->resultdesc=md; if (lc->vtable.show) lc->vtable.show(lc); if (lc->vtable.display_status) lc->vtable.display_status(lc,_("Early media.")); @@ -194,8 +241,7 @@ static void call_ringing(SalOp *h){ lc->ringstream=NULL; } ms_message("Doing early media..."); - linphone_call_start_media_streams(call); - call->media_pending=TRUE; + linphone_core_update_streams (lc,call,md); } } @@ -207,33 +253,23 @@ static void call_ringing(SalOp *h){ static void call_accepted(SalOp *op){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); - + SalMediaDescription *md; + if (call==NULL){ ms_warning("No call to accept."); return ; } - if ((call->audiostream!=NULL) && (call->audiostream->ticker!=NULL)){ - /*case where we accepted early media or already in call*/ - linphone_call_stop_media_streams(call); - } - if (call->audiostream==NULL){ - linphone_call_init_media_streams(call); - } - if (call->resultdesc) - sal_media_description_unref(call->resultdesc); - call->resultdesc=sal_call_get_final_media_description(op); - if (call->resultdesc){ - sal_media_description_ref(call->resultdesc); - call->media_pending=FALSE; - } + + md=sal_call_get_final_media_description(op); + if (call->state==LinphoneCallOutgoingProgress || call->state==LinphoneCallOutgoingRinging || call->state==LinphoneCallOutgoingEarlyMedia){ linphone_call_set_state(call,LinphoneCallConnected,"Connected"); } - if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){ - if (sal_media_description_has_dir(call->resultdesc,SalStreamSendOnly) || - sal_media_description_has_dir(call->resultdesc,SalStreamInactive)){ + if (md && !sal_media_description_empty(md)){ + if (sal_media_description_has_dir(md,SalStreamSendOnly) || + sal_media_description_has_dir(md,SalStreamInactive)){ if (lc->vtable.display_status){ char *tmp=linphone_call_get_remote_address_as_string (call); char *msg=ms_strdup_printf(_("Call with %s is paused."),tmp); @@ -242,7 +278,7 @@ static void call_accepted(SalOp *op){ ms_free(msg); } linphone_call_set_state(call,LinphoneCallPaused,"Call paused"); - }else if (sal_media_description_has_dir(call->resultdesc,SalStreamRecvOnly)){ + }else if (sal_media_description_has_dir(md,SalStreamRecvOnly)){ /*we are put on hold when the call is initially accepted */ if (lc->vtable.display_status){ char *tmp=linphone_call_get_remote_address_as_string (call); @@ -258,7 +294,7 @@ static void call_accepted(SalOp *op){ } linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)"); } - linphone_connect_incoming (lc,call); + linphone_core_update_streams (lc,call,md); }else{ /*send a bye*/ ms_error("Incompatible SDP offer received in 200Ok, need to abort the call"); @@ -274,18 +310,9 @@ static void call_ack(SalOp *op){ return ; } if (call->media_pending){ - if (call->audiostream->ticker!=NULL){ - /*case where we accepted early media */ - linphone_call_stop_media_streams(call); - linphone_call_init_media_streams(call); - } - if (call->resultdesc) - sal_media_description_unref(call->resultdesc); - call->resultdesc=sal_call_get_final_media_description(op); - if (call->resultdesc) - sal_media_description_ref(call->resultdesc); - if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){ - linphone_connect_incoming(lc,call); + SalMediaDescription *md=sal_call_get_final_media_description(op); + if (md && !sal_media_description_empty(md)){ + linphone_core_update_streams (lc,call,md); linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)"); }else{ /*send a bye*/ @@ -293,7 +320,6 @@ static void call_ack(SalOp *op){ linphone_core_abort_call(lc,call,"No codec intersection"); return; } - call->media_pending=FALSE; } } @@ -302,17 +328,14 @@ static void call_updating(SalOp *op){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); LinphoneCallState prevstate=LinphoneCallIdle; + SalMediaDescription *md; - if (call->resultdesc) - sal_media_description_unref(call->resultdesc); - call->resultdesc=sal_call_get_final_media_description(op); - if (call->resultdesc) - sal_media_description_ref(call->resultdesc); - - if (call->resultdesc && !sal_media_description_empty(call->resultdesc)) + md=sal_call_get_final_media_description(op); + + if (md && !sal_media_description_empty(md)) { if ((call->state==LinphoneCallPausedByRemote || call->state==LinphoneCallPaused) && - sal_media_description_has_dir(call->resultdesc,SalStreamSendRecv) && strcmp(call->resultdesc->addr,"0.0.0.0")!=0){ + sal_media_description_has_dir(md,SalStreamSendRecv) && strcmp(md->addr,"0.0.0.0")!=0){ /*make sure we can be resumed */ if (lc->current_call!=NULL && lc->current_call!=call){ ms_warning("Attempt to be resumed but already in call with somebody else!"); @@ -325,9 +348,9 @@ static void call_updating(SalOp *op){ linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)"); } else if(call->state==LinphoneCallStreamsRunning && - ( sal_media_description_has_dir(call->resultdesc,SalStreamRecvOnly) - || sal_media_description_has_dir(call->resultdesc,SalStreamInactive) - || strcmp(call->resultdesc->addr,"0.0.0.0")==0)){ + ( sal_media_description_has_dir(md,SalStreamRecvOnly) + || sal_media_description_has_dir(md,SalStreamInactive) + || strcmp(md->addr,"0.0.0.0")==0)){ if(lc->vtable.display_status) lc->vtable.display_status(lc,_("We are being paused...")); linphone_call_set_state (call,LinphoneCallPausedByRemote,"Call paused by remote"); @@ -340,9 +363,7 @@ static void call_updating(SalOp *op){ } /*accept the modification (sends a 200Ok)*/ sal_call_accept(op); - linphone_call_stop_media_streams (call); - linphone_call_init_media_streams (call); - linphone_call_start_media_streams (call); + linphone_core_update_streams (lc,call,md); if (prevstate!=LinphoneCallIdle){ linphone_call_set_state (call,prevstate,"Connected (streams running)"); } diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 56509c92..1d123b91 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -279,6 +279,8 @@ const char *linphone_call_state_to_string(LinphoneCallState cs){ return "LinphoneCallPausedByRemote"; case LinphoneCallUpdatedByRemote: return "LinphoneCallUpdatedByRemote"; + case LinphoneCallIncomingEarlyMedia: + return "LinphoneCallIncomingEarlyMedia"; } return "undefined state"; } @@ -521,6 +523,17 @@ bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp){ return cp->has_video; } +/** + * Enable sending of real early media (during outgoing calls). +**/ +void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, bool_t enabled){ + cp->real_early_media=enabled; +} + +bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams *cp){ + return cp->real_early_media; +} + /** * **/ @@ -638,9 +651,10 @@ static void post_configure_audio_streams(LinphoneCall*call){ float ng_floorgain=lp_config_get_float(lc->config,"sound","ng_floorgain",0); int dc_removal=lp_config_get_int(lc->config,"sound","dc_removal",0); - if (mic_gain!=-1) + if (!call->audio_muted) audio_stream_set_mic_gain(st,mic_gain); - call->audio_muted=FALSE; + else + audio_stream_set_mic_gain(st,0); recv_gain = lc->sound_conf.soft_play_lev; if (recv_gain != 0) { @@ -738,18 +752,21 @@ static RtpProfile *make_profile(LinphoneCore *lc, const SalMediaDescription *md, return prof; } + static void setup_ring_player(LinphoneCore *lc, LinphoneCall *call){ int pause_time=3000; audio_stream_play(call->audiostream,lc->sound_conf.ringback_tone); ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time); } -static void _linphone_call_start_media_streams(LinphoneCall *call, bool_t send_early_media){ + +void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_muted, bool_t send_ringbacktone){ LinphoneCore *lc=call->core; LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc); const char *tool="linphone-" LINPHONE_VERSION; char *cname; int used_pt=-1; + if(call->audiostream == NULL) { ms_fatal("start_media_stream() called without prior init !"); @@ -783,12 +800,11 @@ static void _linphone_call_start_media_streams(LinphoneCall *call, bool_t send_e if (stream->port==0 || stream->dir==SalStreamRecvOnly){ captcard=NULL; playfile=NULL; - }else if (stream->dir==SalStreamSendOnly || send_early_media){ + }else if (stream->dir==SalStreamSendOnly){ playcard=NULL; captcard=NULL; recfile=NULL; - if (send_early_media) - playfile=NULL; + if (!send_ringbacktone) playfile=NULL; } /*if playfile are supplied don't use soundcards*/ if (lc->use_files) { @@ -809,13 +825,18 @@ static void _linphone_call_start_media_streams(LinphoneCall *call, bool_t send_e captcard, captcard==NULL ? FALSE : linphone_core_echo_cancellation_enabled(lc)); post_configure_audio_streams(call); - if (send_early_media) setup_ring_player(lc,call); + if (all_inputs_muted){ + audio_stream_set_mic_gain(call->audiostream,0); + } + if (send_ringbacktone){ + setup_ring_player(lc,call); + } audio_stream_set_rtcp_information(call->audiostream, cname, tool); }else ms_warning("No audio stream accepted ?"); } } #ifdef VIDEO_ENABLED - if (!send_early_media){ + { const SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc, SalProtoRtpAvp,SalVideo); used_pt=-1; @@ -859,7 +880,7 @@ static void _linphone_call_start_media_streams(LinphoneCall *call, bool_t send_e /*either inactive or incompatible with local capabilities*/ is_inactive=TRUE; } - if (call->camera_active==FALSE){ + if (call->camera_active==FALSE || all_inputs_muted){ cam=get_nowebcam_device(); } if (!is_inactive){ @@ -876,21 +897,14 @@ static void _linphone_call_start_media_streams(LinphoneCall *call, bool_t send_e } } #endif + call->all_muted=all_inputs_muted; + goto end; end: ms_free(cname); linphone_address_destroy(me); } - -void linphone_call_start_media_streams(LinphoneCall *call){ - _linphone_call_start_media_streams(call,FALSE); -} - -void linphone_call_start_early_media(LinphoneCall *call){ - _linphone_call_start_media_streams(call,TRUE); -} - static void linphone_call_log_fill_stats(LinphoneCallLog *log, AudioStream *st){ audio_stream_get_local_rtp_stats (st,&log->local_stats); } diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index d06f3cf3..c21f08e6 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -467,8 +467,9 @@ static void sound_config_read(LinphoneCore *lc) gain=lp_config_get_float(lc->config,"sound","playback_gain_db",0); linphone_core_set_playback_gain_db (lc,gain); - +/* linphone_core_set_remote_ringback_tone (lc,lp_config_get_string(lc->config,"sound","ringback_tone",NULL)); + */ } static void sip_config_read(LinphoneCore *lc) @@ -2221,6 +2222,7 @@ int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call) LinphoneProxyConfig *cfg=NULL; const char *contact=NULL; SalOp *replaced; + SalMediaDescription *new_md; if (call==NULL){ //if just one call is present answer the only one ... @@ -2276,26 +2278,21 @@ int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call) contact=get_fixed_contact(lc,call,cfg); if (contact) sal_op_set_contact(call->op,contact); -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 40000 - linphone_call_init_media_streams(call); -#else - if (call->audiostream!=NULL && call->audiostream->ticker!=NULL){ - /*case where we sent early media*/ - linphone_call_stop_media_streams (call); - linphone_call_init_media_streams (call); - } -#endif + + if (call->audiostream==NULL) + linphone_call_init_media_streams(call); + sal_call_accept(call->op); if (lc->vtable.display_status!=NULL) lc->vtable.display_status(lc,_("Connected.")); lc->current_call=call; linphone_call_set_state(call,LinphoneCallConnected,"Connected"); - call->resultdesc=sal_call_get_final_media_description(call->op); - if (call->resultdesc){ - linphone_call_start_media_streams(call); + new_md=sal_call_get_final_media_description(call->op); + linphone_core_update_streams(lc, call, new_md); + if (new_md){ linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)"); - sal_media_description_ref(call->resultdesc); }else call->media_pending=TRUE; + ms_message("call answered."); return 0; } @@ -2946,17 +2943,12 @@ void linphone_core_mute_mic(LinphoneCore *lc, bool_t val){ } bool_t linphone_core_is_mic_muted(LinphoneCore *lc) { - float gain=1.0; LinphoneCall *call=linphone_core_get_current_call(lc); if (call==NULL){ ms_warning("linphone_core_is_mic_muted(): No current call !"); return FALSE; } - if (call->audiostream && call->audiostream->volsend){ - ms_filter_call_method(call->audiostream->volsend,MS_VOLUME_GET_GAIN,&gain); - }else ms_warning("Could not get gain: gain control wasn't activated. "); - - return gain==0 || call->audio_muted; + return call->audio_muted; } // returns rtp transmission status for an active stream diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 012437f6..83127b9a 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -178,6 +178,8 @@ typedef struct _LinphoneCallParams LinphoneCallParams; LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp); void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled); bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp); +void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, bool_t enabled); +bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams *cp); void linphone_call_params_destroy(LinphoneCallParams *cp); /** @@ -216,7 +218,8 @@ typedef enum _LinphoneCallState{ LinphoneCallError, /**state!=LinphoneGlobalStartup) void _linphone_core_configure_resolver(); diff --git a/coreapi/sal.c b/coreapi/sal.c index ac44470a..979969b2 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -94,6 +94,72 @@ bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir return found; } +/* +static bool_t fmtp_equals(const char *p1, const char *p2){ + if (p1 && p2 && strcmp(p1,p2)==0) return TRUE; + if (p1==NULL && p2==NULL) return TRUE; + return FALSE; +} +*/ + +static bool_t payload_type_equals(const PayloadType *p1, const PayloadType *p2){ + if (p1->type!=p2->type) return FALSE; + if (strcmp(p1->mime_type,p2->mime_type)!=0) return FALSE; + if (p1->clock_rate!=p2->clock_rate) return FALSE; + if (p1->channels!=p2->channels) return FALSE; + /* + Do not compare fmtp right now: they are modified internally when the call is started + */ + /* + if (!fmtp_equals(p1->recv_fmtp,p2->recv_fmtp) || + !fmtp_equals(p1->send_fmtp,p2->send_fmtp)) + return FALSE; + */ + return TRUE; +} + +static bool_t payload_list_equals(const MSList *l1, const MSList *l2){ + const MSList *e1,*e2; + for(e1=l1,e2=l2;e1!=NULL && e2!=NULL; e1=e1->next,e2=e2->next){ + PayloadType *p1=(PayloadType*)e1->data; + PayloadType *p2=(PayloadType*)e2->data; + if (!payload_type_equals(p1,p2)) + return FALSE; + } + if (e1!=NULL || e2!=NULL){ + /*means one list is longer than the other*/ + abort(); + return FALSE; + } + return TRUE; +} + +bool_t sal_stream_description_equals(const SalStreamDescription *sd1, const SalStreamDescription *sd2){ + if (sd1->proto!=sd2->proto) return FALSE; + if (sd1->type!=sd2->type) return FALSE; + if (strcmp(sd1->addr,sd2->addr)!=0) return FALSE; + if (sd1->port!=sd2->port) return FALSE; + if (!payload_list_equals(sd1->payloads,sd2->payloads)) return FALSE; + if (sd1->bandwidth!=sd2->bandwidth) return FALSE; + if (sd1->ptime!=sd2->ptime) return FALSE; + /* compare candidates: TODO */ + if (sd1->dir!=sd2->dir) return FALSE; + return TRUE; +} + +bool_t sal_media_description_equals(const SalMediaDescription *md1, const SalMediaDescription *md2){ + int i; + + if (strcmp(md1->addr,md2->addr)!=0) return FALSE; + if (md1->nstreams!=md2->nstreams) return FALSE; + if (md1->bandwidth!=md2->bandwidth) return FALSE; + for(i=0;instreams;++i){ + if (!sal_stream_description_equals(&md1->streams[i],&md2->streams[i])) + return FALSE; + } + return TRUE; +} + static void assign_string(char **str, const char *arg){ if (*str){ ms_free(*str); diff --git a/coreapi/sal.h b/coreapi/sal.h index b0b3c757..e848f71f 100644 --- a/coreapi/sal.h +++ b/coreapi/sal.h @@ -127,6 +127,7 @@ SalMediaDescription *sal_media_description_new(); void sal_media_description_ref(SalMediaDescription *md); void sal_media_description_unref(SalMediaDescription *md); bool_t sal_media_description_empty(const SalMediaDescription *md); +bool_t sal_media_description_equals(const SalMediaDescription *md1, const SalMediaDescription *md2); bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir dir); SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md, SalMediaProto proto, SalStreamType type); diff --git a/mediastreamer2 b/mediastreamer2 index ffacf567..b1a4c2b6 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit ffacf56718c198cb80a290f7a65975916d8a9b6b +Subproject commit b1a4c2b6470a6de62a8e58d4f2874eda091a8db3