diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 97bc4ef98d..698820f0a8 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -451,7 +451,8 @@ typedef enum { SWITCH_RTP_FLAG_SECURE_SEND_RESET = (1 << 16), SWITCH_RTP_FLAG_SECURE_RECV_RESET = (1 << 17), SWITCH_RTP_FLAG_PROXY_MEDIA = (1 << 18), - SWITCH_RTP_FLAG_SHUTDOWN = (1 << 19) + SWITCH_RTP_FLAG_SHUTDOWN = (1 << 19), + SWITCH_RTP_FLAG_FLUSH = (1 << 20) } switch_rtp_flag_enum_t; typedef uint32_t switch_rtp_flag_t; diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 25a5899ac5..b9534b8177 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -710,72 +710,79 @@ 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_codec.implementation->encoded_bytes_per_packet) { - if (++tech_pvt->mismatch_count >= MAX_MISMATCH_FRAMES) { - switch_size_t codec_ms = (int)(tech_pvt->read_frame.timestamp - - tech_pvt->last_ts) / (tech_pvt->read_codec.implementation->samples_per_second / 1000); - - if ((codec_ms % 10) != 0) { - tech_pvt->check_frames = MAX_CODEC_CHECK_FRAMES; - goto skip; - } else { - if (switch_rtp_ready(tech_pvt->rtp_session) && codec_ms != tech_pvt->codec_ms) { - const char *val; - int rtp_timeout_sec = 0; - int rtp_hold_timeout_sec = 0; - - tech_pvt->codec_ms = codec_ms; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, - "Changing codec ptime to %d. I bet you have a linksys/sipura =D\n", tech_pvt->codec_ms); - switch_core_codec_destroy(&tech_pvt->read_codec); - switch_core_codec_destroy(&tech_pvt->write_codec); - if (sofia_glue_tech_set_codec(tech_pvt, 2) != SWITCH_STATUS_SUCCESS) { - *frame = NULL; - return SWITCH_STATUS_GENERR; - } + switch_size_t codec_ms = (int)(tech_pvt->read_frame.timestamp - + tech_pvt->last_ts) / (tech_pvt->read_codec.implementation->samples_per_second / 1000); - - if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_timeout_sec"))) { - int v = atoi(val); - if (v >= 0) { - rtp_timeout_sec = v; - } - } - - if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_hold_timeout_sec"))) { - int v = atoi(val); - if (v >= 0) { - rtp_hold_timeout_sec = v; - } - } - - if (rtp_timeout_sec) { - tech_pvt->max_missed_packets = (tech_pvt->read_codec.implementation->samples_per_second * rtp_timeout_sec) / - tech_pvt->read_codec.implementation->samples_per_packet; - - switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, tech_pvt->max_missed_packets); - if (!rtp_hold_timeout_sec) { - rtp_hold_timeout_sec = rtp_timeout_sec * 10; - } - } - - if (rtp_hold_timeout_sec) { - tech_pvt->max_missed_hold_packets = (tech_pvt->read_codec.implementation->samples_per_second * rtp_hold_timeout_sec) / - tech_pvt->read_codec.implementation->samples_per_packet; - } - - if (switch_rtp_change_interval(tech_pvt->rtp_session, - tech_pvt->codec_ms * 1000, - tech_pvt->read_codec.implementation->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; - } - - } + if ((codec_ms % 10) != 0) { + tech_pvt->check_frames = MAX_CODEC_CHECK_FRAMES; + goto skip; } + + if (tech_pvt->last_codec_ms && tech_pvt->last_codec_ms == codec_ms) { + tech_pvt->mismatch_count++; + } + + tech_pvt->last_codec_ms = codec_ms; + + if (tech_pvt->mismatch_count > MAX_MISMATCH_FRAMES) { + if (switch_rtp_ready(tech_pvt->rtp_session) && codec_ms != tech_pvt->codec_ms) { + const char *val; + int rtp_timeout_sec = 0; + int rtp_hold_timeout_sec = 0; + + tech_pvt->codec_ms = codec_ms; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, + "Changing codec ptime to %d. I bet you have a linksys/sipura =D\n", tech_pvt->codec_ms); + switch_core_codec_destroy(&tech_pvt->read_codec); + switch_core_codec_destroy(&tech_pvt->write_codec); + if (sofia_glue_tech_set_codec(tech_pvt, 2) != SWITCH_STATUS_SUCCESS) { + *frame = NULL; + return SWITCH_STATUS_GENERR; + } + + + if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_timeout_sec"))) { + int v = atoi(val); + if (v >= 0) { + rtp_timeout_sec = v; + } + } + + if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_hold_timeout_sec"))) { + int v = atoi(val); + if (v >= 0) { + rtp_hold_timeout_sec = v; + } + } + + if (rtp_timeout_sec) { + tech_pvt->max_missed_packets = (tech_pvt->read_codec.implementation->samples_per_second * rtp_timeout_sec) / + tech_pvt->read_codec.implementation->samples_per_packet; + + switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, tech_pvt->max_missed_packets); + if (!rtp_hold_timeout_sec) { + rtp_hold_timeout_sec = rtp_timeout_sec * 10; + } + } + + if (rtp_hold_timeout_sec) { + tech_pvt->max_missed_hold_packets = (tech_pvt->read_codec.implementation->samples_per_second * rtp_hold_timeout_sec) / + tech_pvt->read_codec.implementation->samples_per_packet; + } + + if (switch_rtp_change_interval(tech_pvt->rtp_session, + tech_pvt->codec_ms * 1000, + tech_pvt->read_codec.implementation->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; + } + + } + } else { tech_pvt->mismatch_count = 0; } diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index beb9f73973..d6f32e21ef 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -547,6 +547,7 @@ struct private_object { switch_size_t last_ts; uint32_t check_frames; uint32_t mismatch_count; + uint32_t last_codec_ms; nua_event_t want_event; }; diff --git a/src/switch_core_io.c b/src/switch_core_io.c index c1f2ef882e..1d1730c0ae 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -608,10 +608,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess switch_mutex_lock(session->codec_write_mutex); if ((session->write_codec && frame->codec && session->write_codec->implementation != frame->codec->implementation)) { - need_codec = TRUE; if (session->write_codec->implementation->codec_id == frame->codec->implementation->codec_id) { ptime_mismatch = TRUE; + if (!need_codec) { + status = perform_write(session, frame, flags, stream_id); + goto error; + } } + need_codec = TRUE; } if (session->write_codec && !frame->codec) { diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 2d183a4607..9e925b40b2 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -1264,6 +1264,11 @@ static void do_2833(switch_rtp_t *rtp_session) } SWITCH_DECLARE(void) rtp_flush_read_buffer(switch_rtp_t *rtp_session) +{ + switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_FLUSH); +} + +static void do_flush(switch_rtp_t *rtp_session) { int was_blocking = 0; switch_size_t bytes; @@ -1338,6 +1343,12 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ goto end; } + if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_FLUSH)) { + do_flush(rtp_session); + switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_FLUSH); + continue; + } + if (rtp_session->max_missed_packets) { if (bytes) { rtp_session->missed_count = 0;