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

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


branch "rtcp" has been updated
       via  bf6b453b9d018f6aba0e2b0ab719472495f15d43 (commit)
       via  bdf6351ca12140de2fe16effeb2f6ceeadfeb218 (commit)
      from  6c03dccea7ab9653a2814428ef9670edff0b441d (commit)

Summary of changes:
 .../MediaRTPPJMedia/RtpStateReplicationIf.ice      |    3 +
 src/RTPSession.cpp                                 |   17 ++
 src/RtpStateReplicatorListener.cpp                 |    1 +
 test/TestRTPpjmedia.cpp                            |  277 +++++++++++++++++++-
 4 files changed, 296 insertions(+), 2 deletions(-)


- Log -----------------------------------------------------------------
commit bf6b453b9d018f6aba0e2b0ab719472495f15d43
Author: Joshua Colp <jcolp at digium.com>
Date:   Mon Jul 11 22:10:48 2011 -0300

    Add tests for RTCP support.

diff --git a/test/TestRTPpjmedia.cpp b/test/TestRTPpjmedia.cpp
index 212c58e..ca15d65 100644
--- a/test/TestRTPpjmedia.cpp
+++ b/test/TestRTPpjmedia.cpp
@@ -21,6 +21,8 @@
 #endif
 #define BOOST_TEST_NO_MAIN
 
+#include <pjmedia.h>
+
 #include <boost/test/unit_test.hpp>
 #include <boost/test/debug.hpp>
 #include <boost/thread/thread.hpp>
@@ -33,11 +35,13 @@
 #include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.h>
 #include <AsteriskSCF/Media/MediaIf.h>
 #include <AsteriskSCF/Media/RTP/MediaRTPIf.h>
+#include <AsteriskSCF/Media/RTP/MediaRTCPIf.h>
 
 #include "RtpStateReplicationIf.h"
 
 using namespace std;
 using namespace AsteriskSCF::Core::Discovery::V1;
+using namespace AsteriskSCF::Media;
 using namespace AsteriskSCF::Media::V1;
 using namespace AsteriskSCF::Media::RTP::V1;
 using namespace AsteriskSCF::Replication::MediaRTPPJMedia::V1;
@@ -77,6 +81,33 @@ public:
 
 typedef IceUtil::Handle<TestRtpReplicatorListener> TestRtpReplicatorListenerPtr;
 
+class TestInformationListener : public RTCP::V1::InformationListener
+{
+public:
+    TestInformationListener() : mSsrcChanged(false) { }
+
+    void sourceStatisticsUpdated(const StreamSourceRTPPrx&, const RTCP::V1::StatisticsPtr& statistics, const Ice::Current&)
+    {
+        mSourceStatistics = statistics;
+    }
+
+    void sinkStatisticsUpdated(const StreamSinkRTPPrx&, const RTCP::V1::StatisticsPtr& statistics, const Ice::Current&)
+    {
+        mSinkStatistics = statistics;
+    }
+
+    void sourceSsrcChanged(const StreamSourceRTPPrx&, Ice::Int, const Ice::Current&)
+    {
+        mSsrcChanged = true;
+    }
+
+    RTCP::V1::StatisticsPtr mSourceStatistics;
+    RTCP::V1::StatisticsPtr mSinkStatistics;
+    bool mSsrcChanged;
+};
+
+typedef IceUtil::Handle<TestInformationListener> TestInformationListenerPtr;
+
 /**
  * It seems odd that boost doesn't provide an easy way to access the GLOBAL_FIXTURE members.
  * But it doesn't seem to, so I'm sharing global setup stuff here.
@@ -110,6 +141,16 @@ public:
     RtpStateReplicatorListenerPrx mListenerProxy;
 
     /**
+     * Instance of our RTCP information listener.
+     */
+    TestInformationListenerPtr mInformationListener;
+
+    /**
+     * A proxy to our information listener.
+     */
+    RTCP::V1::InformationListenerPrx mInformationListenerProxy;
+
+    /**
      * A proxy to the RTP session that we requested.
      */
     RTPSessionPrx session;
@@ -275,6 +316,11 @@ struct GlobalIceFixture
 
 	    Testbed.mListenerProxy = RtpStateReplicatorListenerPrx::uncheckedCast(Testbed.adapter->addWithUUID(Testbed.mListener));
 
+            Testbed.mInformationListener = new TestInformationListener();
+
+            Testbed.mInformationListenerProxy = RTCP::V1::InformationListenerPrx::uncheckedCast(Testbed.adapter->addWithUUID(
+                                                                                                    Testbed.mInformationListener));
+
             Testbed.adapter->activate();
 
             Testbed.locator = ServiceLocatorPrx::checkedCast(Testbed.communicator->stringToProxy("LocatorService:tcp -p 4411"));
@@ -476,6 +522,9 @@ BOOST_AUTO_TEST_CASE(ConfirmInitialReplicatedRTPSession)
     StreamSourceRTPPrx source = StreamSourceRTPPrx::uncheckedCast(sources.front());
     BOOST_CHECK(Testbed.mListener->mSession->mSourceIdentity == source->ice_getIdentity());
     BOOST_CHECK(Testbed.mListener->mSession->mPort == source->getLocalPort());
+
+    BOOST_CHECK(!Testbed.mListener->mSession->mRemoteRtcpAddress.size());
+    BOOST_CHECK(!Testbed.mListener->mSession->mRemoteRtcpPort);
 }
 
 /**
@@ -569,6 +618,60 @@ BOOST_AUTO_TEST_CASE(VerifyLocalAddressonSources)
 }
 
 /**
+ * Check that we receive a local port that RTCP remote RTCP is to be sent to
+ */
+BOOST_AUTO_TEST_CASE(VerifyLocalRTCPPortonSession)
+{
+    int port = 0;
+
+    try
+    {
+        RTCP::V1::RTCPSessionPrx session = RTCP::V1::RTCPSessionPrx::checkedCast(Testbed.session,
+                                                                                 RTCP::V1::SessionFacet);
+        port = session->getLocalPort();
+    }
+    catch (const Ice::Exception &e)
+    {
+        BOOST_TEST_MESSAGE(e.ice_name());
+        BOOST_TEST_MESSAGE(e.what());
+    }
+
+    BOOST_CHECK(port);
+}
+
+/**
+ * Check that we can set remote details for RTCP and that they get replicated
+ */
+BOOST_AUTO_TEST_CASE(VerifyReplicatedRTCPRemoteDetails)
+{
+    boost::mutex::scoped_lock lock(Testbed.mLock);
+
+#ifdef IPV6_TEST
+    std::string address = "::1";
+#else
+    std::string address = "127.0.0.1";
+#endif
+
+    try
+    {
+	RTCP::V1::RTCPSessionPrx session = RTCP::V1::RTCPSessionPrx::checkedCast(Testbed.session,
+	    RTCP::V1::SessionFacet);
+
+        session->setRemoteDetails(address, 10001);
+    }
+    catch (const Ice::Exception &e)
+    {
+        BOOST_TEST_MESSAGE(e.ice_name());
+        BOOST_TEST_MESSAGE(e.what());
+    }
+
+    Testbed.mCondition.wait(lock);
+
+    BOOST_CHECK(Testbed.mListener->mSession->mRemoteRtcpAddress == address);
+    BOOST_CHECK(Testbed.mListener->mSession->mRemoteRtcpPort == 10001);
+}
+
+/**
  * Check that the RTP session has at least one sink
  */
 BOOST_AUTO_TEST_CASE(CheckForSink)
@@ -683,7 +786,7 @@ BOOST_AUTO_TEST_CASE(TransmitFrametoEmptySink)
 /**
  * Check that we can set the remote address information properly
  */
-BOOST_AUTO_TEST_CASE(ConfirmRemoteAddressSetting)
+BOOST_AUTO_TEST_CASE(ConfirmRemoteRTPAddressSetting)
 {
     bool set = false;
 
@@ -794,9 +897,102 @@ BOOST_AUTO_TEST_CASE(PushPayloadMappings)
 }
 
 /**
+ * Add RTCP information listener to source
+ */
+BOOST_AUTO_TEST_CASE(AddRTCPListenerToSource)
+{
+    bool added = false;
+
+    try
+    {
+        StreamSourceSeq sources = Testbed.session->getSources();
+        StreamSourceRTPPrx source = StreamSourceRTPPrx::uncheckedCast(sources.front());
+        RTCP::V1::InformationPrx information = RTCP::V1::InformationPrx::checkedCast(source,
+                                                                                     RTCP::V1::Facet);
+        information->addListener(Testbed.mInformationListenerProxy);
+        added = true;
+    }
+    catch (const Ice::Exception &e)
+    {
+        BOOST_TEST_MESSAGE(e.ice_name());
+        BOOST_TEST_MESSAGE(e.what());
+    }
+    catch (...)
+    {
+    }
+
+    BOOST_CHECK(added);
+}
+
+/**
+ * Add RTCP information listener to sink
+ */
+BOOST_AUTO_TEST_CASE(AddRTCPListenerToSink)
+{
+    bool added = false;
+
+    try
+    {
+        StreamSinkSeq sinks = Testbed.session->getSinks();
+        StreamSinkRTPPrx sink = StreamSinkRTPPrx::uncheckedCast(sinks.front());
+        RTCP::V1::InformationPrx information = RTCP::V1::InformationPrx::checkedCast(sink,
+                                                                                     RTCP::V1::Facet);
+        information->addListener(Testbed.mInformationListenerProxy);
+        added = true;
+    }
+    catch (const Ice::Exception &e)
+    {
+        BOOST_TEST_MESSAGE(e.ice_name());
+        BOOST_TEST_MESSAGE(e.what());
+    }
+    catch (...)
+    {
+    }
+
+    BOOST_CHECK(added);
+}
+
+/**
+ * Setup RTCP loopback from the session, to, well, the session
+ */
+BOOST_AUTO_TEST_CASE(SetupRTCPLoopback)
+{
+    bool looped = false;
+
+    try
+    {
+        StreamSourceSeq sources = Testbed.session->getSources();
+        StreamSourceRTPPrx source = StreamSourceRTPPrx::uncheckedCast(sources.front());
+        string address = source->getLocalAddress();
+
+        RTCP::V1::RTCPSessionPrx session = RTCP::V1::RTCPSessionPrx::checkedCast(Testbed.session,
+                                                                                 RTCP::V1::SessionFacet);
+        int port = session->getLocalPort();
+
+        boost::mutex::scoped_lock lock(Testbed.mLock);
+
+        session->setRemoteDetails(address, port);
+
+        looped = true;
+
+        Testbed.mCondition.wait(lock);
+    }
+    catch (const Ice::Exception &e)
+    {
+        BOOST_TEST_MESSAGE(e.ice_name());
+        BOOST_TEST_MESSAGE(e.what());
+    }
+    catch (...)
+    {
+    }
+
+    BOOST_CHECK(looped);
+}
+
+/**
  * Setup RTP loopback from the session to, well, the session
  */
-BOOST_AUTO_TEST_CASE(SetupLoopback)
+BOOST_AUTO_TEST_CASE(SetupRTPLoopback)
 {
     bool looped = false;
 
@@ -1051,6 +1247,83 @@ BOOST_AUTO_TEST_CASE(ReceiveUnknownRTPPacket)
 }
 
 /**
+ * Wait for and retrieve RTCP statistics information from the source.
+ */
+BOOST_AUTO_TEST_CASE(WaitForAndRetrieveSourceRTCPStatistics)
+{
+    RTCP::V1::StatisticsPtr statistics;
+
+    try
+    {
+        StreamSourceSeq sources = Testbed.session->getSources();
+        StreamSourceRTPPrx source = StreamSourceRTPPrx::uncheckedCast(sources.front());
+
+        RTCP::V1::InformationPrx information = RTCP::V1::InformationPrx::checkedCast(source, RTCP::V1::Facet);
+
+        // Give enough time for a few RTCP packets to be sent
+        IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(PJMEDIA_RTCP_INTERVAL * 4));
+
+        // Now retrieve the statistics and peek at them
+        statistics = information->getStatistics();
+    }
+    catch (const Ice::Exception &e)
+    {
+        BOOST_TEST_MESSAGE(e.ice_name());
+        BOOST_TEST_MESSAGE(e.what());
+    }
+    catch (...)
+    {
+    }
+
+    BOOST_CHECK(statistics);
+    BOOST_CHECK(statistics->roundTripDelay->last);
+    BOOST_CHECK(statistics->packets);
+}
+
+/**
+ * Retrieve RTCP statistics information from the sink.
+ */
+BOOST_AUTO_TEST_CASE(RetrieveSinkRTCPStatistics)
+{
+    RTCP::V1::StatisticsPtr statistics;
+
+    try
+    {
+        StreamSinkSeq sinks = Testbed.session->getSinks();
+        StreamSinkRTPPrx sink = StreamSinkRTPPrx::uncheckedCast(sinks.front());
+
+        RTCP::V1::InformationPrx information = RTCP::V1::InformationPrx::checkedCast(sink, RTCP::V1::Facet);
+        statistics = information->getStatistics();
+    }
+    catch (const Ice::Exception &e)
+    {
+        BOOST_TEST_MESSAGE(e.ice_name());
+        BOOST_TEST_MESSAGE(e.what());
+    }
+    catch (...)
+    {
+    }
+
+    BOOST_CHECK(statistics);
+    BOOST_CHECK(statistics->roundTripDelay->last);
+    BOOST_CHECK(statistics->packets);
+}
+
+/**
+ * Confirm that our information listener was called and that statistics information is proper.
+ */
+BOOST_AUTO_TEST_CASE(ConfirmInformationListenerCalled)
+{
+    BOOST_CHECK(Testbed.mInformationListener->mSourceStatistics);
+    BOOST_CHECK(Testbed.mInformationListener->mSourceStatistics->roundTripDelay->last);
+    BOOST_CHECK(Testbed.mInformationListener->mSourceStatistics->packets);
+
+    BOOST_CHECK(Testbed.mInformationListener->mSinkStatistics);
+    BOOST_CHECK(Testbed.mInformationListener->mSinkStatistics->roundTripDelay->last);
+    BOOST_CHECK(Testbed.mInformationListener->mSinkStatistics->packets);
+}
+
+/**
  * Attempt to set an IPv4 address on an IPv6 only sink OR try to set an IPv6 address
  * on an IPv4 only sink.
  */

commit bdf6351ca12140de2fe16effeb2f6ceeadfeb218
Author: Joshua Colp <jcolp at digium.com>
Date:   Mon Jul 11 21:12:32 2011 -0300

    Add the start of replication support for RTCP destination information.

diff --git a/slice/AsteriskSCF/Replication/MediaRTPPJMedia/RtpStateReplicationIf.ice b/slice/AsteriskSCF/Replication/MediaRTPPJMedia/RtpStateReplicationIf.ice
index b9b08d7..8dfb557 100644
--- a/slice/AsteriskSCF/Replication/MediaRTPPJMedia/RtpStateReplicationIf.ice
+++ b/slice/AsteriskSCF/Replication/MediaRTPPJMedia/RtpStateReplicationIf.ice
@@ -87,6 +87,8 @@ module V1
 	AsteriskSCF::Media::V1::FormatSeq mFormats;
 	AsteriskSCF::Media::RTP::V1::PayloadMap mPayloadstoFormats;
 	bool mIPv6;
+        string mRemoteRtcpAddress;
+        int mRemoteRtcpPort;
     };
 
     class RtpStreamSinkStateItem extends RtpStateItem
@@ -100,6 +102,7 @@ module V1
     {
 	AsteriskSCF::Media::V1::StreamSinkSeq mSinks;
     };
+
 }; /* module V1 */
 
 }; /* module MediaRTPPJMedia */
diff --git a/src/RTPSession.cpp b/src/RTPSession.cpp
index e145bfc..f645c16 100644
--- a/src/RTPSession.cpp
+++ b/src/RTPSession.cpp
@@ -400,6 +400,18 @@ RTPSessionImpl::RTPSessionImpl(const Ice::ObjectAdapterPtr& adapter, pj_pool_fac
 
     mImpl->mStreamSink = new StreamSinkRTPImpl(this, "");
     mImpl->mStreamSinkProxy = StreamSinkRTPPrx::uncheckedCast(mImpl->mAdapter->add(mImpl->mStreamSink, sinkIdentity));
+
+    // Create an RTCP session for interaction from the outside
+    mImpl->mRtcpSessionInterface = new RTCPSessionImpl(this);
+    mImpl->mAdapter->addFacet(mImpl->mRtcpSessionInterface, sessionIdentity, RTCP::V1::SessionFacet);
+
+    // Create an RTCP information implementation for Receiver Reports
+    mImpl->mReceiverReport = new RTCPInformationImpl(&mImpl->mRtcpSession.stat, &mImpl->mRtcpSession.stat.rx);
+    mImpl->mAdapter->addFacet(mImpl->mReceiverReport, sourceIdentity, RTCP::V1::Facet);
+
+    // Create an RTCP information implementation for Sender Reports
+    mImpl->mSenderReport = new RTCPInformationImpl(&mImpl->mRtcpSession.stat, &mImpl->mRtcpSession.stat.tx);
+    mImpl->mAdapter->addFacet(mImpl->mSenderReport, sinkIdentity, RTCP::V1::Facet);
 }
 
 /**
@@ -580,7 +592,12 @@ void RTPSessionImpl::setRemoteDetails(const string& address, Ice::Int port)
  */
 void RTPSessionImpl::setRemoteRtcpDetails(const std::string& address, Ice::Int port)
 {
+    mImpl->mSessionStateItem->mRemoteRtcpAddress = address;
+    mImpl->mSessionStateItem->mRemoteRtcpPort = port;
+
     mImpl->mStreamSource->setRemoteRtcpDetails(address, port);
+
+    replicateState(mImpl->mSessionStateItem, 0, 0);
 }
 
 /**
diff --git a/src/RtpStateReplicatorListener.cpp b/src/RtpStateReplicatorListener.cpp
index d7a43f5..f59a5d7 100644
--- a/src/RtpStateReplicatorListener.cpp
+++ b/src/RtpStateReplicatorListener.cpp
@@ -110,6 +110,7 @@ public:
 		}
 
 	        localitem->getSession()->associatePayloads(item->mPayloadstoFormats, Ice::Current());
+		localitem->getSession()->getSource()->setRemoteRtcpDetails(item->mRemoteRtcpAddress, item->mRemoteRtcpPort);
 	    }
 		    
 	    void visitRtpStreamSinkStateItem(const RtpStreamSinkStateItemPtr &item)

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


-- 
asterisk-scf/integration/media_rtp_pjmedia.git



More information about the asterisk-scf-commits mailing list