[svn-commits] file: branch group/vldtmf r39453 - in
/team/group/vldtmf: ./ channels/ includ...
svn-commits at lists.digium.com
svn-commits at lists.digium.com
Tue Aug 8 20:44:19 MST 2006
Author: file
Date: Tue Aug 8 22:44:19 2006
New Revision: 39453
URL: http://svn.digium.com/view/asterisk?rev=39453&view=rev
Log:
Put in what I have so far... basically reception from a regular RFC2833 works for shizzle, and sending from regular should as well. Now we just need to compensate!
Modified:
team/group/vldtmf/channels/chan_sip.c
team/group/vldtmf/include/asterisk/rtp.h
team/group/vldtmf/rtp.c
Modified: team/group/vldtmf/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf/channels/chan_sip.c?rev=39453&r1=39452&r2=39453&view=diff
==============================================================================
--- team/group/vldtmf/channels/chan_sip.c (original)
+++ team/group/vldtmf/channels/chan_sip.c Tue Aug 8 22:44:19 2006
@@ -740,9 +740,10 @@
#define SIP_PAGE2_CALL_ONHOLD (3 << 23) /*!< Call states */
#define SIP_PAGE2_CALL_ONHOLD_ONEDIR (1 << 23) /*!< 23: One directional hold */
#define SIP_PAGE2_CALL_ONHOLD_INACTIVE (2 << 24) /*!< 24: Inactive */
+#define SIP_PAGE2_RFC2833_COMPENSATE (1 << 26)
#define SIP_PAGE2_FLAGS_TO_COPY \
- (SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_VIDEOSUPPORT | SIP_PAGE2_T38SUPPORT)
+ (SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_VIDEOSUPPORT | SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE)
/* SIP packet flags */
#define SIP_PKT_DEBUG (1 << 0) /*!< Debug this packet */
@@ -2513,12 +2514,14 @@
ast_log(LOG_DEBUG, "Setting NAT on RTP to %s\n", natflags ? "On" : "Off");
ast_rtp_setnat(r->rtp, natflags);
ast_rtp_setdtmf(r->rtp, ast_test_flag(&r->flags[0], SIP_DTMF) != SIP_DTMF_INFO);
+ ast_rtp_setdtmfcompensate(r->rtp, ast_test_flag(&r->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
}
if (r->vrtp) {
if (option_debug)
ast_log(LOG_DEBUG, "Setting NAT on VRTP to %s\n", natflags ? "On" : "Off");
ast_rtp_setnat(r->vrtp, natflags);
ast_rtp_setdtmf(r->vrtp, 0);
+ ast_rtp_setdtmfcompensate(r->vrtp, 0);
}
if (r->udptl) {
if (option_debug)
@@ -3437,12 +3440,14 @@
struct sip_pvt *p = ast->tech_pvt;
int res = 0;
- /* XXX Implement me, plz, kthx */
-
ast_mutex_lock(&p->lock);
switch (ast_test_flag(&p->flags[0], SIP_DTMF)) {
case SIP_DTMF_INBAND:
res = -1; /* Tell Asterisk to generate inband indications */
+ break;
+ case SIP_DTMF_RFC2833:
+ if (p->rtp)
+ ast_rtp_senddigit_begin(p->rtp, digit);
break;
default:
break;
@@ -3466,7 +3471,7 @@
break;
case SIP_DTMF_RFC2833:
if (p->rtp)
- ast_rtp_senddigit(p->rtp, digit);
+ ast_rtp_senddigit_end(p->rtp, digit);
break;
case SIP_DTMF_INBAND:
res = -1; /* Tell Asterisk to stop inband indications */
@@ -4063,10 +4068,12 @@
return NULL;
}
ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) != SIP_DTMF_INFO);
+ ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
ast_rtp_settos(p->rtp, global_tos_audio);
if (p->vrtp) {
ast_rtp_settos(p->vrtp, global_tos_video);
ast_rtp_setdtmf(p->vrtp, 0);
+ ast_rtp_setdtmfcompensate(p->vrtp, 0);
}
if (p->udptl)
ast_udptl_settos(p->udptl, global_tos_audio);
@@ -12827,6 +12834,7 @@
extract_uri(p, req); /* Get the Contact URI */
build_contact(p); /* Build our contact header */
ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) != SIP_DTMF_INFO);
+ ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
if (!replace_id && gotdest) { /* No matching extension found */
if (gotdest == 1 && ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWOVERLAP)) {
@@ -14843,6 +14851,9 @@
} else if (!strcasecmp(v->name, "t38pt_tcp")) {
ast_set_flag(&mask[1], SIP_PAGE2_T38SUPPORT_TCP);
ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_T38SUPPORT_TCP);
+ } else if (!strcasecmp(v->name, "rfc2833compensate")) {
+ ast_set_flag(&mask[1], SIP_PAGE2_RFC2833_COMPENSATE);
+ ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_RFC2833_COMPENSATE);
}
return res;
Modified: team/group/vldtmf/include/asterisk/rtp.h
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf/include/asterisk/rtp.h?rev=39453&r1=39452&r2=39453&view=diff
==============================================================================
--- team/group/vldtmf/include/asterisk/rtp.h (original)
+++ team/group/vldtmf/include/asterisk/rtp.h Tue Aug 8 22:44:19 2006
@@ -129,7 +129,9 @@
int ast_rtcp_fd(struct ast_rtp *rtp);
-int ast_rtp_senddigit(struct ast_rtp *rtp, char digit);
+int ast_rtp_senddigit_begin(struct ast_rtp *rtp, char digit);
+
+int ast_rtp_senddigit_end(struct ast_rtp *rtp, char digit);
int ast_rtp_sendcng(struct ast_rtp *rtp, int level);
@@ -168,6 +170,9 @@
/*! \brief Indicate whether this RTP session is carrying DTMF or not */
void ast_rtp_setdtmf(struct ast_rtp *rtp, int dtmf);
+/*! \brief Compensate for devices that send RFC2833 packets all at once */
+void ast_rtp_setdtmfcompensate(struct ast_rtp *rtp, int compensate);
+
int ast_rtp_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
int ast_rtp_proto_register(struct ast_rtp_protocol *proto);
Modified: team/group/vldtmf/rtp.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf/rtp.c?rev=39453&r1=39452&r2=39453&view=diff
==============================================================================
--- team/group/vldtmf/rtp.c (original)
+++ team/group/vldtmf/rtp.c Tue Aug 8 22:44:19 2006
@@ -106,14 +106,12 @@
/*! \brief RTP session description */
struct ast_rtp {
int s;
- char resp;
struct ast_frame f;
unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET];
unsigned int ssrc; /*!< Synchronization source, RFC 3550, page 10. */
unsigned int themssrc; /*!< Their SSRC */
unsigned int rxssrc;
unsigned int lastts;
- unsigned int lastdigitts;
unsigned int lastrxts;
unsigned int lastividtimestamp;
unsigned int lastovidtimestamp;
@@ -128,11 +126,18 @@
unsigned int cycles; /*!< Shifted count of sequence number cycles */
double rxjitter; /*!< Interarrival jitter at the moment */
double rxtransit; /*!< Relative transit time for previous packet */
- unsigned int lasteventendseqn;
int lasttxformat;
int lastrxformat;
+ /* DTMF Reception Variables */
+ char resp;
+ unsigned int lasteventendseqn;
int dtmfcount;
unsigned int dtmfduration;
+ /* DTMF Transmission Variables */
+ unsigned int lastdigitts;
+ char send_digit;
+ int send_compensate;
+ int send_payload;
int nat;
unsigned int flags;
struct sockaddr_in us; /*!< Socket representation of the local endpoint. */
@@ -169,6 +174,7 @@
#define FLAG_NAT_INACTIVE (0 << 1)
#define FLAG_NAT_INACTIVE_NOWARN (1 << 1)
#define FLAG_HAS_DTMF (1 << 3)
+#define FLAG_DTMF_COMPENSATE (1 << 4)
/*!
* \brief Structure defining an RTCP session.
@@ -526,7 +532,12 @@
ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
}
-static struct ast_frame *send_dtmf(struct ast_rtp *rtp)
+void ast_rtp_setdtmfcompensate(struct ast_rtp *rtp, int compensate)
+{
+ ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE);
+}
+
+static struct ast_frame *send_dtmf(struct ast_rtp *rtp, enum ast_frame_type type)
{
if (ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
if (option_debug)
@@ -541,15 +552,13 @@
rtp->f.frametype = AST_FRAME_CONTROL;
rtp->f.subclass = AST_CONTROL_FLASH;
} else {
- rtp->f.frametype = AST_FRAME_DTMF;
+ rtp->f.frametype = type;
rtp->f.subclass = rtp->resp;
}
rtp->f.datalen = 0;
rtp->f.samples = 0;
rtp->f.mallocd = 0;
rtp->f.src = "RTP";
- rtp->resp = 0;
- rtp->dtmfduration = 0;
return &rtp->f;
}
@@ -602,7 +611,7 @@
resp = 'X';
}
if (rtp->resp && (rtp->resp != resp)) {
- f = send_dtmf(rtp);
+ f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN);
}
rtp->resp = resp;
rtp->dtmfcount = dtmftimeout;
@@ -628,6 +637,7 @@
char resp = 0;
struct ast_frame *f = NULL;
+ /* Figure out event, event end, and duration */
event = ntohl(*((unsigned int *)(data)));
event >>= 24;
event_end = ntohl(*((unsigned int *)(data)));
@@ -635,8 +645,12 @@
event_end >>= 24;
duration = ntohl(*((unsigned int *)(data)));
duration &= 0xFFFF;
+
+ /* Print out debug if turned on */
if (rtpdebug || option_debug > 2)
ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
+
+ /* Figure out what digit was pressed */
if (event < 10) {
resp = '0' + event;
} else if (event < 11) {
@@ -648,25 +662,21 @@
} else if (event < 17) { /* Event 16: Hook flash */
resp = 'X';
}
- if (rtp->resp && (rtp->resp != resp)) {
- f = send_dtmf(rtp);
- } else if (event_end & 0x80) {
- if (rtp->resp) {
- if (rtp->lasteventendseqn != seqno) {
- f = send_dtmf(rtp);
- rtp->lasteventendseqn = seqno;
- }
- rtp->resp = 0;
- }
- resp = 0;
- duration = 0;
- } else if (rtp->resp && rtp->dtmfduration && (duration < rtp->dtmfduration)) {
- f = send_dtmf(rtp);
- }
- if (!(event_end & 0x80))
+
+ if ((!(rtp->resp) && (!(event_end & 0x80))) || (rtp->resp && rtp->resp != resp)) {
rtp->resp = resp;
+ /* Only actually send an AST_FRAME_DTMF_BEGIN If we are not compensating */
+ if (!ast_test_flag(rtp, FLAG_DTMF_COMPENSATE))
+ f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN);
+ } else if ((event_end & 0x80) && rtp->resp && rtp->lasteventendseqn != seqno) {
+ rtp->lasteventendseqn = seqno;
+ f = send_dtmf(rtp, AST_FRAME_DTMF_END);
+ rtp->resp = 0;
+ }
+
rtp->dtmfcount = dtmftimeout;
rtp->dtmfduration = duration;
+
return f;
}
@@ -1082,13 +1092,13 @@
duration &= 0xFFFF;
ast_verbose("Got RTP RFC2833 from %s:%d (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u, mark %d, event %08x, end %d, duration %-5.5d) \n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration);
}
- if (rtp->lasteventseqn <= seqno || rtp->resp == 0 || (rtp->lasteventseqn >= 65530 && seqno <= 6)) {
+ if (rtp->lasteventseqn <= seqno || (rtp->lasteventseqn >= 65530 && seqno <= 6)) {
f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno);
rtp->lasteventseqn = seqno;
}
} else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
/* It's really special -- process it the Cisco way */
- if (rtp->lasteventseqn <= seqno || rtp->resp == 0 || (rtp->lasteventseqn >= 65530 && seqno <= 6)) {
+ if (rtp->lasteventseqn <= seqno || (rtp->lasteventseqn >= 65530 && seqno <= 6)) {
f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
rtp->lasteventseqn = seqno;
}
@@ -1126,8 +1136,9 @@
if (rtp->resp && !rtp->dtmfcount) {
if (option_debug)
ast_log(LOG_DEBUG, "Sending pending DTMF\n");
- return send_dtmf(rtp);
- }
+ return send_dtmf(rtp, AST_FRAME_DTMF_BEGIN);
+ }
+
rtp->f.mallocd = 0;
rtp->f.datalen = res - hdrlen;
rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
@@ -1862,29 +1873,36 @@
return (unsigned int) ms;
}
-int ast_rtp_senddigit(struct ast_rtp *rtp, char digit)
+/* Convert DTMF digit into something usable */
+static int digit_convert(char digit)
+{
+ if ((digit <= '9') && (digit >= '0'))
+ digit -= '0';
+ else if (digit == '*')
+ digit = 10;
+ else if (digit == '#')
+ digit = 11;
+ else if ((digit >= 'A') && (digit <= 'D'))
+ digit = digit - 'A' + 12;
+ else if ((digit >= 'a') && (digit <= 'd'))
+ digit = digit - 'a' + 12;
+ else {
+ ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
+ return -1;
+ }
+ return 0;
+}
+
+/*! \brief Send begin frames for DTMF */
+int ast_rtp_senddigit_begin(struct ast_rtp *rtp, char digit)
{
unsigned int *rtpheader;
- int hdrlen = 12;
- int res;
- int x;
- int payload;
+ int hdrlen = 12, res = 0, i = 0, payload = 0;
char data[256];
- if ((digit <= '9') && (digit >= '0'))
- digit -= '0';
- else if (digit == '*')
- digit = 10;
- else if (digit == '#')
- digit = 11;
- else if ((digit >= 'A') && (digit <= 'D'))
- digit = digit - 'A' + 12;
- else if ((digit >= 'a') && (digit <= 'd'))
- digit = digit - 'a' + 12;
- else {
- ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
+ if (digit_convert(digit))
return -1;
- }
+
payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
/* If we have no peer, return immediately */
@@ -1899,7 +1917,8 @@
rtpheader[1] = htonl(rtp->lastdigitts);
rtpheader[2] = htonl(rtp->ssrc);
rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (0));
- for (x = 0; x < 6; x++) {
+
+ for (i = 0; i < 2; i++) {
if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
if (res < 0)
@@ -1911,39 +1930,115 @@
ast_inet_ntoa(rtp->them.sin_addr),
ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
}
- /* Sequence number of last two end packets does not get incremented */
- if (x < 3)
- rtp->seqno++;
+ /* Increment sequence number */
+ rtp->seqno++;
/* Clear marker bit and set seqno */
rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
- /* For the last three packets, set the duration and the end bit */
- if (x == 2) {
-#if 0
- /* No, this is wrong... Do not increment lastdigitts, that's not according
- to the RFC, as best we can determine */
- rtp->lastdigitts++; /* or else the SPA3000 will click instead of beeping... */
- rtpheader[1] = htonl(rtp->lastdigitts);
-#endif
- /* Make duration 800 (100ms) */
- rtpheader[3] |= htonl((800));
- /* Set the End bit */
- rtpheader[3] |= htonl((1 << 23));
- }
- }
- /*! \note Increment the digit timestamp by 120ms, to ensure that digits
- sent sequentially with no intervening non-digit packets do not
- get sent with the same timestamp, and that sequential digits
- have some 'dead air' in between them
- */
- rtp->lastdigitts += 960;
- /* Increment the sequence number to reflect the last packet
- that was sent
- */
+ }
+
+ /* Since we received a begin, we can safely store the digit and disable any compensation */
+ rtp->send_digit = digit;
+ rtp->send_compensate = 0;
+ rtp->send_payload = payload;
+
+ return 0;
+}
+
+/*! \brief Send continuation frame for DTMF */
+static int ast_rtp_senddigit_continuation(struct ast_rtp *rtp)
+{
+ unsigned int *rtpheader;
+ int hdrlen = 12, res = 0;
+ char data[256];
+
+ if (!rtp->them.sin_addr.s_addr)
+ return 0;
+
+ /* Setup packet to send */
+ rtpheader = (unsigned int *)data;
+ rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
+ rtpheader[1] = htonl(rtp->lastdigitts);
+ rtpheader[2] = htonl(rtp->ssrc);
+ rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (0));
+ rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
+
+ /* Transmit */
+ if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
+ res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
+ if (res < 0)
+ ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
+ ast_inet_ntoa(rtp->them.sin_addr),
+ ntohs(rtp->them.sin_port), strerror(errno));
+ if (rtp_debug_test_addr(&rtp->them))
+ ast_verbose("Sent RTP DTMF packet to %s:%d (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
+ ast_inet_ntoa(rtp->them.sin_addr),
+ ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
+ }
+
+ /* Increment sequence number */
rtp->seqno++;
+
return 0;
}
-/* \brief Public function: Send an H.261 fast update request, some devices need this rather than SIP XML */
+/*! \brief Send end packets for DTMF */
+int ast_rtp_senddigit_end(struct ast_rtp *rtp, char digit)
+{
+ unsigned int *rtpheader;
+ int hdrlen = 12, res = 0, i = 0;
+ char data[256];
+ char original_digit = digit;
+
+ /* If no address, then bail out */
+ if (!rtp->them.sin_addr.s_addr)
+ return 0;
+
+ /* Convert our digit to the crazy RTP way */
+ if (digit_convert(digit))
+ return -1;
+
+ /* If no digit was pressed initially, then we need to compensate */
+ if (!rtp->send_digit || rtp->send_digit != digit) {
+ if ((res = ast_rtp_senddigit_begin(rtp, original_digit)))
+ return res;
+ /* Initialize compensation */
+ rtp->send_compensate = 1;
+ } else {
+ /* We can safely send termination here */
+ rtpheader = (unsigned int *)data;
+ rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
+ rtpheader[1] = htonl(rtp->lastdigitts);
+ rtpheader[2] = htonl(rtp->ssrc);
+ rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (0));
+ /* Send duration to 100ms */
+ rtpheader[3] |= htonl((800));
+ /* Set end bit */
+ rtpheader[3] |= htonl((1 << 23));
+ /* Send 3 termination packets */
+ for (i = 0; i < 3; i++) {
+ if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
+ res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
+ if (res < 0)
+ ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
+ ast_inet_ntoa(rtp->them.sin_addr),
+ ntohs(rtp->them.sin_port), strerror(errno));
+ if (rtp_debug_test_addr(&rtp->them))
+ ast_verbose("Sent RTP DTMF packet to %s:%d (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
+ ast_inet_ntoa(rtp->them.sin_addr),
+ ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
+ }
+ }
+ rtp->send_digit = 0;
+ rtp->send_compensate = 0;
+ /* Increment lastdigitts */
+ rtp->lastdigitts += 960;
+ rtp->seqno++;
+ }
+
+ return res;
+}
+
+/*! \brief Public function: Send an H.261 fast update request, some devices need this rather than SIP XML */
int ast_rtcp_send_h261fur(void *data)
{
struct ast_rtp *rtp = data;
More information about the svn-commits
mailing list