Author: sayer
Date: 2009-04-02 22:10:35 +0200 (Thu, 02 Apr 2009)
New Revision: 1352
Modified:
trunk/core/AmDtmfDetector.cpp
trunk/core/AmDtmfDetector.h
trunk/core/AmRtpStream.cpp
Log:
DTMF detection improved, the timestamp of the DTMF RTP packets is considered
- if an RTP event with timestamps differing from the last one is received, the
event is sent out immediately
- RTP DTMF packets with the same timestamp as an already detected keypress are
ignored.
This allows to raise the value for timeout on sending out RTP DTMF event, to 5
packets
(100 or 150ms)
Modified: trunk/core/AmDtmfDetector.cpp
===================================================================
--- trunk/core/AmDtmfDetector.cpp 2009-04-01 19:25:53 UTC (rev 1351)
+++ trunk/core/AmDtmfDetector.cpp 2009-04-02 20:10:35 UTC (rev 1352)
@@ -135,13 +135,14 @@
//
// AmRtpDtmfEvent methods
//
-AmRtpDtmfEvent::AmRtpDtmfEvent(const dtmf_payload_t *payload, int sample_rate)
+AmRtpDtmfEvent::AmRtpDtmfEvent(const dtmf_payload_t *payload, int sample_rate,
unsigned int ts)
: AmDtmfEvent(Dtmf::SOURCE_RTP)
{
m_duration_msec = ntohs(payload->duration) * 1000 / sample_rate;
m_e = payload->e;
m_volume = payload->volume;
m_event = payload->event;
+ m_ts = ts;
// RFC 2833:
// R: This field is reserved for future use. The sender MUST set it
// to zero, the receiver MUST ignore it.
@@ -180,7 +181,8 @@
m_sipDetector(this),
m_eventPending(false), m_sipEventReceived(false),
m_inbandEventReceived(false), m_rtpEventReceived(false),
- m_inband_type(Dtmf::SEMSInternal)
+ m_inband_type(Dtmf::SEMSInternal),
+ m_currentEvent(-1)
{
#ifndef USE_SPANDSP
setInbandDetector(Dtmf::SEMSInternal);
@@ -237,11 +239,12 @@
void AmDtmfDetector::registerKeyReleased(int event, Dtmf::EventSource source,
const struct timeval& start,
- const struct timeval& stop)
+ const struct timeval& stop,
+ bool flush)
{
// Old event has not been sent yet
// push out it now
- if (m_eventPending && m_currentEvent != event)
+ if (flush || (m_eventPending && m_currentEvent != event))
{
reportEvent();
}
@@ -333,7 +336,8 @@
// AmRtpDtmfDetector methods
AmRtpDtmfDetector::AmRtpDtmfDetector(AmKeyPressSink *keysink)
- : m_keysink(keysink), m_eventPending(false), m_packetCount(0)
+ : m_keysink(keysink), m_eventPending(false), m_packetCount(0),
+ m_currentTS(0), m_currentTS_i(false), m_lastTS_i(false)
{
}
@@ -345,44 +349,50 @@
// ITU-T Q.24A)
{
m_packetCount = 0; // reset idle packet counter
+
+ if (m_lastTS_i && m_lastTS == evt->ts()) {
+ // ignore events from past key press which was already reported
+ return;
+ }
+
if (!m_eventPending)
{
gettimeofday(&m_startTime, NULL);
m_eventPending = true;
m_currentEvent = evt->event();
+ m_currentTS = evt->ts();
+ m_currentTS_i = true;
}
-
- if (m_eventPending)
+ else
{
- if (evt->event() != m_currentEvent)
+ if ((evt->event() != m_currentEvent) ||
+ (m_currentTS_i && (evt->ts() != m_currentTS)))
{
// Previous event does not end correctly so send out it now...
- sendPending();
+ sendPending(true);
// ... and reinitialize to process current event
gettimeofday(&m_startTime, NULL);
m_eventPending = true;
m_currentEvent = evt->event();
+ m_currentTS = evt->ts();
+ m_currentTS_i = true;
}
- if (evt->e())
- {
- sendPending();
- }
}
- if (m_eventPending)
- {
- m_keysink->registerKeyPressed(m_currentEvent, Dtmf::SOURCE_RTP);
- }
+ m_keysink->registerKeyPressed(m_currentEvent, Dtmf::SOURCE_RTP);
}
}
-void AmRtpDtmfDetector::sendPending()
+void AmRtpDtmfDetector::sendPending(bool flush)
{
if (m_eventPending)
{
struct timeval end_time;
gettimeofday(&end_time, NULL);
- m_keysink->registerKeyReleased(m_currentEvent, Dtmf::SOURCE_RTP,
m_startTime, end_time);
+ m_keysink->registerKeyReleased(m_currentEvent, Dtmf::SOURCE_RTP,
m_startTime, end_time, flush);
m_eventPending = false;
+ m_currentTS_i = false;
+ m_lastTS = m_currentTS;
+ m_lastTS_i = true;
}
}
Modified: trunk/core/AmDtmfDetector.h
===================================================================
--- trunk/core/AmDtmfDetector.h 2009-04-01 19:25:53 UTC (rev 1351)
+++ trunk/core/AmDtmfDetector.h 2009-04-02 20:10:35 UTC (rev 1352)
@@ -129,9 +129,10 @@
* @param source which detector posted this event
* @param start time when key was pressed
* @param stop time when key was released
+ * @param flush whether key should be registered as own keypress immediately
*/
virtual void registerKeyReleased(int event, Dtmf::EventSource source,
- const struct timeval& start, const struct
timeval& stop) = 0;
+ const struct timeval& start, const struct
timeval& stop, bool flush=false) = 0;
/**
* Through this method the AmDtmfDetector receives events that was
* detected by specific detectors.
@@ -156,13 +157,18 @@
*/
int m_volume;
+ /**
+ * RTP timestamp
+ */
+ unsigned int m_ts;
+
public:
/**
* Constructor
* @param payload data from rtp packet of payload type telephone-event
* @param sample_rate sampling rate (from SDP payload description)
*/
- AmRtpDtmfEvent(const dtmf_payload_t *payload, int sample_rate);
+ AmRtpDtmfEvent(const dtmf_payload_t *payload, int sample_rate, unsigned int
ts);
/**
* Volume value from RTP packet
@@ -172,6 +178,8 @@
* E flag from RTP packet
*/
int e() { return m_e; }
+
+ unsigned int ts() { return m_ts; }
};
/**
@@ -328,9 +336,16 @@
*/
bool m_eventPending;
int m_currentEvent;
+ unsigned int m_currentTS;
+ bool m_currentTS_i;
int m_packetCount;
- static const int MAX_PACKET_WAIT = 3;
+ unsigned int m_lastTS;
+ bool m_lastTS_i;
+
+ // after MAX_PACKET_WAIT packets with no RTP DTMF packets received,
+ // a RTP DTMF event is sent out to the aggregating detector
+ static const int MAX_PACKET_WAIT = 5;
/**
* Time when first packet for current event was received
*/
@@ -339,7 +354,7 @@
/**
* Send out pending event
*/
- void sendPending();
+ void sendPending(bool flush=false);
public:
/**
@@ -404,9 +419,11 @@
* @param source which detector posted this event
* @param start time when key was pressed
* @param stop time when key was released
+ * @param flush whether key should be registered as own keypress immediately
*/
void registerKeyReleased(int event, Dtmf::EventSource source,
- const struct timeval& start, const struct timeval&
stop);
+ const struct timeval& start, const struct timeval&
stop,
+ bool flush=false);
/**
* Through this method the AmDtmfDetector receives events that was
* detected by specific detectors.
Modified: trunk/core/AmRtpStream.cpp
===================================================================
--- trunk/core/AmRtpStream.cpp 2009-04-01 19:25:53 UTC (rev 1351)
+++ trunk/core/AmRtpStream.cpp 2009-04-02 20:10:35 UTC (rev 1352)
@@ -319,9 +319,9 @@
{
dtmf_payload_t* dpl = (dtmf_payload_t*)rp->getData();
- DBG("DTMF: event=%i; e=%i; r=%i; volume=%i; duration=%i\n",
- dpl->event,dpl->e,dpl->r,dpl->volume,ntohs(dpl->duration));
- session->postDtmfEvent(new AmRtpDtmfEvent(dpl, getTelephoneEventRate()));
+ DBG("DTMF: event=%i; e=%i; r=%i; volume=%i; duration=%i; ts=%u\n",
+
dpl->event,dpl->e,dpl->r,dpl->volume,ntohs(dpl->duration),rp->timestamp);
+ session->postDtmfEvent(new AmRtpDtmfEvent(dpl, getTelephoneEventRate(),
rp->timestamp));
mem.freePacket(rp);
return RTP_DTMF;
}
_______________________________________________
Semsdev mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/semsdev