aboutsummaryrefslogtreecommitdiffstats
path: root/main/rtp.c
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-01-19 17:49:38 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-01-19 17:49:38 +0000
commitcc3938c1989d0b9f6a907ee2d64f2f66a01b2e29 (patch)
tree3fe50ce72af12ead588e9b25a6bf636f67b0993d /main/rtp.c
parent397418eb0c2c20f83505c9af8d5bb8aa89cab8af (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.c36
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;