[asterisk-scf-commits] asterisk-scf/integration/media_operations_core.git branch "jitterbuffer" created.
Commits to the Asterisk SCF project code repositories
asterisk-scf-commits at lists.digium.com
Thu Oct 13 01:55:16 CDT 2011
branch "jitterbuffer" has been created
at ae3b5349290dd8cfced62b86dcc779cc52f0596a (commit)
- Log -----------------------------------------------------------------
commit ae3b5349290dd8cfced62b86dcc779cc52f0596a
Author: Ken Hunt <ken.hunt at digium.com>
Date: Thu Oct 13 01:53:34 2011 -0500
Changes to support jitter buffer operation based on WebRtc NetEQ.
diff --git a/slice/AsteriskSCF/Replication/MediaOperationsCore/MediaOperationsCoreIf.ice b/slice/AsteriskSCF/Replication/MediaOperationsCore/MediaOperationsCoreIf.ice
index ec46309..41af72a 100644
--- a/slice/AsteriskSCF/Replication/MediaOperationsCore/MediaOperationsCoreIf.ice
+++ b/slice/AsteriskSCF/Replication/MediaOperationsCore/MediaOperationsCoreIf.ice
@@ -100,6 +100,13 @@ class ResamplerMediaOperationStateItem extends TranslatorMediaOperationStateItem
};
/**
+ * State item for a Jitter Buffer operatiion.
+ */
+class JitterBufferMediaOperationStateItem extends TranslatorMediaOperationStateItem
+{
+};
+
+/**
* State item for G722 translators
*/
class G722MediaOperationStateItem extends TranslatorMediaOperationStateItem
diff --git a/src/BufferedTranslator.cpp b/src/BufferedTranslator.cpp
new file mode 100644
index 0000000..0c3dad2
--- /dev/null
+++ b/src/BufferedTranslator.cpp
@@ -0,0 +1,51 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#include "BufferedTranslator.h"
+
+namespace AsteriskSCF
+{
+
+namespace MediaOperationsCore
+{
+
+using namespace AsteriskSCF::Media::V1;
+using namespace AsteriskSCF::System::Logging;
+
+BufferedTranslator::BufferedTranslator(const TranslatorSourcePtr& source,
+ const FormatPtr& inputFormat,
+ const FormatPtr& outputFormat,
+ const Logger& logger)
+ : mSource(source),
+ mInputFormat(inputFormat),
+ mOutputFormat(outputFormat),
+ mLogger(logger)
+{
+}
+
+BufferedTranslator::~BufferedTranslator()
+{
+}
+
+void BufferedTranslator::translateFrames(const FrameSeq& frames)
+{
+ FrameSeq translated;
+ translated.resize(frames.size());
+ // std::for_each(frames.begin(), frames.end(), );
+}
+
+}
+}
diff --git a/src/Translator.h b/src/BufferedTranslator.h
similarity index 69%
copy from src/Translator.h
copy to src/BufferedTranslator.h
index 2884875..6056973 100644
--- a/src/Translator.h
+++ b/src/BufferedTranslator.h
@@ -19,6 +19,7 @@
#include <AsteriskSCF/Media/MediaIf.h>
#include <AsteriskSCF/logger.h>
+#include "Translator.h"
#include "TranslatorSource.h"
namespace AsteriskSCF
@@ -27,29 +28,34 @@ namespace AsteriskSCF
namespace MediaOperationsCore
{
-class Translator : public IceUtil::Shared
+/**
+ * A base class for encapsualting translation of frame sequences.
+ * For use by translation operations that may need to buffer the
+ * input frames.
+ */
+class BufferedTranslator : public Translator
{
public:
- Translator(const TranslatorSourcePtr& source,
+ BufferedTranslator(const TranslatorSourcePtr& source,
const AsteriskSCF::Media::V1::FormatPtr& inputFormat,
const AsteriskSCF::Media::V1::FormatPtr& outputFormat,
const AsteriskSCF::System::Logging::Logger& logger);
- virtual ~Translator();
+ virtual ~BufferedTranslator();
/**
- * Translate each frame from the input format into the
- * output format.
+ * Buffer the input frame.
*
* Note that implementors of this function should perform
* a check to be certain that the format of the frame
- * being translated is what is expected for this translator
+ * being buffered is what is expected for this translator
*/
- virtual AsteriskSCF::Media::V1::FramePtr translate(const AsteriskSCF::Media::V1::FramePtr inFrame) = 0;
+ virtual void buffer(const AsteriskSCF::Media::V1::FramePtr inFrame) = 0;
/**
+ * @Override
* Feeds each of the frames in the
- * sequence into the translate() function
+ * sequence to the buffer function.
*/
void translateFrames(const AsteriskSCF::Media::V1::FrameSeq& frames);
@@ -60,7 +66,7 @@ protected:
AsteriskSCF::System::Logging::Logger mLogger;
};
-typedef IceUtil::Handle<Translator> TranslatorPtr;
+typedef IceUtil::Handle<BufferedTranslator> BufferedTranslatorPtr;
}
}
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index d4b15f4..b881108 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,9 +1,18 @@
include_directories(${logger_dir}/include)
include_directories(${astscf-ice-util-cpp_dir}/include)
+include_directories(${astscf-webtrc_dir}/src/modules/NetEQ/main/interface)
+include_directories(${astscf-webtrc_dir}/src/modules/NetEQ/main/source)
+include_directories(${astscf-webtrc_dir}/src/modules/audio_coding/codecs/CNG/main/interface)
+include_directories(${astscf-webtrc_dir}/src/modules/audio_coding/codecs/PCM16B/main/interface)
+include_directories(${astscf-webtrc_dir}/src/common_audio/signal_processing_library/main/interface)
+include_directories(${astscf-webtrc_dir}/src)
astscf_component_init(MediaOperationsCore)
-astscf_component_add_files(MediaOperationsCore Translator.cpp)
astscf_component_add_files(MediaOperationsCore Translator.h)
+astscf_component_add_files(MediaOperationsCore BufferedTranslator.cpp)
+astscf_component_add_files(MediaOperationsCore BufferedTranslator.h)
+astscf_component_add_files(MediaOperationsCore NonBufferedTranslator.cpp)
+astscf_component_add_files(MediaOperationsCore NonBufferedTranslator.h)
astscf_component_add_files(MediaOperationsCore TranslatorSink.cpp)
astscf_component_add_files(MediaOperationsCore TranslatorSink.h)
astscf_component_add_files(MediaOperationsCore TranslatorSource.cpp)
@@ -16,6 +25,10 @@ astscf_component_add_files(MediaOperationsCore ulaw_alaw.h)
astscf_component_add_files(MediaOperationsCore ulaw_alaw.cpp)
astscf_component_add_files(MediaOperationsCore resample.h)
astscf_component_add_files(MediaOperationsCore resample.cpp)
+astscf_component_add_files(MediaOperationsCore NetEqWrapper.h)
+astscf_component_add_files(MediaOperationsCore NetEqWrapper.cpp)
+astscf_component_add_files(MediaOperationsCore JitterBufferOperation.h)
+astscf_component_add_files(MediaOperationsCore JitterBufferOperation.cpp)
astscf_component_add_files(MediaOperationsCore g722.h)
astscf_component_add_files(MediaOperationsCore g722.cpp)
astscf_component_add_files(MediaOperationsCore g722/g722_encode.c)
@@ -31,7 +44,7 @@ astscf_component_add_slices(MediaOperationsCore PROJECT AsteriskSCF/Replication/
astscf_component_add_slice_collection_libraries(MediaOperationsCore ASTSCF)
astscf_component_add_boost_libraries(MediaOperationsCore core thread date_time)
astscf_component_build_icebox(MediaOperationsCore)
-target_link_libraries(MediaOperationsCore logging-client astscf-ice-util-cpp astscf-ice-util-cpp-pjlib)
+target_link_libraries(MediaOperationsCore logging-client astscf-ice-util-cpp astscf-ice-util-cpp-pjlib astscf-webrtc-neteq)
pjproject_link(MediaOperationsCore pjlib)
pjproject_link(MediaOperationsCore pjlib-util)
diff --git a/src/JitterBufferOperation.cpp b/src/JitterBufferOperation.cpp
new file mode 100644
index 0000000..06113e0
--- /dev/null
+++ b/src/JitterBufferOperation.cpp
@@ -0,0 +1,288 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#include <boost/thread.hpp>
+
+#include <IceUtil/UUID.h>
+#include <IceUtil/Timer.h>
+
+#include <AsteriskSCF/Media/Formats/AudioFormats.h>
+#include <AsteriskSCF/Replication/MediaOperationsCore/MediaOperationsCoreIf.h>
+
+#include "JitterBufferOperation.h"
+#include "TranslatorSource.h"
+#include "BufferedTranslator.h"
+#include "TranslatorSink.h"
+#include "TranslatorOperation.h"
+#include "NetEqWrapper.h"
+
+#include "mcu_dsp_common.h"
+#include "webrtc_neteq_internal.h"
+
+using namespace AsteriskSCF::Media::V1;
+using namespace AsteriskSCF::Core::Discovery::V1;
+using namespace AsteriskSCF::Media::Formats::Audio::V1;
+using namespace AsteriskSCF::System::Logging;
+using namespace AsteriskSCF::Replication::MediaOperationsCore::V1;
+
+namespace AsteriskSCF
+{
+namespace MediaOperationsCore
+{
+
+class JitterBufferOperation : public TranslatorOperation
+{
+private:
+
+ class JitterBufferSendTask : public IceUtil::TimerTask
+ {
+ public:
+ JitterBufferSendTask(const TranslatorSourcePtr& source,
+ const AudioFormatPtr& inFormat,
+ const AudioFormatPtr& outFormat,
+ boost::shared_mutex& mutex,
+ int numFramesToPush)
+ : mSource(source),
+ mOutFormat(outFormat),
+ mInFormat(inFormat),
+ mLock(mutex),
+ mNumFramesToPush(numFramesToPush)
+ {
+ }
+
+ AudioFramePtr getNextFrame()
+ {
+ AudioFramePtr frame = new AudioFrame();
+ frame->mediaFormat = mOutFormat;
+
+ ShortSeqPayloadPtr outPayload = new ShortSeqPayload(Ice::ShortSeq(mOutFormat->frameSize/2));
+ WebRtc_Word16 length;
+
+ {
+ boost::unique_lock<boost::shared_mutex> lock(mLock);
+
+ WebRtcNetEQ_RecOut(mNetEq->getInstance(),
+ (WebRtc_Word16*)&outPayload->payload.front(),
+ &length);
+ }
+ frame->payload = outPayload;
+
+ // This just seems wrong...
+ // But I don't see a way to access the sequence number and timestamp via any RecOut operation.
+ frame->timestamp = IceUtil::Time::now().toMilliSeconds();
+ frame->seqno = mSeqNumber++;
+
+ return frame;
+ }
+
+ void runTimerTask()
+ {
+ FrameSeq frameSeq;
+
+ for (int i=0; i < mNumFramesToPush; ++i)
+ {
+ AudioFramePtr frame = getNextFrame();
+ frameSeq.push_back(frame);
+ }
+
+ mSource->distributeToSinks(frameSeq);
+ }
+
+ private:
+ TranslatorSourcePtr mSource;
+ NetEqWrapperPtr mNetEq;
+ AudioFormatPtr mOutFormat;
+ AudioFormatPtr mInFormat;
+ long mSeqNumber;
+ boost::shared_mutex &mLock;
+ int mNumFramesToPush;
+ };
+
+ class JitterBuffer : public BufferedTranslator
+ {
+ public:
+ JitterBuffer(const TranslatorSourcePtr& source,
+ const FormatPtr& inputFormat,
+ const FormatPtr& outputFormat,
+ const Logger& logger,
+ const NetEqWrapperPtr& netEqWrapper)
+ : BufferedTranslator(source, inputFormat, outputFormat, logger),
+ mNetEq(netEqWrapper),
+ mSsrc(rand()),
+ mFrameCount(0),
+ mBufferSending(false)
+ {
+ mInAudioFormat = AudioFormatPtr::dynamicCast(inputFormat);
+ mOutAudioFormat = AudioFormatPtr::dynamicCast(outputFormat);
+ }
+
+ ~JitterBuffer()
+ {
+ if (mTimer)
+ {
+ mTimer->destroy();
+ }
+ }
+
+ void buffer(const FramePtr inFrame)
+ {
+ if (!TranslatorOperationFactory::formatsEqual(inFrame->mediaFormat, mInputFormat))
+ {
+ mLogger(Error) << "Cannot resample frame because the format is not what was expected";
+ throw UnsupportedMediaFormatException();
+ }
+
+ MainInst_t* netEqInstance = mNetEq->getInstance();
+
+ StreamFramePtr streamFrame = StreamFramePtr::dynamicCast(inFrame);
+
+ // We're going to utilize an alternate RecIn operation that doesn't require us to have
+ // the raw datagram to parse.
+ WebRtcNetEQ_RTPInfo rtpInfo;
+ rtpInfo.payloadType = NETEQ_CODEC_PCM16B_PT;
+ rtpInfo.sequenceNumber = (WebRtc_UWord16)streamFrame->seqno;
+ rtpInfo.SSRC = mSsrc;
+ rtpInfo.timeStamp = (WebRtc_UWord32)streamFrame->timestamp;
+ //rtpInfo.markerBit = // Assuming this one is safe to leave unset.
+
+ ShortSeqPayloadPtr inPayload = ShortSeqPayloadPtr::dynamicCast(inFrame->payload);
+
+ {
+ boost::unique_lock<boost::shared_mutex> lock(mLock);
+
+ // Buffer the frame.
+ WebRtcNetEQ_RecInRTPStruct(netEqInstance,
+ &rtpInfo,
+ (WebRtc_UWord8*)&inPayload->payload.front(),
+ mInAudioFormat->frameSize,
+ (WebRtc_UWord32)IceUtil::Time::now().toMilliSeconds());
+ }
+ mFrameCount++;
+
+ if (!mBufferSending)
+ {
+ int framesToBuffer = mNetEq->getBufferSizeInBytes() / mInAudioFormat->frameSize;
+ if (mFrameCount >= framesToBuffer)
+ {
+ mBufferSending = true;
+
+ // Compute the timer period, and use a configurable number of frames so
+ // that the timer task isn't pushing single frames.
+ const int framesToPush(10); // TBD... config item
+
+ int frameDuration = mOutAudioFormat->sampleRate / mOutAudioFormat->frameSize;
+
+ // Start a timer to push buffered frames.
+ IceUtil::TimerTaskPtr sendTask = new JitterBufferSendTask(mSource,
+ mInAudioFormat,
+ mOutAudioFormat,
+ mLock,
+ framesToPush);
+ mTimer->scheduleRepeated(sendTask, IceUtil::Time::milliSeconds(frameDuration * framesToPush));
+ }
+ }
+ }
+
+ private:
+ boost::shared_mutex mLock;
+ AudioFormatPtr mInAudioFormat;
+ AudioFormatPtr mOutAudioFormat;
+ NetEqWrapperPtr mNetEq;
+ WebRtc_UWord32 mSsrc;
+ int mFrameCount;
+ bool mBufferSending;
+ IceUtil::TimerPtr mTimer;
+ };
+
+public:
+ JitterBufferOperation(const Ice::ObjectAdapterPtr& adapter,
+ const Logger& logger,
+ const FormatPtr& sourceFormat,
+ const FormatPtr& sinkFormat,
+ const Ice::Identity& factoryId,
+ const MediaOperationReplicationContextPtr& replicationContext,
+ const NetEqWrapperPtr netEqWrapper
+ )
+ : TranslatorOperation(adapter,
+ logger,
+ sourceFormat,
+ sinkFormat,
+ factoryId,
+ replicationContext,
+ new JitterBufferMediaOperationStateItem)
+ {
+
+ mSink->setTranslator(new JitterBuffer(mSource, sinkFormat, sourceFormat, mLogger,
+ netEqWrapper));
+ }
+
+private:
+};
+
+typedef IceUtil::Handle<JitterBufferOperation> JitterBufferOperationPtr;
+
+JitterBufferOperationFactory::JitterBufferOperationFactory(const Ice::ObjectAdapterPtr& adapter,
+ const AsteriskSCF::System::Logging::Logger& logger,
+ const MediaOperationReplicationContextPtr& replicationContext,
+ bool forFax)
+ : TranslatorOperationFactory(adapter, logger, replicationContext, "JitterBuffer"),
+ mForFax(forFax)
+{
+ buildTranslations();
+}
+
+MediaOperationPrx JitterBufferOperationFactory::createMediaOperation(
+ const FormatPtr& sourceFormat,
+ const FormatPtr& sinkFormat,
+ const std::string& operationId)
+{
+ AudioFormatPtr audioFormat = AudioFormatPtr::dynamicCast(sourceFormat);
+
+ NetEqWrapperPtr netEqWrapper(NetEqWrapper::createNetEqInstance(audioFormat->sampleRate, mForFax));
+
+ JitterBufferOperationPtr operation(
+ new JitterBufferOperation(
+ mAdapter,
+ mLogger,
+ sourceFormat,
+ sinkFormat,
+ getProxy()->ice_getIdentity(),
+ mReplicationContext,
+ netEqWrapper));
+
+ MediaOperationPrx proxy = operation->activate(operationId);
+ return proxy;
+}
+
+void JitterBufferOperationFactory::buildTranslations()
+{
+ FormatPtr slin8 = new SignedLinear();
+ slin8->name = SignedLinear8Name;
+
+ FormatPtr slin16 = new SignedLinear();
+ slin16->name = SignedLinear16Name;
+
+ FormatPtr slin8noJitter = new SignedLinear();
+ slin8noJitter->name = SignedLinear8NoJitterName;
+
+ FormatPtr slin16noJitter = new SignedLinear();
+ slin16noJitter->name = SignedLinear16NoJitterName;
+
+ addTranslation(slin8, slin8noJitter, 100);
+ addTranslation(slin16, slin16noJitter, 100);
+}
+} //end namespace MediaOperationsCore
+} //end namespace AsteriskSCF
diff --git a/src/JitterBufferOperation.h b/src/JitterBufferOperation.h
new file mode 100644
index 0000000..14dc984
--- /dev/null
+++ b/src/JitterBufferOperation.h
@@ -0,0 +1,51 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#pragma once
+
+#include <boost/thread/locks.hpp>
+
+#include "TranslatorOperationFactory.h"
+#include "NetEqWrapper.h"
+
+namespace AsteriskSCF
+{
+namespace MediaOperationsCore
+{
+
+class JitterBufferOperationFactory : public TranslatorOperationFactory
+{
+public:
+ JitterBufferOperationFactory(const Ice::ObjectAdapterPtr&,
+ const AsteriskSCF::System::Logging::Logger& logger,
+ const MediaOperationReplicationContextPtr& replicationContext,
+ bool forFax);
+
+ AsteriskSCF::Media::V1::MediaOperationPrx createMediaOperation(
+ const AsteriskSCF::Media::V1::FormatPtr& sourceFormat,
+ const AsteriskSCF::Media::V1::FormatPtr& sinkFormat,
+ const std::string& operationId);
+
+private:
+ void buildTranslations();
+
+ boost::mutex mLock;
+ bool mForFax;
+};
+typedef IceUtil::Handle<JitterBufferOperationFactory> JitterBufferOperationFactoryPtr;
+
+} //end namespace MediaOperationsCore
+} //end namespace AsteriskSCF
diff --git a/src/MediaOperationStateReplicatorListener.cpp b/src/MediaOperationStateReplicatorListener.cpp
index 2943d21..11edfdb 100644
--- a/src/MediaOperationStateReplicatorListener.cpp
+++ b/src/MediaOperationStateReplicatorListener.cpp
@@ -19,6 +19,7 @@
#include "ulaw_alaw.h"
#include "resample.h"
#include "g722.h"
+#include "JitterBufferOperation.h"
namespace AsteriskSCF
{
@@ -62,6 +63,10 @@ void MediaOperationStateReplicatorListenerImpl::stateRemovedForItems(
{
mAdapter->remove(mAdapter->getCommunicator()->stringToIdentity(g722->operationId));
}
+ void visitJitterBufferMediaOperationStateItem(const JitterBufferMediaOperationStateItemPtr& jitterBuffer)
+ {
+ mAdapter->remove(mAdapter->getCommunicator()->stringToIdentity(jitterBuffer->operationId));
+ }
Ice::ObjectAdapterPtr mAdapter;
};
@@ -105,6 +110,13 @@ void MediaOperationStateReplicatorListenerImpl::stateSet(
createTranslationMediaOperation(factory, g722);
}
+ void visitJitterBufferMediaOperationStateItem(const JitterBufferMediaOperationStateItemPtr& jitterBuffer)
+ {
+ JitterBufferOperationFactoryPtr factory = JitterBufferOperationFactoryPtr::dynamicCast(mAdapter->find(jitterBuffer->factoryId));
+
+ createTranslationMediaOperation(factory, jitterBuffer);
+ }
+
void createTranslationMediaOperation(const TranslatorOperationFactoryPtr& factory,
const TranslatorMediaOperationStateItemPtr& item)
{
diff --git a/src/NetEqWrapper.cpp b/src/NetEqWrapper.cpp
new file mode 100644
index 0000000..c18bcc0
--- /dev/null
+++ b/src/NetEqWrapper.cpp
@@ -0,0 +1,151 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+#include "mcu_dsp_common.h"
+#include "webrtc_neteq_help_macros.h"
+#include "pcm16b.h"
+
+#include "NetEqWrapper.h"
+
+namespace AsteriskSCF
+{
+namespace MediaOperationsCore
+{
+
+const int RATE_8K(8000);
+const int SAMPLERATE_PCMB(RATE_8K);
+const int MAX_NETEQ_BUFFERSIZE(170000); // Picked this up from NetEqRTPplay.cc
+
+class NetEqWrapperImpl : public NetEqWrapper
+{
+public:
+ NetEqWrapperImpl(int sampleRate, bool forFax);
+ ~NetEqWrapperImpl();
+
+ virtual MainInst_t* getInstance() {return mNetEqInstance;}
+
+ virtual int getBufferSizeInBytes() {return mBufferSizeInBytes;}
+ virtual int getBufferMaxPackets() {return mNetEqBufferMaxPackets;}
+private:
+ MainInst_t* mNetEqInstance;
+ WebRtc_Word16 *mNetEqPacketBuffer;
+ WebRtcNetEQ_CodecDef mCodecDef;
+
+ int mBufferSizeInBytes;
+ int mNetEqBufferMaxPackets;
+};
+
+NetEqWrapperImpl::NetEqWrapperImpl(int sampleRate, bool forFax)
+{
+ int memSize;
+ int resultCode;
+ WebRtcNetEQDecoder defaultDecoder(kDecoderPCM16B);
+
+ if((resultCode = WebRtcNetEQ_AssignSize(&memSize)) < 0)
+ {
+ throw NetEqInitException("WebRtcNetEQ returned error from WebRtcNetEQ_AssignSize: " + resultCode);
+ }
+
+ WebRtc_Word8* instMemory = new WebRtc_Word8[memSize];
+ if (instMemory == 0)
+ {
+ throw NetEqInitException("Unable to allocate memory for NetEQ instance.");
+ }
+
+ if((resultCode = WebRtcNetEQ_Assign(reinterpret_cast<void **>(&mNetEqInstance), instMemory)) < 0)
+ {
+ delete instMemory;
+ throw NetEqInitException("WebRtcNetEQ returned error assigning memory for our instance: " + resultCode);
+ }
+
+ // Initial sample rate in Hz (may change with payload)
+ int rate = SAMPLERATE_PCMB;
+
+ if((resultCode = WebRtcNetEQ_Init(mNetEqInstance, sampleRate)) < 0)
+ {
+ std::string msg = "WebRtcNetEQ returned error initializing our instance: " + resultCode;
+ msg += (" with a sampleRate of " + sampleRate);
+ throw NetEqInitException(msg);
+ }
+
+ // Determine playout mode
+ WebRtcNetEQPlayoutMode playoutMode = kPlayoutStreaming; // kPlayoutFax, kPlayoutOn
+ if (forFax)
+ {
+ playoutMode = kPlayoutFax;
+ }
+
+ if((resultCode = WebRtcNetEQ_SetPlayoutMode(mNetEqInstance, playoutMode)) < 0)
+ {
+ throw NetEqInitException("WebRtcNetEQ returned error setting playout mode: " + resultCode);
+ }
+
+ // Get a recommended buffer size based on the codec(s) we're using.
+ const int numSupportedCodecs(1);
+ WebRtcNetEQDecoder usedCodec[numSupportedCodecs];
+ usedCodec[0] = defaultDecoder;
+
+ if((resultCode = WebRtcNetEQ_GetRecommendedBufferSize(mNetEqInstance,
+ usedCodec,
+ numSupportedCodecs,
+ kTCPLargeJitter, // This could be a config item
+ &mNetEqBufferMaxPackets,
+ &mBufferSizeInBytes)) < 0)
+ {
+ throw NetEqInitException("WebRtcNetEQ error getting recommended buffer size: " + resultCode);
+ }
+
+ mNetEqPacketBuffer = new WebRtc_Word16[MAX_NETEQ_BUFFERSIZE>>1];
+ if (mNetEqPacketBuffer == 0)
+ {
+ throw NetEqInitException("Unable to allocate memory for NetEQ packet buffer.");
+ }
+
+ if((resultCode = WebRtcNetEQ_AssignBuffer(mNetEqInstance, mNetEqBufferMaxPackets, mNetEqPacketBuffer, mBufferSizeInBytes)) < 0)
+ {
+ throw NetEqInitException("WebRtcNetEQ returned error from WebRtcNetEQ_AssignBuffer: " + resultCode);
+ }
+
+ /**
+ * Set the codec to use.
+ */
+ SET_CODEC_PAR(mCodecDef,defaultDecoder,NETEQ_CODEC_PCM16B_PT,NULL,sampleRate);
+ SET_PCM16B_FUNCTIONS(mCodecDef);
+ WebRtcNetEQ_CodecDbAdd(mNetEqInstance, &mCodecDef);
+
+ // Note: Not setting master/slave relations, since we currently don't have way to associate
+ // stereo channels.
+
+
+}
+
+NetEqWrapperImpl::~NetEqWrapperImpl()
+{
+ delete mNetEqInstance;
+ delete mNetEqPacketBuffer;
+}
+
+/**
+ * Factory method.
+ */
+NetEqWrapperPtr NetEqWrapper::createNetEqInstance(int sampleRate, bool forFax)
+{
+ NetEqWrapperPtr ptr(new NetEqWrapperImpl(sampleRate, forFax));
+ return ptr;
+}
+
+
+} //end namespace MediaOperationsCore
+} //end namespace AsteriskSCF
diff --git a/src/NetEqWrapper.h b/src/NetEqWrapper.h
new file mode 100644
index 0000000..080402c
--- /dev/null
+++ b/src/NetEqWrapper.h
@@ -0,0 +1,73 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include "mcu_dsp_common.h"
+
+// These values are from NetEQ's PayloadTypes.h in it's test dir.
+// TBD... why??? would payload types only be defined in test header?
+#define NETEQ_CODEC_PCM16B_PT 93
+#define NETEQ_CODEC_PCM16B_WB_PT 94
+
+namespace AsteriskSCF
+{
+namespace MediaOperationsCore
+{
+
+class NetEqInitException : public std::exception
+{
+public:
+ NetEqInitException(const std::string& msg) : mWhat(msg) {}
+ NetEqInitException(const char* msg) : mWhat(msg) {}
+
+ virtual const char* what() const throw()
+ {
+ return mWhat.c_str();
+ }
+
+private:
+ std::string mWhat;
+};
+
+class NetEqWrapper;
+typedef boost::shared_ptr<NetEqWrapper> NetEqWrapperPtr;
+
+/**
+ * This class is a helper for managing an instance of the WebRTC NetEQ functionality.
+ */
+class NetEqWrapper
+{
+public:
+ /**
+ * Factory method.
+ */
+ static NetEqWrapperPtr createNetEqInstance(int sampleRate, bool forFax);
+
+ virtual ~NetEqWrapper() {};
+
+ virtual MainInst_t* getInstance() = 0;
+
+ virtual int getBufferSizeInBytes() = 0;
+ virtual int getBufferMaxPackets() = 0;
+
+protected:
+ NetEqWrapper() {};
+};
+
+} //end namespace MediaOperationsCore
+} //end namespace AsteriskSCF
diff --git a/src/NonBufferedTranslator.cpp b/src/NonBufferedTranslator.cpp
new file mode 100644
index 0000000..5803fe1
--- /dev/null
+++ b/src/NonBufferedTranslator.cpp
@@ -0,0 +1,52 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#include "NonBufferedTranslator.h"
+
+namespace AsteriskSCF
+{
+
+namespace MediaOperationsCore
+{
+
+using namespace AsteriskSCF::Media::V1;
+using namespace AsteriskSCF::System::Logging;
+
+NonBufferedTranslator::NonBufferedTranslator(const TranslatorSourcePtr& source,
+ const FormatPtr& inputFormat,
+ const FormatPtr& outputFormat,
+ const Logger& logger)
+ : mSource(source),
+ mInputFormat(inputFormat),
+ mOutputFormat(outputFormat),
+ mLogger(logger)
+{
+}
+
+NonBufferedTranslator::~NonBufferedTranslator()
+{
+}
+
+void NonBufferedTranslator::translateFrames(const FrameSeq& frames)
+{
+ FrameSeq translated;
+ translated.resize(frames.size());
+ std::transform(frames.begin(), frames.end(), translated.begin(), std::bind1st(std::mem_fun(&NonBufferedTranslator::translate), this));
+ mSource->distributeToSinks(translated);
+}
+
+}
+}
diff --git a/src/Translator.h b/src/NonBufferedTranslator.h
similarity index 80%
copy from src/Translator.h
copy to src/NonBufferedTranslator.h
index 2884875..97b85a0 100644
--- a/src/Translator.h
+++ b/src/NonBufferedTranslator.h
@@ -19,6 +19,7 @@
#include <AsteriskSCF/Media/MediaIf.h>
#include <AsteriskSCF/logger.h>
+#include "Translator.h"
#include "TranslatorSource.h"
namespace AsteriskSCF
@@ -27,15 +28,20 @@ namespace AsteriskSCF
namespace MediaOperationsCore
{
-class Translator : public IceUtil::Shared
+/**
+ * A base class for encapsualting translation of frame sequences.
+ * For use by translation operations that can be processed in
+ * a syncrhonous fashion.
+ */
+class NonBufferedTranslator : public Translator
{
public:
- Translator(const TranslatorSourcePtr& source,
+ NonBufferedTranslator(const TranslatorSourcePtr& source,
const AsteriskSCF::Media::V1::FormatPtr& inputFormat,
const AsteriskSCF::Media::V1::FormatPtr& outputFormat,
const AsteriskSCF::System::Logging::Logger& logger);
- virtual ~Translator();
+ virtual ~NonBufferedTranslator();
/**
* Translate each frame from the input format into the
@@ -48,6 +54,7 @@ public:
virtual AsteriskSCF::Media::V1::FramePtr translate(const AsteriskSCF::Media::V1::FramePtr inFrame) = 0;
/**
+ * @Override
* Feeds each of the frames in the
* sequence into the translate() function
*/
@@ -60,7 +67,7 @@ protected:
AsteriskSCF::System::Logging::Logger mLogger;
};
-typedef IceUtil::Handle<Translator> TranslatorPtr;
+typedef IceUtil::Handle<NonBufferedTranslator> NonBufferedTranslatorPtr;
}
}
diff --git a/src/Translator.h b/src/Translator.h
index 2884875..d3e20a5 100644
--- a/src/Translator.h
+++ b/src/Translator.h
@@ -27,37 +27,22 @@ namespace AsteriskSCF
namespace MediaOperationsCore
{
+/**
+ * Interface for providing a translation of frame sequences.
+ */
class Translator : public IceUtil::Shared
{
public:
- Translator(const TranslatorSourcePtr& source,
- const AsteriskSCF::Media::V1::FormatPtr& inputFormat,
- const AsteriskSCF::Media::V1::FormatPtr& outputFormat,
- const AsteriskSCF::System::Logging::Logger& logger);
- virtual ~Translator();
-
- /**
- * Translate each frame from the input format into the
- * output format.
- *
- * Note that implementors of this function should perform
- * a check to be certain that the format of the frame
- * being translated is what is expected for this translator
- */
- virtual AsteriskSCF::Media::V1::FramePtr translate(const AsteriskSCF::Media::V1::FramePtr inFrame) = 0;
+ virtual ~Translator() {}
/**
- * Feeds each of the frames in the
- * sequence into the translate() function
+ * Process the in incoming frames.
*/
- void translateFrames(const AsteriskSCF::Media::V1::FrameSeq& frames);
+ virtual void translateFrames(const AsteriskSCF::Media::V1::FrameSeq& frames) = 0;
protected:
- TranslatorSourcePtr mSource;
- AsteriskSCF::Media::V1::FormatPtr mInputFormat;
- AsteriskSCF::Media::V1::FormatPtr mOutputFormat;
- AsteriskSCF::System::Logging::Logger mLogger;
+ Translator() {}
};
typedef IceUtil::Handle<Translator> TranslatorPtr;
diff --git a/src/TranslatorOperation.cpp b/src/TranslatorOperation.cpp
index ea25865..00d07db 100644
--- a/src/TranslatorOperation.cpp
+++ b/src/TranslatorOperation.cpp
@@ -54,7 +54,7 @@ TranslatorOperation::~TranslatorOperation()
mAdapter->remove(mSourceProxy->ice_getIdentity());
mAdapter->remove(mSinkProxy->ice_getIdentity());
}
- catch (const Ice::Exception& ex)
+ catch (const Ice::Exception&)
{
mLogger(Error) << "Exception caught while trying to remove source and sink from object adapter";
}
diff --git a/src/TranslatorSink.h b/src/TranslatorSink.h
index 80b07db..68f2fcd 100644
--- a/src/TranslatorSink.h
+++ b/src/TranslatorSink.h
@@ -35,7 +35,7 @@ public:
~TranslatorSink();
- void write(const AsteriskSCF::Media::V1::FrameSeq& frames, const Ice::Current&);
+ virtual void write(const AsteriskSCF::Media::V1::FrameSeq& frames, const Ice::Current&);
void setTranslator(const TranslatorPtr& translator);
diff --git a/src/g722.cpp b/src/g722.cpp
index 038110d..0135f03 100644
--- a/src/g722.cpp
+++ b/src/g722.cpp
@@ -20,6 +20,7 @@
#include "g722.h"
#include "TranslatorOperation.h"
+#include "NonBufferedTranslator.h"
namespace AsteriskSCF
{
@@ -35,14 +36,14 @@ using namespace AsteriskSCF::Replication::MediaOperationsCore::V1;
class G722Operation : public TranslatorOperation
{
private:
- class G722Translator : public Translator
+ class G722Translator : public NonBufferedTranslator
{
public:
G722Translator (const TranslatorSourcePtr& source,
const FormatPtr& inputFormat,
const FormatPtr& outputFormat,
const Logger& logger)
- : Translator(source, inputFormat, outputFormat, logger)
+ : NonBufferedTranslator(source, inputFormat, outputFormat, logger)
{
//XXX Do we have any intention of supporting 48 Kbps or
//56 Kbps G.722?
diff --git a/src/resample.cpp b/src/resample.cpp
index 754d48f..1571e3b 100644
--- a/src/resample.cpp
+++ b/src/resample.cpp
@@ -20,7 +20,7 @@
#include "resample.h"
#include "TranslatorSource.h"
-#include "Translator.h"
+#include "NonBufferedTranslator.h"
#include "TranslatorSink.h"
#include "TranslatorOperation.h"
@@ -40,7 +40,7 @@ using namespace AsteriskSCF::Replication::MediaOperationsCore::V1;
class ResampleOperation : public TranslatorOperation
{
private:
- class Resampler : public Translator
+ class Resampler : public NonBufferedTranslator
{
public:
Resampler(const TranslatorSourcePtr& source,
@@ -48,7 +48,7 @@ private:
const FormatPtr& outputFormat,
const Logger& logger,
pj_caching_pool *caching_pool)
- : Translator(source, inputFormat, outputFormat, logger),
+ : NonBufferedTranslator(source, inputFormat, outputFormat, logger),
mParentPool(caching_pool),
mPool(0),
mResample(0)
diff --git a/src/ulaw_alaw.cpp b/src/ulaw_alaw.cpp
index 2d3e2a9..135c7e9 100644
--- a/src/ulaw_alaw.cpp
+++ b/src/ulaw_alaw.cpp
@@ -21,7 +21,7 @@
#include "ulaw_alaw.h"
#include "TranslatorSource.h"
-#include "Translator.h"
+#include "NonBufferedTranslator.h"
#include "TranslatorSink.h"
#include "TranslatorOperation.h"
@@ -40,14 +40,14 @@ using namespace AsteriskSCF::Replication::MediaOperationsCore::V1;
class UlawAlawOperation : public TranslatorOperation
{
private:
- class UlawAlawTranslator : public Translator
+ class UlawAlawTranslator : public NonBufferedTranslator
{
public:
UlawAlawTranslator(const TranslatorSourcePtr source,
const FormatPtr& inputFormat,
const FormatPtr& outputFormat,
const Logger& logger)
- : Translator(source, inputFormat, outputFormat, logger)
+ : NonBufferedTranslator(source, inputFormat, outputFormat, logger)
{
}
commit f652a95e1599540c3eeabc71046a2df1e597d598
Author: Kevin P. Fleming <kpfleming at digium.com>
Date: Fri Sep 30 13:27:25 2011 -0500
Use AsteriskSCF::PJLib::ThreadHook for tracking threads created by the
Ice runtime.
Review: https://code.asterisk.org/code/cru/CR-ASTSCF-168
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 8fb6d1f..d4b15f4 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -31,7 +31,7 @@ astscf_component_add_slices(MediaOperationsCore PROJECT AsteriskSCF/Replication/
astscf_component_add_slice_collection_libraries(MediaOperationsCore ASTSCF)
astscf_component_add_boost_libraries(MediaOperationsCore core thread date_time)
astscf_component_build_icebox(MediaOperationsCore)
-target_link_libraries(MediaOperationsCore logging-client astscf-ice-util-cpp)
+target_link_libraries(MediaOperationsCore logging-client astscf-ice-util-cpp astscf-ice-util-cpp-pjlib)
pjproject_link(MediaOperationsCore pjlib)
pjproject_link(MediaOperationsCore pjlib-util)
diff --git a/src/MediaOperationsCore.cpp b/src/MediaOperationsCore.cpp
index 7c80d67..edaec40 100644
--- a/src/MediaOperationsCore.cpp
+++ b/src/MediaOperationsCore.cpp
@@ -19,6 +19,7 @@
#include <AsteriskSCF/Component/Component.h>
#include <AsteriskSCF/Media/MediaOperationIf.h>
+#include <AsteriskSCF/PJLib/ThreadHook.h>
#include <AsteriskSCF/logger.h>
#include "MediaOperationReplicationContext.h"
@@ -96,83 +97,6 @@ private:
typedef IceUtil::Handle<MediaOperationsCompare> MediaOperationsComparePtr;
-/**
- * Wrapper class around pj_thread_desc.
- */
-class ThreadDescWrapper
-{
-public:
- ThreadDescWrapper()
- {
- memset(mDesc, 0, sizeof(mDesc));
- }
-
- /**
- * pjthread thread description information, must persist for the life of the thread
- */
- pj_thread_desc mDesc;
-};
-
-/**
- * Type definition used to create a smart pointer for the above.
- */
-typedef boost::shared_ptr<ThreadDescWrapper> ThreadDescWrapperPtr;
-
-//XXX Seriously how many places is this repeated?
-/**
- * Implementation of the Ice::ThreadNotification class.
- */
-class pjlibHook : public Ice::ThreadNotification
-{
-public:
- pjlibHook()
- {
- pj_init();
- }
-
- /**
- * Implementation of the start function which is called when a thread starts.
- */
- void start()
- {
- ThreadDescWrapperPtr wrapper(new ThreadDescWrapper());
- pj_thread_t *thread;
- pj_status_t win = pj_thread_register("ICE Thread", wrapper->mDesc, &thread);
- if (win != PJ_SUCCESS)
- {
- lg(Critical) << "Unable to register thread with PJLIB.";
- return;
- }
- else
- {
- boost::lock_guard<boost::mutex> lock(mLock);
- mpjThreads.insert(std::make_pair(thread, wrapper));
- }
- }
-
- /**
- * Implementation of the stop function which is called when a thread stops.
- */
- void stop()
- {
- if (pj_thread_is_registered())
- {
- boost::lock_guard<boost::mutex> lock(mLock);
- mpjThreads.erase(pj_thread_this());
- }
- }
-
-private:
- /**
- * A map containing thread lifetime persistent data.
- */
- std::map<pj_thread_t*, ThreadDescWrapperPtr> mpjThreads;
- /**
- * Mutex to protect the map
- */
- boost::mutex mLock;
-};
-
class MediaOperationsComponent : public AsteriskSCF::Component::Component
{
public:
@@ -197,7 +121,7 @@ private:
factory->setProxy(factoryProxy);
mFactories.push_back(std::make_pair(factory, factoryProxy));
}
-
+
void createOperationFactories()
{
lg(Debug) << "Creating UlawAlawFactory";
@@ -228,7 +152,7 @@ private:
try
{
AsteriskSCF::Discovery::SmartProxy<MediaOperationStateReplicatorPrx> pw(getServiceLocator(), params, lg);
- MediaOperationReplicationContextPtr context =
+ MediaOperationReplicationContextPtr context =
boost::static_pointer_cast<MediaOperationReplicationContext>(getReplicationContext());
context->setReplicator(pw);
@@ -257,19 +181,19 @@ private:
iter->first->getName(),
iter->first->getLocatorParams(),
iter->first->getName()));
-
+
managePrimaryService(wrapper);
}
}
// Below are overrides of the base component class.
-
+
void onPreInitialize()
{
try
{
Ice::InitializationData id;
- id.threadHook = new pjlibHook();
+ id.threadHook = new AsteriskSCF::PJLib::ThreadHook("Ice");
id.properties = getCommunicator()->getProperties();
setCommunicator(Ice::initialize(id));
@@ -320,7 +244,7 @@ private:
MediaOperationStateReplicatorListenerPrx replicatorListener =
MediaOperationStateReplicatorListenerPrx::uncheckedCast(getBackplaneAdapter()->addWithUUID(mReplicatorListener));
-
+
mReplicatorListenerProxy = MediaOperationStateReplicatorListenerPrx::uncheckedCast(replicatorListener->ice_oneway());
}
@@ -340,7 +264,7 @@ private:
}
try
- {
+ {
if (context->getState() == STANDBY_IN_REPLICA_GROUP)
{
context->getReplicator()->addListener(mReplicatorListenerProxy);
@@ -356,14 +280,14 @@ private:
void stopListeningToStateReplicators()
{
- MediaOperationReplicationContextPtr context =
+ MediaOperationReplicationContextPtr context =
boost::static_pointer_cast<MediaOperationReplicationContext>(getReplicationContext());
-
+
if ((!context->getReplicator().isInitialized()) || (mListeningToReplicator == false))
{
return;
}
-
+
try
{
context->getReplicator()->removeListener(mReplicatorListenerProxy);
commit 4f1d6bb50856993502dba2b38e9c0851093f8fed
Author: David M. Lee <dlee at digium.com>
Date: Fri Sep 30 12:06:42 2011 -0500
Even better category for the state replicator.
diff --git a/slice/AsteriskSCF/Replication/MediaOperationsCore/MediaOperationsCoreIf.ice b/slice/AsteriskSCF/Replication/MediaOperationsCore/MediaOperationsCoreIf.ice
index e6fbe5f..ec46309 100644
--- a/slice/AsteriskSCF/Replication/MediaOperationsCore/MediaOperationsCoreIf.ice
+++ b/slice/AsteriskSCF/Replication/MediaOperationsCore/MediaOperationsCoreIf.ice
@@ -33,8 +33,8 @@ module MediaOperationsCore
module V1
{
-const string StateReplicatorComponentCategory = "MediaOperationsCoreComponent";
-const string StateReplicatorDiscoveryCategory = "MediaOperationsCore";
+const string StateReplicatorComponentCategory = "MediaOperationsCoreStateReplicatorComponent";
+const string StateReplicatorDiscoveryCategory = "MediaOperationsCoreStateReplicator";
["visitor"] local class MediaOperationStateItemVisitor
{
commit b8869a1342af77213729e7cf4f7e6e7ae0386042
Author: David M. Lee <dlee at digium.com>
Date: Fri Sep 30 12:03:38 2011 -0500
Fixed copy/paste error in discovery categories.
diff --git a/slice/AsteriskSCF/Replication/MediaOperationsCore/MediaOperationsCoreIf.ice b/slice/AsteriskSCF/Replication/MediaOperationsCore/MediaOperationsCoreIf.ice
index 313bc60..e6fbe5f 100644
--- a/slice/AsteriskSCF/Replication/MediaOperationsCore/MediaOperationsCoreIf.ice
+++ b/slice/AsteriskSCF/Replication/MediaOperationsCore/MediaOperationsCoreIf.ice
@@ -33,8 +33,8 @@ module MediaOperationsCore
module V1
{
-const string StateReplicatorComponentCategory = "SipStateReplicatorComponent";
-const string StateReplicatorDiscoveryCategory = "SipStateReplicator";
+const string StateReplicatorComponentCategory = "MediaOperationsCoreComponent";
+const string StateReplicatorDiscoveryCategory = "MediaOperationsCore";
["visitor"] local class MediaOperationStateItemVisitor
{
commit ca09cf28123cbde2597978569feaa47dd734b196
Author: Ken Hunt <ken.hunt at digium.com>
Date: Thu Sep 22 13:04:11 2011 -0500
Update ice config file for unit tests for recent config updates.
diff --git a/config/test_component.conf b/config/test_component.conf
index e3ec775..d605e16 100644
--- a/config/test_component.conf
+++ b/config/test_component.conf
@@ -14,9 +14,9 @@ IceBox.LoadOrder=ServiceDiscovery,MediaOperationsCore,MediaOperationsCoreTest
LocatorServiceManagement.Proxy=LocatorServiceManagement:tcp -p 4422
LocatorService.Proxy=LocatorService:tcp -p 4411
-MediaOperationsCore.Endpoints=default
+MediaOperationsCore.ServiceAdapter.Endpoints=default
-MediaOperationsCore.Backplane.Endpoints=default
+MediaOperationsCore.BackplaneAdapter.Endpoints=default
MediaOperationsCore.Standalone=true
@@ -24,47 +24,19 @@ MediaOperationsCore.ComponentTest=false
MediaOperationsCore.ServiceName=MediaOperationsCoreService
-TopicManager.Proxy=AsteriskSCFIceStorm/TopicManager:tcp -p 10000
+TopicManager.Proxy=ServiceDiscovery/TopicManager:tcp -p 4421
##########################################
# Service Locator properties
-AsteriskSCFIceStorm.InstanceName=AsteriskSCFIceStorm
-#
-# This property defines the endpoints on which the IceStorm
-# TopicManager listens.
-#
-AsteriskSCFIceStorm.TopicManager.Endpoints=default -p 10000
-
-#
-# This property defines the endpoints on which the topic
-# publisher objects listen. If you want to federate
-# IceStorm instances this must run on a fixed port (or use
-# IceGrid).
-#
-AsteriskSCFIceStorm.Publish.Endpoints=tcp -p 10001:udp -p 10001
-
-#
-# TopicManager Tracing
-#
-# 0 = no tracing
-# 1 = trace topic creation, subscription, unsubscription
-# 2 = like 1, but with more detailed subscription information
-#
-AsteriskSCFIceStorm.Trace.TopicManager=2
-AsteriskSCFIceStorm.Transient=1
-
-#
-AsteriskSCFIceStorm.Flush.Timeout=2000
-# This is a configuration file used in conjunction with the service locator test driver
-
-# Test endpoints for the service locator management adapter
-ServiceLocatorManagementAdapter.Endpoints=tcp -p 4422
-
-# Test endpoints for the service locator adapter
-ServiceLocatorAdapter.Endpoints=tcp -p 4411
-ServiceLocatorLocalAdapter.Endpoints=tcp -p 4412
-
-# Logger configuration
-LoggerAdapter.Endpoints=default
-AsteriskSCF.Logging.logger.AsteriskSCF=Debug
+ServiceDiscovery.IceStorm.InstanceName=ServiceDiscovery
+
+ServiceDiscovery.IceStorm.TopicManager.Endpoints=tcp -p 4421
+ServiceDiscovery.IceStorm.Publish.Endpoints=tcp -p 4423
+ServiceDiscovery.IceStorm.Trace.TopicManager=2
+ServiceDiscovery.IceStorm.Transient=1
+ServiceDiscovery.IceStorm.Flush.Timeout=2000
+
+LocatorServiceManagement.Proxy=LocatorServiceManagement:tcp -p 4412
+LocatorService.Proxy=LocatorService:tcp -p 4411
+
commit 4a225125a0701d5446c0e27c93c8610ba18f01c2
Merge: d4088b2 52a1c39
Author: Kevin P. Fleming <kpfleming at digium.com>
Date: Thu Sep 22 10:43:55 2011 -0500
Merge branch 'master' of git.asterisk.org:asterisk-scf/release/media_operations_core
commit d4088b2c7514a2dcfbb7036fc4d0cfee9a046626
Author: Kevin P. Fleming <kpfleming at digium.com>
Date: Thu Sep 22 10:40:49 2011 -0500
Various PJLIB-related fixes to resolve a crash problem.
After starting this component, and leaving it idle, the Ice runtime will decide
to terminate a number of the threads it started initially. At this point, the
component crashed due a double-free being attempted. The underlying cause for
this was not calling pj_init() before calling pj_thread_register(), so this
patch corrects that and also changes a few other things.
* Add a constructor to ThreadDescWrapper to ensure that mDesc is zeroed.
* Add a constructor to pjLibHook to call pj_init().
* Rename pjLibHook::pjThreads to mpjThreads to conform to coding guidelines.
* Test for a non-success result from pj_thread_register() (although unfortunately
it does not return a failure in the situation described above).
diff --git a/src/MediaOperationsCore.cpp b/src/MediaOperationsCore.cpp
index 296d41b..7c80d67 100644
--- a/src/MediaOperationsCore.cpp
+++ b/src/MediaOperationsCore.cpp
@@ -102,6 +102,11 @@ typedef IceUtil::Handle<MediaOperationsCompare> MediaOperationsComparePtr;
class ThreadDescWrapper
{
public:
+ ThreadDescWrapper()
+ {
+ memset(mDesc, 0, sizeof(mDesc));
+ }
+
/**
* pjthread thread description information, must persist for the life of the thread
*/
@@ -120,17 +125,28 @@ typedef boost::shared_ptr<ThreadDescWrapper> ThreadDescWrapperPtr;
class pjlibHook : public Ice::ThreadNotification
{
public:
+ pjlibHook()
+ {
+ pj_init();
+ }
+
/**
* Implementation of the start function which is called when a thread starts.
*/
void start()
{
- ThreadDescWrapperPtr wrapper = ThreadDescWrapperPtr(new ThreadDescWrapper());
+ ThreadDescWrapperPtr wrapper(new ThreadDescWrapper());
pj_thread_t *thread;
- pj_thread_register("ICE Thread", wrapper->mDesc, &thread);
+ pj_status_t win = pj_thread_register("ICE Thread", wrapper->mDesc, &thread);
+ if (win != PJ_SUCCESS)
+ {
+ lg(Critical) << "Unable to register thread with PJLIB.";
+ return;
+ }
+ else
{
boost::lock_guard<boost::mutex> lock(mLock);
- pjThreads.insert(std::make_pair(thread, wrapper));
+ mpjThreads.insert(std::make_pair(thread, wrapper));
}
}
@@ -142,7 +158,7 @@ public:
if (pj_thread_is_registered())
{
boost::lock_guard<boost::mutex> lock(mLock);
- pjThreads.erase(pj_thread_this());
+ mpjThreads.erase(pj_thread_this());
}
}
@@ -150,7 +166,7 @@ private:
/**
* A map containing thread lifetime persistent data.
*/
- std::map<pj_thread_t*, ThreadDescWrapperPtr> pjThreads;
+ std::map<pj_thread_t*, ThreadDescWrapperPtr> mpjThreads;
/**
* Mutex to protect the map
*/
commit 52a1c399215cca3fd4c3627818639113e30d1148
Author: Brent Eagles <beagles at digium.com>
Date: Wed Sep 21 20:43:00 2011 -0230
Fix what would probably cause a problem if pj lib's function doesn't check for
null.
diff --git a/src/resample.cpp b/src/resample.cpp
index 5d986d1..754d48f 100644
--- a/src/resample.cpp
+++ b/src/resample.cpp
@@ -63,7 +63,10 @@ private:
~Resampler()
{
- pj_pool_release(mPool);
+ if (mPool)
+ {
+ pj_pool_release(mPool);
+ }
}
FramePtr translate(const FramePtr inFrame)
commit e1cb6f9361e048b2a93abdd58f7050ef4e81a9c2
Author: Brent Eagles <beagles at digium.com>
Date: Wed Sep 21 11:39:45 2011 -0230
Fix a problem where pjX methods were being called from the IceBox start thread
which does not have the pjthread hook installed. I altered the initialization
to be "lazy" so the pjlib methods are only called through the Ice communicator
that has the appropriate hook installed.
diff --git a/src/resample.cpp b/src/resample.cpp
index 572bc1a..5d986d1 100644
--- a/src/resample.cpp
+++ b/src/resample.cpp
@@ -48,24 +48,17 @@ private:
const FormatPtr& outputFormat,
const Logger& logger,
pj_caching_pool *caching_pool)
- : Translator(source, inputFormat, outputFormat, logger)
+ : Translator(source, inputFormat, outputFormat, logger),
+ mParentPool(caching_pool),
+ mPool(0),
+ mResample(0)
{
- mPool = pj_pool_create(&caching_pool->factory, "Who cares", 256, 256, NULL);
-
AudioFormatPtr inputAudio = AudioFormatPtr::dynamicCast(inputFormat);
AudioFormatPtr outputAudio = AudioFormatPtr::dynamicCast(outputFormat);
mOutputFrameSize = (outputAudio->sampleRate * inputAudio->frameSize) / inputAudio->sampleRate;
mLogger(Debug) << "Output frames for resampler will contain " << mOutputFrameSize << " samples";
- pjmedia_resample_create(mPool,
- true,
- true,
- 1,
- inputAudio->sampleRate,
- outputAudio->sampleRate,
- inputAudio->frameSize,
- &mResample);
}
~Resampler()
@@ -75,6 +68,23 @@ private:
FramePtr translate(const FramePtr inFrame)
{
+ //
+ // Lazy initialization to avoid issues with when the pjlib thread hook is installed.
+ //
+ if (!mPool)
+ {
+ mPool = pj_pool_create(&mParentPool->factory, "Who cares", 256, 256, NULL);
+ AudioFormatPtr inputAudio = AudioFormatPtr::dynamicCast(mInputFormat);
+ AudioFormatPtr outputAudio = AudioFormatPtr::dynamicCast(mOutputFormat);
+ pjmedia_resample_create(mPool,
+ true,
+ true,
+ 1,
+ inputAudio->sampleRate,
+ outputAudio->sampleRate,
+ inputAudio->frameSize,
+ &mResample);
+ }
if (!TranslatorOperationFactory::formatsEqual(inFrame->mediaFormat, mInputFormat))
{
mLogger(Error) << "Cannot resample frame because the format is not what was expected";
@@ -106,6 +116,7 @@ private:
return new Frame(outFormat, outPayload);
}
private:
+ pj_caching_pool* mParentPool;
pj_pool_t *mPool;
pjmedia_resample *mResample;
int mOutputFrameSize;
@@ -137,12 +148,10 @@ typedef IceUtil::Handle<ResampleOperation> ResampleOperationPtr;
ResampleFactory::ResampleFactory(const Ice::ObjectAdapterPtr& adapter,
const AsteriskSCF::System::Logging::Logger& logger,
const MediaOperationReplicationContextPtr& replicationContext)
- : TranslatorOperationFactory(adapter, logger, replicationContext, "ResampleFactory")
+ : TranslatorOperationFactory(adapter, logger, replicationContext, "ResampleFactory"),
+ mInitialized(false)
{
buildTranslations();
-
- pj_memset(&mCachingPool, 0, sizeof(mCachingPool));
- pj_caching_pool_init(&mCachingPool, NULL, 1024 * 1024);
}
MediaOperationPrx ResampleFactory::createMediaOperation(
@@ -150,6 +159,19 @@ MediaOperationPrx ResampleFactory::createMediaOperation(
const FormatPtr& sinkFormat,
const std::string& operationId)
{
+ {
+ //
+ // Lazy initialization to avoid calling pjlib functions in a thread before the
+ // required hooks can be called.
+ //
+ boost::mutex::scoped_lock lock(mLock);
+ if (!mInitialized)
+ {
+ pj_memset(&mCachingPool, 0, sizeof(mCachingPool));
+ pj_caching_pool_init(&mCachingPool, NULL, 1024 * 1024);
+ mInitialized = true;
+ }
+ }
ResampleOperationPtr operation(
new ResampleOperation(
mAdapter,
diff --git a/src/resample.h b/src/resample.h
index b3ae897..11719c0 100644
--- a/src/resample.h
+++ b/src/resample.h
@@ -19,6 +19,7 @@
#include <pjmedia.h>
#include "TranslatorOperationFactory.h"
+#include <boost/thread/locks.hpp>
namespace AsteriskSCF
{
@@ -40,6 +41,8 @@ public:
private:
void buildTranslations();
+ boost::mutex mLock;
+ bool mInitialized;
pj_caching_pool mCachingPool;
};
commit 2f1f5f2b6a16000e46a51bc6b83f99e8b2c40dda
Author: Joshua Colp <jcolp at digium.com>
Date: Mon Sep 19 16:25:22 2011 -0300
Make the media operations core component conform to the configuration file in the examples repo.
diff --git a/config/test_component.config b/config/test_component.conf
similarity index 100%
rename from config/test_component.config
rename to config/test_component.conf
diff --git a/src/MediaOperationStateReplicatorApp.cpp b/src/MediaOperationStateReplicatorApp.cpp
index ed01019..ed61e9e 100644
--- a/src/MediaOperationStateReplicatorApp.cpp
+++ b/src/MediaOperationStateReplicatorApp.cpp
@@ -52,7 +52,8 @@ public:
virtual void stop();
void createStateReplicator(const Ice::CommunicatorPtr& communicator);
- void registerWithServiceLocator(const Ice::CommunicatorPtr& communicator);
+ void registerWithServiceLocator(const Ice::CommunicatorPtr& communicator,
+ const std::string& appName);
ServiceLocatorManagementPrx mManagement;
Ice::ObjectAdapterPtr mAdapter;
@@ -65,7 +66,8 @@ void MediaOperationStateReplicatorService::createStateReplicator(const Ice::Comm
mAdapter->add(mReplicator, communicator->stringToIdentity(ReplicatorId));
}
-void MediaOperationStateReplicatorService::registerWithServiceLocator(const Ice::CommunicatorPtr& communicator)
+void MediaOperationStateReplicatorService::registerWithServiceLocator(const Ice::CommunicatorPtr& communicator,
+ const std::string& appName)
{
MediaOperationStateReplicatorPrx stateReplicatorProxy =
MediaOperationStateReplicatorPrx::uncheckedCast(mAdapter->createDirectProxy(communicator->stringToIdentity(ReplicatorId)));
@@ -74,21 +76,21 @@ void MediaOperationStateReplicatorService::registerWithServiceLocator(const Ice:
ServiceLocatorParamsPtr params = new ServiceLocatorParams();
params->category = StateReplicatorDiscoveryCategory;
- params->service = communicator->getProperties()->getPropertyWithDefault("MediaOperationStateReplicator.Service", "default");
- params->id = communicator->getProperties()->getPropertyWithDefault("MediaOperationStateReplicator.Name", "default");
+ params->service = communicator->getProperties()->getPropertyWithDefault(appName + ".ServiceName", "default");
+ params->id = appName;
serviceManagement->addLocatorParams(params, "");
}
void MediaOperationStateReplicatorService::start(
- const std::string&,
+ const std::string& appName,
const Ice::CommunicatorPtr& communicator,
const Ice::StringSeq&)
{
- mManagement = ServiceLocatorManagementPrx::checkedCast(communicator->propertyToProxy("ServiceLocatorManagementProxy"));
- mAdapter = communicator->createObjectAdapter("MediaOperationStateReplicatorAdapter");
+ mManagement = ServiceLocatorManagementPrx::checkedCast(communicator->propertyToProxy("LocatorServiceManagement.Proxy"));
+ mAdapter = communicator->createObjectAdapter(appName + ".Adapter");
createStateReplicator(communicator);
- registerWithServiceLocator(communicator);
+ registerWithServiceLocator(communicator, appName);
mAdapter->activate();
}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 82b0a08..88140cb 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -10,7 +10,7 @@ astscf_component_add_boost_libraries(MediaOperationsCoreTest unit_test_framework
astscf_component_add_slice_collection_libraries(MediaOperationsCoreTest ASTSCF)
astscf_component_build_icebox(MediaOperationsCoreTest)
-astscf_test_icebox(MediaOperationsCoreTest config/test_component.config)
+astscf_test_icebox(MediaOperationsCoreTest config/test_component.conf)
target_link_libraries(MediaOperationsCoreTest astscf-ice-util-cpp)
pjproject_link(MediaOperationsCoreTest pjsip)
commit ccb310e61f696d54ec43df4b074c1cf35ac1e148
Author: Brent Eagles <beagles at digium.com>
Date: Fri Sep 16 14:24:30 2011 -0230
Some fixes for building on Windows
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b7aee9c..8fb6d1f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -29,6 +29,7 @@ astscf_component_add_files(MediaOperationsCore MediaOperationReplicationContext.
astscf_component_add_files(MediaOperationsCore MediaOperationStateReplicator.h)
astscf_component_add_slices(MediaOperationsCore PROJECT AsteriskSCF/Replication/MediaOperationsCore/MediaOperationsCoreIf.ice)
astscf_component_add_slice_collection_libraries(MediaOperationsCore ASTSCF)
+astscf_component_add_boost_libraries(MediaOperationsCore core thread date_time)
astscf_component_build_icebox(MediaOperationsCore)
target_link_libraries(MediaOperationsCore logging-client astscf-ice-util-cpp)
@@ -36,7 +37,6 @@ pjproject_link(MediaOperationsCore pjlib)
pjproject_link(MediaOperationsCore pjlib-util)
pjproject_link(MediaOperationsCore pjmedia)
pjproject_link(MediaOperationsCore pjnath)
-pjproject_link(MediaOperationsCore resample)
astscf_component_install(MediaOperationsCore)
astscf_component_init(MediaOperationStateReplicator)
diff --git a/src/g722/g722_decode.c b/src/g722/g722_decode.c
index 233bee5..0f33daf 100644
--- a/src/g722/g722_decode.c
+++ b/src/g722/g722_decode.c
@@ -28,7 +28,16 @@
#endif
#include <stdio.h>
+
+#ifndef _WIN32
#include <inttypes.h>
+#define INLINE __inline__
+#else
+#ifndef INLINE
+#define INLINE /**/
+#endif
+#endif
+
#include <memory.h>
#include <stdlib.h>
#if 0
@@ -44,7 +53,7 @@
#define TRUE (!FALSE)
#endif
-static __inline__ int16_t saturate(int32_t amp)
+static INLINE int16_t saturate(int32_t amp)
{
int16_t amp16;
diff --git a/src/g722/g722_encode.c b/src/g722/g722_encode.c
index db563a7..ed2d165 100644
--- a/src/g722/g722_encode.c
+++ b/src/g722/g722_encode.c
@@ -30,7 +30,16 @@
#endif
#include <stdio.h>
+
+#ifndef _WIN32
#include <inttypes.h>
+#define INLINE __inline__
+#else
+#ifndef INLINE
+#define INLINE /**/
+#endif
+#endif
+
#include <memory.h>
#include <stdlib.h>
#if 0
@@ -46,7 +55,7 @@
#define TRUE (!FALSE)
#endif
-static __inline__ int16_t saturate(int32_t amp)
+static INLINE int16_t saturate(int32_t amp)
{
int16_t amp16;
-----------------------------------------------------------------------
--
asterisk-scf/integration/media_operations_core.git
More information about the asterisk-scf-commits
mailing list