diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 8dc5cad9e..bb6b5b9fb 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -411,6 +411,7 @@ 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; + bool_t update_state=TRUE; if (call==NULL){ ms_warning("No call to accept."); @@ -433,12 +434,21 @@ static void call_accepted(SalOp *op){ if (md) /*make sure re-invite will not propose video again*/ call->params->has_video &= linphone_core_media_description_contains_video_stream(md); - if (call->state==LinphoneCallOutgoingProgress || - call->state==LinphoneCallOutgoingRinging || - call->state==LinphoneCallOutgoingEarlyMedia){ - linphone_call_set_state(call,LinphoneCallConnected,"Connected"); - if (call->referer) linphone_core_notify_refer_state(lc,call->referer,call); + switch (call->state){ + case LinphoneCallOutgoingProgress: + case LinphoneCallOutgoingRinging: + case LinphoneCallOutgoingEarlyMedia: + linphone_call_set_state(call,LinphoneCallConnected,"Connected"); + if (call->referer) linphone_core_notify_refer_state(lc,call->referer,call); + break; + case LinphoneCallEarlyUpdating: + linphone_call_set_state(call,call->prevstate,"Early update accepted"); + update_state=FALSE; + break; + default: + break; } + if (md && !sal_media_description_empty(md) && !linphone_core_incompatible_security(lc,md)){ linphone_call_update_remote_session_id_and_ver(call); if (sal_media_description_has_dir(md,SalStreamSendOnly) || @@ -451,7 +461,7 @@ static void call_accepted(SalOp *op){ ms_free(msg); } linphone_core_update_streams (lc,call,md); - linphone_call_set_state(call,LinphoneCallPaused,"Call paused"); + if (update_state) linphone_call_set_state(call,LinphoneCallPaused,"Call paused"); if (call->refer_pending) linphone_core_start_refered_call(lc,call,NULL); }else if (sal_media_description_has_dir(md,SalStreamRecvOnly)){ @@ -464,7 +474,7 @@ static void call_accepted(SalOp *op){ ms_free(msg); } linphone_core_update_streams (lc,call,md); - linphone_call_set_state(call,LinphoneCallPausedByRemote,"Call paused by remote"); + if (update_state) linphone_call_set_state(call,LinphoneCallPausedByRemote,"Call paused by remote"); }else{ if (call->state!=LinphoneCallUpdating){ if (call->state==LinphoneCallResuming){ @@ -485,8 +495,7 @@ static void call_accepted(SalOp *op){ linphone_call_fix_call_parameters(call); if (!call->current_params->in_conference) lc->current_call=call; - if (call->prevstate != LinphoneCallIncomingEarlyMedia) /*don't change state in aswer to a SIP UPDATE in early media*/ - linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running"); + if (update_state) linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running"); } }else{ /*send a bye*/ @@ -570,7 +579,8 @@ static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call, bool_t if (rmd==NULL) call->expect_media_in_ack=TRUE; } else if (is_update){ /*SIP UPDATE case, can occur in early states*/ - _linphone_core_accept_call_update(lc,call,NULL,call->state,linphone_call_state_to_string(call->state)); + linphone_call_set_state(call, LinphoneCallEarlyUpdatedByRemote, "EarlyUpdatedByRemote"); + _linphone_core_accept_call_update(lc,call,NULL,call->prevstate,linphone_call_state_to_string(call->prevstate)); } } @@ -627,6 +637,8 @@ static void call_updating(SalOp *op, bool_t is_update){ case LinphoneCallRefered: case LinphoneCallError: case LinphoneCallReleased: + case LinphoneCallEarlyUpdatedByRemote: + case LinphoneCallEarlyUpdating: ms_warning("Receiving reINVITE or UPDATE while in state [%s], should not happen.",linphone_call_state_to_string(call->state)); break; } diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 5e7f9e5af..152f35e2c 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -924,6 +924,10 @@ const char *linphone_call_state_to_string(LinphoneCallState cs){ return "LinphoneCallUpdating"; case LinphoneCallReleased: return "LinphoneCallReleased"; + case LinphoneCallEarlyUpdatedByRemote: + return "LinphoneCallEarlyUpdatedByRemote"; + case LinphoneCallEarlyUpdating: + return "LinphoneCallEarlyUpdating"; } return "undefined state"; } diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index b01430066..40723820a 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -3281,15 +3281,20 @@ int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call){ **/ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){ int err=0; + LinphoneCallState nextstate; #if defined(VIDEO_ENABLED) && defined(BUILD_UPNP) bool_t has_video = FALSE; #endif switch(call->state){ - case LinphoneCallIncomingEarlyMedia: case LinphoneCallIncomingReceived: + case LinphoneCallIncomingEarlyMedia: + case LinphoneCallOutgoingRinging: + case LinphoneCallOutgoingEarlyMedia: + nextstate=LinphoneCallEarlyUpdating; + break; case LinphoneCallStreamsRunning: - /*these states are allowed for linphone_core_update_call()*/ + nextstate=LinphoneCallUpdating; break; default: ms_error("linphone_core_update_call() is not allowed in [%s] state",linphone_call_state_to_string(call->state)); @@ -3297,7 +3302,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho } if (params!=NULL){ - linphone_call_set_state(call,LinphoneCallUpdating,"Updating call"); + linphone_call_set_state(call,nextstate,"Updating call"); #if defined(VIDEO_ENABLED) && defined(BUILD_UPNP) has_video = call->params->has_video; @@ -6413,6 +6418,7 @@ LinphoneCallParams *linphone_core_create_default_call_parameters(LinphoneCore *l * @param lc the LinphoneCore * @param call the call for which the parameters are to be build, or NULL in the case where the parameters are to be used for a new outgoing call. * @return a new LinphoneCallParams + * @ingroup call_control */ LinphoneCallParams *linphone_core_create_call_params(LinphoneCore *lc, LinphoneCall *call){ if (!call) return linphone_core_create_default_call_parameters(lc); diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index bac438e93..f3fbe22cb 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -638,7 +638,9 @@ typedef enum _LinphoneCallState{ LinphoneCallUpdatedByRemote, /**number_of_LinphoneCallIncomingEarlyMedia++;break; case LinphoneCallUpdating :counters->number_of_LinphoneCallUpdating++;break; case LinphoneCallReleased :counters->number_of_LinphoneCallReleased++;break; + case LinphoneCallEarlyUpdating: counters->number_of_LinphoneCallEarlyUpdating++;break; + case LinphoneCallEarlyUpdatedByRemote: counters->number_of_LinphoneCallEarlyUpdatedByRemote++;break; default: CU_FAIL("unexpected event");break; } @@ -1906,7 +1908,9 @@ static void call_with_file_player(void) { snprintf(hellopath,sizeof(hellopath), "%s/sounds/hello8000.wav", liblinphone_tester_file_prefix); - /*caller uses soundcard*/ + /*caller uses files instead of soundcard in order to avoid mixing soundcard input with file played using call's player*/ + linphone_core_use_files(pauline->lc,TRUE); + linphone_core_set_play_file(pauline->lc,NULL); /*callee is recording and plays file*/ linphone_core_use_files(pauline->lc,TRUE); @@ -1963,8 +1967,9 @@ static void call_with_mkv_file_player(void) { snprintf(hellowav,sizeof(hellowav), "%s/sounds/hello8000.wav", liblinphone_tester_file_prefix); snprintf(hellomkv,sizeof(hellomkv), "%s/sounds/hello8000.mkv", liblinphone_tester_file_prefix); - /*caller uses soundcard*/ - + /*caller uses files instead of soundcard in order to avoid mixing soundcard input with file played using call's player*/ + linphone_core_use_files(pauline->lc,TRUE); + linphone_core_set_play_file(pauline->lc,NULL); /*callee is recording and plays file*/ linphone_core_use_files(pauline->lc,TRUE); linphone_core_set_play_file(pauline->lc,hellowav); /*just to send something but we are not testing what is sent by pauline*/ @@ -1985,7 +1990,7 @@ static void call_with_mkv_file_player(void) { CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1)); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1)); CU_ASSERT_TRUE(ms_audio_diff(hellowav,recordpath,&similar,NULL,NULL)==0); - CU_ASSERT_TRUE(similar>0.9); + CU_ASSERT_TRUE(similar>0.6); CU_ASSERT_TRUE(similar<=1.0); ms_free(recordpath); @@ -2185,7 +2190,6 @@ static void early_media_call_with_update_base(bool_t media_change){ if (media_change) { disable_all_audio_codecs_except_one(marie->lc,"pcmu",-1); disable_all_audio_codecs_except_one(pauline->lc,"pcmu",-1); - } /* Marie calls Pauline, and after the call has rung, transitions to an early_media session @@ -2216,26 +2220,23 @@ static void early_media_call_with_update_base(bool_t media_change){ linphone_call_params_set_session_name(pauline_params,UPDATED_SESSION_NAME); linphone_core_update_call(pauline->lc, pauline_call, pauline_params); + CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallEarlyUpdating,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallEarlyUpdatedByRemote,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingEarlyMedia,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingEarlyMedia,1,2000)); /*just to wait 2s*/ liblinphone_tester_check_rtcp(marie, pauline); - wait_for_list(lcs, &marie->stat.number_of_LinphoneCallUpdatedByRemote,100000,2000); CU_ASSERT_STRING_EQUAL( linphone_call_params_get_session_name(linphone_call_get_remote_params(marie_call)) , UPDATED_SESSION_NAME); 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)); - - CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallOutgoingEarlyMedia,1); - CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallStreamsRunning,1); - CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallConnected,1); - - CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallIncomingEarlyMedia,1); - CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallStreamsRunning,1); - CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallConnected,1); - CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallUpdating,1); + CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallConnected, 1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1,1000)); liblinphone_tester_check_rtcp(marie, pauline); diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index 9178bac8f..eda851698 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -116,6 +116,8 @@ typedef struct _stats { int number_of_LinphoneCallIncomingEarlyMedia; int number_of_LinphoneCallUpdating; int number_of_LinphoneCallReleased; + int number_of_LinphoneCallEarlyUpdatedByRemote; + int number_of_LinphoneCallEarlyUpdating; int number_of_LinphoneTransferCallOutgoingInit; int number_of_LinphoneTransferCallOutgoingProgress; diff --git a/tester/sounds/hello8000.mkv b/tester/sounds/hello8000.mkv index 42fa387e5..812d62563 100644 Binary files a/tester/sounds/hello8000.mkv and b/tester/sounds/hello8000.mkv differ