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
00032
00033
00034 mFile.open(mFilename.c_str(), ios_base::in | ios_base::binary);
00035
00036 const unsigned long BUFF_SIZE = 4096;
00037 unsigned char* locBuff = new unsigned char[BUFF_SIZE];
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
00066 locSeekInfo = mStreamMaps[i].mSeekTable->getStartPos(inTime);
00067
00068
00069
00070
00071
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
00077 retEarliestPos = locSeekInfo.second.first;
00078 retBestSeekInfo = locSeekInfo;
00079 locGotAValidPos = true;
00080 }
00081 }
00082 }
00083
00084 return retBestSeekInfo;
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
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
00103 if (locGranule != -1) {
00104 LOOG_INT64 locRealTime = -1;
00105 if ((inOggPage->numPackets() > locNumBrokenPacks)) {
00106
00107 if ((locMapping.mSeekInterface != NULL) && (locMapping.mSeekTable != NULL)) {
00108
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
00119
00120 if ((locMapping.mSeekInterface != NULL) && (locMapping.mSeekTable != NULL)) {
00121
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
00134
00135
00136
00137
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 }