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) 



git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@1352 8eb893ce-cfd4-0310-b710-fb5ebe64c474
sayer/1.4-spce2.6
Stefan Sayer 18 years ago
parent cc1a0a88f4
commit 5ab8284bb6

@ -135,13 +135,14 @@ void AmSipDtmfEvent::parseLine(const string& line)
//
// 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 @@ AmDtmfDetector::AmDtmfDetector(AmSession *session)
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::process(AmEvent *evt)
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 @@ void AmDtmfDetector::putDtmfAudio(const unsigned char *buf, int size, int user_t
// 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 @@ void AmRtpDtmfDetector::process(AmRtpDtmfEvent *evt)
// 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;
}
}

@ -129,9 +129,10 @@ class AmKeyPressSink {
* @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 @@ class AmRtpDtmfEvent : public AmDtmfEvent
*/
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 @@ class AmRtpDtmfEvent : public AmDtmfEvent
* E flag from RTP packet
*/
int e() { return m_e; }
unsigned int ts() { return m_ts; }
};
/**
@ -328,9 +336,16 @@ class AmRtpDtmfDetector
*/
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 @@ class AmRtpDtmfDetector
/**
* Send out pending event
*/
void sendPending();
void sendPending(bool flush=false);
public:
/**
@ -404,9 +419,11 @@ class AmDtmfDetector
* @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.

@ -319,9 +319,9 @@ int AmRtpStream::receive( unsigned char* buffer, unsigned int size,
{
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;
}

Loading…
Cancel
Save