mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-18 07:48:14 +00:00
Correct behavior on Cisco's DTMF
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@43539 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
69
main/rtp.c
69
main/rtp.c
@@ -604,10 +604,58 @@ static struct ast_frame *process_cisco_dtmf(struct ast_rtp *rtp, unsigned char *
|
|||||||
unsigned int event;
|
unsigned int event;
|
||||||
char resp = 0;
|
char resp = 0;
|
||||||
struct ast_frame *f = NULL;
|
struct ast_frame *f = NULL;
|
||||||
event = ntohl(*((unsigned int *)(data)));
|
unsigned char seq;
|
||||||
event &= 0x001F;
|
unsigned int datalen;
|
||||||
|
unsigned int flag;
|
||||||
|
unsigned int power;
|
||||||
|
|
||||||
|
/* We should have at least 4 bytes in RTP data */
|
||||||
|
if (len < 4)
|
||||||
|
return f;
|
||||||
|
|
||||||
|
/* The format of Cisco RTP DTMF packet looks like next:
|
||||||
|
+0 - sequence number of DTMF RTP packet (begins from 1,
|
||||||
|
wrapped to 0)
|
||||||
|
+1 (bits 7-0) - count of bytes carrying DTMF information (if DTMF
|
||||||
|
information repeates 3 times, i.e. packet have 6
|
||||||
|
bytes of DTMF information, this value equal to 6).
|
||||||
|
Last bit should always be zero (because DTMF info
|
||||||
|
is multiple of 2 bytes) but really uses as described
|
||||||
|
below.
|
||||||
|
+1 (bit 0) - flaps by different DTMF digits delimited by audio
|
||||||
|
or repeated digit without audio
|
||||||
|
+2 (+4,+6,...) - power level? (rises from 0 to 32 at begin of tone
|
||||||
|
then falls to 0 at its end)
|
||||||
|
+3 (+5,+7,...) - detected DTMF digit (0..9,*,#,A-D,...)
|
||||||
|
Repeated DTMF information (bytes 4/5, 6/7) is history shifted right
|
||||||
|
by each new packet and thus provides some redudancy.
|
||||||
|
|
||||||
|
Sample of Cisco RTP DTMF packet is (all data in hex):
|
||||||
|
19 07 00 02 12 02 20 02
|
||||||
|
showing end of DTMF digit '2'.
|
||||||
|
|
||||||
|
The packets
|
||||||
|
27 07 00 02 0A 02 20 02
|
||||||
|
28 06 20 02 00 02 0A 02
|
||||||
|
shows begin of new digit '2' with very short pause (20 ms) after
|
||||||
|
previous digit '2'. Bit +1.0 flips at begin of new digit.
|
||||||
|
|
||||||
|
Cisco RTP DTMF packets comes as replacement of audio RTP packets
|
||||||
|
so its uses the same sequencing and timestamping rules as replaced
|
||||||
|
audio packets. Repeat interval of DTMF packets is 20 ms and not rely
|
||||||
|
on audio framing parameters. Marker bit isn't used within stream of
|
||||||
|
DTMFs nor audio stream coming immediately after DTMF stream. Timestamps
|
||||||
|
are not sequential at borders between DTMF and audio streams,
|
||||||
|
*/
|
||||||
|
|
||||||
|
seq = data[0];
|
||||||
|
datalen = data[1] & ~1;
|
||||||
|
flag = data[1] & 1;
|
||||||
|
power = data[2];
|
||||||
|
event = data[3] & 0x1f;
|
||||||
|
|
||||||
if (option_debug > 2 || rtpdebug)
|
if (option_debug > 2 || rtpdebug)
|
||||||
ast_log(LOG_DEBUG, "Cisco DTMF Digit: %08x (len = %d)\n", event, len);
|
ast_log(LOG_DEBUG, "Cisco DTMF Digit: %02x (len=%d, seq=%d, repeat=%d, power=%d, history count=%d)\n", event, len, seq, flag, power, datalen / 2 - 1);
|
||||||
if (event < 10) {
|
if (event < 10) {
|
||||||
resp = '0' + event;
|
resp = '0' + event;
|
||||||
} else if (event < 11) {
|
} else if (event < 11) {
|
||||||
@@ -619,10 +667,19 @@ static struct ast_frame *process_cisco_dtmf(struct ast_rtp *rtp, unsigned char *
|
|||||||
} else if (event < 17) {
|
} else if (event < 17) {
|
||||||
resp = 'X';
|
resp = 'X';
|
||||||
}
|
}
|
||||||
if (rtp->resp && (rtp->resp != resp)) {
|
if ((!rtp->resp && power) || (rtp->resp && (rtp->resp != resp))) {
|
||||||
f = send_dtmf(rtp, AST_FRAME_DTMF_END);
|
|
||||||
}
|
|
||||||
rtp->resp = resp;
|
rtp->resp = resp;
|
||||||
|
/* Why we should care on DTMF compensation at receiption? */
|
||||||
|
if (!ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) {
|
||||||
|
f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN);
|
||||||
|
rtp->dtmfduration = 0;
|
||||||
|
}
|
||||||
|
} else if ((rtp->resp == resp) && !power) {
|
||||||
|
f = send_dtmf(rtp, AST_FRAME_DTMF_END);
|
||||||
|
f->samples = rtp->dtmfduration * 8;
|
||||||
|
rtp->resp = 0;
|
||||||
|
} else if (rtp->resp == resp)
|
||||||
|
rtp->dtmfduration += 20 * 8;
|
||||||
rtp->dtmfcount = dtmftimeout;
|
rtp->dtmfcount = dtmftimeout;
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user