[asterisk-scf-commits] asterisk-scf/integration/file_media_service.git branch "initial_development" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Wed Oct 12 09:52:51 CDT 2011


branch "initial_development" has been updated
       via  883f26046f8ebe1d4337581de99a07e32d86d3e9 (commit)
      from  12ee5808908be376f29b5246c71106e5d0704f67 (commit)

Summary of changes:
 src/MatroskaCodec.cpp |   30 -
 src/MatroskaCodec.h   |   83 ---
 src/MatroskaUtils.cpp | 1541 -------------------------------------------------
 src/MatroskaUtils.h   |  275 ---------
 4 files changed, 0 insertions(+), 1929 deletions(-)
 delete mode 100755 src/MatroskaCodec.cpp
 delete mode 100755 src/MatroskaCodec.h
 delete mode 100755 src/MatroskaUtils.cpp
 delete mode 100755 src/MatroskaUtils.h


- Log -----------------------------------------------------------------
commit 883f26046f8ebe1d4337581de99a07e32d86d3e9
Author: Brent Eagles <beagles at digium.com>
Date:   Wed Oct 12 12:22:17 2011 -0230

    Remove files that use  the LGPL libmatroska.

diff --git a/src/MatroskaCodec.cpp b/src/MatroskaCodec.cpp
deleted file mode 100755
index 62da989..0000000
--- a/src/MatroskaCodec.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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 "MatroskaCodec.h"
-
-using namespace AsteriskSCF::FileMediaService::Implementation;
-
-
-CodecPtr MatroskaCodecTranslator::create(const AsteriskSCF::Media::V1::FormatPtr&)
-{
-    return CodecPtr();
-}
-
-AsteriskSCF::Media::V1::FormatPtr create(const CodecPtr&)
-{
-    return AsteriskSCF::Media::V1::FormatPtr();
-}
diff --git a/src/MatroskaCodec.h b/src/MatroskaCodec.h
deleted file mode 100755
index 5433be0..0000000
--- a/src/MatroskaCodec.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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 <AsteriskSCF/Media/MediaIf.h>
-#include <boost/shared_ptr.hpp>
-#include <vector>
-#include <string>
-
-namespace AsteriskSCF
-{
-namespace FileMediaService
-{
-namespace Implementation
-{
-
-/** 
- * Base class for mapping codec information into matroska codec encodings.
- * TODO: Matching implementation and factories for each codec of import/or translations
- * to AsteriskSCF Media Format classes.
- */
-class Codec
-{
-public:
-    virtual ~Codec() {}
-
-    virtual std::vector<unsigned char> privateBytes() const = 0;
-    virtual std::string id() const = 0;
-};
-typedef boost::shared_ptr<Codec> CodecPtr;
-
-/**
- * Specialization for audio codecs.
- */
-class AudioCodec : public Codec
-{
-public:
-    virtual unsigned int channels() = 0;
-    virtual double sampleRate() = 0;
-    virtual unsigned int bitDepth() = 0;
-    virtual double outputSampleRate() = 0;
-};
-typedef boost::shared_ptr<AudioCodec> AudioCodecPtr;
-
-/** 
- * Specialization for video codecs.
- */
-class VideoCodec : public Codec
-{
-public:
-    virtual unsigned int width() = 0;
-    virtual unsigned int height() = 0;
-    virtual unsigned int displayWidth() = 0;
-    virtual unsigned int displayHeight() = 0;
-};
-typedef boost::shared_ptr<VideoCodec> VideoCodecPtr;
-
-/**
- * Facility for converting AsteriskSCF format objects to Matroska utility codecs and
- * vice-versa.
- */
-class MatroskaCodecTranslator
-{
-public:
-    static CodecPtr create(const AsteriskSCF::Media::V1::FormatPtr& format);
-    static AsteriskSCF::Media::V1::FormatPtr create(const CodecPtr& codec);
-};
-
-} /* End of namespace implementation */
-} /* End of namespace FileMediaService */
-} /* End of namespace AsteriskSCF */
diff --git a/src/MatroskaUtils.cpp b/src/MatroskaUtils.cpp
deleted file mode 100755
index 9f2a51c..0000000
--- a/src/MatroskaUtils.cpp
+++ /dev/null
@@ -1,1541 +0,0 @@
-/*
- * 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.
- */
-
-//
-// boost does something here that VC++ complains loudly and annoyingly about.
-// Unfortunately GCC complains about the pragma and warnings-as-errors busts
-// compilation.
-//
-#ifdef WIN32
-#pragma warning(disable: 4996)
-#endif
-
-#include "MatroskaUtils.h"
-
-#include <ebml/EbmlHead.h>
-#include <ebml/EbmlSubHead.h>
-#include <ebml/EbmlUInteger.h>
-#include <ebml/EbmlVoid.h>
-#include <ebml/EbmlUnicodeString.h>
-
-#include <matroska/KaxSeekHead.h>
-#include <matroska/KaxTracks.h>
-#include <matroska/KaxCluster.h>
-#include <matroska/KaxBlock.h>
-#include <matroska/KaxCues.h>
-#include <matroska/KaxSegment.h>
-#include <matroska/KaxVersion.h>
-#include <matroska/KaxTrackAudio.h>
-#include <matroska/KaxTrackVideo.h>
-
-#include <sstream>
-#include <map>
-#include <iostream>
-#include <list>
-
-#include <time.h>
-
-#include <boost/uuid/uuid.hpp>
-#include <boost/uuid/uuid_generators.hpp>
-#include <boost/enable_shared_from_this.hpp>
-#include <boost/thread/locks.hpp>
-#include <boost/thread/shared_mutex.hpp>
-
-//
-// TODO: TimeCode or Timecode.. pick one.
-//
-
-using namespace libebml;
-using namespace libmatroska;
-using namespace std;
-
-namespace AsteriskSCF
-{
-namespace FileMediaService
-{
-namespace Implementation
-{
-
-//
-// A little range checking casting function I cooked up. It
-// isn't used consistently because I decided to write it part
-// way through and didn't retro fit.
-//
-inline unsigned char trackNo(unsigned long value)
-{
-    assert(value < 256);
-    if (value > 255)
-    {
-        throw InvalidTrackNumber();
-    }
-    return static_cast<unsigned char>(value);
-}
-
-int AudioTrackType::getType() const
-{
-    return track_audio;
-}
-
-int VideoTrackType::getType() const
-{
-    return track_video;
-}
-
-void Header::writeTo(const OpaqueContainerDataPtr& data)
-{
-    EbmlHead header;
-    EDocType& docType = GetChild<EDocType>(header);
-    EbmlString* stringField = dynamic_cast<EbmlString*>(&docType);
-    assert(stringField);
-    *stringField = "matroska";
-    EDocTypeVersion& docTypeVer = GetChild<EDocTypeVersion>(header);
-    EbmlUInteger* uintField = dynamic_cast<EbmlUInteger*>(&docTypeVer); 
-    assert(uintField);
-    *uintField = 1;
-    EDocTypeReadVersion& docTypeReadVer = GetChild<EDocTypeReadVersion>(header);
-    uintField = dynamic_cast<EbmlUInteger*>(&docTypeReadVer);
-    assert(uintField);
-    *uintField = 1;
-
-    //
-    // DO NOT allow default arg or pass false as the second argument! Many
-    // code examples do, but it will end in tears! The matroska lib will
-    // not write "default" values if you do and to it, and value that is
-    // set but is the same as it might have as a default is the same
-    // thing as you not setting it. 
-    //
-    header.Render(*data->getIO(), true);
-}
-    
-namespace Internal
-{
-
-typedef boost::shared_ptr<KaxSegment> KaxSegmentPtr;
-
-
-class ContainerWriterImpl;
-typedef boost::shared_ptr<ContainerWriterImpl> ContainerWriterImplPtr;
-
-//
-// Internal wrapper around KaxCluster. Do NOT delete mCluster, you don't
-// own it! Cluster for the moment is about writing only.. the name should 
-// probably be changed.
-//
-// Note: the matroska website says that blocks that are part of a cluster
-// have timecodes relative to the parent cluster. This seems not to be
-// the case... mkvtoolnix does not generate them this way and matroska lib
-// freaks out if you try that.
-//
-class Cluster 
-{
-public:
-    Cluster(KaxCluster* cluster, const ContainerWriterImplPtr& segment, 
-        uint64 initialTimeCode, uint64 lastTimeCode);
-    uint64 startTimeCode() const;
-    void render(IOCallback* io, KaxCues* cues);
-    KaxCluster* kax();
-    uint64 increaseSize(uint64 addThisMuch);
-    uint64 size() const;
-
-private:
-    KaxCluster* mCluster;
-    ContainerWriterImplPtr mContainer;
-    const uint64 mTimeCode;
-    uint64 mSize;
-};
-typedef boost::shared_ptr<Cluster> ClusterPtr;
-
-//
-// Implementation of the A::M::I::TrackWriter. Like many things, deleting the wrapped
-// KaxEntry will probably end in tears. If there is a proper time to kill it, 
-// it is not clear yet. It is probably simply a pointer to an internal structure
-// of KaxSegment so let's not worry about it for now.
-//
-class Writer : public TrackWriter, public boost::enable_shared_from_this<Writer>
-{
-public:
-    Writer(const ContainerWriterImplPtr& containerWriter, KaxTrackEntry* t, unsigned char number);
-    void setCodecAndType(const CodecPtr& codec, const TrackTypePtr& trackType);
-    void addTag(const string& name, const string& value);
-    void write(uint64 timeCode, uint32 duration, const unsigned char* data, size_t len);
-
-    uint64 getSize();
-    TagSeq getTags();
-    void finished();
-    uint64 getID();
-
-private:
-    ContainerWriterImplPtr mContainer;
-    KaxTrackEntry* mTrack;
-    CodecPtr mCodec;
-    TrackTypePtr mTrackType;
-    KaxBlockGroup* mGroup;
-    TagSeq mTags;
-    uint64 mLastTimeCode;
-    uint32 mDuration;
-    uint64 mByteCount;
-    uint64 mTotalTime;
-};
-typedef boost::shared_ptr<Writer> WriterPtr;
-
-class ContainerReaderImpl;
-typedef boost::shared_ptr<ContainerReaderImpl> ContainerReaderImplPtr;
-
-/**
- * I'm going to implement this stuff in line so it is a little more clear what is going
- * on. I *will* document it, but for the moment this is more for me so I don't forget
- * what I'm at.
- */
-class BlockAccessTracker
-{
-public:
-    BlockAccessTracker(KaxBlockGroup* block) :
-      mBlock(block)
-    {
-    }
-
-    ~BlockAccessTracker()
-    {
-        mBlock->ReleaseFrames();
-    }
-
-    KaxBlockGroup* blockGroup()
-    {
-        return mBlock;
-    }
-    
-private:
-    KaxBlockGroup* mBlock;
-};
-
-typedef boost::shared_ptr<BlockAccessTracker> BlockAccessTrackerPtr;
-typedef vector<BlockAccessTrackerPtr> BlockAccessTrackers;
-
-class TrackingDataBuf
-{
-public:
-    TrackingDataBuf(const BlockAccessTrackers& trackers);
-
-    size_t fillFrames(FrameSeq& frames, size_t frameCount);
-    void getAllFrames(FrameSeq& frames);
-
-    //
-    // Shouldn't be used by anybody.. more for testing than anything
-    //
-    BlockAccessTrackers getTrackers() { return mTrackers; }
-    
-private:
-    BlockAccessTrackers  mTrackers;
-    BlockAccessTrackers::iterator mCurrentTracker;
-    size_t mCurrentFrame;
-};
-typedef boost::shared_ptr<TrackingDataBuf> TrackingDataBufPtr;
-
-typedef vector<KaxCluster*> KaxClusterSeq;
-typedef vector<KaxBlockGroup*> KaxBlockGroupSeq;
-
-class TrackData
-{
-public:
-    TrackData(const KaxSegmentPtr& segment, const OpaqueContainerDataPtr& data);
-
-    void addBlock(KaxBlockGroup* block);
-
-    uint64 getStartTimeCode();
-    uint64 getLastTimeCode();
-    uint64 getDuration();
-
-    TrackingDataBufPtr getFromUntil(uint64 startTime, uint64 endTime);
-    
-    TrackingDataBufPtr getBlocks(size_t pos, size_t count);
-
-private:
-    KaxSegmentPtr mSegment;
-    BlockAccessTrackers mBlocks;
-    OpaqueContainerDataPtr mDataFile;
-
-    boost::shared_mutex mLock;
-    typedef boost::unique_lock<boost::shared_mutex> UniqueLock;
-    typedef boost::shared_lock<boost::shared_mutex> SharedLock;
-};
-
-typedef boost::shared_ptr<TrackData> TrackDataPtr;
-
-//
-// Track number to track data mapping!
-//
-typedef map<unsigned char, TrackDataPtr> TrackDataMap;
-
-//
-// A given container has only one pool and every container view gets
-// their data from here.
-// 
-class TrackDataPool
-{
-public:
-    TrackDataPool(const KaxSegmentPtr& container, const OpaqueContainerDataPtr& dataFile);
-    TrackDataPtr getTrackData(unsigned char trackNumber);
-private:
-    KaxSegmentPtr mSegment;
-    TrackDataMap mDataMap;
-    OpaqueContainerDataPtr mDataFile;
-    boost::shared_mutex mLock;
-    typedef boost::unique_lock<boost::shared_mutex> UniqueLock;
-    typedef boost::shared_lock<boost::shared_mutex> SharedLock;
-};
-typedef boost::shared_ptr<TrackDataPool> TrackDataPoolPtr;
-
-//
-// Implementation of the TrackReader
-//
-class Reader : public TrackReader , public boost::enable_shared_from_this<Reader>
-{
-public:
-    Reader(const ContainerReaderImplPtr& containerReader, KaxTrackEntry* t, unsigned char number,
-        const TrackDataPtr& data);
-
-    uint64 getSize();
-    TagSeq getTags();
-    uint64 getID();
-
-    void reset();
-
-    void getFrames(FrameSeq& frames, size_t requestedNumberOfFrames);
-
-    void getFrames(FrameSeq& frames, uint64 fromTime, uint64 untilTime);
-
-    uint64 getStartTimecode();
-
-    CodecPtr getCodec();
-
-    TrackTypePtr getType();
-    
-private:
-    ContainerReaderImplPtr mContainer;
-    TrackDataPtr mTrackData;
-    KaxTrackEntry* mTrack;
-    TrackingDataBufPtr mCurrentData;
-    const unsigned char mTrackNumber;
-    size_t mBlockIndex;
-};
-typedef boost::shared_ptr<Reader> ReaderPtr;
-
-//
-// Base class for both the reader and writers of KSegments.
-//
-class ContainerImplBase
-{
-public:
-    ContainerImplBase(const KaxSegmentPtr& segment);
-
-    KaxSegment& kax();
-
-    uint64 globalTimeScale() const;
-
-protected:
-    KaxSegmentPtr mSegment;
-    KaxSeekHead* mSeekHead;
-    EbmlVoid* mIndexSpace;
-    KaxTracks* mTracks;
-    KaxSeekHead* mLeftOverSeek;
-    KaxCues* mCues;
-
-    OpaqueContainerDataPtr mContainer;
-
-    ClusterPtr mActiveCluster;
-
-    //
-    // Should be configurable for new files. Existing files will have this set on them. If
-    // they do, we will probably want to normalize to something consistent for the service.
-    //
-    uint64 mTimeCodeScale;
-    uint64 mMaxTimePerCluster;
-    uint64 mPrevTime;
-    uint16 mPrevTrack;
-    uint64 mLastTime;
-
-    typedef map<uint64, TagSeq> TrackTags;
-    TrackTags mTrackTags;
-
-    uint64 mClusterCount;
-
-    void initialize();
-};
-
-//
-// Wrapper around the "segment" for writing, where everything happens.
-//
-class ContainerWriterImpl : public ContainerWriter, public ContainerImplBase,
-    public boost::enable_shared_from_this<ContainerWriterImpl>
-{
-public:
-    //
-    // The default constructor is creating a new segment.
-    //
-    ContainerWriterImpl();
-
-
-    void addTo(const OpaqueContainerDataPtr& data);
-
-    size_t getTrackCount();
-    TrackWriterPtr getTrack(unsigned char track);
-
-    void close();
-
-    //
-    // Internal implementation details.
-    //
-
-    ClusterPtr getCluster(uint64 currentTimeCode);
-    uint64 addTime(uint64 moreTime);
-
-    void commit(const WriterPtr& track);
-
-private:
-    ClusterPtr mActiveCluster;
-};
-
-// 
-// Wrapper around the "segment" for reading, where everything happens... well, reading stuff that is...
-// the writing stuff is.. well you know.
-//
-class ContainerReaderImpl : public ContainerImplBase, public ContainerReader, 
-    public boost::enable_shared_from_this<ContainerReaderImpl>
-{
-public:
-    ContainerReaderImpl(const KaxSegmentPtr& segment, const OpaqueContainerDataPtr& dataFile);
-    size_t getTrackCount();
-    //
-    // I know it is kind of weird that matroska defines a track number as single byte value
-    // but the matroska lib defines track collection to be of possible size size_t. <shrug>
-    //
-    TrackReaderPtr getTrack(unsigned char trackNumber);
-    TrackReaderSeq getTracks();
-    void close();
-
-private:
-    OpaqueContainerDataPtr mDataFile;
-    TrackDataPoolPtr mTrackPool;
-
-    TrackDataPtr getTrackData(unsigned char trackNumber);
-};
-
-//
-// IMPL
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-// TrackingDataBuf implementation.
-//
-TrackingDataBuf::TrackingDataBuf(const BlockAccessTrackers& trackers) :
-    mTrackers(trackers),
-    mCurrentTracker(mTrackers.begin()),
-    mCurrentFrame(0)
-{
-}
-
-class DataToFrameAdapter : public Frame
-{
-public:
-    DataToFrameAdapter(const DataBuffer& buf)
-    {
-        copy(buf.Buffer(), buf.Buffer()+buf.Size(), mData.begin());
-    }
-};
-
-size_t TrackingDataBuf::fillFrames(FrameSeq& frames, size_t frameCount)
-{
-    size_t framesFilled = 0;
-    //
-    // We descend through the structures and iterate through the collections
-    // until we successfully retrieve up to count bytes. We keep track of where 
-    // we were when this accomplished so the next read will start where we left 
-    // off.
-    //
-    // NOTE: this should be *heavily* unit tested.
-    // 
-    for(; mCurrentTracker != mTrackers.end() && frameCount > 0 ; ++mCurrentTracker)
-    {
-        KaxInternalBlock& current = (KaxInternalBlock&)(*(*mCurrentTracker)->blockGroup());
-        
-        for (; mCurrentFrame < current.NumberFrames() && frameCount > 0; ++mCurrentFrame, ++framesFilled)
-        {
-            DataBuffer& buf = current.GetBuffer(static_cast<unsigned int>(mCurrentFrame));
-            frames.push_back(FramePtr(new DataToFrameAdapter(buf)));
-            --frameCount;
-        }
-    }
-    return framesFilled;
-}
-
-void TrackingDataBuf::getAllFrames(FrameSeq& frames)
-{
-    for (BlockAccessTrackers::iterator iter = mTrackers.begin(); iter != mTrackers.end(); ++iter)
-    {
-        KaxInternalBlock& current = (KaxInternalBlock&)(*(*mCurrentTracker)->blockGroup());
-        
-        for (unsigned long currentBuf = 0; currentBuf < current.NumberFrames(); ++currentBuf)
-        {
-            DataBuffer& buf = current.GetBuffer(static_cast<unsigned int>(currentBuf));
-            frames.push_back(FramePtr(new DataToFrameAdapter(buf)));
-        }
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-// TrackData implementation.
-//
-TrackData::TrackData(const KaxSegmentPtr& segment, const OpaqueContainerDataPtr& dataFile) :
-    mSegment(segment),
-    mDataFile(dataFile)
-{
-}
-
-void TrackData::addBlock(KaxBlockGroup* block)
-{
-    if (mBlocks.size() == 0)
-    {
-        mBlocks.push_back(BlockAccessTrackerPtr(new BlockAccessTracker(block)));
-        return;
-    }
-
-    if (block->GlobalTimecode() < mBlocks.front()->blockGroup()->GlobalTimecode())
-    {
-        mBlocks.insert(mBlocks.begin(), BlockAccessTrackerPtr(new BlockAccessTracker(block)));
-    }
-    else if (block->GlobalTimecode() > mBlocks.back()->blockGroup()->GlobalTimecode())
-    {
-        mBlocks.push_back(BlockAccessTrackerPtr(new BlockAccessTracker(block)));
-    }
-    else
-    {
-        for (BlockAccessTrackers::iterator i = mBlocks.end() -1; i != mBlocks.begin(); --i)
-        {
-            if (block->GlobalTimecode() > (*i)->blockGroup()->GlobalTimecode())
-            {
-                //
-                // This is actually safe because the "tack on" the last block case is handled.
-                //
-                ++i;
-                mBlocks.insert(i, BlockAccessTrackerPtr(new BlockAccessTracker(block)));
-                break;
-            }
-        }
-    }
-}
-
-uint64 TrackData::getStartTimeCode()
-{
-    if (mBlocks.size() == 0)
-    {
-        return 0;
-    }
-
-    return mBlocks.front()->blockGroup()->GlobalTimecode();
-}
-
-uint64 TrackData::getLastTimeCode()
-{
-    if (mBlocks.size() == 0)
-    {
-        return 0;
-    }
-    return mBlocks.back()->blockGroup()->GlobalTimecode();
-}
-
-uint64 TrackData::getDuration()
-{
-    if (mBlocks.size() == 0)
-    {
-        return 0;
-    }
-    uint64 lastBlockDuration = 0;
-    if (!mBlocks.back()->blockGroup()->GetBlockDuration(lastBlockDuration))
-    {
-        //
-        // Probably want to log somethin' here. We don't have a proper duration on this last block.
-        //
-    }
-    return mBlocks.back()->blockGroup()->GlobalTimecode() - mBlocks.front()->blockGroup()->GlobalTimecode() 
-        + lastBlockDuration;
-}
-
-TrackingDataBufPtr TrackData::getFromUntil(uint64 startTime, uint64 endTime)
-{
-    SharedLock lock(mLock);
-    BlockAccessTrackers subset;
-    for (BlockAccessTrackers::const_iterator i = mBlocks.begin(); i != mBlocks.end(); ++i)
-    {
-        uint64 timecode = (*i)->blockGroup()->GlobalTimecode();
-        if (timecode >= startTime && timecode < endTime)
-        {
-            if (!(*i)->blockGroup()->ValueIsSet())
-            {
-                IOCallback* io = mDataFile->getIO();
-                if (io)
-                {
-                    (*i)->blockGroup()->ReadData(*(mDataFile->getIO()), SCOPE_ALL_DATA);
-                }
-            }
-            subset.push_back(*i);
-        }
-    }
-    return TrackingDataBufPtr(new TrackingDataBuf(subset)); 
-}
-
-TrackingDataBufPtr TrackData::getBlocks(size_t pos, size_t count)
-{
-    SharedLock lock(mLock);
-    if (pos > mBlocks.size())
-    {
-        return TrackingDataBufPtr();
-    }
-    BlockAccessTrackers subset;
-    subset.reserve(count);
-
-    for (size_t i = pos; (i < mBlocks.size()) && (i < (pos + count)); ++i)
-    {
-        if (!mBlocks[i]->blockGroup()->ValueIsSet())
-        {
-            IOCallback* io = mDataFile->getIO();
-            if (io)
-            {
-                mBlocks[i]->blockGroup()->ReadData(*mDataFile->getIO(), SCOPE_ALL_DATA);
-            }
-        }
-
-        subset.push_back(mBlocks[i]);
-    }
-    return TrackingDataBufPtr(new TrackingDataBuf(subset));
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-// TrackDataPool implementation.
-//
-TrackDataPool::TrackDataPool(const KaxSegmentPtr& segment, const OpaqueContainerDataPtr& dataFile) :
-    mSegment(segment),
-    mDataFile(dataFile)
-{
-    KaxTracks& tracks = GetChild<KaxTracks>(*mSegment);
-
-    for (size_t i = 0; i < tracks.ListSize(); ++i)
-    {
-        KaxTrackEntry* t = static_cast<KaxTrackEntry*>(tracks[static_cast<unsigned int>(i)]);
-        unsigned char trackNumber = (uint8)(t->TrackNumber());
-        mDataMap[trackNumber] = TrackDataPtr(new TrackData(segment, mDataFile));
-    }
-    KaxClusterSeq allClusters;
-    for (EBML_MASTER_ITERATOR clusterIter = mSegment->begin(); clusterIter != mSegment->end(); ++clusterIter)
-    {
-        if (EbmlId(**clusterIter) == EBML_ID(KaxCluster))
-        {
-            KaxCluster* cluster = static_cast<KaxCluster*>(*clusterIter);
-            allClusters.push_back(cluster);
-
-            for (EBML_MASTER_ITERATOR blockGroupIter = cluster->begin(); blockGroupIter != cluster->end();
-                 ++blockGroupIter)
-            {
-                if (EbmlId(**blockGroupIter) == EBML_ID(KaxBlockGroup))
-                {
-                    KaxBlockGroup* blockGroup = static_cast<KaxBlockGroup*>(*blockGroupIter);
-                    TrackDataMap::iterator mapEntry = mDataMap.find(trackNo(blockGroup->TrackNumber()));
-                    if (mapEntry == mDataMap.end())
-                    {
-                        //
-                        // This actually indicates that something is probably wrong with the source
-                        // matroska file.
-                        //
-                        mDataMap[trackNo(blockGroup->TrackNumber())] = TrackDataPtr(new TrackData(segment, mDataFile));
-                    }
-                    mDataMap[trackNo(blockGroup->TrackNumber())]->addBlock(blockGroup);
-                }
-            }
-        }
-    }
-}
-
-TrackDataPtr TrackDataPool::getTrackData(unsigned char trackNumber)
-{
-    SharedLock lock(mLock);
-    TrackDataMap::iterator mapEntry = mDataMap.find(trackNumber);
-    if (mapEntry == mDataMap.end())
-    {
-        throw InvalidTrackNumber();
-    }
-    return mapEntry->second;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-// Cluster implementation.
-//
-Cluster::Cluster(KaxCluster* cluster, const ContainerWriterImplPtr& container, 
-        uint64 initialTimeCode, uint64 lastTimeCode) :
-      mCluster(cluster),
-      mContainer(container),
-      mTimeCode(initialTimeCode),
-      mSize(0)
-{
-    mCluster->SetParent(mContainer->kax());
-    mCluster->SetGlobalTimecodeScale(mContainer->globalTimeScale());
-    mCluster->SetPreviousTimecode(lastTimeCode * mContainer->globalTimeScale(), mContainer->globalTimeScale());
-    mCluster->InitTimecode(initialTimeCode, mContainer->globalTimeScale());
-    mCluster->EnableChecksum();
-    KaxClusterTimecode& tc = GetChild<KaxClusterTimecode>(*mCluster);
-    EbmlUInteger* uintField = dynamic_cast<EbmlUInteger*>(&tc);
-    assert(uintField);
-    *uintField = initialTimeCode;
-}
-
-uint64 Cluster::startTimeCode() const
-{
-    return mTimeCode;
-}
-
-void Cluster::render(IOCallback* io, KaxCues* cues)
-{
-    mCluster->Render(*io, *cues);
-    mCluster->ReleaseFrames();
-}
-
-KaxCluster* Cluster::kax()
-{
-    return mCluster;
-}
-
-uint64 Cluster::increaseSize(uint64 addThisMuch)
-{
-    mSize += addThisMuch;
-    return mSize;
-}
-
-uint64 Cluster::size() const
-{
-    return mSize;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-// Writer implementation.
-//
-Writer::Writer(const ContainerWriterImplPtr& container, KaxTrackEntry* t, unsigned char number) :
-    TrackWriter(number),
-    mContainer(container),
-    mTrack(t),
-    mGroup(0),
-    mLastTimeCode(0),
-    mDuration(0),
-    mByteCount(0),
-    mTotalTime(0)
-{
-}
-
-void Writer::setCodecAndType(const CodecPtr& codec, const TrackTypePtr& trackType)
-{
-    //
-    // Generic codec info to matroska stuff translation
-    //
-    mCodec = codec;
-    mTrackType = trackType;
-    EbmlUInteger* uintField = dynamic_cast<EbmlUInteger*>(&GetChild<KaxTrackType>(*mTrack));
-    assert(uintField);
-    *uintField = trackType->getType();
-    EbmlString* stringField = dynamic_cast<EbmlString*>(&GetChild<KaxCodecID>(*mTrack));
-    assert(stringField);
-    *stringField = codec->id();
-    if (codec->privateBytes().size() != 0)
-    {
-        KaxCodecPrivate& privateData = GetChild<KaxCodecPrivate>(*mTrack);
-        vector<unsigned char> codecsData = codec->privateBytes();
-        privateData.CopyBuffer(static_cast<unsigned char*>(&codecsData[0]), static_cast<uint32>(codecsData.size()));
-    }
-
-    if (mTrackType->getType() == track_audio)
-    {
-        KaxTrackAudio& audio = GetChild<KaxTrackAudio>(*mTrack);
-        AudioCodecPtr audioCodec = boost::dynamic_pointer_cast<AudioCodec>(codec);
-        assert(audioCodec);
-        if (audioCodec->channels() != 0)
-        {
-            uintField = dynamic_cast<EbmlUInteger*>(&GetChild<KaxAudioChannels>(audio));
-            assert(uintField);
-            *uintField = audioCodec->channels();
-        }
-
-        if (audioCodec->sampleRate() != 0)
-        {
-            KaxAudioSamplingFreq& freq = GetChild<KaxAudioSamplingFreq>(audio);
-            EbmlFloat* floatField = dynamic_cast<EbmlFloat*>(&freq);
-            assert(floatField);
-            *floatField = audioCodec->sampleRate();
-            freq.ValidateSize();
-        }
-
-        if (audioCodec->outputSampleRate() > 0.0)
-        {
-            KaxAudioOutputSamplingFreq& freq = GetChild<KaxAudioOutputSamplingFreq>(audio);
-            EbmlFloat* floatField = dynamic_cast<EbmlFloat*>(&freq);
-            assert(floatField);
-            *floatField = audioCodec->sampleRate();
-            freq.ValidateSize();
-        }
-
-        if (audioCodec->bitDepth() != 0)
-        {
-            uintField = dynamic_cast<EbmlUInteger*>(&GetChild<KaxAudioBitDepth>(audio));
-            assert(uintField);
-            *uintField = audioCodec->bitDepth();
-        }
-    }
-    else
-    {
-        VideoCodecPtr videoCodec = boost::dynamic_pointer_cast<VideoCodec>(codec);
-        assert(videoCodec);
-
-        KaxTrackVideo& video = GetChild<KaxTrackVideo>(*mTrack);
-        unsigned int defaultDisplayWidth = 0;
-        if (videoCodec->width() != 0)
-        {
-            uintField = dynamic_cast<EbmlUInteger*>(&GetChild<KaxVideoPixelWidth>(video));
-            assert(uintField);
-            *uintField = videoCodec->width();
-            defaultDisplayWidth = videoCodec->width();
-        }
-        if (videoCodec->displayWidth() != 0)
-        {
-            defaultDisplayWidth = videoCodec->displayWidth();
-        }
-
-        unsigned int defaultDisplayHeight = 0;
-        if (videoCodec->height() != 0)
-        {
-            uintField = dynamic_cast<EbmlUInteger*>(&GetChild<KaxVideoPixelHeight>(video));
-            assert(uintField);
-            *uintField = videoCodec->height();
-            defaultDisplayHeight = videoCodec->height();
-        }
-        if (videoCodec->displayHeight() != 0)
-        {
-            defaultDisplayHeight = videoCodec->displayHeight();
-        }
-
-        if (defaultDisplayWidth != 0)
-        {
-            uintField = dynamic_cast<EbmlUInteger*>(&GetChild<KaxVideoDisplayWidth>(video));
-            assert(uintField);
-            *uintField = defaultDisplayWidth;
-        }
-
-        if (defaultDisplayHeight != 0)
-        {
-            uintField = dynamic_cast<EbmlUInteger*>(&GetChild<KaxVideoDisplayHeight>(video));
-            assert(uintField);
-            *uintField = defaultDisplayHeight;
-        }
-    }
-}
-
-void Writer::addTag(const string& name, const string& value)
-{
-    mTags.push_back(Tag(name, value));
-}
-
-void Writer::write(uint64 timeCode, uint32 duration, const unsigned char* data, size_t len)
-{
-    ClusterPtr cluster = mContainer->getCluster(timeCode);
-    //
-    // Lazy initializtion of the current block group.
-    //
-    if (!mGroup)
-    {
-        mGroup = &cluster->kax()->GetNewBlock();
-        mGroup->SetParent(*cluster->kax());
-        mGroup->SetParentTrack(*mTrack);
-    }
-    else if (mGroup->GetParentCluster() != cluster->kax())
-    {
-        // 
-        // The cluster may have changed on us if we exceeded the limits. If we did, we need to 
-        // get a new block agroup and set it up.
-        //
-        mGroup = &cluster->kax()->GetNewBlock();
-        mGroup->SetParent(*cluster->kax());
-        mGroup->SetParentTrack(*mTrack);
-    }
-    //
-    // Keep track. While we do need the info for matroska, it is pretty handy for debugging
-    // anyway.
-    //
-    mByteCount += len;
-    mTotalTime += duration;
-
-    //
-    // Add the data to the actual block.
-    //
-    KaxBlock& block = GetChild<KaxBlock>(*mGroup);
-    block.SetParent(*cluster->kax());
-
-    //
-    // We need to allocate heap and copy the data to it, the block seems to take ownership.
-    //
-    binary* copiedData = new binary[len];
-    memcpy(copiedData, data, len);
-    DataBuffer* buf = new DataBuffer(copiedData, static_cast<uint32>(len));
-
-    //
-    // The AddFrame call may return "false" indicating it does not want to have any more frames added
-    // to it. In which case we create a new blockgroup on the next go'round.
-    //
-    bool blockWantsMore = block.AddFrame(*mTrack, mLastTimeCode * mContainer->globalTimeScale(), *buf);
-    cluster->increaseSize(buf->Size());
-    mDuration += duration;
-    
-    //
-    // While a nuisance, we want to set the duration each time we change it
-    //
-    mGroup->SetBlockDuration(mDuration * mContainer->globalTimeScale());
-
-    //
-    // If we are creating a new group, we probably want to finish this one up with some tidying.
-    // Notice how the method name "SetBlockDuration" is on an instance of block group and how the 
-    // call to create the new blockgroup is GetNewBlock()? I noticed.... don't be confused, sometimes
-    // it is best just to go with it.
-    //
-    if (!blockWantsMore)
-    {
-        mGroup = 0;
-        mLastTimeCode = mDuration + mLastTimeCode; 
-        mDuration = 0;
-    }
-
-    //
-    // We are not doing references at this time so nothing to do there.
-    // TODO: Supposedly there is something we should be doing with the cues if 
-    // this is a video track.
-    //
-    if ((uint8)(GetChild<KaxTrackType>(*mTrack)) == track_video)
-    {
-        //
-        // TODO: update cues. In addition to the other interesting bits, some of the code
-        // examples I looked at use a non-existent method. I checked.. it has been deprecated.
-        // I guess deprecated means "removed for good, too bad". Who knew?
-        //
-    }
-}
-
-uint64 Writer::getSize()
-{
-    return mByteCount;
-}
-
-TagSeq Writer::getTags()
-{
-    return mTags;
-}
-
-void Writer::finished()
-{
-    if (!mTrackType || !mCodec)
-    {
-        throw IncompleteException();
-    }
-    mContainer->addTime(mTotalTime);
-    mContainer->commit(shared_from_this());
-}
-
-uint64 Writer::getID()
-{
-    return static_cast<uint64>(GetChild<KaxTrackUID>(*mTrack));
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-// Reader implementation
-//
-Reader::Reader(const ContainerReaderImplPtr& containerReader, KaxTrackEntry* t, unsigned char number,
-    const TrackDataPtr& data) :
-     TrackReader(number),
-     mContainer(containerReader),
-     mTrackData(data),
-     mTrack(t),
-     mTrackNumber(number),
-     mBlockIndex(0)
-{
-    mCurrentData = mTrackData->getBlocks(mBlockIndex++, 1);
-}
-
-uint64 Reader::getSize()
-{
-    return 0; // XXX it is not clear whether this is meanignful.
-}
-
-TagSeq Reader::getTags()
-{
-    return TagSeq(); // XXX
-}
-
-uint64 Reader::getID()
-{
-    return static_cast<uint64>(GetChild<KaxTrackUID>(*mTrack));
-}
-
-void Reader::reset()
-{
-    mBlockIndex = 0;
-    mCurrentData = mTrackData->getBlocks(mBlockIndex, 1);
-}
-
-void Reader::getFrames(FrameSeq& frames, size_t requestedNumberOfFrames)
-{
-    if (!mCurrentData)
-    {
-        //
-        // We are out of data.
-        //
-        return;
-    }
-
-    for (size_t framesRead = mCurrentData->fillFrames(frames, requestedNumberOfFrames);
-         framesRead < requestedNumberOfFrames; )
-    {
-        //
-        // The current data set is exhausted.. let's go get some more blocks.
-        //
-        mCurrentData = mTrackData->getBlocks(mBlockIndex++, 1);
-        if (!mCurrentData)
-        {
-            //
-            // That's it folks.. no more data.
-            //
-            return;
-        }
-        framesRead += mCurrentData->fillFrames(frames, requestedNumberOfFrames - framesRead);
-    }
-}
-
-void Reader::getFrames(FrameSeq& frames, uint64 fromTime, uint64 untilTime)
-{
-    TrackingDataBufPtr data = mTrackData->getFromUntil(fromTime * mTrack->GlobalTimecodeScale(), 
-        untilTime * mTrack->GlobalTimecodeScale());
-    data->getAllFrames(frames);
-}
-
-uint64 Reader::getStartTimecode() 
-{
-    return mTrackData->getStartTimeCode();
-}
-
-CodecPtr Reader::getCodec()
-{
-    //
-    // XXX translate track codec info to our codec objectsj
-    // 
-    return CodecPtr();
-}
-
-TrackTypePtr Reader::getType()
-{
-    EbmlUInteger* uintField = dynamic_cast<EbmlUInteger*>(&GetChild<KaxTrackType>(*mTrack));
-    assert(uintField);
-    if ((uint16)(*uintField) == track_audio)
-    {
-        return TrackTypePtr(new AudioTrackType);
-    }
-    else if ((uint16)(*uintField) == track_video)
-    {
-        return TrackTypePtr(new VideoTrackType);
-    }
-    return TrackTypePtr();
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-// ContainerImplBase implementation.
-//
-ContainerImplBase::ContainerImplBase(const KaxSegmentPtr& segment) :
-    mSegment(segment)
-{
-    if (mSegment->ValueIsSet())
-    {
-        KaxInfo& info = GetChild<KaxInfo>(*mSegment);
-        KaxTimecodeScale& scale = GetChild<KaxTimecodeScale>(info);
-        mTimeCodeScale = (uint64)scale;
-    }
-    else
-    {
-        mTimeCodeScale = 1000000;          // Means our times are all in milliseconds... TODO: define a constant.
-    }
-}
-
-KaxSegment& ContainerImplBase::kax()
-{
-    //
-    // Ok.. it grieves me to return a reference here, but I don't want to refactor anymore right now.
-    //
-    return *mSegment;
-}
-
-uint64 ContainerImplBase::globalTimeScale() const
-{
-    return mTimeCodeScale;
-}
-
-void ContainerImplBase::initialize()
-{
-    mMaxTimePerCluster = 1000;           // How many milliseconds per cluster.
-    mPrevTime = 0xFFFFFFFFFFFFFFFF;     // Dummy value to make sure we start off right.
-    mPrevTrack = 0xFFFF;                 // This isn't really used much as we haven't start setting up references.
-    mLastTime = 0;                       // The rest is general initialization.
-
-    //
-    // initialize helper members into the segment.
-    //
-    mSeekHead = &GetChild<KaxSeekHead>(*mSegment);
-    mIndexSpace = &GetChild<EbmlVoid>(*mSegment);
-    mTracks = &GetChild<KaxTracks>(*mSegment);
-    mLeftOverSeek = &GetChild<KaxSeekHead>(*mSegment);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-// ContainerWriterImpl implementation.
-//
-ContainerWriterImpl::ContainerWriterImpl() :
-    ContainerImplBase(KaxSegmentPtr(new KaxSegment))
-{
-    initialize();
-}
-
-void ContainerWriterImpl::addTo(const OpaqueContainerDataPtr& data)
-{
-    mContainer = data;
-
-    //
-    // Write the "head" of the segment.. I guess. The number 5 means set everything for
-    // a file that might hold a huge bunch of data.. it is a size classification.. .maybe?
-    //
-    mSegment->WriteHead(*(data->getIO()), 5);
-
-    //
-    // Make space for seek head. This could be rightsized... the number I picked was arbitrary.
-    // A lot of code examples used 1000 bytes, so maybe this is too big?
-    //
-    mIndexSpace->SetSize(2 * 1024);
-    mIndexSpace->Render(*(data->getIO()));
-
-    //
-    // The info part of the segment talks about what who is doing what... presumably
-    // so an app that reads this file and chokes and dies because we did something
-    // wrong knows who to blame.
-    //
-    KaxInfo& info = GetChild<KaxInfo>(*mSegment);
-    KaxWritingApp& writingApp = GetChild<KaxWritingApp>(info);
-    EbmlUnicodeString* unicodeField = dynamic_cast<EbmlUnicodeString*>(&writingApp);
-    assert(unicodeField);
-    *unicodeField = L"Asterisk SCF";
-    stringstream os;
-    os << "Asterisk SCF Matroska Container Library with libmatroska " << KaxCodeVersion << " and libebml " << EbmlCodeVersion;
-    UTFstring muxerName;
-    muxerName.SetUTF8(os.str());
-    KaxMuxingApp& muxer = GetChild<KaxMuxingApp>(info);
-    unicodeField = dynamic_cast<EbmlUnicodeString*>(&muxer);
-    assert(unicodeField);
-    *unicodeField = muxerName;
-    KaxDateUTC& date = GetChild<KaxDateUTC>(info);
-    date.SetEpochDate(static_cast<int32>(time(0)));
-    KaxTimecodeScale& scale = GetChild<KaxTimecodeScale>(info);
-    EbmlUInteger* uintField = dynamic_cast<EbmlUInteger*>(&scale);
-    assert(uintField);
-    *uintField = mTimeCodeScale;
-    KaxDuration& duration = GetChild<KaxDuration>(info);
-    EbmlFloat* floatField = dynamic_cast<EbmlFloat*>(&duration);
-    assert(floatField);
-    *floatField = 10000; // We set a dummy value for this right now.
-    KaxSegmentUID& uuid = GetChild<KaxSegmentUID>(info);
-    boost::uuids::uuid idValue = boost::uuids::random_generator()();
-    binary* buf = new binary[idValue.static_size()];
-    for (boost::uuids::uuid::const_iterator i = idValue.begin(); i != idValue.end(); ++i)
-    {
-        *buf = *i;
-    }
-    uuid.SetBuffer(buf, static_cast<uint32>(idValue.static_size()));
-    info.Render(*(data->getIO()));
-
-    mSeekHead->IndexThis(info, *mSegment);
-    mCues = &GetChild<KaxCues>(*mSegment);
-    mCues->SetGlobalTimecodeScale(mTimeCodeScale);
-    //
-    // We are writing the tracks here initially.. but we haven't added tracks yet. I don't 
-    // know either.. except VLC hates me if I don't do this.
-    //
-    mTracks->Render(*(data->getIO()));
-  
-    //
-    // The problem is of course.. we don't know how many tracks are really going to be in
-    // here yet, so I write some more blank space. 1k might be too small here. If the track
-    // count is big enough, when we come back and write the real track info, we might
-    // clobber the first cluster.... things that make you go "hmmmm".
-    //
-    EbmlVoid moreSpace;
-    moreSpace.SetSize(1024);
-    moreSpace.Render(*(data->getIO()));
-    //
-    // Ok.. so I think that is it for setup .. whew!
-    //
-}
-
-size_t ContainerWriterImpl::getTrackCount()
-{
-    if (mTracks)
-    {
-        return mTracks->ListSize();
-    }
-    return 0;
-}
-
-TrackWriterPtr ContainerWriterImpl::getTrack(unsigned char track) 
-{
-    if (track == 0)
-    {
-        throw InvalidTrackNumber("Track list index starts at 1.");
-    }
-    KaxTrackEntry* t = 0;
-    if (mTracks->ListSize() < track)
-    {
-
-        //
-        // We need to create a new track!
-        //
-        if (mTracks->ListSize() == 0)
-        {
-            t = &GetChild<KaxTrackEntry>(*mTracks);
-        }
-        else
-        {
-            t = &GetNextChild<KaxTrackEntry>(*mTracks, 
-                static_cast<KaxTrackEntry&>(*(*mTracks)[static_cast<unsigned int>(mTracks->ListSize()-1)]));
-        }
-
-        //
-        // Initialize me! Mostly just generic stuff.
-        //
-        assert(t);
-        KaxTrackNumber& trackNumber = GetChild<KaxTrackNumber>(*t);
-        EbmlUInteger* uintField = dynamic_cast<EbmlUInteger*>(&trackNumber);
-        assert(uintField);
-        *uintField = track;
-        KaxTrackUID& trackId = GetChild<KaxTrackUID>(*t);
-        uintField = dynamic_cast<EbmlUInteger*>(&trackId);
-        assert(uintField);
-        *uintField = rand();
-        KaxTrackLanguage& lang = GetChild<KaxTrackLanguage>(*t);
-        EbmlString* stringField = dynamic_cast<EbmlString*>(&lang);
-        assert(stringField);
-        *stringField = "eng";
-        t->SetGlobalTimecodeScale(mTimeCodeScale);
-        uintField = dynamic_cast<EbmlUInteger*>(&GetChild<KaxTrackFlagLacing>(*t));
-        assert(uintField);
-        *uintField = true;
-    }
-    else
-    {
-        t = dynamic_cast<KaxTrackEntry*>((*mTracks)[track-1]);
-        assert(t);
-    }
-    return TrackWriterPtr(new Writer(shared_from_this(), t, track));
-}
-
-void ContainerWriterImpl::close()
-{
-    //
-    // Done are we? Make sure we write the last cluster out.
-    //
-    if (mActiveCluster)
-    {
-        mActiveCluster->render(mContainer->getIO(), mCues);
-        mActiveCluster.reset();
-    }
-
-    //
-    // Now.. we are writing at the end of the file. Cues can go here.. that's okay.
-    //
-    if (mCues && mCues->ElementSize() != 0)
-    {
-        mCues->Render(*mContainer->getIO());
-        if (mSeekHead)
-        {
-            mSeekHead->IndexThis(*mCues, *mSegment);
-        }
-    }
-
-    //
-    // Info was back near the front remember? Remember to seek back before rendering.. oh and remember
-    // where we are before we move or we will be very unhappy.
-    //
-    KaxInfo& info = GetChild<KaxInfo>(*mSegment);
-    KaxDuration& duration = GetChild<KaxDuration>(info);
-    EbmlFloat* floatField = dynamic_cast<EbmlFloat*>(&duration);
-    assert(floatField);
-    *floatField = static_cast<double>(mLastTime);
-    info.UpdateSize();
-    uint64 bookmark = mContainer->getIO()->getFilePointer();
-    mContainer->getIO()->setFilePointer(info.GetElementPosition());
-    info.Render(*mContainer->getIO());
-
-    //
-    // As I recall the tracks were right after info, so we can write them now too..
-    //
-    mTracks->Render(*mContainer->getIO());
-    mSeekHead->IndexThis(*mTracks, *mSegment);
-
-    // 
-    // Didn't forget to add the index entry? Good for you. Now where were we...?
-    //
-    mContainer->getIO()->setFilePointer(bookmark);
-
-    //
-    // Now is a good time to write the tags.. they are related to tracks, but they go in there
-    // own space.
-    //
-    KaxTags& tags = GetChild<KaxTags>(*mSegment);
-    KaxTag* lastTag = 0;
-    for (TrackTags::iterator i = mTrackTags.begin(); i != mTrackTags.end(); ++i)
-    {
-        KaxTag* current = 0;
-        if (lastTag)
-        {
-            current = &GetNextChild<KaxTag>(tags, *lastTag);
-        }
-        else
-        {
-            current = &GetChild<KaxTag>(tags);
-        }
-        lastTag = current;
-
-        KaxTagTargets& targets = GetChild<KaxTagTargets>(*current);
-        KaxTagTrackUID& trackUID = GetChild<KaxTagTrackUID>(targets);
-        EbmlUInteger* uintField = dynamic_cast<EbmlUInteger*>(&trackUID);
-        assert(uintField);
-        *uintField = i->first;
-        KaxTagSimple* tagEntry = 0;
-        for (TagSeq::const_iterator t = i->second.begin(); t != i->second.end(); ++t)
-        {
-            KaxTagSimple* currentEntry = 0;
-            if (tagEntry)
-            {
-                currentEntry = &GetNextChild<KaxTagSimple>(*current, *tagEntry);
-            }
-            else
-            {
-                currentEntry = &GetChild<KaxTagSimple>(*current);
-            }
-            tagEntry = currentEntry;
-            EbmlUnicodeString* unicodeField = dynamic_cast<EbmlUnicodeString*>(&GetChild<KaxTagName>(*currentEntry));
-            assert(unicodeField);
-            UTFstring utf;
-            utf.SetUTF8(t->name);
-            *unicodeField = utf;
-
-            unicodeField = dynamic_cast<EbmlUnicodeString*>(&GetChild<KaxTagString>(*currentEntry));
-            assert(unicodeField);
-            utf.SetUTF8(t->value);
-            *unicodeField = utf;
-        }
-    }
-
-    //
-    // But don't forget to write!
-    //
-    tags.Render(*mContainer->getIO());
-
-    if (mSeekHead)
-    {
-        mSeekHead->IndexThis(tags, *mSegment);
-    }
-
-    if (mIndexSpace)
-    {
-        //
-        // Now we have real index info, so lets go back and fix that. Umm.. did that re-render? I
-        // studies say yes. Why can't everything work that way?
-        //
-        mIndexSpace->ReplaceWith(*mSeekHead, *mContainer->getIO());
-    }
-
-    //
-    // Let's find out where whether we need to something with our size and rewrite that "head" bit.
-    //
-    mContainer->getIO()->setFilePointer(0, seek_end);
-    uint64 newSize = mContainer->getIO()->getFilePointer() - mSegment->GetElementPosition() - mSegment->HeadSize();
-    mContainer->getIO()->setFilePointer(mSegment->GetElementPosition());
-    if (mSegment->ForceSize(newSize))
-    {
-        mSegment->OverwriteHead(*mContainer->getIO());
-    }
-}
-
-//
-// Internal implementation details.
-//
-ClusterPtr ContainerWriterImpl::getCluster(uint64 currentTimeCode)
-{
-    uint64 oldTimeCode = 0;
-    if (mActiveCluster)
-    {
-        if ((currentTimeCode - mActiveCluster->startTimeCode()) < mMaxTimePerCluster)
-        {
-            return mActiveCluster;
-        }
-        mActiveCluster->render(mContainer->getIO(), mCues);
-        oldTimeCode = mActiveCluster->startTimeCode();
-    }
-    ++mClusterCount;
-    mActiveCluster.reset(new Cluster(new KaxCluster, shared_from_this(), currentTimeCode, oldTimeCode));
-    return mActiveCluster;
-}
-
-uint64 ContainerWriterImpl::addTime(uint64 moreTime)
-{
-    mLastTime += moreTime;
-    return mLastTime;
-}
-
-void ContainerWriterImpl::commit(const WriterPtr& track)
-{
-    mTrackTags[track->getID()] = track->getTags();
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-// ContainerReaderImpl implementation.
-//
-ContainerReaderImpl::ContainerReaderImpl(const KaxSegmentPtr& segment, 
-    const OpaqueContainerDataPtr& dataFile) :
-    ContainerImplBase(segment),
-    mDataFile(dataFile),
-    mTrackPool(new TrackDataPool(segment, dataFile))
-{
-    initialize();
-}
-
-//
-// TODO: move method to base class.
-// Yeah, I know there is some code duplication. I had originally separated these because I suspected
-// that they would be different. I think they could probably be safely merged.
-//
-size_t ContainerReaderImpl::getTrackCount()
-{
-    return mTracks->ListSize();
-}
-
-TrackReaderPtr ContainerReaderImpl::getTrack(unsigned char trackNumber)
-{
-    if (trackNumber == 0)
-    {
-        throw InvalidTrackNumber("track numbers start at 1.");
-    }
-
-    if (trackNumber > mTracks->ListSize())
-    {
-        throw InvalidTrackNumber();
-    }
-    KaxTrackEntry* t = dynamic_cast<KaxTrackEntry*>((*mTracks)[trackNumber-1]);
-    if (!t->ValueIsSet())
-    {
-        t->ReadData(*mContainer->getIO(), SCOPE_ALL_DATA);
-    }
-    return TrackReaderPtr(new Reader(shared_from_this(), t, trackNumber, 
-        mTrackPool->getTrackData(trackNumber)));
-}
-
-TrackReaderSeq ContainerReaderImpl::getTracks()
-{
-    //
-    // A little note on getTracks(): I could cache the track entries once they've been created, 
-    // but I expect a container file to be open by multiple threads. The Reader should be 
-    // unique to the thread, but I think the read clusters ought to pool and be shared.
-    //
-    TrackReaderSeq result;
-    for (uint32 i = 0; i < mTracks->ListSize(); ++i)
-    {
-        uint32 trackNumber = i + 1;
-        KaxTrackEntry* t = dynamic_cast<KaxTrackEntry*>((*mTracks)[i]);
-        if (!t->ValueIsSet())
-        {
-            t->ReadData(*mContainer->getIO(), SCOPE_ALL_DATA);
-        }
-        result.push_back(TrackReaderPtr(new Reader(shared_from_this(), t, trackNo(trackNumber),
-            mTrackPool->getTrackData(trackNo(trackNumber)))));
-    }
-    return result;
-}
-
-void ContainerReaderImpl::close()
-{
-    //
-    // Not sold that I want this method... I was kind of thinking that this would really
-    // be reference count based.
-    //
-}
-
-} /* End of namespace internal. */
-
-using namespace ::AsteriskSCF::FileMediaService::Implementation::Internal;
-
-ContainerWriterPtr ContainerWriter::create()
-{
-    return ContainerWriterPtr(new ContainerWriterImpl);
-}
-
-ContainerReaderPtr ContainerReader::read(const OpaqueContainerDataPtr& data)
-{
-    //
-    // Here is kind of the dilemna.. do we seek to where we expect things to be or not?
-    // Tell you what, let someone else decide! There is a second method that finds the right
-    // place in the file!
-    //
-    KaxSegmentPtr seg(new KaxSegment);
-    seg->ReadData(*data->getIO(), SCOPE_ALL_DATA);
-    return ContainerReaderPtr(new ContainerReaderImpl(seg, data));
-}
-
-ContainerReaderPtr ContainerReader::locateAndRead(const OpaqueContainerDataPtr& data)
-{
-    //
-    // Find the right place.. well that is all well and good, but I'm not sure that we
-    // can be sure how big EbmlHeader is going to be. So we will brute force it and 
-    // read the EbmlHead anyways. The chances of someone else having read that info first is
-    // slim anyways.
-    //
-    
-    //
-    // Make sure we go to the start of the file... in at least one version of the
-    // matroska library, all the read does is seek to EbmlHeader().GetSize() from current.
-    // If we are not at the start of the file.. kaboom. Full of sighs.
-    //
-    data->getIO()->setFilePointer(0);
-    EbmlHead header;
-
-    //
-    // The "true" is for "read fully"... which is garbage as it looks like some versions
-    // of libmatroska do not actually read anything at all for this call, but oh well.
-    //
-    header.ReadData(*data->getIO(), SCOPE_ALL_DATA);   
-    
-    //
-    // Ok, so now we are presumably at where the segment starts. We'll delegate to the
-    // non-seeky version for the actual creation.
-    //
-    return ContainerReader::read(data);
-}
-
-} /* End of namespace Implementation */
-} /* End of namespace FileMediaService */
-} /* End of namespace AsteriskSCF */
-
diff --git a/src/MatroskaUtils.h b/src/MatroskaUtils.h
deleted file mode 100755
index 222fd44..0000000
--- a/src/MatroskaUtils.h
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * 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 "OpaqueContainerData.h"
-
-#include <ebml/EbmlTypes.h>
-#include <boost/shared_ptr.hpp>
-#include <vector>
-#include <string>
-#include <stdexcept>
-
-#include "MatroskaCodec.h"
-
-namespace AsteriskSCF
-{
-namespace FileMediaService
-{
-namespace Implementation
-{
-
-/**
- * File header that must be added to every matroska file being created before the "Segment" is added to it.
- */
-class Header
-{
-public:
-    void writeTo(const OpaqueContainerDataPtr& data);
-};
-
-/**
- * Simple track types.
- */
-class TrackType
-{
-public:
-    virtual ~TrackType() {}
-    virtual int getType() const = 0;
-};
-typedef boost::shared_ptr<TrackType> TrackTypePtr;
-
-class AudioTrackType : public TrackType
-{
-public:
-    int getType() const;
-};
-
-class VideoTrackType : public TrackType
-{
-public:
-    int getType() const;
-};
-
-/**
- * Matroska supports track tagging which is pretty awesome because we
- * can add app-support data.
- */
-struct Tag
-{
-    std::string name;
-    std::string value;
-
-    Tag(const std::string& n, const std::string& v) :
-    name(n), value(v) {}
-};
-typedef std::vector<Tag> TagSeq;
-
-class TrackBase 
-{
-public:
-    virtual ~TrackBase() {}
-
-    unsigned char trackNumber()
-    {
-        return mTrackNumber;
-    }
-
-    virtual uint64 getSize() = 0;
-    virtual TagSeq getTags() = 0;
-    virtual uint64 getID() = 0;
-
-protected:
-    unsigned char mTrackNumber;
-
-    TrackBase(unsigned char trackNo) :
-         mTrackNumber(trackNo)
-    {
-    }
-};
-
-/**
- * Encapsulation of tracks for writing. Virtual because I'm trying to keep matroska-specific stuff
- * out of the headers.
- */
-class TrackWriter : public TrackBase
-{
-public:
-
-    class IncompleteException : public std::logic_error
-    {
-    public:
-        IncompleteException() :
-          std::logic_error("IncompleteException")
-        {
-        }
-    };
-
-    virtual ~TrackWriter() {}
-
-    //
-    // Move to a track writer class.
-    //
-    virtual void setCodecAndType(const CodecPtr& codec, const TrackTypePtr& trackType) = 0;
-    virtual void addTag(const std::string& name, const std::string& value) = 0;
-    virtual void write(uint64 timeCode, uint32 duration, const unsigned char* data, size_t len) = 0;
-    virtual void finished() = 0;
-
-protected:
-    TrackWriter(unsigned char trackNum) :
-         TrackBase(trackNum) {}
-};
-typedef boost::shared_ptr<TrackWriter> TrackWriterPtr;
-
-class Frame
-{
-public:
-    std::vector<unsigned char>& data() const;
-
-protected:
-    std::vector<unsigned char> mData;
-};
-typedef boost::shared_ptr<Frame> FramePtr;
-typedef std::vector<FramePtr> FrameSeq;
-
-/**
- * Encapsulation of tracks for reading.
- */
-class TrackReader : public TrackBase
-{
-public:
-    /**
-     * Start at the beginning.
-     */
-    virtual void reset() = 0;
-
-    virtual void getFrames(FrameSeq& frames, size_t requestedNumberOfFrames) = 0;
-
-    virtual void getFrames(FrameSeq& frames, uint64 fromTime, uint64 untilTime) = 0;
-
-    virtual uint64 getStartTimecode() = 0;
-
-    virtual CodecPtr getCodec() = 0;
-
-    virtual TrackTypePtr getType() = 0;
-
-    /**
-     * Note the absence of a close method. This is because a track reader only provides
-     * a view on data that is read or in the process of being read. The resources
-     * allocated to this process belong to the library itself. A close() method
-     * is really not necessary. When the library realizes that the container and
-     * it's associated readers are no longer in use, it will free up any cached
-     * resources and close "stuff".
-     */
-
-protected:
-    TrackReader(unsigned char trackNum) :
-         TrackBase(trackNum)
-    {
-    }
-};
-typedef boost::shared_ptr<TrackReader> TrackReaderPtr;
-typedef std::vector<TrackReaderPtr> TrackReaderSeq;
-
-class InvalidTrackNumber : public std::out_of_range
-{
-public:
-    InvalidTrackNumber(const std::string& hint) :
-        std::out_of_range(std::string("Track number does not exist: ") + hint)
-    {
-    }
-
-    InvalidTrackNumber() :
-        std::out_of_range("Track number does not exists")
-    {
-    }
-};
-
-class ContainerWriter;
-typedef boost::shared_ptr<ContainerWriter> ContainerWriterPtr;
-
-/**
- * Regarding the matroska specific stuff... I forgot myself and used Matroska specific terminology
- * if not types... I should rename this to be something more generic.
- */
-class ContainerWriter
-{
-    //
-    // Hidden and unimplemented.
-    //
-    ContainerWriter(const ContainerWriter&);
-    void operator=(const ContainerWriter&);
-
-public:
-
-    virtual ~ContainerWriter() {}
-    virtual void addTo(const OpaqueContainerDataPtr& data) = 0;
-
-    virtual size_t getTrackCount() = 0;
-    virtual TrackWriterPtr getTrack(unsigned char trackNumber) = 0;
-
-
-    virtual void close() = 0;
-
-    /**
-     * Create a Segment instance for writing a new container file.
-     */
-    static ContainerWriterPtr create();
-
-protected:
-    ContainerWriter() {}
-};
-
-class ContainerReader;
-typedef boost::shared_ptr<ContainerReader> ContainerReaderPtr;
-
-class ContainerReader
-{
-    //
-    // Hidden and unimplemented.
-    //
-    ContainerReader(const ContainerReader&);
-    void operator=(const ContainerReader&);
-
-public:
-    virtual ~ContainerReader() {}
-
-    virtual size_t getTrackCount() = 0;
-    virtual TrackReaderPtr getTrack(unsigned char trackNumber) =0;
-    virtual TrackReaderSeq getTracks() = 0;
-
-    virtual void close() = 0;
-
-    /**
-     * Attempt to read a segment from the container data at the current location.
-     */
-    static ContainerReaderPtr read(const OpaqueContainerDataPtr& data);
-
-    /**
-     * Seek to the expected location for the Matroska segment in the specified file
-     * and create a segement from the data there. We don't set the file pointer back
-     * to where it was.. so if it is necessary to go back there, you will have
-     * to track it yourself. Sorry.
-     */
-    static ContainerReaderPtr locateAndRead(const OpaqueContainerDataPtr& data);
-
-protected:
-    ContainerReader() {}
-
-};
-
-} /* End of namespace Implementation */
-} /* End of namespace FileMediaService */
-} /* End of namepsace AsteriskSCF */

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


-- 
asterisk-scf/integration/file_media_service.git



More information about the asterisk-scf-commits mailing list