AutoOggChainGranuleSeekTable.cpp

Go to the documentation of this file.
00001 #include "StdAfx.h"
00002 #include ".\autooggchaingranuleseektable.h"
00003 
00004 AutoOggChainGranuleSeekTable::AutoOggChainGranuleSeekTable(string inFilename)
00005         :       mFilename(inFilename)
00006         ,       mFilePos(0)
00007         ,       mOggDemux(NULL)
00008         ,       mDuration(0)
00009         ,       mPreviousFilePos(0)
00010         ,       mIsEnabled(false)
00011 {
00012         mOggDemux = new OggDataBuffer;
00013         mOggDemux->registerVirtualCallback(this);
00014 
00015 }
00016 
00017 AutoOggChainGranuleSeekTable::~AutoOggChainGranuleSeekTable(void)
00018 {
00019         delete mOggDemux;
00020 
00021         for (size_t i = 0; i < mStreamMaps.size(); i++) {
00022                 delete mStreamMaps[i].mSeekTable;
00023         }
00024 }
00025 
00026 
00027 bool AutoOggChainGranuleSeekTable::buildTable()
00028 {
00029         if (mFilename.find("http") != 0) {
00030                 
00031                 //mSeekMap.clear();
00032                 //addSeekPoint(0, 0);
00033 
00034                 mFile.open(mFilename.c_str(), ios_base::in | ios_base::binary);
00035                 //TODO::: Error check
00036                 const unsigned long BUFF_SIZE = 4096;
00037                 unsigned char* locBuff = new unsigned char[BUFF_SIZE];          //Deleted this function.
00038                 while (!mFile.eof()) {
00039                         mFile.read((char*)locBuff, BUFF_SIZE);
00040                         mOggDemux->feed((const unsigned char*)locBuff, mFile.gcount());
00041                 }
00042                 delete[] locBuff;
00043 
00044                 mFile.close();
00045                 mIsEnabled = true;
00046                 
00047         } else {
00048                 mIsEnabled = false;
00049         }
00050         return true;
00051 }
00052 OggGranuleSeekTable::tSeekPair AutoOggChainGranuleSeekTable::seekPos(LOOG_INT64 inTime)
00053 {
00054         unsigned long retEarliestPos = 4294967295UL;
00055 
00056         LOOG_INT64 locStreamTime = -1;
00057         bool locGotAValidPos = false;
00058 
00059 
00060         OggGranuleSeekTable::tSeekPair locSeekInfo;
00061         OggGranuleSeekTable::tSeekPair retBestSeekInfo;
00062         for (size_t i = 0; i < mStreamMaps.size(); i++) {
00063 
00064                 if ((mStreamMaps[i].mSeekTable != NULL) && (mStreamMaps[i].mSeekInterface != NULL)) {
00065                         //Get the preliminary seek info
00066                         locSeekInfo = mStreamMaps[i].mSeekTable->getStartPos(inTime);
00067                         //1. Get the granule pos in the preliminary seek
00068                         //2. Ask the seek interface what granule we must seek before to make this a valid seek
00069                         //              ie if preroll or keyframes, this value must be less than the original seek value
00070                         //3. Convert the new granule to time
00071                         //4. Repeat the seek
00072                         locStreamTime = mStreamMaps[i].mSeekInterface->convertGranuleToTime(mStreamMaps[i].mSeekInterface->mustSeekBefore(locSeekInfo.second.second));
00073                         locSeekInfo = mStreamMaps[i].mSeekTable->getStartPos(locStreamTime);
00074 
00075                         if (retEarliestPos >= locSeekInfo.second.first) {
00076                                 //Update the earliest position
00077                                 retEarliestPos = locSeekInfo.second.first;
00078                                 retBestSeekInfo = locSeekInfo;
00079                                 locGotAValidPos = true;
00080                         }
00081                 }
00082         }       
00083 
00084         return retBestSeekInfo;//retEarliestPos;
00085 
00086 }
00087 LOOG_INT64 AutoOggChainGranuleSeekTable::fileDuration()
00088 {
00089         return mDuration;
00090 }
00091 bool AutoOggChainGranuleSeekTable::acceptOggPage(OggPage* inOggPage)
00092 {
00093         LOOG_INT64 locGranule = inOggPage->header()->GranulePos();
00094         unsigned long locSerialNo = inOggPage->header()->StreamSerialNo();
00095         sStreamMapping locMapping = getMapping(locSerialNo);
00096 
00097         //There can be upto 2 incomplete packets on any page, one at the end and one at the start
00098         unsigned long locNumBrokenPacks = (inOggPage->header()->isContinuation() ? 1 : 0);
00099         if (inOggPage->numPackets() > 0) {
00100                 locNumBrokenPacks += (inOggPage->getPacket(inOggPage->numPackets() - 1)->isTruncated() ? 1 : 0);
00101         }
00102         //Exclude pages, with -1 granule pos, or that have no complete packets
00103         if (locGranule != -1) { 
00104                 LOOG_INT64 locRealTime = -1;
00105                 if ((inOggPage->numPackets() > locNumBrokenPacks)) {
00106                         
00107                         if ((locMapping.mSeekInterface != NULL) && (locMapping.mSeekTable != NULL)) {
00108                                 //There is valid stream info
00109                                 locRealTime = locMapping.mSeekInterface->convertGranuleToTime(locGranule);
00110                                 if (locRealTime >= 0) {
00111                                         locMapping.mSeekTable->addSeekPoint(locRealTime, mFilePos, locGranule);
00112                                         if (locRealTime > mDuration) {
00113                                                 mDuration = locRealTime;
00114                                         }
00115                                 }
00116                         }
00117                 } else {
00118                         //If there's a granule pos, but no complete packets, there must at least be the end of a packet
00119                         //      so mark  the seek point with the previous filepos from a page that had a packet start on it
00120                         if ((locMapping.mSeekInterface != NULL) && (locMapping.mSeekTable != NULL)) {
00121                                 //There is valid stream info
00122                                 locRealTime = locMapping.mSeekInterface->convertGranuleToTime(locGranule);
00123                                 if (locRealTime >= 0) {
00124                                         locMapping.mSeekTable->addSeekPoint(locRealTime, mPreviousFilePos, locGranule);
00125                                         if (locRealTime > mDuration) {
00126                                                 mDuration = locRealTime;
00127                                         }
00128                                 }
00129                         }
00130                 }
00131         }
00132 
00133         //Only remember the previous file position, if a packet started on this page, otherwise, we might
00134         //      use the start point of the previous page, and that previous page may have not had any packets
00135         //      on it.
00136         //
00137         //Any page that is not a continuation and has more than 1 packet, must have a packet starting on it
00138         if (!(inOggPage->header()->isContinuation() && (inOggPage->numPackets() <= 1))) {
00139                 mPreviousFilePos = mFilePos;
00140         }
00141         mFilePos += inOggPage->pageSize();
00142 
00143         delete inOggPage;
00144         return true;
00145 }
00146 AutoOggChainGranuleSeekTable::sStreamMapping AutoOggChainGranuleSeekTable::getMapping(unsigned long inSerialNo)
00147 {
00148         for (size_t i = 0; i < mStreamMaps.size(); i++) {
00149                 if (mStreamMaps[i].mSerialNo == inSerialNo) {
00150                         return mStreamMaps[i];
00151                 }
00152         }
00153 
00154         sStreamMapping retMapping;
00155         retMapping.mSeekInterface = NULL;
00156         retMapping.mSeekTable = NULL;
00157         retMapping.mSerialNo = 0;
00158 
00159         return retMapping;
00160 }
00161 bool AutoOggChainGranuleSeekTable::addStream(unsigned long inSerialNo, IOggDecoderSeek* inSeekInterface)
00162 {
00163         sStreamMapping locMapping;
00164         locMapping.mSerialNo = inSerialNo;
00165         locMapping.mSeekInterface = inSeekInterface;
00166         if (inSeekInterface == NULL) {
00167                 locMapping.mSeekTable = NULL;
00168         } else {
00169                 locMapping.mSeekTable = new OggGranuleSeekTable;
00170         }
00171         mStreamMaps.push_back(locMapping);
00172 
00173         return true;
00174 
00175 }

Generated on Thu Feb 16 23:48:16 2006 for oggdsf by  doxygen 1.3.9