add rtp_bug IGNORE_DTMF_DURATION to speed up dtmf detection of RFC2833 on strange carriers

This commit is contained in:
Anthony Minessale 2011-01-07 16:04:24 -06:00
parent cd13030f25
commit b3fc001e6c
3 changed files with 46 additions and 12 deletions

View File

@ -632,9 +632,13 @@ typedef enum {
This flag will never send any. Sheesh....
*/
RTP_BUG_IGNORE_DTMF_DURATION = (1 << 6)
/*
Guess Who? ... Yep, Sonus (and who know's who else) likes to interweave DTMF with the audio stream making it take
2X as long as it should and sending an incorrect duration making the DTMF very delayed.
This flag will treat every dtmf as if it were 50ms and queue it on recipt of the leading packet rather than at the end.
*/
} switch_rtp_bug_flag_t;

View File

@ -6188,6 +6188,14 @@ void sofia_glue_parse_rtp_bugs(uint32_t *flag_pole, const char *str)
if (switch_stristr("~NEVER_SEND_MARKER", str)) {
*flag_pole &= ~RTP_BUG_NEVER_SEND_MARKER;
}
if (switch_stristr("IGNORE_DTMF_DURATION", str)) {
*flag_pole |= RTP_BUG_IGNORE_DTMF_DURATION;
}
if (switch_stristr("~IGNORE_DTMF_DURATION", str)) {
*flag_pole &= ~RTP_BUG_IGNORE_DTMF_DURATION;
}
}
char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sofia_nat_parse_t *np)

View File

@ -133,6 +133,7 @@ struct switch_rtp_rfc2833_data {
char last_digit;
switch_queue_t *dtmf_inqueue;
switch_mutex_t *dtmf_mutex;
uint8_t in_digit_queued;
};
struct switch_rtp {
@ -2479,7 +2480,8 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
}
}
if ((!(io_flags & SWITCH_IO_FLAG_NOBLOCK)) && (rtp_session->dtmf_data.out_digit_dur == 0 || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO))) {
if ((!(io_flags & SWITCH_IO_FLAG_NOBLOCK)) &&
(rtp_session->dtmf_data.out_digit_dur == 0 || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO))) {
return_cng_frame();
}
}
@ -2819,7 +2821,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
}
#ifdef DEBUG_2833
if (rtp_session->dtmf_data.in_digit_sanity && !(rtp_session->dtmf_data.in_digit_sanity % 100)) {
printf("sanity %d\n", rtp_session->dtmf_data.in_digit_sanity);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sanity %d\n", rtp_session->dtmf_data.in_digit_sanity);
}
#endif
@ -2869,7 +2871,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
}
}
#ifdef DEBUG_2833
printf("packet[%d]: %02x %02x %02x %02x\n", (int) len, (unsigned) packet[0], (unsigned)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "packet[%d]: %02x %02x %02x %02x\n", (int) len, (unsigned) packet[0], (unsigned)
packet[1], (unsigned) packet[2], (unsigned) packet[3]);
#endif
@ -2878,16 +2880,28 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
rtp_session->dtmf_data.in_digit_seq = in_digit_seq;
#ifdef DEBUG_2833
printf("read: %c %u %u %u %u %d %d %s\n",
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "read: %c %u %u %u %u %d %d %s\n",
key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq,
ts, duration, rtp_session->recv_msg.header.m, end, end && !rtp_session->dtmf_data.in_digit_ts ? "ignored" : "");
#endif
if (!rtp_session->dtmf_data.in_digit_queued && (rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION) &&
rtp_session->dtmf_data.in_digit_ts) {
switch_dtmf_t dtmf = { key, switch_core_min_dtmf_duration(0) };
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Early Queuing digit %c:%d\n", dtmf.digit, dtmf.duration / 8);
#endif
switch_rtp_queue_rfc2833_in(rtp_session, &dtmf);
rtp_session->dtmf_data.in_digit_queued = 1;
}
/* only set sanity if we do NOT ignore the packet */
if (rtp_session->dtmf_data.in_digit_ts) {
rtp_session->dtmf_data.in_digit_sanity = 2000;
}
if (rtp_session->dtmf_data.last_duration > duration && rtp_session->dtmf_data.last_duration > 0xFC17 && ts == rtp_session->dtmf_data.in_digit_ts) {
if (rtp_session->dtmf_data.last_duration > duration &&
rtp_session->dtmf_data.last_duration > 0xFC17 && ts == rtp_session->dtmf_data.in_digit_ts) {
rtp_session->dtmf_data.flip++;
}
@ -2902,18 +2916,26 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
dtmf.duration += rtp_session->dtmf_data.flip * 0xFFFF;
rtp_session->dtmf_data.flip = 0;
#ifdef DEBUG_2833
printf("you're welcome!\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "you're welcome!\n");
#endif
}
#ifdef DEBUG_2833
printf("done digit=%c ts=%u start_ts=%u dur=%u ddur=%u\n",
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "done digit=%c ts=%u start_ts=%u dur=%u ddur=%u\n",
dtmf.digit, ts, rtp_session->dtmf_data.in_digit_ts, duration, dtmf.duration);
#endif
switch_rtp_queue_rfc2833_in(rtp_session, &dtmf);
if (!(rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION) && !rtp_session->dtmf_data.in_digit_queued) {
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Queuing digit %c:%d\n", dtmf.digit, dtmf.duration / 8);
#endif
switch_rtp_queue_rfc2833_in(rtp_session, &dtmf);
}
rtp_session->dtmf_data.last_digit = rtp_session->dtmf_data.first_digit;
rtp_session->dtmf_data.in_digit_ts = 0;
rtp_session->dtmf_data.in_digit_sanity = 0;
rtp_session->dtmf_data.in_digit_queued = 0;
do_cng = 1;
} else {
if (!switch_rtp_ready(rtp_session)) {
@ -2932,7 +2954,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
rtp_session->dtmf_data.last_duration = duration;
} else {
#ifdef DEBUG_2833
printf("drop: %c %u %u %u %u %d %d\n",
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "drop: %c %u %u %u %u %d %d\n",
key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq, ts, duration, rtp_session->recv_msg.header.m, end);
#endif
switch_cond_next();
@ -3540,7 +3562,7 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
#ifdef RTP_DEBUG_WRITE_DELTA
{
int delta = (int) (now - rtp_session->send_time) / 1000;
printf("WRITE %d delta %d\n", (int) bytes, delta);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "WRITE %d delta %d\n", (int) bytes, delta);
}
#endif
rtp_session->send_time = now;