[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