[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