Commit f6ced13e authored by Tristan Matthews's avatar Tristan Matthews

* #10797: send DTMF over RTP as per RFC2833

They must be sent repeatedly and eventually with an end bit set.
Fixes regression from commit 9a8bc388
parent f88f6c3b
......@@ -47,6 +47,14 @@ std::ofstream rtpResampled ("testRtpOutputResampled.raw", std::ifstream::binary)
std::ofstream rtpNotResampled("testRtpOutput.raw", std::ifstream::binary);
#endif
DTMFEvent::DTMFEvent(int digit) : payload(), newevent(true), length(1000)
{
payload.event = digit;
payload.ebit = false; // end of event bit
payload.rbit = false; // reserved bit
payload.duration = 1; // duration for this event
}
AudioRtpRecord::AudioRtpRecord() :
audioCodec_(0)
, audioCodecMutex_()
......@@ -131,7 +139,8 @@ void AudioRtpRecordHandler::initNoiseSuppress()
void AudioRtpRecordHandler::putDtmfEvent(int digit)
{
audioRtpRecord_.dtmfQueue_.push_back(digit);
DTMFEvent dtmf(digit);
audioRtpRecord_.dtmfQueue_.push_back(dtmf);
}
int AudioRtpRecordHandler::processDataEncode()
......
......@@ -67,6 +67,13 @@ timeval2microtimeout(const timeval& t)
return ((t.tv_sec * 1000000ul) + t.tv_usec);
}
struct DTMFEvent {
DTMFEvent(int digit);
ost::RTPPacket::RFC2833Payload payload;
bool newevent;
int length;
};
/**
* Class meant to store internal data in order to encode/decode,
* resample, process, and packetize audio streams. This class should not be
......@@ -90,7 +97,7 @@ class AudioRtpRecord {
int codecSampleRate_;
int codecFrameSize_;
int converterSamplingRate_;
std::list<int> dtmfQueue_;
std::list<DTMFEvent> dtmfQueue_;
SFLDataFormat fadeFactor_;
NoiseSuppress *noiseSuppressEncode_;
NoiseSuppress *noiseSuppressDecode_;
......@@ -138,7 +145,7 @@ class AudioRtpRecordHandler {
return audioRtpRecord_.hasDynamicPayloadType_;
}
int DtmfPending() const {
bool hasDTMFPending() const {
return not audioRtpRecord_.dtmfQueue_.empty();
}
......
......@@ -110,25 +110,13 @@ void AudioRtpSession::setSessionMedia(AudioCodec &audioCodec)
}
}
void AudioRtpSession::incrementTimestampForDTMF()
{
timestamp_ += timestampIncrement_;
}
void AudioRtpSession::sendDtmfEvent()
{
ost::RTPPacket::RFC2833Payload payload;
payload.event = audioRtpRecord_.dtmfQueue_.front();
payload.ebit = false; // end of event bit
payload.rbit = false; // reserved bit
payload.duration = 1; // duration for this event
audioRtpRecord_.dtmfQueue_.pop_front();
DEBUG("Send RTP Dtmf (%d)", payload.event);
DTMFEvent &dtmf(audioRtpRecord_.dtmfQueue_.front());
DEBUG("Send RTP Dtmf (%d)", dtmf.payload.event);
incrementTimestampForDTMF();
const int increment = getIncrementForDTMF();
timestamp_ += increment;
// discard equivalent size of audio
processDataEncode();
......@@ -136,13 +124,29 @@ void AudioRtpSession::sendDtmfEvent()
// change Payload type for DTMF payload
queue_.setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) getDtmfPayloadType(), 8000));
queue_.setMark(true);
queue_.sendImmediate(timestamp_, (const unsigned char *)(&payload), sizeof(payload));
queue_.setMark(false);
// Set marker in case this is a new Event
if (dtmf.newevent)
queue_.setMark(true);
queue_.sendImmediate(timestamp_, (const unsigned char *) (& (dtmf.payload)), sizeof (ost::RTPPacket::RFC2833Payload));
// get back the payload to audio
// This is no longer a new event
if (dtmf.newevent) {
dtmf.newevent = false;
queue_.setMark(false);
}
// restore the payload to audio
const ost::StaticPayloadFormat pf(static_cast<ost::StaticPayloadType>(getCodecPayloadType()));
queue_.setPayloadFormat(pf);
// decrease length remaining to process for this event
dtmf.length -= increment;
dtmf.payload.duration++;
// next packet is going to be the last one
if ((dtmf.length - increment) < increment)
dtmf.payload.ebit = true;
if (dtmf.length < increment)
audioRtpRecord_.dtmfQueue_.pop_front();
}
......@@ -253,4 +257,9 @@ bool AudioRtpSession::onRTPPacketRecv(ost::IncomingRTPPkt&)
return true;
}
int AudioRtpSession::getIncrementForDTMF() const
{
return timestampIncrement_;
}
}
......@@ -66,6 +66,8 @@ class AudioRtpSession : public AudioRtpRecordHandler {
*/
void updateDestinationIpAddress();
virtual int getIncrementForDTMF() const;
protected:
/**
* Set the audio codec for this RTP session
......@@ -122,11 +124,6 @@ class AudioRtpSession : public AudioRtpRecordHandler {
*/
void receiveSpeakerData();
/**
* Increment timestamp for DTMF event
*/
virtual void incrementTimestampForDTMF();
// Main destination address for this rtp session.
// Stored in case or reINVITE, which may require to forget
// this destination and update a new one.
......
......@@ -70,7 +70,7 @@ void AudioSymmetricRtpSession::AudioRtpThread::run()
while (running_) {
// Send session
if (rtpSession_.DtmfPending())
if (rtpSession_.hasDTMFPending())
rtpSession_.sendDtmfEvent();
else
rtpSession_.sendMicData();
......
......@@ -133,7 +133,7 @@ void AudioZrtpSession::run()
timeout = getSchedulingTimeout();
// Send session
if (DtmfPending())
if (hasDTMFPending())
sendDtmfEvent();
else
sendMicData();
......@@ -162,9 +162,9 @@ void AudioZrtpSession::run()
DEBUG("Left main loop for call %s", call_.getCallId().c_str());
}
void AudioZrtpSession::incrementTimestampForDTMF()
int AudioZrtpSession::getIncrementForDTMF() const
{
timestamp_ += 160;
return 160;
}
void AudioZrtpSession::setSessionMedia(AudioCodec &audioCodec)
......
......@@ -71,8 +71,8 @@ class AudioZrtpSession :
void sendMicData();
void initializeZid();
std::string zidFilename_;
void incrementTimestampForDTMF();
void setSessionMedia(AudioCodec &codec);
virtual int getIncrementForDTMF() const;
};
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment