diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 60c7a56338..b7a4bca92c 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -789,7 +789,7 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f if (tech_pvt->read_frame.datalen > 0) { uint32_t bytes = 0; int frames = 1; - + if (!switch_test_flag((&tech_pvt->read_frame), SFF_CNG)) { if (!tech_pvt->read_codec.implementation || !switch_core_codec_ready(&tech_pvt->read_codec)) { *frame = NULL; @@ -808,11 +808,13 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f if (tech_pvt->last_ts && tech_pvt->read_frame.datalen != tech_pvt->read_impl.encoded_bytes_per_packet) { uint32_t codec_ms = (int)(tech_pvt->read_frame.timestamp - tech_pvt->last_ts) / (tech_pvt->read_impl.samples_per_second / 1000); - if ((codec_ms % 10) != 0) { - tech_pvt->check_frames = MAX_CODEC_CHECK_FRAMES; + + if ((codec_ms % 10) != 0 || codec_ms > tech_pvt->read_impl.samples_per_packet * 10) { + tech_pvt->last_ts = 0; goto skip; } + if (tech_pvt->last_codec_ms && tech_pvt->last_codec_ms == codec_ms) { tech_pvt->mismatch_count++; } @@ -839,22 +841,18 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f "This issue has so far been identified to happen on the following broken platforms/devices:\n" "Linksys/Sipura aka Cisco\n" "ShoreTel\n" - "Sonus/L3 (If you're really lucky, you may even get this message twice once they " - "answer and change it back again!! Go Sonus!)\n" + "Sonus/L3\n" "We will try to fix it but some of the devices on this list are so broken who knows what will happen..\n" , (int)tech_pvt->codec_ms, (int)codec_ms); - tech_pvt->codec_ms = codec_ms; - switch_core_session_lock_codec_write(session); - switch_core_session_lock_codec_read(session); - switch_core_codec_destroy(&tech_pvt->read_codec); - switch_core_codec_destroy(&tech_pvt->write_codec); + switch_channel_set_variable_printf(channel, "sip_h_X-Broken-PTIME", "Adv=%d;Sent=%d", + (int)tech_pvt->codec_ms, (int)codec_ms); + + tech_pvt->codec_ms = codec_ms; if (sofia_glue_tech_set_codec(tech_pvt, 2) != SWITCH_STATUS_SUCCESS) { *frame = NULL; - switch_core_session_unlock_codec_write(session); - switch_core_session_unlock_codec_read(session); return SWITCH_STATUS_GENERR; } @@ -887,19 +885,11 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f tech_pvt->read_impl.samples_per_packet; } - if (switch_rtp_change_interval(tech_pvt->rtp_session, - tech_pvt->codec_ms * 1000, - tech_pvt->read_impl.samples_per_packet - ) != SWITCH_STATUS_SUCCESS) { - switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); - - } - - tech_pvt->check_frames = MAX_CODEC_CHECK_FRAMES; + + tech_pvt->check_frames = 0; + tech_pvt->last_ts = 0; /* inform them of the codec they are actually sending */ sofia_glue_do_invite(session); - switch_core_session_unlock_codec_write(session); - switch_core_session_unlock_codec_read(session); } @@ -1182,10 +1172,15 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi } - if ((var = switch_channel_get_variable(channel, SOFIA_SECURE_MEDIA_VARIABLE)) && switch_true(var)) { sofia_set_flag_locked(tech_pvt, TFLAG_SECURE); } + + if (sofia_test_pflag(tech_pvt->profile, PFLAG_AUTOFIX_TIMING)) { + tech_pvt->check_frames = 0; + tech_pvt->last_ts = 0; + } + } break; default: diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 41203ffc54..4304b43b68 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -3337,6 +3337,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status if (sofia_test_pflag(tech_pvt->profile, PFLAG_AUTOFIX_TIMING)) { tech_pvt->check_frames = 0; + tech_pvt->last_ts = 0; } } diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 0ae8ca6a65..79b66ff8f9 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -2057,21 +2057,24 @@ switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force) int ms; switch_status_t status = SWITCH_STATUS_SUCCESS; int resetting = 0; - + if (!tech_pvt->iananame) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "No audio codec available\n"); switch_goto_status(SWITCH_STATUS_FALSE, end); } - if (tech_pvt->read_codec.implementation && switch_core_codec_ready(&tech_pvt->read_codec)) { + if (switch_core_codec_ready(&tech_pvt->read_codec)) { if (!force) { switch_goto_status(SWITCH_STATUS_SUCCESS, end); } - if (strcasecmp(tech_pvt->read_codec.implementation->iananame, tech_pvt->iananame) || - tech_pvt->read_codec.implementation->samples_per_second != tech_pvt->rm_rate) { + if (strcasecmp(tech_pvt->read_impl.iananame, tech_pvt->iananame) || + tech_pvt->read_impl.samples_per_second != tech_pvt->rm_rate || + tech_pvt->codec_ms != tech_pvt->read_impl.microseconds_per_packet) { + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Changing Codec from %s@%dms to %s@%dms\n", + tech_pvt->read_impl.iananame, tech_pvt->read_impl.microseconds_per_packet / 1000, + tech_pvt->rm_encoding, tech_pvt->codec_ms); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Changing Codec from %s to %s\n", - tech_pvt->read_codec.implementation->iananame, tech_pvt->rm_encoding); switch_core_session_lock_codec_write(tech_pvt->session); switch_core_session_lock_codec_read(tech_pvt->session); resetting = 1; @@ -2079,7 +2082,7 @@ switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force) switch_core_codec_destroy(&tech_pvt->write_codec); switch_core_session_reset(tech_pvt->session, SWITCH_TRUE, SWITCH_TRUE); } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Already using %s\n", tech_pvt->read_codec.implementation->iananame); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Already using %s\n", tech_pvt->read_impl.iananame); switch_goto_status(SWITCH_STATUS_SUCCESS, end); } } @@ -2119,9 +2122,14 @@ switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force) if (switch_rtp_ready(tech_pvt->rtp_session)) { switch_assert(tech_pvt->read_codec.implementation); - switch_rtp_set_interval(tech_pvt->rtp_session, - tech_pvt->write_codec.implementation->microseconds_per_packet, - tech_pvt->read_impl.samples_per_packet); + + if (switch_rtp_change_interval(tech_pvt->rtp_session, + tech_pvt->read_impl.microseconds_per_packet, + tech_pvt->read_impl.samples_per_packet + ) != SWITCH_STATUS_SUCCESS) { + switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + switch_goto_status(SWITCH_STATUS_FALSE, end); + } } tech_pvt->read_frame.rate = tech_pvt->rm_rate; diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 88ef813351..730edcb019 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -1052,26 +1052,38 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_interval(switch_rtp_t *rtp_sessio SWITCH_DECLARE(switch_status_t) switch_rtp_change_interval(switch_rtp_t *rtp_session, uint32_t ms_per_packet, uint32_t samples_per_interval) { + switch_status_t status = SWITCH_STATUS_SUCCESS; + int change_timer = 0; + + if (rtp_session->ms_per_packet && rtp_session->ms_per_packet != ms_per_packet) { + change_timer = 1; + } switch_rtp_set_interval(rtp_session, ms_per_packet, samples_per_interval); - if (rtp_session->timer_name) { + if (change_timer && rtp_session->timer_name) { + READ_INC(rtp_session); + WRITE_INC(rtp_session); + if (rtp_session->timer.timer_interface) { switch_core_timer_destroy(&rtp_session->timer); } - if (switch_core_timer_init(&rtp_session->timer, - rtp_session->timer_name, ms_per_packet / 1000, samples_per_interval, rtp_session->pool) == SWITCH_STATUS_SUCCESS) { + if ((status = switch_core_timer_init(&rtp_session->timer, + rtp_session->timer_name, ms_per_packet / 1000, + samples_per_interval, rtp_session->pool)) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RE-Starting timer [%s] %d bytes per %dms\n", rtp_session->timer_name, samples_per_interval, ms_per_packet); } else { memset(&rtp_session->timer, 0, sizeof(rtp_session->timer)); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Problem RE-Starting timer [%s] %d bytes per %dms\n", rtp_session->timer_name, samples_per_interval, ms_per_packet / 1000); - return SWITCH_STATUS_FALSE; } + + WRITE_DEC(rtp_session); + READ_DEC(rtp_session); } - return SWITCH_STATUS_SUCCESS; + return status; } SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session,