[asterisk-scf-commits] asterisk-scf/integration/media_rtp_pjmedia.git branch "rtcp" created.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Mon Jul 11 15:20:21 CDT 2011


branch "rtcp" has been created
        at  7959b9db758e935ed9f8152a582dac39a2e15df2 (commit)

- Log -----------------------------------------------------------------
commit 7959b9db758e935ed9f8152a582dac39a2e15df2
Author: Joshua Colp <jcolp at digium.com>
Date:   Mon Jul 11 17:20:57 2011 -0300

    Add current progress on RTCP support.

diff --git a/src/RTPSession.cpp b/src/RTPSession.cpp
index b3ae801..942a0c7 100644
--- a/src/RTPSession.cpp
+++ b/src/RTPSession.cpp
@@ -19,9 +19,11 @@
 
 #include <Ice/Ice.h>
 #include <IceUtil/UUID.h>
+#include <IceUtil/Timer.h>
 
 #include <AsteriskSCF/Media/MediaIf.h>
 #include <AsteriskSCF/Media/RTP/MediaRTPIf.h>
+#include <AsteriskSCF/Media/RTP/MediaRTCPIf.h>
 #include <AsteriskSCF/System/Component/ReplicaIf.h>
 
 #include "RtpStateReplicationIf.h"
@@ -36,6 +38,7 @@ using namespace std;
 using namespace AsteriskSCF::Core::Discovery::V1;
 using namespace AsteriskSCF::Media::V1;
 using namespace AsteriskSCF::Media::RTP::V1;
+using namespace AsteriskSCF::Media;
 using namespace AsteriskSCF::Replication::MediaRTPPJMedia::V1;
 using namespace AsteriskSCF::System::Component::V1;
 using namespace AsteriskSCF::Discovery;
@@ -51,6 +54,69 @@ using namespace AsteriskSCF::Discovery;
 #define DEFAULT_RTP_PORT_MAXIMUM 20000
 
 /**
+ * TimerTask implementation which sends RTCP at a defined interval.
+ */
+class RtcpTransmission : public IceUtil::TimerTask
+{
+public:
+    RtcpTransmission(const RTPSessionImplPtr& session) : mSession(session) { }
+
+    void runTimerTask()
+    {
+        void *packet;
+        int packet_size;
+
+        pjmedia_rtcp_build_rtcp(mSession->getRtcpSession(), &packet, &packet_size);
+        pjmedia_transport_send_rtcp(mSession->getTransport(), packet, packet_size);
+    }
+
+private:
+    /**
+     * A pointer to the RTP session we are associated with.
+     */
+    RTPSessionImplPtr mSession;
+};
+
+/**
+ * Smart pointer for the above RtcpTransmission class.
+ */
+typedef IceUtil::Handle<RtcpTransmission> RtcpTransmissionPtr;
+
+/**
+ * RTCP Information Interface implementation.
+ */
+class RTCPInformationImpl : public RTCP::V1::Information
+{
+public:
+    RTCPInformationImpl(pjmedia_rtcp_stat *general, pjmedia_rtcp_stream_stat *stream) :
+	mGeneralStatistics(general), mStreamStatistics(stream) { }
+
+private:
+    /**
+     * Lock to protect the listeners.
+     */
+
+    /**
+     * Listeners present.
+     */
+
+    /**
+     * Structure where general RTCP information is.
+     */
+    pjmedia_rtcp_stat *mGeneralStatistics;
+
+    /**
+     * Structure where stream RTCP information is.
+     */
+    pjmedia_rtcp_stream_stat *mStreamStatistics;
+};
+
+/**
+ * Smart pointer for the above RTCPInformationImpl class.
+ */
+typedef IceUtil::Handle<RTCPInformationImpl> RTCPInformationImplPtr;
+
+/**
  * Private implementation details for the RTPSessionImpl class.
  */
 class RTPSessionImplPriv
@@ -128,6 +194,54 @@ public:
      * A proxy to the state replicator where we are sending updates to.
      */
     AsteriskSCF::Discovery::SmartProxy<RtpStateReplicatorPrx> mStateReplicator;
+
+    /**
+     * RTCP session for this RTP session.
+     */
+    pjmedia_rtcp_session mRtcpSession;
+
+    /**
+     * A pointer to the RTCP session interface.
+     */
+    RTCP::V1::RTCPSessionPtr mRtcpSessionInterface;
+};
+
+/**
+ * Implementation of the RTCPSession interface as defined in MediaRTCPIf.ice
+ */
+class RTCPSessionImpl : public RTCP::V1::RTCPSession
+{
+public:
+    /**
+     * Constructor for this implementation.
+     */
+    RTCPSessionImpl(const RTPSessionImplPtr& rtpSession) : mRtpSession(rtpSession) { }
+
+    /**
+     * Method used to retrieve the port our RTCP session is listening on.
+     */
+    int getLocalPort(const Ice::Current&)
+    {
+        pjmedia_transport_info transportInfo;
+
+        pjmedia_transport_info_init(&transportInfo);
+        pjmedia_transport_get_info(mRtpSession->getTransport(), &transportInfo);
+
+        return pj_sockaddr_get_port(&transportInfo.sock_info.rtcp_addr_name);
+    }
+
+    /**
+     * Method used to set the port to send RTCP packets to.
+     */
+    void setRemotePort(Ice::Int port, const Ice::Current&)
+    {
+    }
+
+private:
+    /**
+     * Pointer to the RTP session.
+     */
+    RTPSessionImplPtr mRtpSession;
 };
 
 /**
@@ -181,6 +295,8 @@ RTPSessionImpl::RTPSessionImpl(const Ice::ObjectAdapterPtr& adapter, const RTPSe
     mImpl->mSessionStateItem->mFormats = params->formats;
     mImpl->mSessionStateItem->mIPv6 = params->ipv6;
 
+    // TODO Initialize the RTCP session with some default settings
+
     /* First up for our own stuff is... a source! Media needs to come from somewhere, you know. */
     mImpl->mStreamSource = new StreamSourceRTPImpl(this, mImpl->mSessionStateItem->key);
     mImpl->mStreamSourceProxy = StreamSourceRTPPrx::uncheckedCast(mImpl->mAdapter->addWithUUID(mImpl->mStreamSource));
@@ -191,6 +307,10 @@ RTPSessionImpl::RTPSessionImpl(const Ice::ObjectAdapterPtr& adapter, const RTPSe
     mImpl->mStreamSinkProxy = StreamSinkRTPPrx::uncheckedCast(mImpl->mAdapter->addWithUUID(mImpl->mStreamSink));
     mImpl->mSessionStateItem->mSinkIdentity = mImpl->mStreamSinkProxy->ice_getIdentity();
 
+    // Create an RTCP session for interaction from the outside
+    mImpl->mRtcpSessionInterface = new RTCPSessionImpl(this);
+    mImpl->mAdapter->addFacet(mImpl->mRtcpSessionInterface, mImpl->mProxy->ice_getIdentity(), RTCP::V1::SessionFacet);
+
     // Since everything has just come into creation send one big update with all state items
     replicateState(mImpl->mSessionStateItem, mImpl->mStreamSink->getStateItem(), mImpl->mStreamSource->getStateItem());
 }
@@ -290,11 +410,11 @@ void RTPSessionImpl::release(const Ice::Current&)
     // Remove everything from the state replicator if present
     removeState(mImpl->mSessionStateItem, mImpl->mStreamSink->getStateItem(), mImpl->mStreamSource->getStateItem());
 
-    /* Drop the source and sink from the ASM */
+    /* Drop the source, sink, and RTCP session from the ASM */
     mImpl->mAdapter->remove(mImpl->mStreamSourceProxy->ice_getIdentity());
     mImpl->mAdapter->remove(mImpl->mStreamSinkProxy->ice_getIdentity());
 
-    /* Since both the source and sink have a pointer back to the session we need to get rid of them,
+    /* 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.
      */
     mImpl->mStreamSource = 0;
@@ -343,6 +463,16 @@ pjmedia_transport* RTPSessionImpl::getTransport()
 }
 
 /**
+ * API call which returns the RTCP session used for this RTP session.
+ *
+ * @return A pointer to the RTCP session.
+ */
+pjmedia_rtcp_session* RTPSessionImpl::getRtcpSession()
+{
+    return &mImpl->mRtcpSession;
+}
+
+/**
  * API call which returns the formats the RTP session is expected to carry.
  *
  * @return A sequence of media formats.
diff --git a/src/RTPSession.h b/src/RTPSession.h
index 802d942..8dca6fd 100644
--- a/src/RTPSession.h
+++ b/src/RTPSession.h
@@ -57,6 +57,7 @@ public:
     void release(const Ice::Current&);
     AsteriskSCF::Media::RTP::V1::RTPSessionPrx getProxy();
     pjmedia_transport* getTransport();
+    pjmedia_rtcp_session* getRtcpSession();
     AsteriskSCF::Media::V1::FormatSeq getFormats();
     void associatePayloads(const AsteriskSCF::Media::RTP::V1::PayloadMap&, const Ice::Current&);
     void setRemoteDetails(const std::string& address, Ice::Int port);
diff --git a/src/RTPSink.cpp b/src/RTPSink.cpp
index 7c65568..d996cc3 100644
--- a/src/RTPSink.cpp
+++ b/src/RTPSink.cpp
@@ -142,6 +142,9 @@ void StreamSinkRTPImpl::write(const AsteriskSCF::Media::V1::FrameSeq& frames, co
             /* TODO: Transmission failed... what to do? */
             continue;
         }
+
+	// Update RTCP information
+	pjmedia_rtcp_tx_rtp(mImpl->mSession->getRtcpSession(), (*frame)->payload.size());
     }
 }
 
diff --git a/src/RTPSource.cpp b/src/RTPSource.cpp
index c7c9c58..049950c 100644
--- a/src/RTPSource.cpp
+++ b/src/RTPSource.cpp
@@ -213,7 +213,12 @@ static void receiveRTP(void *userdata, void *packet, pj_ssize_t size)
     }
 
     // Update RTP stack information before writing to sinks, it's fine to do it
-    pjmedia_rtp_session_update(&source->mImpl->mIncomingSession, header, NULL);
+    pjmedia_rtp_status rtpStatus;
+    pjmedia_rtp_session_update2(&source->mImpl->mIncomingSession, header, &rtpStatus, PJ_FALSE);
+
+    // Update RTCP information
+    pjmedia_rtcp_rx_rtp2(source->mImpl->mSession->getRtcpSession(), pj_ntohs(header->seq), pj_ntohl(header->ts),
+                         payload_size, (rtpStatus.status.flag.bad || !payload_size) ? PJ_TRUE : PJ_FALSE);
 
     if (source->mImpl->mSourceStateItem->mSinks.empty())
     {
@@ -284,6 +289,23 @@ static void receiveRTP(void *userdata, void *packet, pj_ssize_t size)
 }
 
 /**
+ * Function which is called when RTCP is received.
+ */
+static void receiveRTCP(void *userdata, void *packet, pj_ssize_t size)
+{
+    StreamSourceRTPImpl* source = static_cast<StreamSourceRTPImpl*>(userdata);
+
+    /* Ensure that no errors occurred when reading this packet in */
+    if (size < 0)
+    {
+        lg(Error) << "We attempted to read data from an RTCP session but failed.";
+        return;
+    }
+
+    pjmedia_rtcp_rx_rtcp(source->mImpl->mSession->getRtcpSession(), packet, size);
+}
+
+/**
  * API call which sets up our pjmedia transport and allows media to be sent and received.
  */
 void StreamSourceRTPImpl::setRemoteDetails(const string& address, Ice::Int port)
@@ -319,7 +341,8 @@ void StreamSourceRTPImpl::setRemoteDetails(const string& address, Ice::Int port)
     pjmedia_transport_detach(mImpl->mSession->getTransport(), this);
 
     /* All ready... actually do it! */
-    status = pjmedia_transport_attach(mImpl->mSession->getTransport(), this, &addr, NULL, pj_sockaddr_get_len(&addr), &receiveRTP, NULL);
+    status = pjmedia_transport_attach(mImpl->mSession->getTransport(), this, &addr, NULL, pj_sockaddr_get_len(&addr),
+                                      &receiveRTP, &receiveRTCP);
 
     if (status != PJ_SUCCESS)
     {

commit 81d77c7225125378e784fa969695795f0fe139d9
Author: Joshua Colp <jcolp at digium.com>
Date:   Sun Jul 10 14:08:51 2011 -0300

    Remove old RTCP stuff.

diff --git a/src/RTPSession.cpp b/src/RTPSession.cpp
index 05ce690..b3ae801 100644
--- a/src/RTPSession.cpp
+++ b/src/RTPSession.cpp
@@ -283,22 +283,6 @@ std::string RTPSessionImpl::getId(const Ice::Current&)
 }
 
 /**
- * Implementation of the useRTCP method as defined in MediaRTPIf.ice
- */
-void RTPSessionImpl::useRTCP(bool, const Ice::Current&)
-{
-}
-
-/**
- * Implementation of the getRTCPSession method as defined in MediaRTPIf.ice
- */
-RTCPSessionPrx RTPSessionImpl::getRTCPSession(const Ice::Current&)
-{
-    RTCPSessionPrx proxy;
-    return proxy;
-}
-
-/**
  * Implementation of the release method as defined in MediaRTPIf.ice
  */
 void RTPSessionImpl::release(const Ice::Current&)
diff --git a/src/RTPSession.h b/src/RTPSession.h
index ed7861e..802d942 100644
--- a/src/RTPSession.h
+++ b/src/RTPSession.h
@@ -54,8 +54,6 @@ public:
     AsteriskSCF::Media::V1::StreamSourceSeq getSources(const Ice::Current&);
     AsteriskSCF::Media::V1::StreamSinkSeq getSinks(const Ice::Current&);
     std::string getId(const Ice::Current&);
-    void useRTCP(bool, const Ice::Current&);
-    AsteriskSCF::Media::RTP::V1::RTCPSessionPrx getRTCPSession(const Ice::Current&);
     void release(const Ice::Current&);
     AsteriskSCF::Media::RTP::V1::RTPSessionPrx getProxy();
     pjmedia_transport* getTransport();

commit e495e075f2f28738b0d8236dd76b353316240f41
Author: Joshua Colp <jcolp at digium.com>
Date:   Sun Jul 10 11:49:45 2011 -0300

    Merge revised media design implementation.

diff --git a/slice/AsteriskSCF/Replication/MediaRTPPJMedia/RtpStateReplicationIf.ice b/slice/AsteriskSCF/Replication/MediaRTPPJMedia/RtpStateReplicationIf.ice
index ee5862c..b9b08d7 100644
--- a/slice/AsteriskSCF/Replication/MediaRTPPJMedia/RtpStateReplicationIf.ice
+++ b/slice/AsteriskSCF/Replication/MediaRTPPJMedia/RtpStateReplicationIf.ice
@@ -98,7 +98,7 @@ module V1
 
     class RtpStreamSourceStateItem extends RtpStateItem
     {
-	AsteriskSCF::Media::V1::StreamSink *mSink;
+	AsteriskSCF::Media::V1::StreamSinkSeq mSinks;
     };
 }; /* module V1 */
 
diff --git a/src/RTPSink.cpp b/src/RTPSink.cpp
index 2cf4741..7c65568 100644
--- a/src/RTPSink.cpp
+++ b/src/RTPSink.cpp
@@ -98,7 +98,7 @@ void StreamSinkRTPImpl::write(const AsteriskSCF::Media::V1::FrameSeq& frames, co
         AudioFormatPtr audioformat;
 
         /* TODO: Add support for other types of media */
-        if (!(audioformat = AudioFormatPtr::dynamicCast((*frame)->mediaformat)))
+        if (!(audioformat = AudioFormatPtr::dynamicCast((*frame)->mediaFormat)))
         {
             continue;
         }
@@ -108,15 +108,15 @@ void StreamSinkRTPImpl::write(const AsteriskSCF::Media::V1::FrameSeq& frames, co
         int payload;
 
         // Only allow media formats through that we support
-        if ((payload = mImpl->mSession->getPayload((*frame)->mediaformat)) < 0)
+        if ((payload = mImpl->mSession->getPayload((*frame)->mediaFormat)) < 0)
         {
             throw UnsupportedMediaFormatException();
         }
 
         /* Using the available information construct an RTP header that we can place at the front of our packet */
         pj_status_t status = pjmedia_rtp_encode_rtp(&mImpl->mOutgoingSession,
-						    mImpl->mSession->getPayload((*frame)->mediaformat), 0, (int) (*frame)->payload.size(),
-						    (int) (*frame)->payload.size(), &header, &header_len);
+                                                    payload, 0, (int) (*frame)->payload.size(),
+                                                    (int) (*frame)->payload.size(), &header, &header_len);
 
         if (status != PJ_SUCCESS)
         {
diff --git a/src/RTPSource.cpp b/src/RTPSource.cpp
index 909bbc5..c7c9c58 100644
--- a/src/RTPSource.cpp
+++ b/src/RTPSource.cpp
@@ -16,9 +16,12 @@
 
 #include <pjlib.h>
 #include <pjmedia.h>
+
 #include <Ice/Ice.h>
 #include <IceUtil/UUID.h>
 
+#include <boost/thread.hpp>
+
 #include <AsteriskSCF/Media/MediaIf.h>
 #include <AsteriskSCF/Media/RTP/MediaRTPIf.h>
 #include <AsteriskSCF/logger.h>
@@ -66,6 +69,11 @@ public:
      * Stream source state item.
      */
     RtpStreamSourceStateItemPtr mSourceStateItem;
+
+    /**
+     * Lock that protects information contained.
+     */
+    boost::shared_mutex mLock;
 };
 
 /**
@@ -88,21 +96,37 @@ StreamSourceRTPImpl::StreamSourceRTPImpl(const RTPSessionImplPtr& session, const
 }
 
 /**
- * Implementation of the setSink method as defined in MediaIf.ice
+ * Implementation of the addSink method as defined in MediaIf.ice
  */
-void StreamSourceRTPImpl::setSink(const AsteriskSCF::Media::V1::StreamSinkPrx& sink, const Ice::Current&)
+void StreamSourceRTPImpl::addSink(const AsteriskSCF::Media::V1::StreamSinkPrx& sink, const Ice::Current&)
 {
-    mImpl->mSourceStateItem->mSink = sink;
+    boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
+
+    mImpl->mSourceStateItem->mSinks.push_back(sink);
 
     mImpl->mSession->replicateState(0, 0, mImpl->mSourceStateItem);
 }
 
 /**
- * Implementation of the getSink method as defined in MediaIf.ice
+ * Implementation of the removeSink method as defined in MediaIf.ice
  */
-AsteriskSCF::Media::V1::StreamSinkPrx StreamSourceRTPImpl::getSink(const Ice::Current&)
+void StreamSourceRTPImpl::removeSink(const AsteriskSCF::Media::V1::StreamSinkPrx& sink, const Ice::Current&)
 {
-    return mImpl->mSourceStateItem->mSink;
+    boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
+
+    mImpl->mSourceStateItem->mSinks.erase(std::remove(mImpl->mSourceStateItem->mSinks.begin(),
+	    mImpl->mSourceStateItem->mSinks.end(),
+	    sink), mImpl->mSourceStateItem->mSinks.end());
+
+    mImpl->mSession->replicateState(0, 0, mImpl->mSourceStateItem);
+}
+
+/**
+ * Implementation of the getSinks method as defined in MediaIf.ice
+ */
+AsteriskSCF::Media::V1::StreamSinkSeq StreamSourceRTPImpl::getSinks(const Ice::Current&)
+{
+    return mImpl->mSourceStateItem->mSinks;
 }
 
 /**
@@ -188,45 +212,75 @@ static void receiveRTP(void *userdata, void *packet, pj_ssize_t size)
         return;
     }
 
-    if (source->mImpl->mSourceStateItem->mSink != 0)
+    // Update RTP stack information before writing to sinks, it's fine to do it
+    pjmedia_rtp_session_update(&source->mImpl->mIncomingSession, header, NULL);
+
+    if (source->mImpl->mSourceStateItem->mSinks.empty())
+    {
+	// No sinks present so frames can not go anywhere
+	return;
+    }
+
+    FormatPtr mediaformat = source->mImpl->mSession->getFormat(header->pt);
+
+    if (!mediaformat)
+    {
+	// If this is for a payload we don't know about just drop the frame
+	return;
+    }
+
+    FrameSeq frames;
+
+    AudioFormatPtr audioformat;
+    VideoFormatPtr videoformat;
+
+    if ((audioformat = AudioFormatPtr::dynamicCast(mediaformat)))
+    {
+        AudioFramePtr frame = new AudioFrame();
+        frame->mediaFormat = mediaformat;
+
+        // Populate the common data
+        frame->timestamp = header->ts;
+        frame->seqno = header->seq;
+
+        // Copy the payload from the RTP packet into the frame
+        copy(payload, payload + payload_size, std::back_inserter(frame->payload));
+
+        // Into the frames sequence it goes
+        frames.push_back(frame);
+    }
+    else if ((videoformat = VideoFormatPtr::dynamicCast(mediaformat)))
+    {
+        VideoFramePtr frame = new VideoFrame();
+        frame->mediaFormat = mediaformat;
+        frame->timestamp = header->ts;
+        frame->seqno = header->seq;
+        copy(payload, payload + payload_size, std::back_inserter(frame->payload));
+        frames.push_back(frame);
+    }
+
+    if (frames.empty())
     {
-        FormatPtr mediaformat = source->mImpl->mSession->getFormat(header->pt);
+        // If the media format ended up being a type we don't understand don't bother writing it out
+        return;
+    }
 
-        if (mediaformat != 0)
+    boost::shared_lock<boost::shared_mutex> lock(source->mImpl->mLock);
+
+    for (StreamSinkSeq::iterator sink = source->mImpl->mSourceStateItem->mSinks.begin();
+         sink != source->mImpl->mSourceStateItem->mSinks.end();
+         ++sink)
+    {
+        try
+        {
+            (*sink)->write(frames);
+        }
+        catch (const Ice::Exception&)
         {
-            FrameSeq frames;
-
-            AudioFormatPtr audioformat;
-
-            if ((audioformat = AudioFormatPtr::dynamicCast(mediaformat)))
-            {
-                AudioFramePtr frame = new AudioFrame();
-                frame->mediaformat = mediaformat;
-
-                /* Populate the common data */
-                frame->timestamp = header->ts;
-                frame->seqno = header->seq;
-
-                /* Copy the payload from the RTP packet to the frame, yahoo! */
-                copy(payload, payload + payload_size, std::back_inserter(frame->payload));
-
-                /* Into the sequence it goes, yarrrrrrrrrr matey */
-                frames.push_back(frame);
-            }
-
-            try
-            {
-                source->mImpl->mSourceStateItem->mSink->write(frames);
-            }
-            catch (const Ice::Exception&)
-            {
-                lg(Error) << "Exception caught while attempting to write media to an RTP sink";
-            }
+            lg(Error) << "Exception caught while attempting to write media to RTP sink " << (*sink);
         }
     }
 
-    /* Now that all is said and done update the internal RTP stack state */
-    pjmedia_rtp_session_update(&source->mImpl->mIncomingSession, header, NULL);
 }
 
 /**
@@ -280,3 +334,13 @@ RtpStreamSourceStateItemPtr StreamSourceRTPImpl::getStateItem()
 {
     return mImpl->mSourceStateItem;
 }
+
+/**
+ * API call which sets the sinks.
+ */
+void StreamSourceRTPImpl::setSinks(const AsteriskSCF::Media::V1::StreamSinkSeq& sinks)
+{
+    boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
+
+    mImpl->mSourceStateItem->mSinks = sinks;
+}
diff --git a/src/RTPSource.h b/src/RTPSource.h
index 9da0b2a..f032f88 100644
--- a/src/RTPSource.h
+++ b/src/RTPSource.h
@@ -22,14 +22,17 @@ class StreamSourceRTPImpl : public AsteriskSCF::Media::RTP::V1::StreamSourceRTP
 {
 public:
     StreamSourceRTPImpl(const RTPSessionImplPtr&, const std::string&);
-    void setSink(const AsteriskSCF::Media::V1::StreamSinkPrx&, const Ice::Current&);
-    AsteriskSCF::Media::V1::StreamSinkPrx getSink(const Ice::Current&);
+    void addSink(const AsteriskSCF::Media::V1::StreamSinkPrx&, const Ice::Current&);
+    void removeSink(const AsteriskSCF::Media::V1::StreamSinkPrx&, const Ice::Current&);
+    AsteriskSCF::Media::V1::StreamSinkSeq getSinks(const Ice::Current&);
     AsteriskSCF::Media::V1::FormatSeq getFormats(const Ice::Current&);
     std::string getId(const Ice::Current&);
     void requestFormat(const AsteriskSCF::Media::V1::FormatPtr&, const Ice::Current&);
     std::string getLocalAddress(const Ice::Current&);
     Ice::Int getLocalPort(const Ice::Current&);
+
     void setRemoteDetails(const std::string& address, Ice::Int port);
+    void setSinks(const AsteriskSCF::Media::V1::StreamSinkSeq&);
     AsteriskSCF::Replication::MediaRTPPJMedia::V1::RtpStreamSourceStateItemPtr getStateItem();
 
     /**
diff --git a/src/RtpStateReplicatorListener.cpp b/src/RtpStateReplicatorListener.cpp
index e3af713..d7a43f5 100644
--- a/src/RtpStateReplicatorListener.cpp
+++ b/src/RtpStateReplicatorListener.cpp
@@ -130,7 +130,7 @@ public:
                     mImpl->mStateItems.find(item->mSessionId);
 		if (i != mImpl->mStateItems.end())
 		{
-		    i->second->getSession()->getSource()->setSink(item->mSink, Ice::Current());
+		    i->second->getSession()->getSource()->setSinks(item->mSinks);
 		}
 	    }
 	};
diff --git a/test/TestRTPpjmedia.cpp b/test/TestRTPpjmedia.cpp
index 36eab74..212c58e 100644
--- a/test/TestRTPpjmedia.cpp
+++ b/test/TestRTPpjmedia.cpp
@@ -495,7 +495,7 @@ BOOST_AUTO_TEST_CASE(ConfirmInitialReplicatedRTPSink)
 BOOST_AUTO_TEST_CASE(ConfirmInitialReplicatedRTPSource)
 {
     BOOST_CHECK(Testbed.mListener->mSource);
-    BOOST_CHECK(!Testbed.mListener->mSource->mSink);
+    BOOST_CHECK(Testbed.mListener->mSource->mSinks.empty());
 }
 
 /**
@@ -645,7 +645,7 @@ BOOST_AUTO_TEST_CASE(TransmitFrametoEmptySink)
         format->frameSize = 20;
 
         AudioFramePtr frame = new AudioFrame();
-        frame->mediaformat = format;
+        frame->mediaFormat = format;
 
         /* Populate the payload with some useless data, but enough to confirm the payload passes unaltered. */
         frame->payload.push_back('a');
@@ -735,9 +735,9 @@ BOOST_AUTO_TEST_CASE(ConfirmSinkSetting)
         {
             StreamSourceRTPPrx source = StreamSourceRTPPrx::checkedCast((*i));
 
-            source->setSink(Testbed.sink);
+            source->addSink(Testbed.sink);
 
-            StreamSinkPrx sink = source->getSink();
+            StreamSinkPrx sink = source->getSinks().front();
 
             if (Testbed.sink == sink)
             {
@@ -851,7 +851,7 @@ BOOST_AUTO_TEST_CASE(ConfirmPopulatedReplicatedRTPSink)
  */
 BOOST_AUTO_TEST_CASE(ConfirmPopulatedReplicatedRTPSource)
 {
-    BOOST_CHECK(Testbed.mListener->mSource->mSink == Testbed.sink);
+    BOOST_CHECK(Testbed.mListener->mSource->mSinks.front() == Testbed.sink);
 }
 
 /**
@@ -869,7 +869,7 @@ BOOST_AUTO_TEST_CASE(TransmitandReceiveFrame)
         format->frameSize = 20;
 
         AudioFramePtr frame = new AudioFrame();
-        frame->mediaformat = format;
+        frame->mediaFormat = format;
 
         /* Populate the payload with some useless data, but enough to confirm the payload passes unaltered. */
         frame->payload.push_back('a');
@@ -901,10 +901,10 @@ BOOST_AUTO_TEST_CASE(TransmitandReceiveFrame)
         AudioFramePtr received_frame;
         if (Testbed.frames.size() == 1 &&
             (received_frame = AudioFramePtr::dynamicCast(Testbed.frames.front())) &&
-            (received_frame->mediaformat->name == format->name))
+            (received_frame->mediaFormat->name == format->name))
         {
             AudioFormatPtr received_format;
-            if ((received_format = AudioFormatPtr::dynamicCast(received_frame->mediaformat)) &&
+            if ((received_format = AudioFormatPtr::dynamicCast(received_frame->mediaFormat)) &&
                 (received_format->frameSize == format->frameSize) &&
                 (received_frame->payload == frame->payload))
             {
@@ -938,7 +938,7 @@ BOOST_AUTO_TEST_CASE(TransmitFrameWithUnsupportedMediaFormat)
         format->frameSize = 20;
 
         AudioFramePtr frame = new AudioFrame();
-        frame->mediaformat = format;
+        frame->mediaFormat = format;
 
         frame->payload.push_back('a');
         frame->payload.push_back('b');
@@ -1015,7 +1015,7 @@ BOOST_AUTO_TEST_CASE(ReceiveUnknownRTPPacket)
         sink->setRemoteDetails(address, port);
 
         AudioFramePtr frame = new AudioFrame();
-        frame->mediaformat = format;
+        frame->mediaFormat = format;
 
         /* Populate the payload with some useless data, but enough to confirm the payload passes unaltered. */
         frame->payload.push_back('a');

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


-- 
asterisk-scf/integration/media_rtp_pjmedia.git



More information about the asterisk-scf-commits mailing list