FS-4932 FS-5090 --resolve

This commit is contained in:
Anthony Minessale 2013-07-29 10:18:05 -05:00
parent 4fc8bc7696
commit 39ad799683
6 changed files with 186 additions and 97 deletions

View File

@ -68,6 +68,7 @@ typedef enum {
SCMF_RUNNING, SCMF_RUNNING,
SCMF_DISABLE_TRANSCODING, SCMF_DISABLE_TRANSCODING,
SCMF_AUTOFIX_TIMING, SCMF_AUTOFIX_TIMING,
SCMF_AUTOFIX_PT,
SCMF_CODEC_GREEDY, SCMF_CODEC_GREEDY,
SCMF_CODEC_SCROOGE, SCMF_CODEC_SCROOGE,
SCMF_DISABLE_HOLD, SCMF_DISABLE_HOLD,
@ -242,7 +243,7 @@ SWITCH_DECLARE(switch_rtp_stats_t *) switch_core_media_get_stats(switch_core_ses
SWITCH_DECLARE(void) switch_core_media_set_sdp_codec_string(switch_core_session_t *session, const char *r_sdp); SWITCH_DECLARE(void) switch_core_media_set_sdp_codec_string(switch_core_session_t *session, const char *r_sdp);
SWITCH_DECLARE(void) switch_core_media_reset_autofix_timing(switch_core_session_t *session, switch_media_type_t type); SWITCH_DECLARE(void) switch_core_media_reset_autofix(switch_core_session_t *session, switch_media_type_t type);
SWITCH_DECLARE(void) switch_core_media_check_outgoing_proxy(switch_core_session_t *session, switch_core_session_t *o_session); SWITCH_DECLARE(void) switch_core_media_check_outgoing_proxy(switch_core_session_t *session, switch_core_session_t *o_session);
SWITCH_DECLARE(switch_status_t) switch_core_media_codec_chosen(switch_core_session_t *session, switch_media_type_t media); SWITCH_DECLARE(switch_status_t) switch_core_media_codec_chosen(switch_core_session_t *session, switch_media_type_t media);
SWITCH_DECLARE (void) switch_core_media_recover_session(switch_core_session_t *session); SWITCH_DECLARE (void) switch_core_media_recover_session(switch_core_session_t *session);

View File

@ -762,10 +762,17 @@ typedef enum {
If this setting is enabled it will NOT do this (old behaviour). If this setting is enabled it will NOT do this (old behaviour).
*/ */
RTP_BUG_FLUSH_JB_ON_DTMF = (1 << 10) RTP_BUG_FLUSH_JB_ON_DTMF = (1 << 10),
/* FLUSH JITTERBUFFER When getting RFC2833 to reduce bleed through */ /* FLUSH JITTERBUFFER When getting RFC2833 to reduce bleed through */
RTP_BUG_ACCEPT_ANY_PAYLOAD = (1 << 11)
/*
Make FS accept any payload type instead of dropping and returning CNG frame. Workaround while FS only supports a single payload per rtp session.
This can be used by endpoint modules to detect payload changes and act appropriately (ex: sofia could send a reINVITE with single codec).
This should probably be a flag, but flag enum is already full!
*/
} switch_rtp_bug_flag_t; } switch_rtp_bug_flag_t;

View File

@ -1273,8 +1273,8 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
switch_channel_set_flag(tech_pvt->channel, CF_SECURE); switch_channel_set_flag(tech_pvt->channel, CF_SECURE);
} }
if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING)) { if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING) || sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_PT)) {
switch_core_media_reset_autofix_timing(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO); switch_core_media_reset_autofix(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
} }
} }
break; break;

View File

@ -3714,6 +3714,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
sofia_set_pflag(profile, PFLAG_DISABLE_100REL); sofia_set_pflag(profile, PFLAG_DISABLE_100REL);
profile->auto_restart = 1; profile->auto_restart = 1;
sofia_set_media_flag(profile, SCMF_AUTOFIX_TIMING); sofia_set_media_flag(profile, SCMF_AUTOFIX_TIMING);
sofia_set_media_flag(profile, SCMF_AUTOFIX_PT);
sofia_set_media_flag(profile, SCMF_RTP_AUTOFLUSH_DURING_BRIDGE); sofia_set_media_flag(profile, SCMF_RTP_AUTOFLUSH_DURING_BRIDGE);
profile->contact_user = SOFIA_DEFAULT_CONTACT_USER; profile->contact_user = SOFIA_DEFAULT_CONTACT_USER;
sofia_set_pflag(profile, PFLAG_PASS_CALLEE_ID); sofia_set_pflag(profile, PFLAG_PASS_CALLEE_ID);
@ -4325,6 +4326,12 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else { } else {
sofia_clear_media_flag(profile, SCMF_AUTOFIX_TIMING); sofia_clear_media_flag(profile, SCMF_AUTOFIX_TIMING);
} }
} else if (!strcasecmp(var, "rtp-autofix-pt")) {
if (switch_true(val)) {
sofia_set_media_flag(profile, SCMF_AUTOFIX_PT);
} else {
sofia_clear_media_flag(profile, SCMF_AUTOFIX_PT);
}
} else if (!strcasecmp(var, "contact-user")) { } else if (!strcasecmp(var, "contact-user")) {
profile->contact_user = switch_core_strdup(profile->pool, val); profile->contact_user = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "nat-options-ping")) { } else if (!strcasecmp(var, "nat-options-ping")) {
@ -5188,8 +5195,8 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
sofia_update_callee_id(session, profile, sip, SWITCH_FALSE); sofia_update_callee_id(session, profile, sip, SWITCH_FALSE);
if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING)) { if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING) || sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_PT)) {
switch_core_media_reset_autofix_timing(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO); switch_core_media_reset_autofix(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
} }
} }

View File

@ -591,6 +591,14 @@ SWITCH_DECLARE(void) switch_core_media_parse_rtp_bugs(switch_rtp_bug_flag_t *fla
*flag_pole &= ~RTP_BUG_ACCEPT_ANY_PACKETS; *flag_pole &= ~RTP_BUG_ACCEPT_ANY_PACKETS;
} }
if (switch_stristr("ACCEPT_ANY_PAYLOAD", str)) {
*flag_pole |= RTP_BUG_ACCEPT_ANY_PAYLOAD;
}
if (switch_stristr("~ACCEPT_ANY_PAYLOAD", str)) {
*flag_pole &= ~RTP_BUG_ACCEPT_ANY_PAYLOAD;
}
if (switch_stristr("GEN_ONE_GEN_ALL", str)) { if (switch_stristr("GEN_ONE_GEN_ALL", str)) {
*flag_pole |= RTP_BUG_GEN_ONE_GEN_ALL; *flag_pole |= RTP_BUG_GEN_ONE_GEN_ALL;
} }
@ -1333,8 +1341,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
if ((engine->read_frame.datalen % 10) == 0 && /* check for timing or codec issues */
(smh->media_flags[SCMF_AUTOFIX_TIMING]) && engine->check_frames < MAX_CODEC_CHECK_FRAMES) { if ((smh->media_flags[SCMF_AUTOFIX_TIMING] || smh->media_flags[SCMF_AUTOFIX_PT]) &&
engine->check_frames < MAX_CODEC_CHECK_FRAMES) {
int reset_codec = 0;
engine->check_frames++; engine->check_frames++;
if (!engine->read_impl.encoded_bytes_per_packet) { if (!engine->read_impl.encoded_bytes_per_packet) {
@ -1342,111 +1354,172 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session
goto skip; goto skip;
} }
if (engine->last_ts && engine->read_frame.datalen != engine->read_impl.encoded_bytes_per_packet) { /* autofix payload type */
uint32_t codec_ms = (int) (engine->read_frame.timestamp - if (smh->media_flags[SCMF_AUTOFIX_PT] &&
engine->last_ts) / (engine->read_impl.samples_per_second / 1000); engine->read_frame.payload != smh->mparams->cng_pt &&
engine->read_frame.payload != smh->mparams->recv_te &&
engine->read_frame.payload != smh->mparams->te &&
engine->read_frame.payload != engine->codec_params.recv_pt &&
engine->read_frame.payload != engine->codec_params.agreed_pt &&
engine->read_frame.payload != engine->codec_params.pt) {
if ((codec_ms % 10) != 0 || codec_ms > engine->read_impl.samples_per_packet * 10) { int i = 0;
engine->last_ts = 0;
goto skip; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
"Invalid payload received (received %d, expecting %d). "
"FS doesn't support multiple payload types in a single RTP session.\n",
(int) engine->read_frame.payload, (int) engine->codec_params.agreed_pt);
/* search for payload type */
for (i = 0; i < smh->mparams->num_codecs; i++) {
if (engine->read_frame.payload == smh->ianacodes[i]) {
const switch_codec_implementation_t *imp = smh->codecs[i];
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
"Changing current codec to %s (payload type %d).\n",
imp->iananame, (int) engine->read_frame.payload);
engine->codec_params.iananame = switch_core_session_strdup(smh->session, imp->iananame);
engine->codec_params.pt = imp->ianacode;
engine->codec_params.agreed_pt = imp->ianacode;
engine->codec_params.recv_pt = imp->ianacode;
engine->codec_params.rm_encoding = switch_core_session_strdup(smh->session, imp->iananame);
engine->codec_params.rm_fmtp = NULL;
engine->codec_params.rm_rate = imp->samples_per_second;
engine->codec_params.codec_ms = imp->microseconds_per_packet / 1000;
engine->codec_params.bitrate = imp->bits_per_second;
engine->codec_params.channels = 1;
/* mark to re-set codec */
reset_codec = 1;
break;
}
} }
if (!reset_codec) {
if (engine->last_codec_ms && engine->last_codec_ms == codec_ms) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
engine->mismatch_count++; "Could not change to payload type %d, ignoring...\n",
(int) engine->read_frame.payload);
} }
engine->last_codec_ms = codec_ms; /* autofix timing */
} else if (smh->media_flags[SCMF_AUTOFIX_TIMING] && (engine->read_frame.datalen % 10) == 0) {
if (engine->mismatch_count > MAX_MISMATCH_FRAMES) { if (engine->last_ts && engine->read_frame.datalen != engine->read_impl.encoded_bytes_per_packet) {
if (switch_rtp_ready(engine->rtp_session) && codec_ms != engine->codec_params.codec_ms) {
const char *val;
int rtp_timeout_sec = 0;
int rtp_hold_timeout_sec = 0;
if (codec_ms > 120) { /* yeah right */ uint32_t codec_ms = (int) (engine->read_frame.timestamp -
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, engine->last_ts) / (engine->read_impl.samples_per_second / 1000);
"Your phone is trying to send timestamps that suggest an increment of %dms per packet\n"
"That seems hard to believe so I am going to go on ahead and um ignore that, mmkay?\n",
(int) codec_ms);
engine->check_frames = MAX_CODEC_CHECK_FRAMES;
goto skip;
}
engine->read_frame.datalen = 0; if ((codec_ms % 10) != 0 || codec_ms > engine->read_impl.samples_per_packet * 10) {
if (codec_ms != engine->codec_params.codec_ms) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
"Asynchronous PTIME not supported, changing our end from %d to %d\n",
(int) engine->codec_params.codec_ms,
(int) codec_ms
);
switch_channel_set_variable_printf(session->channel, "rtp_h_X-Broken-PTIME", "Adv=%d;Sent=%d",
(int) engine->codec_params.codec_ms, (int) codec_ms);
engine->codec_params.codec_ms = codec_ms;
}
if (switch_core_media_set_codec(session, 2, 0) != SWITCH_STATUS_SUCCESS) {
*frame = NULL;
return SWITCH_STATUS_GENERR;
}
if ((val = switch_channel_get_variable(session->channel, "rtp_timeout_sec"))) {
int v = atoi(val);
if (v >= 0) {
rtp_timeout_sec = v;
}
}
if ((val = switch_channel_get_variable(session->channel, "rtp_hold_timeout_sec"))) {
int v = atoi(val);
if (v >= 0) {
rtp_hold_timeout_sec = v;
}
}
if (rtp_timeout_sec) {
engine->max_missed_packets = (engine->read_impl.samples_per_second * rtp_timeout_sec) /
engine->read_impl.samples_per_packet;
switch_rtp_set_max_missed_packets(engine->rtp_session, engine->max_missed_packets);
if (!rtp_hold_timeout_sec) {
rtp_hold_timeout_sec = rtp_timeout_sec * 10;
}
}
if (rtp_hold_timeout_sec) {
engine->max_missed_hold_packets = (engine->read_impl.samples_per_second * rtp_hold_timeout_sec) /
engine->read_impl.samples_per_packet;
}
engine->check_frames = 0;
engine->last_ts = 0; engine->last_ts = 0;
goto skip;
*frame = &engine->read_frame;
switch_set_flag((*frame), SFF_CNG);
(*frame)->datalen = engine->read_impl.encoded_bytes_per_packet;
memset((*frame)->data, 0, (*frame)->datalen);
return SWITCH_STATUS_SUCCESS;
} }
if (engine->last_codec_ms && engine->last_codec_ms == codec_ms) {
engine->mismatch_count++;
}
engine->last_codec_ms = codec_ms;
if (engine->mismatch_count > MAX_MISMATCH_FRAMES) {
if (codec_ms != engine->codec_params.codec_ms) {
if (codec_ms > 120) { /* yeah right */
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
"Your phone is trying to send timestamps that suggest an increment of %dms per packet\n"
"That seems hard to believe so I am going to go on ahead and um ignore that, mmkay?\n",
(int) codec_ms);
engine->check_frames = MAX_CODEC_CHECK_FRAMES;
goto skip;
}
engine->read_frame.datalen = 0;
if (codec_ms != engine->codec_params.codec_ms) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
"Asynchronous PTIME not supported, changing our end from %d to %d\n",
(int) engine->codec_params.codec_ms,
(int) codec_ms
);
switch_channel_set_variable_printf(session->channel, "rtp_h_X-Broken-PTIME", "Adv=%d;Sent=%d",
(int) engine->codec_params.codec_ms, (int) codec_ms);
engine->codec_params.codec_ms = codec_ms;
/* mark to re-set codec */
reset_codec = 2;
}
}
}
} else {
engine->mismatch_count = 0;
} }
engine->last_ts = engine->read_frame.timestamp;
} else { } else {
engine->mismatch_count = 0; engine->mismatch_count = 0;
engine->last_ts = 0;
} }
engine->last_ts = engine->read_frame.timestamp; /* re-set codec if necessary */
if (reset_codec > 0) {
const char *val;
int rtp_timeout_sec = 0;
int rtp_hold_timeout_sec = 0;
if (switch_rtp_ready(engine->rtp_session)) {
if (switch_core_media_set_codec(session, 2, 0) != SWITCH_STATUS_SUCCESS) {
*frame = NULL;
return SWITCH_STATUS_GENERR;
}
} else { if ((val = switch_channel_get_variable(session->channel, "rtp_timeout_sec"))) {
engine->mismatch_count = 0; int v = atoi(val);
engine->last_ts = 0; if (v >= 0) {
rtp_timeout_sec = v;
}
}
if ((val = switch_channel_get_variable(session->channel, "rtp_hold_timeout_sec"))) {
int v = atoi(val);
if (v >= 0) {
rtp_hold_timeout_sec = v;
}
}
if (rtp_timeout_sec) {
engine->max_missed_packets = (engine->read_impl.samples_per_second * rtp_timeout_sec) /
engine->read_impl.samples_per_packet;
switch_rtp_set_max_missed_packets(engine->rtp_session, engine->max_missed_packets);
if (!rtp_hold_timeout_sec) {
rtp_hold_timeout_sec = rtp_timeout_sec * 10;
}
}
if (rtp_hold_timeout_sec) {
engine->max_missed_hold_packets = (engine->read_impl.samples_per_second * rtp_hold_timeout_sec) /
engine->read_impl.samples_per_packet;
}
}
engine->check_frames = 0;
engine->last_ts = 0;
/* return CNG for now */
*frame = &engine->read_frame;
switch_set_flag((*frame), SFF_CNG);
(*frame)->datalen = engine->read_impl.encoded_bytes_per_packet;
memset((*frame)->data, 0, (*frame)->datalen);
return SWITCH_STATUS_SUCCESS;
}
} }
skip: skip:
if ((bytes = engine->read_impl.encoded_bytes_per_packet)) { if ((bytes = engine->read_impl.encoded_bytes_per_packet)) {
@ -3372,7 +3445,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_proxy_remote_addr(switch_core_
/* Reactivate the NAT buster flag. */ /* Reactivate the NAT buster flag. */
switch_rtp_set_flag(v_engine->rtp_session, SWITCH_RTP_FLAG_AUTOADJ); switch_rtp_set_flag(v_engine->rtp_session, SWITCH_RTP_FLAG_AUTOADJ);
} }
if (switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_TIMING)) { if (switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_TIMING) || switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_PT)) {
v_engine->check_frames = 0; v_engine->check_frames = 0;
} }
} }
@ -3410,7 +3483,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_proxy_remote_addr(switch_core_
/* Reactivate the NAT buster flag. */ /* Reactivate the NAT buster flag. */
switch_rtp_set_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_AUTOADJ); switch_rtp_set_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_AUTOADJ);
} }
if (switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_TIMING)) { if (switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_TIMING) || switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_PT)) {
a_engine->check_frames = 0; a_engine->check_frames = 0;
} }
status = SWITCH_STATUS_SUCCESS; status = SWITCH_STATUS_SUCCESS;
@ -3514,7 +3587,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_ext_address_lookup(switch_core
} }
//? //?
SWITCH_DECLARE(void) switch_core_media_reset_autofix_timing(switch_core_session_t *session, switch_media_type_t type) SWITCH_DECLARE(void) switch_core_media_reset_autofix(switch_core_session_t *session, switch_media_type_t type)
{ {
switch_rtp_engine_t *engine; switch_rtp_engine_t *engine;
switch_media_handle_t *smh; switch_media_handle_t *smh;

View File

@ -4819,7 +4819,8 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
rtp_session->recv_msg.header.pt != 13 && rtp_session->recv_msg.header.pt != 13 &&
rtp_session->recv_msg.header.pt != rtp_session->recv_te && rtp_session->recv_msg.header.pt != rtp_session->recv_te &&
(!rtp_session->cng_pt || rtp_session->recv_msg.header.pt != rtp_session->cng_pt) && (!rtp_session->cng_pt || rtp_session->recv_msg.header.pt != rtp_session->cng_pt) &&
rtp_session->recv_msg.header.pt != rtp_session->rpayload && !(rtp_session->rtp_bugs & RTP_BUG_ACCEPT_ANY_PACKETS)) { rtp_session->recv_msg.header.pt != rtp_session->rpayload &&
!(rtp_session->rtp_bugs & RTP_BUG_ACCEPT_ANY_PAYLOAD) && !(rtp_session->rtp_bugs & RTP_BUG_ACCEPT_ANY_PACKETS)) {
/* drop frames of incorrect payload number and return CNG frame instead */ /* drop frames of incorrect payload number and return CNG frame instead */
return_cng_frame(); return_cng_frame();
} }