[asterisk-scf-commits] asterisk-scf/integration/bridging.git branch "mediamixer" updated.
Commits to the Asterisk SCF project code repositories
asterisk-scf-commits at lists.digium.com
Wed Aug 31 16:21:35 CDT 2011
branch "mediamixer" has been updated
via c503f171554fa572219ebdcecba7729a963b8128 (commit)
from e5cae4226e48ac5ba477e598292e0c185e3188bf (commit)
Summary of changes:
src/MediaMixer.cpp | 138 +++++++++++++++++++++++++++++++++++++++++++++-----
src/MediaSplicer.cpp | 9 ++--
2 files changed, 130 insertions(+), 17 deletions(-)
- Log -----------------------------------------------------------------
commit c503f171554fa572219ebdcecba7729a963b8128
Author: Joshua Colp <jcolp at digium.com>
Date: Wed Aug 31 18:26:09 2011 -0300
Put in a slew of fixes which gets things to the point where a mixer is setup and frames go to it as expected. Hangup is not currently functional though, it seems.
diff --git a/src/MediaMixer.cpp b/src/MediaMixer.cpp
index 594d95d..f0f703d 100755
--- a/src/MediaMixer.cpp
+++ b/src/MediaMixer.cpp
@@ -145,6 +145,8 @@ public:
{
boost::unique_lock<boost::shared_mutex> lock(mLock);
+ std::cout << "Frame goes in" << std::endl;
+
mFrames.insert(mFrames.begin(), frames.begin(), frames.end());
}
@@ -186,10 +188,9 @@ public:
{
boost::unique_lock<boost::shared_mutex> lock(mLock);
- mProvidedFrame = mFrames.back();
-
- if (mProvidedFrame)
+ if (!mFrames.empty())
{
+ mProvidedFrame = mFrames.back();
mFrames.pop_back();
}
@@ -225,6 +226,14 @@ public:
return mProxy;
}
+ /**
+ * Internal function which returns the local source.
+ */
+ MediaMixerSourcePtr getLocalSource()
+ {
+ return mLocalSource;
+ }
+
private:
/**
* Lock which protects this sink.
@@ -268,10 +277,36 @@ private:
FramePtr mProvidedFrame;
};
+/**
+ * Simple callback object used when writing to sinks.
+ */
+class WriteCallback : public IceUtil::Shared
+{
+public:
+ void writtenCB()
+ {
+ }
+
+ void failureCB(const Ice::Exception&)
+ {
+ }
+};
+
+/**
+ * Smart pointer for the above WriteCallback class.
+ */
+typedef IceUtil::Handle<WriteCallback> WriteCallbackPtr;
+
class MediaMixerI
{
public:
- MediaMixerI(const Ice::ObjectAdapterPtr& adapter) : mAdapter(adapter), mTimer(new IceUtil::Timer()) { }
+ MediaMixerI(const Ice::ObjectAdapterPtr& adapter) : mAdapter(adapter), mTimer(new IceUtil::Timer()),
+ mCallback(new WriteCallback()) { }
+
+ /**
+ * Lock which protects the mixer.
+ */
+ boost::shared_mutex mLock;
/**
* Object adapter that sinks/sources are on.
@@ -292,6 +327,11 @@ public:
* Timer thread used to mix the media.
*/
IceUtil::TimerPtr mTimer;
+
+ /**
+ * Callback object for when writing to sinks.
+ */
+ WriteCallbackPtr mCallback;
};
MediaMixer::MediaMixer(const Ice::ObjectAdapterPtr& adapter) : mImpl(new MediaMixerI(adapter))
@@ -302,44 +342,116 @@ MediaMixer::MediaMixer(const Ice::ObjectAdapterPtr& adapter) : mImpl(new MediaMi
void MediaMixer::createMixing(const Ice::Identity& sinkId, AsteriskSCF::Media::V1::StreamSinkPrx& mixerSink,
const Ice::Identity& sourceId, AsteriskSCF::Media::V1::StreamSourcePrx& mixerSource)
{
+ boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
+
// The source is where mixed audio will originate from, within this implementation it essentially acts
// as a store of sinks we need to write to for this source
- MediaMixerSourcePtr source = new MediaMixerSource(this);
- mImpl->mSources.push_back(source);
Ice::Identity id = sourceId;
id.name += ".mixer";
- mixerSource = StreamSourcePrx::uncheckedCast(mImpl->mAdapter->add(source, id));
- source->setProxy(mixerSource);
+ MediaMixerSourcePtr source;
+ if (mImpl->mAdapter->find(id))
+ {
+ mixerSource = StreamSourcePrx::uncheckedCast(mImpl->mAdapter->createProxy(id));
+ }
+ else
+ {
+ source = new MediaMixerSource(this);
+ mImpl->mSources.push_back(source);
+ mixerSource = StreamSourcePrx::uncheckedCast(mImpl->mAdapter->add(source, id));
+ source->setProxy(mixerSource);
+ }
// The sink is where the source will send audio to to be mixed into the bridge, the reason the local source
// is associated is because we need to know what media to remove from the mixed frame when writing out
- MediaMixerSinkPtr sink = new MediaMixerSink(this, source);
- mImpl->mSinks.push_back(sink);
id = sinkId;
id.name += ".mixer";
- mixerSink = StreamSinkPrx::uncheckedCast(mImpl->mAdapter->add(sink, id));
- sink->setProxy(mixerSink);
+ if (mImpl->mAdapter->find(id))
+ {
+ mixerSink = StreamSinkPrx::uncheckedCast(mImpl->mAdapter->createProxy(id));
+ }
+ else
+ {
+ MediaMixerSinkPtr sink = new MediaMixerSink(this, source);
+ mImpl->mSinks.push_back(sink);
+ mixerSink = StreamSinkPrx::uncheckedCast(mImpl->mAdapter->add(sink, id));
+ sink->setProxy(mixerSink);
+ }
}
void MediaMixer::runTimerTask()
{
- // MIXING CODE GOES HERE
+ std::vector<MediaMixerSinkPtr> sinks;
+
+ {
+ boost::shared_lock<boost::shared_mutex> lock(mImpl->mLock);
+ sinks = mImpl->mSinks;
+ }
+
+ FramePtr frame = new Frame();
+
+ for (std::vector<MediaMixerSinkPtr>::const_iterator sink = sinks.begin();
+ sink != sinks.end();
+ ++sink)
+ {
+ FramePtr sinkFrame = (*sink)->getFrame();
+
+ // If no frame exists for us to mix in skip doing so
+ if (!sinkFrame)
+ {
+ continue;
+ }
+ }
+
+ for (std::vector<MediaMixerSinkPtr>::const_iterator sink = sinks.begin();
+ sink != sinks.end();
+ ++sink)
+ {
+ FramePtr sinkFrame = (*sink)->popFrame();
+ FramePtr theirFrame(frame);
+
+ if (sinkFrame)
+ {
+ // If a frame was mixed in mix it out so we don't send their own audio to them
+ theirFrame = FramePtr::dynamicCast(frame->ice_clone());
+ }
+
+ // Send this frame to all the sinks we should
+ StreamSinkSeq sourceSinks = (*sink)->getLocalSource()->getSinks(Ice::Current());
+
+ FrameSeq frames;
+ frames.push_back(theirFrame);
+
+ for (StreamSinkSeq::const_iterator sourceSink = sourceSinks.begin();
+ sourceSink != sourceSinks.end();
+ ++sourceSink)
+ {
+ (*sourceSink)->begin_write(frames, newCallback_StreamSink_write(mImpl->mCallback,
+ &WriteCallback::writtenCB,
+ &WriteCallback::failureCB));
+ }
+ }
}
void MediaMixer::removeSource(const MediaMixerSourcePtr& source, const StreamSourcePrx& proxy)
{
+ boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
+
mImpl->mSources.erase(std::remove(mImpl->mSources.begin(), mImpl->mSources.end(), source), mImpl->mSources.end());
mImpl->mAdapter->remove(proxy->ice_getIdentity());
}
void MediaMixer::removeSink(const MediaMixerSinkPtr& sink, const StreamSinkPrx& proxy)
{
+ boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
+
mImpl->mSinks.erase(std::remove(mImpl->mSinks.begin(), mImpl->mSinks.end(), sink), mImpl->mSinks.end());
mImpl->mAdapter->remove(proxy->ice_getIdentity());
}
void MediaMixer::stop()
{
+ boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
+
mImpl->mTimer->destroy();
for (std::vector<MediaMixerSinkPtr>::const_iterator sink = mImpl->mSinks.begin();
diff --git a/src/MediaSplicer.cpp b/src/MediaSplicer.cpp
index 6b2ccab..42b19df 100755
--- a/src/MediaSplicer.cpp
+++ b/src/MediaSplicer.cpp
@@ -398,7 +398,7 @@ public:
mBridgeId(bridgeId),
mReplicator(replicator),
mLogger(logger),
- mMixer(false),
+ mMixer(true),
mAdapter(adapter)
{
}
@@ -508,7 +508,7 @@ public:
}
MediaMixerPtr mixer;
- while ((mixer = mMediaMixers.back()))
+ while (!mMediaMixers.empty())
{
mixer->stop();
mMediaMixers.pop_back();
@@ -555,10 +555,10 @@ public:
continue;
}
- MediaMixerPtr mixer = mixers.back();
+ MediaMixerPtr mixer;
// How do we determine what the 'right' mixer is to use?
- if (mixer == 0)
+ if (mixers.empty())
{
mLogger(Debug) << FUNLOG << ": creating media mixer.";
mixer = new MediaMixer(mAdapter);
@@ -567,6 +567,7 @@ public:
else
{
mLogger(Debug) << FUNLOG << ": using found media mixer.";
+ mixer = mixers.back();
mixers.pop_back();
}
-----------------------------------------------------------------------
--
asterisk-scf/integration/bridging.git
More information about the asterisk-scf-commits
mailing list