mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-20 20:44:20 +00:00
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:
46
main/rtp.c
46
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 */
|
||||
@@ -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;
|
||||
|
Reference in New Issue
Block a user