Merged revisions 51311 via svnmerge from

https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r51311 | russell | 2007-01-19 11:49:38 -0600 (Fri, 19 Jan 2007) | 23 lines

Merge the changes from the /team/group/vldtmf_fixup branch.

The main bug being addressed here is a problem introduced when two SIP
channels using SIP INFO dtmf have their media directly bridged.  So, when a
DTMF END frame comes into Asterisk from an incoming INFO message, Asterisk
would try to emulate a digit of some length by first sending a DTMF BEGIN
frame and sending a DTMF END later timed off of incoming audio.  However,
since there was no audio coming in, the DTMF_END was never generated.  This
caused DTMF based features to no longer work.

To fix this, the core now knows when a channel doesn't care about DTMF BEGIN
frames (such as a SIP channel sending INFO dtmf).  If this is the case, then
Asterisk will not emulate a digit of some length, and will instead just pass
through the single DTMF END event.

Channel drivers also now get passed the length of the digit to their digit_end
callback.  This improves SIP INFO support even further by enabling us to put
the real digit duration in the INFO message instead of a hard coded 250ms.
Also, for an incoming INFO message, the duration is read from the frame and
passed into the core instead of just getting ignored.

(issue #8597, maybe others...)

........


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@51314 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Russell Bryant
2007-01-19 18:06:03 +00:00
parent 9d509eaf76
commit dcca8f345f
19 changed files with 223 additions and 128 deletions

View File

@@ -140,7 +140,7 @@ struct ast_rtp {
char resp;
unsigned int lasteventendseqn;
int dtmfcount;
unsigned int dtmfduration;
unsigned int dtmfsamples;
/* DTMF Transmission Variables */
unsigned int lastdigitts;
char sending_digit; /* boolean - are we sending digits */
@@ -431,7 +431,7 @@ static int stun_handle_packet(int s, struct sockaddr_in *src, unsigned char *dat
if (len < sizeof(struct stun_header)) {
if (option_debug)
ast_log(LOG_DEBUG, "Runt STUN packet (only %d, wanting at least %d)\n", (int) len, sizeof(struct stun_header));
ast_log(LOG_DEBUG, "Runt STUN packet (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header));
return -1;
}
if (stundebug)
@@ -446,7 +446,7 @@ static int stun_handle_packet(int s, struct sockaddr_in *src, unsigned char *dat
while(len) {
if (len < sizeof(struct stun_attr)) {
if (option_debug)
ast_log(LOG_DEBUG, "Runt Attribute (got %d, expecting %d)\n", (int)len, sizeof(struct stun_attr));
ast_log(LOG_DEBUG, "Runt Attribute (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr));
break;
}
attr = (struct stun_attr *)data;
@@ -619,7 +619,7 @@ static struct ast_frame *send_dtmf(struct ast_rtp *rtp, enum ast_frame_type type
if (option_debug)
ast_log(LOG_DEBUG, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr));
rtp->resp = 0;
rtp->dtmfduration = 0;
rtp->dtmfsamples = 0;
return &ast_null_frame;
}
if (option_debug)
@@ -732,14 +732,14 @@ static struct ast_frame *process_cisco_dtmf(struct ast_rtp *rtp, unsigned char *
/* Why we should care on DTMF compensation at reception? */
if (!ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) {
f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN);
rtp->dtmfduration = 0;
rtp->dtmfsamples = 0;
}
} else if ((rtp->resp == resp) && !power) {
f = send_dtmf(rtp, AST_FRAME_DTMF_END);
f->samples = rtp->dtmfduration * 8;
f->samples = rtp->dtmfsamples * 8;
rtp->resp = 0;
} else if (rtp->resp == resp)
rtp->dtmfduration += 20 * 8;
rtp->dtmfsamples += 20 * 8;
rtp->dtmfcount = dtmftimeout;
return f;
}
@@ -759,18 +759,18 @@ static struct ast_frame *process_rfc2833(struct ast_rtp *rtp, unsigned char *dat
{
unsigned int event;
unsigned int event_end;
unsigned int duration;
unsigned int samples;
char resp = 0;
struct ast_frame *f = NULL;
/* Figure out event, event end, and duration */
/* Figure out event, event end, and samples */
event = ntohl(*((unsigned int *)(data)));
event >>= 24;
event_end = ntohl(*((unsigned int *)(data)));
event_end <<= 8;
event_end >>= 24;
duration = ntohl(*((unsigned int *)(data)));
duration &= 0xFFFF;
samples = ntohl(*((unsigned int *)(data)));
samples &= 0xFFFF;
/* Print out debug if turned on */
if (rtpdebug || option_debug > 2)
@@ -795,19 +795,19 @@ static struct ast_frame *process_rfc2833(struct ast_rtp *rtp, unsigned char *dat
f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN);
} else if (event_end & 0x80 && rtp->lasteventendseqn != seqno && rtp->resp) {
f = send_dtmf(rtp, AST_FRAME_DTMF_END);
f->samples = duration;
f->len = ast_tvdiff_ms(ast_samp2tv(samples, 8000), ast_tv(0, 0)); /* XXX hard coded 8kHz */
rtp->resp = 0;
rtp->lasteventendseqn = seqno;
} else if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && event_end & 0x80 && rtp->lasteventendseqn != seqno) {
rtp->resp = resp;
f = send_dtmf(rtp, AST_FRAME_DTMF_END);
f->samples = duration;
f->len = ast_tvdiff_ms(ast_samp2tv(samples, 8000), ast_tv(0, 0)); /* XXX hard coded 8kHz */
rtp->resp = 0;
rtp->lasteventendseqn = seqno;
}
rtp->dtmfcount = dtmftimeout;
rtp->dtmfduration = duration;
rtp->dtmfsamples = samples;
return f;
}
@@ -2065,7 +2065,7 @@ void ast_rtp_reset(struct ast_rtp *rtp)
rtp->lasttxformat = 0;
rtp->lastrxformat = 0;
rtp->dtmfcount = 0;
rtp->dtmfduration = 0;
rtp->dtmfsamples = 0;
rtp->seqno = 0;
rtp->rxseqno = 0;
}
@@ -3281,6 +3281,22 @@ enum ast_bridge_result ast_rtp_bridge(struct ast_channel *c0, struct ast_channel
audio_p1_res = AST_RTP_TRY_PARTIAL;
}
/* If both sides are not using the same method of DTMF transmission
* (ie: one is RFC2833, other is INFO... then we can not do direct media.
* --------------------------------------------------
* | DTMF Mode | HAS_DTMF | Accepts Begin Frames |
* |-----------|------------|-----------------------|
* | Inband | False | True |
* | RFC2833 | True | True |
* | SIP Info | False | False |
* --------------------------------------------------
*/
if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
(!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
audio_p0_res = AST_RTP_TRY_PARTIAL;
audio_p1_res = AST_RTP_TRY_PARTIAL;
}
/* Get codecs from both sides */
codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;