[asterisk-scf-commits] asterisk-scf/integration/media_rtp_pjmedia.git branch "telephony-events2" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Tue Aug 9 18:50:25 CDT 2011


branch "telephony-events2" has been updated
       via  51a1d11783701bff96ba621e275824e0aae6454c (commit)
       via  f32a2b7829c7442bbd0bfbfeec6c4c0511b00bc4 (commit)
       via  1bf93e4bb3b668e45fb1d9227814efbce416a031 (commit)
       via  7abcf7e1c41b909a2aaf1a2c44be0baf1c3ada56 (commit)
       via  851ca93f58b1fab9a0e6349852a016bae9a76374 (commit)
       via  b6db1d069bcf3013327d8adee49e7b4d8a1d6c0a (commit)
       via  fa8e68b106cd0c1b6f49733764c0c29f6d728387 (commit)
       via  c62a7f5070867013ae428a3c9af2c83f6840a716 (commit)
      from  cd50386c941baa0c1661ccfefaeb3ef1dd51a291 (commit)

Summary of changes:
 src/RTPSession.cpp              |   35 ++++++++++--
 src/RTPSink.cpp                 |   31 ++++++-----
 src/RTPSink.h                   |    7 ++-
 src/RTPSource.cpp               |   27 ++++-----
 src/RTPSource.h                 |    8 ++-
 src/RTPTelephonyEventSink.cpp   |  111 ++++++++++++++++++++++++++++++++++++++-
 src/RTPTelephonyEventSink.h     |   17 ++++++-
 src/RTPTelephonyEventSource.cpp |   79 ++++++++++++++++------------
 src/RTPTelephonyEventSource.h   |   27 +++-------
 9 files changed, 245 insertions(+), 97 deletions(-)


- Log -----------------------------------------------------------------
commit 51a1d11783701bff96ba621e275824e0aae6454c
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Aug 9 18:51:02 2011 -0500

    Add XXX note to add support for long duration events on telephony event sink.
    
    I'll get that tomorrow.

diff --git a/src/RTPTelephonyEventSink.cpp b/src/RTPTelephonyEventSink.cpp
index 0709e08..b3198e1 100644
--- a/src/RTPTelephonyEventSink.cpp
+++ b/src/RTPTelephonyEventSink.cpp
@@ -94,6 +94,9 @@ void RTPTelephonyEventSink::write_async(
 
     //The fifth parameter is set to 0 here since the RTP timestamp is the same
     //for all packets sent during an event.
+    //
+    //XXX The fifth parameter will need to be set to 0xFFFF each time that
+    //the event "rolls over" on long duration events.
     pj_status_t status = pjmedia_rtp_encode_rtp(
             mSession,
             payloadType,

commit f32a2b7829c7442bbd0bfbfeec6c4c0511b00bc4
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Aug 9 18:48:50 2011 -0500

    Add logic to the telephony event source to allow for long duration
    events.

diff --git a/src/RTPTelephonyEventSource.cpp b/src/RTPTelephonyEventSource.cpp
index 3d4a4a1..fc08248 100644
--- a/src/RTPTelephonyEventSource.cpp
+++ b/src/RTPTelephonyEventSource.cpp
@@ -27,7 +27,7 @@ Logger lg = getLoggerFactory().getLogger("AsteriskSCF.MediaRTP");
 }
 
 RTPTelephonyEventSource::RTPTelephonyEventSource(pjmedia_rtp_session *session) 
-    : mSession(session), mOnEnd(false), mCachedEvent(255), mEventDuration(0)
+    : mSession(session), mOnEnd(false), mTimestamp(0)
 {
 }
 
@@ -61,7 +61,7 @@ TelephonyEventSourcePrx RTPTelephonyEventSource::getProxy()
     return mProxy;
 }
 
-void RTPTelephonyEventSource::read(const pjmedia_rtp_hdr*, const Ice::Byte* payload)
+void RTPTelephonyEventSource::read(const pjmedia_rtp_hdr* header, const Ice::Byte* payload)
 {
     //Even though this structure has "dtmf" in its name, it is used for
     //other RFC 4733 events, since they all have the same payload
@@ -76,41 +76,59 @@ void RTPTelephonyEventSource::read(const pjmedia_rtp_hdr*, const Ice::Byte* payl
     lg(Debug) << "This is " << (event->e_vol & 0x80 ? "" : "not ") << "an end";
 
     bool isEnd = (event->e_vol & 0x80);
+
     //We'll typically get three end frames. We don't need to send
     //multiple end events though, which is why we check to see if
     //we already are processing end frames.
     if (isEnd && !mOnEnd)
     {
-        sendEndEvent(event);
+        int duration = calculateDuration(header, event);
+        sendEndEvent(event, duration);
         mOnEnd = true;
-        mEventDuration = 0;
     }
     else if (!isEnd)
     {
-        //Either beginning or continuing.
-
-        //If we just processed an end, then it's clearly beginning
-        //a new event. Alternatively, we could have missed the end
-        //of the last event due to bad network conditions and now
-        //are getting the beginning of a new event.
-        if (mOnEnd || mCachedEvent != event->event)
+        //The m bit is set to indicate the beginning of a new
+        //event.
+        //
+        //XXX Do we need to add safeguards in the situation where
+        //this packet is lost?
+        if (header->m)
         {
             sendBeginEvent(event);
             mOnEnd = false;
-            mCachedEvent = event->event;
-            //Duration is expressed in timestamp units, i.e. samples.
-            //Since we want to express duration in milliseconds, we multiply
-            //by the number of milliseconds in a second and divide by the
-            //number of samples per second.
-            //
-            //XXX Is it safe to hardcode 8000 here?
-            //XXX Need to account for when duration rolls over (events greater than ~8 secs)
-            mEventDuration = (pj_ntohs(event->duration) * 1000) / 8000;
+            mTimestamp = pj_ntohl(header->ts);
+        }
+        else
+        {
+            //Continuation
+            int duration = calculateDuration(header, event);
+            sendContinuationEvent(event, duration);
         }
-        sendContinuationEvent(event);
     }
-    //The implied else here is an end that we already know about. No
-    //need to take further action.
+}
+
+int RTPTelephonyEventSource::calculateDuration(const pjmedia_rtp_hdr *header, const pjmedia_rtp_dtmf_event *event)
+{
+    //Duration is expressed in timestamp units, i.e. samples.
+    //Since we want to express duration in milliseconds, we multiply
+    //by the number of milliseconds in a second and divide by the
+    //number of samples per second.
+    int timestampMS = (pj_ntohs(event->duration) * 1000) / 8000;
+
+    //RFC 4733 specifies that if an event should last more than FFFF timestamp
+    //units then the sender is to send an event with duration FFFF. Then the RTP
+    //timestamp is updated to reflect a new "segment" for the event. From then
+    //on, the duration will reset and count back up to FFFF (without setting
+    //the m bit in the RTP header). This allows for durations longer than ~8 seconds
+    //to occur when using an 8000 Hz clock.
+    //
+    //By caching the original RTP timestamp at the beginning of the event, we
+    //can subtract the timestamp in the beginning packet from the timestamp in
+    //this one to determine the cumulative duration of the event.
+    int baseMS = ((pj_ntohl(header->ts) - mTimestamp) * 1000) / 8000;
+
+    return (baseMS + timestampMS);
 }
 
 void RTPTelephonyEventSource::sendBeginEvent(const pjmedia_rtp_dtmf_event *event)
@@ -124,26 +142,26 @@ void RTPTelephonyEventSource::sendBeginEvent(const pjmedia_rtp_dtmf_event *event
     }
 }
 
-void RTPTelephonyEventSource::sendContinuationEvent(const pjmedia_rtp_dtmf_event *event)
+void RTPTelephonyEventSource::sendContinuationEvent(const pjmedia_rtp_dtmf_event *event, int duration)
 {
     //DTMF
     if (event->event <= 15)
     {
         ContinueDTMFEventPtr dtmf(new ContinueDTMFEvent);
         dtmf->signal = translateDTMF(event->event);
-        dtmf->duration = mEventDuration;
+        dtmf->duration = duration;
         distributeToSinks(dtmf);
     }
 }
 
-void RTPTelephonyEventSource::sendEndEvent(const pjmedia_rtp_dtmf_event *event)
+void RTPTelephonyEventSource::sendEndEvent(const pjmedia_rtp_dtmf_event *event, int duration)
 {
     //DTMF
     if (event->event <= 15)
     {
         EndDTMFEventPtr dtmf(new EndDTMFEvent);
         dtmf->signal = translateDTMF(event->event);
-        dtmf->duration = mEventDuration;
+        dtmf->duration = duration;
         distributeToSinks(dtmf);
     }
     //Flash
diff --git a/src/RTPTelephonyEventSource.h b/src/RTPTelephonyEventSource.h
index 60946df..2013ec3 100644
--- a/src/RTPTelephonyEventSource.h
+++ b/src/RTPTelephonyEventSource.h
@@ -44,9 +44,11 @@ protected:
     ~RTPTelephonyEventSource();
 
 private:
+
+    int calculateDuration(const pjmedia_rtp_hdr *header, const pjmedia_rtp_dtmf_event *event);
     void sendBeginEvent(const pjmedia_rtp_dtmf_event *event);
-    void sendContinuationEvent(const pjmedia_rtp_dtmf_event *event);
-    void sendEndEvent(const pjmedia_rtp_dtmf_event *event);
+    void sendContinuationEvent(const pjmedia_rtp_dtmf_event *event, int duration);
+    void sendEndEvent(const pjmedia_rtp_dtmf_event *event, int duration);
     void distributeToSinks(const AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr& event);
     Ice::Byte translateDTMF(pj_uint8_t event);
 
@@ -60,16 +62,10 @@ private:
      */
     bool mOnEnd;
     /**
-     * Keep track of the last event we received. This way if we miss the end
-     * of an event, we can see if the new incoming event is actually a
-     * continuation of the previous event or if it is actually a new event.
-     */
-    pj_uint8_t mCachedEvent;
-    /**
-     * The duration of the event in milliseconds. We use the duration field
-     * of the event to keep a running total of the duration of the event.
+     * The timestamp of the RTP packet that begins an RFC 4733 event. We keep
+     * this handy for calculating the duration of long events.
      */
-    pj_uint32_t mEventDuration;
+    pj_uint32_t mTimestamp;
     /**
      * Sinks to send events to
      */

commit 1bf93e4bb3b668e45fb1d9227814efbce416a031
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Aug 9 17:44:58 2011 -0500

    Make sure to mod the duration in outgoing RFC4733 packets by 0xFFFF

diff --git a/src/RTPTelephonyEventSink.cpp b/src/RTPTelephonyEventSink.cpp
index 65d822c..0709e08 100644
--- a/src/RTPTelephonyEventSink.cpp
+++ b/src/RTPTelephonyEventSink.cpp
@@ -68,13 +68,13 @@ void RTPTelephonyEventSink::write_async(
     {
         payload.event = translateDTMF(endDTMF->signal);
         payload.e_vol = DTMFVolume;
-        payload.duration = pj_htons( (pj_uint16_t)((endDTMF->duration * 8000) / 1000));
+        payload.duration = pj_htons((pj_uint16_t)(((endDTMF->duration * 8000) / 1000) % 0xFFFF));
     }
     else if (continueDTMF = ContinueDTMFEventPtr::dynamicCast(event))
     {
         payload.event = translateDTMF(continueDTMF->signal);
         payload.e_vol = DTMFVolume | 0x80;
-        payload.duration = pj_htons( (pj_uint16_t)((continueDTMF->duration * 8000) / 1000));
+        payload.duration = pj_htons((pj_uint16_t)(((continueDTMF->duration * 8000) / 1000) % 0xFFFF));
     }
     else if (flash = FlashEventPtr::dynamicCast(event))
     {

commit 7abcf7e1c41b909a2aaf1a2c44be0baf1c3ada56
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Aug 9 17:06:47 2011 -0500

    Alter the constructors for RTP sinks and sources.
    
    This makes it much easier to manager adding and removing stuff from
    object adapters.

diff --git a/src/RTPSession.cpp b/src/RTPSession.cpp
index dc91507..95da958 100644
--- a/src/RTPSession.cpp
+++ b/src/RTPSession.cpp
@@ -35,6 +35,7 @@
 #include <AsteriskSCF/Media/RTP/MediaRTPIf.h>
 #include <AsteriskSCF/Media/RTP/MediaRTCPIf.h>
 #include <AsteriskSCF/System/Component/ReplicaIf.h>
+#include <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.h>
 
 using namespace std;
 using namespace AsteriskSCF::Core::Discovery::V1;
@@ -45,6 +46,7 @@ using namespace AsteriskSCF::Replication::MediaRTPPJMedia::V1;
 using namespace AsteriskSCF::System::Component::V1;
 using namespace AsteriskSCF::Discovery;
 using namespace AsteriskSCF::PJMediaRTP;
+using namespace AsteriskSCF::SessionCommunications::V1;
 
 /**
  * RTCP Information Interface implementation.
@@ -320,6 +322,9 @@ private:
      * RTCP information for Sender Report.
      */
     RTCPInformationImplPtr mSenderReport;
+
+    TelephonyEventSourcePrx mTelephonyEventSourcePrx;
+    TelephonyEventSinkPrx mTelephonyEventSinkPrx;
 };
 
 /**
@@ -586,6 +591,15 @@ void RTPSessionImpl::release(const Ice::Current&)
     mAdapter->remove(mStreamSourceProxy->ice_getIdentity());
     mAdapter->remove(mStreamSinkProxy->ice_getIdentity());
 
+    if (mTelephonyEventSourcePrx)
+    {
+        mAdapter->remove(mTelephonyEventSourcePrx->ice_getIdentity());
+    }
+    if (mTelephonyEventSinkPrx)
+    {
+        mAdapter->remove(mTelephonyEventSinkPrx->ice_getIdentity());
+    }
+
     /* Since the source and sink have a pointer back to the session we need to get rid of them,
      * which will in turn get rid of ourselves once we are removed from the ASM.
      */
@@ -885,16 +899,25 @@ RTPSessionPrx RTPSessionImpl::activate(
                 mTransport,
                 mId,
                 StreamSourceRTPPrx::uncheckedCast(mAdapter->createDirectProxy(sourceId)),
-                StreamSinkRTPPrx::uncheckedCast(mAdapter->createDirectProxy(sinkId)),
-                options,
-                outputs);
+                StreamSinkRTPPrx::uncheckedCast(mAdapter->createDirectProxy(sinkId)));
 
         mStreamSink = new StreamSinkRTPImpl(
                 mSessionAdapter,
                 mTransport,
-                mId,
-                options,
-                outputs);
+                mId);
+
+        if (options->handleTelephonyEvents)
+        {
+            outputs = new RTPAllocationOutputs();
+
+            mTelephonyEventSourcePrx =
+                mStreamSource->createTelephonyEventSource(mAdapter);
+            outputs->eventSources.push_back(mTelephonyEventSourcePrx);
+
+            mTelephonyEventSinkPrx =
+                mStreamSink->createTelephonyEventSink(mAdapter);
+            outputs->eventSinks.push_back(mTelephonyEventSinkPrx);
+        }
 
         mRtcpSessionInterface = new RTCPSessionImpl(this);
         mReceiverReport = new RTCPInformationImpl(&mRtcpSession.stat, &mRtcpSession.stat.rx);
diff --git a/src/RTPSink.cpp b/src/RTPSink.cpp
index df7b0ff..4932182 100644
--- a/src/RTPSink.cpp
+++ b/src/RTPSink.cpp
@@ -34,6 +34,7 @@ using namespace AsteriskSCF::Media::V1;
 using namespace AsteriskSCF::Media::RTP::V1;
 using namespace AsteriskSCF::PJMediaRTP;
 using namespace AsteriskSCF::Replication::MediaRTPPJMedia::V1;
+using namespace AsteriskSCF::SessionCommunications::V1;
 
 /**
  * Private implementation details for the StreamSinkRTPImpl class.
@@ -47,9 +48,7 @@ public:
     StreamSinkRTPImplPriv(
             const SessionAdapterPtr& sessionAdapter, 
             const PJMediaTransportPtr& transport,
-            const std::string&,
-            const RTPOptionsPtr& options,
-            RTPAllocationOutputsPtr& outputs);
+            const std::string&);
 
     /**
      * A structure containing outgoing pjmedia session data.
@@ -85,9 +84,7 @@ public:
 StreamSinkRTPImplPriv::StreamSinkRTPImplPriv(
         const SessionAdapterPtr& session, 
         const PJMediaTransportPtr& transport,
-        const string& sessionId,
-        const RTPOptionsPtr& options,
-        RTPAllocationOutputsPtr& /*outputs*/) :
+        const string& sessionId) :
     mSessionAdapter(session), mTransport(transport), 
     mSinkStateItem(new RtpStreamSinkStateItem), 
     mSessionId(sessionId)
@@ -96,11 +93,6 @@ StreamSinkRTPImplPriv::StreamSinkRTPImplPriv(
     mSinkStateItem->sessionId = sessionId;
     mSinkStateItem->key = IceUtil::generateUUID();
     mSinkStateItem->remotePort = 0;
-
-    if (options->handleTelephonyEvents)
-    {
-        mTelephonyEventSink = new RTPTelephonyEventSink(&mOutgoingSession, mTransport, mSessionAdapter);
-    }
 };
 
 /**
@@ -109,13 +101,22 @@ StreamSinkRTPImplPriv::StreamSinkRTPImplPriv(
 StreamSinkRTPImpl::StreamSinkRTPImpl(
         const SessionAdapterPtr& session,
         const PJMediaTransportPtr& transport,
-        const string& sessionId,
-        const RTPOptionsPtr& options,
-        RTPAllocationOutputsPtr& outputs) :
-    mImpl(new StreamSinkRTPImplPriv(session, transport, sessionId, options, outputs))
+        const string& sessionId) :
+    mImpl(new StreamSinkRTPImplPriv(session, transport, sessionId))
 {
 }
 
+TelephonyEventSinkPrx StreamSinkRTPImpl::createTelephonyEventSink(Ice::ObjectAdapterPtr& adapter)
+{
+    mImpl->mTelephonyEventSink =
+        new RTPTelephonyEventSink(
+            &mImpl->mOutgoingSession,
+            mImpl->mTransport,
+            mImpl->mSessionAdapter);
+
+    return TelephonyEventSinkPrx::uncheckedCast(adapter->addWithUUID(mImpl->mTelephonyEventSink));
+}
+
 /**
  * Implementation of the write method as defined in MediaIf.ice
  */
diff --git a/src/RTPSink.h b/src/RTPSink.h
index 0b87b77..a40738c 100644
--- a/src/RTPSink.h
+++ b/src/RTPSink.h
@@ -12,6 +12,8 @@
 #include "SessionAdapter.h"
 #include <boost/shared_ptr.hpp>
 #include <IceUtil/Handle.h>
+//Needed for TelephonySink
+#include <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.h>
 
 /**
  * Forward definition for our private implementation of StreamSinkRTP.
@@ -27,9 +29,7 @@ public:
     StreamSinkRTPImpl(
             const AsteriskSCF::PJMediaRTP::SessionAdapterPtr& sessionAdapter, 
             const AsteriskSCF::PJMediaRTP::PJMediaTransportPtr& transport, 
-            const std::string& sessionId,
-            const AsteriskSCF::Media::RTP::V1::RTPOptionsPtr& options,
-            AsteriskSCF::Media::RTP::V1::RTPAllocationOutputsPtr& outputs);
+            const std::string& sessionId);
 
     /**
      * AsteriskSCF::Media::RTP::V1::StreamSinkRTP implementation.
@@ -43,6 +43,7 @@ public:
     std::string getRemoteAddress(const Ice::Current&);
     Ice::Int getRemotePort(const Ice::Current&);
 
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx createTelephonyEventSink(Ice::ObjectAdapterPtr& adapter);
     /**
      * Internal implementation methods.
      */
diff --git a/src/RTPSource.cpp b/src/RTPSource.cpp
index e3fc845..c12d023 100644
--- a/src/RTPSource.cpp
+++ b/src/RTPSource.cpp
@@ -43,6 +43,7 @@ using namespace AsteriskSCF::Replication::MediaRTPPJMedia::V1;
 using namespace AsteriskSCF::System::Logging;
 using namespace AsteriskSCF::PJMediaRTP;
 using namespace AsteriskSCF::Media::Formats::Other::V1;
+using namespace AsteriskSCF::SessionCommunications::V1;
 
 namespace
 {
@@ -119,9 +120,7 @@ public:
                             const PJMediaTransportPtr& transport,
                             const string& parentSessionId,
                             const StreamSourceRTPPrx& source,
-                            const StreamSinkRTPPrx& sink,
-                            const RTPOptionsPtr& options,
-                            RTPAllocationOutputsPtr& outputs
+                            const StreamSinkRTPPrx& sink
         );
 
     /**
@@ -183,9 +182,7 @@ StreamSourceRTPImplPriv::StreamSourceRTPImplPriv(const SessionAdapterPtr& sessio
                                                  const PJMediaTransportPtr& transport, 
                                                  const string& sessionId,
                                                  const StreamSourceRTPPrx& source,
-                                                 const StreamSinkRTPPrx& sink,
-                                                 const RTPOptionsPtr& options,
-                                                 RTPAllocationOutputsPtr& /*outputs*/) :
+                                                 const StreamSinkRTPPrx& sink) :
     mSessionAdapter(session), mTransport(transport), 
     mSourceStateItem(new RtpStreamSourceStateItem), 
     mSessionId(sessionId),
@@ -195,11 +192,6 @@ StreamSourceRTPImplPriv::StreamSourceRTPImplPriv(const SessionAdapterPtr& sessio
     pjmedia_rtp_session_init(&mIncomingSession, 0, 0);
     mSourceStateItem->sessionId = sessionId;
     mSourceStateItem->key = IceUtil::generateUUID();
-
-    if (options->handleTelephonyEvents)
-    {
-        mTelephonyEventSource = new RTPTelephonyEventSource(&mIncomingSession);
-    }
 }
 
 /**
@@ -220,13 +212,18 @@ StreamSourceRTPImplPriv::~StreamSourceRTPImplPriv()
 StreamSourceRTPImpl::StreamSourceRTPImpl(const SessionAdapterPtr& session,
                                          const PJMediaTransportPtr& transport, const string& sessionId,
                                          const StreamSourceRTPPrx& source,
-                                         const StreamSinkRTPPrx& sink,
-                                         const RTPOptionsPtr& options,
-                                         RTPAllocationOutputsPtr& outputs) :
-    mImpl(new StreamSourceRTPImplPriv(session, transport, sessionId, source, sink, options, outputs))
+                                         const StreamSinkRTPPrx& sink) :
+    mImpl(new StreamSourceRTPImplPriv(session, transport, sessionId, source, sink))
 {
 }
 
+TelephonyEventSourcePrx StreamSourceRTPImpl::createTelephonyEventSource(Ice::ObjectAdapterPtr& adapter)
+{
+    mImpl->mTelephonyEventSource = new RTPTelephonyEventSource(&mImpl->mIncomingSession);
+
+    return TelephonyEventSourcePrx::uncheckedCast(adapter->addWithUUID(mImpl->mTelephonyEventSource));
+}
+
 /**
  * Implementation of the addSink method as defined in MediaIf.ice
  */
diff --git a/src/RTPSource.h b/src/RTPSource.h
index ab3f38c..a69e722 100644
--- a/src/RTPSource.h
+++ b/src/RTPSource.h
@@ -12,6 +12,8 @@
 #include "SessionAdapter.h"
 #include <boost/shared_ptr.hpp>
 #include <IceUtil/Handle.h>
+//Needed for TelephonySource 
+#include <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.h>
 
 /**
  * Forward definition for our private implementation of StreamSourceRTP.
@@ -28,9 +30,7 @@ public:
                         const AsteriskSCF::PJMediaRTP::PJMediaTransportPtr& transport,
                         const std::string& parentSessionId,
                         const AsteriskSCF::Media::RTP::V1::StreamSourceRTPPrx& source,
-                        const AsteriskSCF::Media::RTP::V1::StreamSinkRTPPrx& sink,
-                        const AsteriskSCF::Media::RTP::V1::RTPOptionsPtr& options,
-                        AsteriskSCF::Media::RTP::V1::RTPAllocationOutputsPtr& outputs);
+                        const AsteriskSCF::Media::RTP::V1::StreamSinkRTPPrx& sink);
 
     void addSink(const AsteriskSCF::Media::V1::StreamSinkPrx&, const Ice::Current&);
     void removeSink(const AsteriskSCF::Media::V1::StreamSinkPrx&, const Ice::Current&);
@@ -49,6 +49,8 @@ public:
 
     void setSinkImpl(const AsteriskSCF::Media::V1::StreamSinkPrx& proxy);
 
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx createTelephonyEventSource(Ice::ObjectAdapterPtr& adapter);
+
     /**
      * Private implementation data for StreamSourceRTPImpl.
      * Note: This is public on purpose so that our RTP callback can access it.

commit 851ca93f58b1fab9a0e6349852a016bae9a76374
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Aug 9 15:03:19 2011 -0500

    Fix timestamp calculation when encoding RFC 4733 events.

diff --git a/src/RTPTelephonyEventSink.cpp b/src/RTPTelephonyEventSink.cpp
index 8b4b331..65d822c 100644
--- a/src/RTPTelephonyEventSink.cpp
+++ b/src/RTPTelephonyEventSink.cpp
@@ -92,12 +92,14 @@ void RTPTelephonyEventSink::write_async(
     //a new one on every write.
     payloadType = mSessionAdapter->getPayload(new AsteriskSCF::Media::Formats::Other::V1::RFC4733());
 
+    //The fifth parameter is set to 0 here since the RTP timestamp is the same
+    //for all packets sent during an event.
     pj_status_t status = pjmedia_rtp_encode_rtp(
             mSession,
             payloadType,
             sizeof(payload),
             setMarker ? 1 : 0,
-            payload.duration,
+            0,
             &header,
             &header_len);
 

commit b6db1d069bcf3013327d8adee49e7b4d8a1d6c0a
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Aug 9 14:39:09 2011 -0500

    Send RTP frames for telephony events.

diff --git a/src/RTPSink.cpp b/src/RTPSink.cpp
index 1c69ea5..df7b0ff 100644
--- a/src/RTPSink.cpp
+++ b/src/RTPSink.cpp
@@ -99,7 +99,7 @@ StreamSinkRTPImplPriv::StreamSinkRTPImplPriv(
 
     if (options->handleTelephonyEvents)
     {
-        mTelephonyEventSink = new RTPTelephonyEventSink(&mOutgoingSession);
+        mTelephonyEventSink = new RTPTelephonyEventSink(&mOutgoingSession, mTransport, mSessionAdapter);
     }
 };
 
diff --git a/src/RTPTelephonyEventSink.cpp b/src/RTPTelephonyEventSink.cpp
index 653872c..8b4b331 100644
--- a/src/RTPTelephonyEventSink.cpp
+++ b/src/RTPTelephonyEventSink.cpp
@@ -16,9 +16,16 @@
 
 #include "RTPTelephonyEventSink.h"
 
+#include <AsteriskSCF/Media/Formats/OtherFormats.h>
+
 namespace
 {
+// The volume of DTMF tones is something
+// that could be made configurable. For now
+// we're just going with a hard-coded value
+// since it's not especially important.
 const pj_uint8_t DTMFVolume = 15;
+
 //Duration is used either for events where
 //duration isn't really a factor (like for
 //flash) or where we cannot determined a satisfactory
@@ -30,9 +37,13 @@ const pj_uint16_t Duration = 160;
 } // end anonymous namespace
 
 using namespace AsteriskSCF::SessionCommunications::V1;
+using namespace AsteriskSCF::PJMediaRTP;
 
-RTPTelephonyEventSink::RTPTelephonyEventSink(pjmedia_rtp_session *session)
-    :mSession(session) { }
+RTPTelephonyEventSink::RTPTelephonyEventSink(
+        pjmedia_rtp_session *session,
+        const PJMediaTransportPtr& transport,
+        const SessionAdapterPtr& sessionAdapter)
+    : mSession(session), mTransport(transport), mSessionAdapter(sessionAdapter) { }
 
 void RTPTelephonyEventSink::write_async(
         const AMD_TelephonyEventSink_writePtr& cb,
@@ -43,42 +54,79 @@ void RTPTelephonyEventSink::write_async(
     EndDTMFEventPtr endDTMF;
     ContinueDTMFEventPtr continueDTMF;
     FlashEventPtr flash;
+    
+    pjmedia_rtp_dtmf_event payload;
+    bool setMarker = false;
     if ((beginDTMF = BeginDTMFEventPtr::dynamicCast(event)))
     {
-        pjmedia_rtp_dtmf_event payload;
         payload.event = translateDTMF(beginDTMF->signal);
         payload.e_vol = DTMFVolume;
         payload.duration = Duration;
+        setMarker = true;
     }
     else if (endDTMF = EndDTMFEventPtr::dynamicCast(event))
     {
-        pjmedia_rtp_dtmf_event payload;
         payload.event = translateDTMF(endDTMF->signal);
         payload.e_vol = DTMFVolume;
         payload.duration = pj_htons( (pj_uint16_t)((endDTMF->duration * 8000) / 1000));
     }
     else if (continueDTMF = ContinueDTMFEventPtr::dynamicCast(event))
     {
-        pjmedia_rtp_dtmf_event payload;
         payload.event = translateDTMF(continueDTMF->signal);
-        payload.e_vol = DTMFVolume;
+        payload.e_vol = DTMFVolume | 0x80;
         payload.duration = pj_htons( (pj_uint16_t)((continueDTMF->duration * 8000) / 1000));
     }
     else if (flash = FlashEventPtr::dynamicCast(event))
     {
-        pjmedia_rtp_dtmf_event payload;
         payload.event = 16;
         payload.e_vol = DTMFVolume;
         payload.duration = Duration;
+        setMarker = true;
+    }
+
+    const void *header;
+    int header_len;
+    int payloadType;
+
+    //XXX We could probably just cache this pointer so we don't have to create
+    //a new one on every write.
+    payloadType = mSessionAdapter->getPayload(new AsteriskSCF::Media::Formats::Other::V1::RFC4733());
+
+    pj_status_t status = pjmedia_rtp_encode_rtp(
+            mSession,
+            payloadType,
+            sizeof(payload),
+            setMarker ? 1 : 0,
+            payload.duration,
+            &header,
+            &header_len);
+
+    if (status != PJ_SUCCESS)
+    {
+        //fffffffuuuuuuuuuuuu
+    }
+
+    char packet[1500];
+
+    pj_memcpy(packet, (const pjmedia_rtp_hdr*)header, header_len);
+    pj_memcpy(packet + header_len, &payload, sizeof(payload));
+
+    status = pjmedia_transport_send_rtp(mTransport->getTransport(), packet, sizeof(payload) + header_len);
+
+    if (status != PJ_SUCCESS)
+    {
+        //fffffffuuuuuuuuuuuu
     }
+
     cb->ice_response();
 }
 
 void RTPTelephonyEventSink::setSource_async(
         const AMD_TelephonyEventSink_setSourcePtr& cb,
-        const TelephonyEventSourcePrx&,
+        const TelephonyEventSourcePrx& source,
         const Ice::Current&)
 {
+    mSource = source;
     cb->ice_response();
 }
 
diff --git a/src/RTPTelephonyEventSink.h b/src/RTPTelephonyEventSink.h
index 1d299f8..95c0f70 100644
--- a/src/RTPTelephonyEventSink.h
+++ b/src/RTPTelephonyEventSink.h
@@ -16,15 +16,20 @@
 
 #pragma once
 
+#include <pjmedia.h>
 #include <AsteriskSCF/SessionCommunications/TelephonyEventsIf.h>
 
-#include <pjmedia.h>
+#include "PJMediaTransport.h"
+#include "SessionAdapter.h"
 
 class RTPTelephonyEventSink : public AsteriskSCF::SessionCommunications::V1::TelephonyEventSink
 {
 public:
 
-    RTPTelephonyEventSink(pjmedia_rtp_session *session);
+    RTPTelephonyEventSink(
+            pjmedia_rtp_session *session,
+            const AsteriskSCF::PJMediaRTP::PJMediaTransportPtr& transport,
+            const AsteriskSCF::PJMediaRTP::SessionAdapterPtr& sessionAdapter);
 
     void write_async(
             const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_writePtr&,
@@ -44,6 +49,8 @@ private:
     pj_uint8_t translateDTMF(Ice::Byte signal);
 
     pjmedia_rtp_session *mSession;
+    AsteriskSCF::PJMediaRTP::PJMediaTransportPtr mTransport;
+    AsteriskSCF::PJMediaRTP::SessionAdapterPtr mSessionAdapter;
     AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx mSource;
 };
 

commit fa8e68b106cd0c1b6f49733764c0c29f6d728387
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Aug 9 11:30:01 2011 -0500

    Populate pjmedia_rtp_dtmf_event payloads in the sink.
    
    The next step is to actually start encoding and sending...

diff --git a/src/RTPSink.cpp b/src/RTPSink.cpp
index 3379cb4..1c69ea5 100644
--- a/src/RTPSink.cpp
+++ b/src/RTPSink.cpp
@@ -99,7 +99,7 @@ StreamSinkRTPImplPriv::StreamSinkRTPImplPriv(
 
     if (options->handleTelephonyEvents)
     {
-        mTelephonyEventSink = new RTPTelephonyEventSink();
+        mTelephonyEventSink = new RTPTelephonyEventSink(&mOutgoingSession);
     }
 };
 
diff --git a/src/RTPTelephonyEventSink.cpp b/src/RTPTelephonyEventSink.cpp
index 7246e52..653872c 100644
--- a/src/RTPTelephonyEventSink.cpp
+++ b/src/RTPTelephonyEventSink.cpp
@@ -16,8 +16,24 @@
 
 #include "RTPTelephonyEventSink.h"
 
+namespace
+{
+const pj_uint8_t DTMFVolume = 15;
+//Duration is used either for events where
+//duration isn't really a factor (like for
+//flash) or where we cannot determined a satisfactory
+//duration.
+//
+//This is derived from an 8000 Hz clock rate at
+//20 ms packetization.
+const pj_uint16_t Duration = 160;
+} // end anonymous namespace
+
 using namespace AsteriskSCF::SessionCommunications::V1;
 
+RTPTelephonyEventSink::RTPTelephonyEventSink(pjmedia_rtp_session *session)
+    :mSession(session) { }
+
 void RTPTelephonyEventSink::write_async(
         const AMD_TelephonyEventSink_writePtr& cb,
         const TelephonyEventPtr& event,
@@ -29,15 +45,31 @@ void RTPTelephonyEventSink::write_async(
     FlashEventPtr flash;
     if ((beginDTMF = BeginDTMFEventPtr::dynamicCast(event)))
     {
+        pjmedia_rtp_dtmf_event payload;
+        payload.event = translateDTMF(beginDTMF->signal);
+        payload.e_vol = DTMFVolume;
+        payload.duration = Duration;
     }
     else if (endDTMF = EndDTMFEventPtr::dynamicCast(event))
     {
+        pjmedia_rtp_dtmf_event payload;
+        payload.event = translateDTMF(endDTMF->signal);
+        payload.e_vol = DTMFVolume;
+        payload.duration = pj_htons( (pj_uint16_t)((endDTMF->duration * 8000) / 1000));
     }
     else if (continueDTMF = ContinueDTMFEventPtr::dynamicCast(event))
     {
+        pjmedia_rtp_dtmf_event payload;
+        payload.event = translateDTMF(continueDTMF->signal);
+        payload.e_vol = DTMFVolume;
+        payload.duration = pj_htons( (pj_uint16_t)((continueDTMF->duration * 8000) / 1000));
     }
     else if (flash = FlashEventPtr::dynamicCast(event))
     {
+        pjmedia_rtp_dtmf_event payload;
+        payload.event = 16;
+        payload.e_vol = DTMFVolume;
+        payload.duration = Duration;
     }
     cb->ice_response();
 }
@@ -57,3 +89,27 @@ void RTPTelephonyEventSink::getSource_async(
     cb->ice_response(mSource);
 }
 
+pj_uint8_t RTPTelephonyEventSink::translateDTMF(Ice::Byte signal)
+{
+    if (signal >= '0' && signal <= '9')
+    {
+        return (pj_uint8_t) (signal - '0');
+    }
+    else if (signal == '*')
+    {
+        return 10;
+    }
+    else if (signal == '#')
+    {
+        return 11;
+    }
+    else if (signal >= 'A' && signal <= 'D')
+    {
+        return (pj_uint8_t) ((signal - 'A') + 12);
+    }
+    else
+    {
+        //uhhhhhhhh
+        return 255;
+    }
+}
diff --git a/src/RTPTelephonyEventSink.h b/src/RTPTelephonyEventSink.h
index 7e1a160..1d299f8 100644
--- a/src/RTPTelephonyEventSink.h
+++ b/src/RTPTelephonyEventSink.h
@@ -18,10 +18,14 @@
 
 #include <AsteriskSCF/SessionCommunications/TelephonyEventsIf.h>
 
+#include <pjmedia.h>
+
 class RTPTelephonyEventSink : public AsteriskSCF::SessionCommunications::V1::TelephonyEventSink
 {
-
 public:
+
+    RTPTelephonyEventSink(pjmedia_rtp_session *session);
+
     void write_async(
             const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_writePtr&,
             const AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr&,
@@ -36,6 +40,10 @@ public:
             const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_getSourcePtr&,
             const Ice::Current&);
 private:
+
+    pj_uint8_t translateDTMF(Ice::Byte signal);
+
+    pjmedia_rtp_session *mSession;
     AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx mSource;
 };
 
diff --git a/src/RTPTelephonyEventSource.h b/src/RTPTelephonyEventSource.h
index a1361ee..60946df 100644
--- a/src/RTPTelephonyEventSource.h
+++ b/src/RTPTelephonyEventSource.h
@@ -20,7 +20,7 @@
 
 #include <AsteriskSCF/SessionCommunications/TelephonyEventsIf.h>
 
-#include "pjmedia.h"
+#include <pjmedia.h>
 
 class RTPTelephonyEventSource : public AsteriskSCF::SessionCommunications::V1::TelephonyEventSource
 {

commit c62a7f5070867013ae428a3c9af2c83f6840a716
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Aug 9 09:50:39 2011 -0500

    Remove seqno check since this is already done by pjmedia.
    
    Thanks, Joshua!!

diff --git a/src/RTPTelephonyEventSource.cpp b/src/RTPTelephonyEventSource.cpp
index 478db39..3d4a4a1 100644
--- a/src/RTPTelephonyEventSource.cpp
+++ b/src/RTPTelephonyEventSource.cpp
@@ -27,7 +27,7 @@ Logger lg = getLoggerFactory().getLogger("AsteriskSCF.MediaRTP");
 }
 
 RTPTelephonyEventSource::RTPTelephonyEventSource(pjmedia_rtp_session *session) 
-    : mSession(session), mOnEnd(false), mCachedEvent(255), mLastSeqno(0), mEventDuration(0)
+    : mSession(session), mOnEnd(false), mCachedEvent(255), mEventDuration(0)
 {
 }
 
@@ -61,15 +61,8 @@ TelephonyEventSourcePrx RTPTelephonyEventSource::getProxy()
     return mProxy;
 }
 
-void RTPTelephonyEventSource::read(const pjmedia_rtp_hdr *header, const Ice::Byte* payload)
+void RTPTelephonyEventSource::read(const pjmedia_rtp_hdr*, const Ice::Byte* payload)
 {
-    if (header->seq < mLastSeqno && mLastSeqno - header->seq < 50)
-    {
-        //Out of order packet. Don't process it.
-        return;
-    }
-    mLastSeqno = header->seq;
-
     //Even though this structure has "dtmf" in its name, it is used for
     //other RFC 4733 events, since they all have the same payload
     //structure.
diff --git a/src/RTPTelephonyEventSource.h b/src/RTPTelephonyEventSource.h
index 4878b57..a1361ee 100644
--- a/src/RTPTelephonyEventSource.h
+++ b/src/RTPTelephonyEventSource.h
@@ -66,13 +66,6 @@ private:
      */
     pj_uint8_t mCachedEvent;
     /**
-     * We keep track of the sequence number of the previous event we received
-     * so we can detect out of order frames. If we do not ensure the integrity
-     * of the sequence number, it is possible under odd circumstances to
-     * improperly report duplicate events.
-     */
-    pj_uint16_t mLastSeqno;
-    /**
      * The duration of the event in milliseconds. We use the duration field
      * of the event to keep a running total of the duration of the event.
      */

-----------------------------------------------------------------------


-- 
asterisk-scf/integration/media_rtp_pjmedia.git



More information about the asterisk-scf-commits mailing list