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

Reply via email to