diff options
author | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2007-01-19 17:49:38 +0000 |
---|---|---|
committer | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2007-01-19 17:49:38 +0000 |
commit | cc3938c1989d0b9f6a907ee2d64f2f66a01b2e29 (patch) | |
tree | 3fe50ce72af12ead588e9b25a6bf636f67b0993d /main/rtp.c | |
parent | 397418eb0c2c20f83505c9af8d5bb8aa89cab8af (diff) |
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: http://svn.digium.com/svn/asterisk/branches/1.4@51311 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main/rtp.c')
-rw-r--r-- | main/rtp.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/main/rtp.c b/main/rtp.c index 9b4431d06..dc6efbd81 100644 --- a/main/rtp.c +++ b/main/rtp.c @@ -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 */ @@ -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) @@ -709,18 +709,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) @@ -745,19 +745,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; } @@ -2000,7 +2000,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; } @@ -3180,6 +3180,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; |