int rtpkeepalive; /*!< Send RTP comfort noice packets for keepalive */
/* DTMF Reception Variables */
- char resp;
- unsigned int lastevent;
- unsigned int dtmf_duration; /*!< Total duration in samples since the digit start event */
- unsigned int dtmf_timeout; /*!< When this timestamp is reached we consider END frame lost and forcibly abort digit */
+ char resp; /*!< The current digit being processed */
+ unsigned int last_seqno; /*!< The last known sequence number for any DTMF packet */
+ unsigned int last_end_timestamp; /*!< The last known timestamp received from an END packet */
+ unsigned int dtmf_duration; /*!< Total duration in samples since the digit start event */
+ unsigned int dtmf_timeout; /*!< When this timestamp is reached we consider END frame lost and forcibly abort digit */
unsigned int dtmfsamples;
- enum ast_rtp_dtmf_mode dtmfmode;/*!< The current DTMF mode of the RTP stream */
+ enum ast_rtp_dtmf_mode dtmfmode; /*!< The current DTMF mode of the RTP stream */
/* DTMF Transmission Variables */
unsigned int lastdigitts;
char sending_digit; /*!< boolean - are we sending digits */
rtp->dtmfsamples = 0;
return &ast_null_frame;
}
- ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp,
- ast_sockaddr_stringify(&remote_address));
+ ast_debug(1, "Creating %s DTMF Frame: %d (%c), at %s\n",
+ type == AST_FRAME_DTMF_END ? "END" : "BEGIN",
+ rtp->resp, rtp->resp,
+ ast_sockaddr_stringify(&remote_address));
if (rtp->resp == 'X') {
rtp->f.frametype = AST_FRAME_CONTROL;
rtp->f.subclass.integer = AST_CONTROL_FLASH;
}
if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)) {
- if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) {
+ if ((rtp->last_end_timestamp != timestamp) || (rtp->resp && rtp->resp != resp)) {
rtp->resp = resp;
rtp->dtmf_timeout = 0;
f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)));
f->len = 0;
- rtp->lastevent = timestamp;
+ rtp->last_end_timestamp = timestamp;
AST_LIST_INSERT_TAIL(frames, f, frame_list);
}
} else {
}
new_duration = (new_duration & ~0xFFFF) | samples;
- /* The second portion of this check is to not mistakenly
- * stop accepting DTMF if the seqno rolls over beyond
- * 65535.
- */
- if (rtp->lastevent > seqno && rtp->lastevent - seqno < 50) {
- /* Out of order frame. Processing this can cause us to
- * improperly duplicate incoming DTMF, so just drop
- * this.
- */
- return;
- }
-
if (event_end & 0x80) {
/* End event */
- if ((rtp->lastevent != seqno) && rtp->resp) {
+ if ((rtp->last_seqno != seqno) && (timestamp > rtp->last_end_timestamp)) {
+ rtp->last_end_timestamp = timestamp;
rtp->dtmf_duration = new_duration;
+ rtp->resp = resp;
f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0));
f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(&f->subclass.format)), ast_tv(0, 0));
rtp->resp = 0;
rtp->dtmf_duration = rtp->dtmf_timeout = 0;
AST_LIST_INSERT_TAIL(frames, f, frame_list);
+ } else if (rtpdebug) {
+ ast_debug(1, "Dropping duplicate or out of order DTMF END frame (seqno: %d, ts %d, digit %c)\n",
+ seqno, timestamp, resp);
}
} else {
/* Begin/continuation */
+ /* The second portion of the seqno check is to not mistakenly
+ * stop accepting DTMF if the seqno rolls over beyond
+ * 65535.
+ */
+ if ((rtp->last_seqno > seqno && rtp->last_seqno - seqno < 50)
+ || timestamp <= rtp->last_end_timestamp) {
+ /* Out of order frame. Processing this can cause us to
+ * improperly duplicate incoming DTMF, so just drop
+ * this.
+ */
+ if (rtpdebug) {
+ ast_debug(1, "Dropping out of order DTMF frame (seqno %d, ts %d, digit %c)\n",
+ seqno, timestamp, resp);
+ }
+ return;
+ }
+
if (rtp->resp && rtp->resp != resp) {
/* Another digit already began. End it */
f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0));
rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout;
}
- rtp->lastevent = seqno;
+ rtp->last_seqno = seqno;
}
rtp->dtmfsamples = samples;