00001 //=========================================================================== 00002 //Copyright (C) 2003, 2004 Zentaro Kavanagh 00003 // 00004 //Redistribution and use in source and binary forms, with or without 00005 //modification, are permitted provided that the following conditions 00006 //are met: 00007 // 00008 //- Redistributions of source code must retain the above copyright 00009 // notice, this list of conditions and the following disclaimer. 00010 // 00011 //- Redistributions in binary form must reproduce the above copyright 00012 // notice, this list of conditions and the following disclaimer in the 00013 // documentation and/or other materials provided with the distribution. 00014 // 00015 //- Neither the name of Zentaro Kavanagh nor the names of contributors 00016 // may be used to endorse or promote products derived from this software 00017 // without specific prior written permission. 00018 // 00019 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00020 //``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00021 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00022 //PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR 00023 //CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00024 //EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00025 //PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00026 //PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00027 //LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00028 //NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00029 //SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00030 //=========================================================================== 00031 #include "stdafx.h" 00032 #include "theorastream.h" 00033 00034 TheoraStream::TheoraStream(OggPage* inBOSPage, OggDemuxSourceFilter* inOwningFilter, bool inAllowSeek) 00035 : OggStream(inBOSPage, inOwningFilter, inAllowSeek) 00036 , mTheoraFormatBlock(NULL) 00037 { 00038 InitCodec(inBOSPage->getStampedPacket(0)); 00039 //debugLog.open("G:\\logs\\theorastream.log", ios_base::out); 00040 } 00041 00042 TheoraStream::~TheoraStream(void) 00043 { 00044 delete mTheoraFormatBlock; 00045 } 00046 00047 bool TheoraStream::InitCodec(StampedOggPacket* inOggPacket) { 00048 //Can probably abstract this out of here too ! 00049 mCodecHeaders = new StreamHeaders; 00050 mCodecHeaders->mCodecType = StreamHeaders::THEORA; 00051 mCodecHeaders->addPacket((StampedOggPacket*)inOggPacket->clone()); 00052 //What to do with commment fields ?? 00053 mNumHeadersNeeded = 2; 00054 return true; 00055 } 00056 00057 wstring TheoraStream::getPinName() { 00058 wstring locName = L"Theora Out"; 00059 return locName; 00060 } 00061 00062 bool TheoraStream::createFormatBlock() { 00063 mTheoraFormatBlock = new sTheoraFormatBlock; 00064 //Fix the format block data... use header version and other version. 00065 unsigned char* locIdentHeader = mCodecHeaders->getPacket(0)->packetData(); 00066 //mTheoraFormatBlock->TheoraVersion = OggMath::charArrToULong(mCodecHeaders->getPacket(0)->packetData() + 28); 00067 //mTheoraFormatBlock->numChannels = OggMath::charArrToULong(mCodecHeaders->getPacket(0)->packetData() + 48); 00068 //mTheoraFormatBlock->samplesPerSec = OggMath::charArrToULong(mCodecHeaders->getPacket(0)->packetData() + 36); 00069 00070 //0 - 55 theora ident 0 - 6 00071 //56 - 63 ver major 7 - 7 00072 //64 - 71 ver minor 8 - 8 00073 //72 - 79 ver subversion 9 = 9 00074 //80 - 95 width/16 10 - 11 00075 //96 - 111 height/16 12 - 13 00076 //112 - 135 framewidth 14 - 16 00077 //136 - 159 frameheight 17 - 19 00078 //160 - 167 xoffset 20 - 20 00079 //168 - 175 yoffset 21 - 21 00080 //176 - 207 framerateNum 22 - 25 00081 //208 - 239 frameratedenom 26 - 29 00082 //240 - 263 aspectNum 30 - 32 00083 //264 - 287 aspectdenom 33 - 35 00084 //288 - 295 colourspace 36 - 36 00085 //296 - 319 targetbitrate 37 - 39 00086 //320 - 325 targetqual 40 - 40.75 00087 //326 - 330 keyframintlog 40.75- 41.375 00088 mTheoraFormatBlock->theoraVersion = (iBE_Math::charArrToULong(locIdentHeader + 7)) >>8; 00089 mTheoraFormatBlock->outerFrameWidth = (iBE_Math::charArrToUShort(locIdentHeader + 10)) * 16; 00090 mTheoraFormatBlock->outerFrameHeight = (iBE_Math::charArrToUShort(locIdentHeader + 12)) * 16; 00091 mTheoraFormatBlock->pictureWidth = (iBE_Math::charArrToULong(locIdentHeader + 14)) >>8; 00092 mTheoraFormatBlock->pictureHeight = (iBE_Math::charArrToULong(locIdentHeader + 17)) >>8; 00093 mTheoraFormatBlock->xOffset = locIdentHeader[20]; 00094 mTheoraFormatBlock->yOffset = locIdentHeader[21]; 00095 mTheoraFormatBlock->frameRateNumerator = iBE_Math::charArrToULong(locIdentHeader + 22); 00096 mTheoraFormatBlock->frameRateDenominator = iBE_Math::charArrToULong(locIdentHeader + 26); 00097 mTheoraFormatBlock->aspectNumerator = (iBE_Math::charArrToULong(locIdentHeader + 30)) >>8; 00098 mTheoraFormatBlock->aspectDenominator = (iBE_Math::charArrToULong(locIdentHeader + 33)) >>8; 00099 mTheoraFormatBlock->colourSpace = locIdentHeader[36]; 00100 mTheoraFormatBlock->targetBitrate = (iBE_Math::charArrToULong(locIdentHeader + 37)) >>8; 00101 mTheoraFormatBlock->targetQuality = (locIdentHeader[40]) >> 2; 00102 00103 mTheoraFormatBlock->maxKeyframeInterval= (((locIdentHeader[40]) % 4) << 3) + (locIdentHeader[41] >> 5); 00104 00105 return true; 00106 } 00107 00108 void TheoraStream::setLastEndGranPos(__int64 inPos) { 00109 //debugLog<<"Theora inPos: "<<inPos<<endl; 00110 LONGLONG locFrameDuration = (UNITS * mTheoraFormatBlock->frameRateDenominator) / (mTheoraFormatBlock->frameRateNumerator); 00111 00112 LONGLONG locAbsFramePos = inPos / locFrameDuration; 00113 //Timestamp hacks start here... 00114 unsigned long locMod = (unsigned long)pow(2, mTheoraFormatBlock->maxKeyframeInterval); 00115 mLastEndGranulePos = ((locAbsFramePos/locMod) << mTheoraFormatBlock->maxKeyframeInterval) + (locAbsFramePos % locMod); 00116 //unsigned long locInterFrameNo = (mLastSeenStartGranPos) % locMod); 00117 //LONGLONG locAbsFramePos = ((mLastSeenStartGranPos >> locFilter->mTheoraFormatInfo->maxKeyframeInterval) * locMod) + locInterFrameNo; 00118 //REFERENCE_TIME locTimeBase = ((locAbsFramePos * mFrameDuration) - locThis->mSeekTimeBase; 00119 //mLastEndGranulePos = (inPos * (__int64)mSpeexFormatBlock->samplesPerSec)/ UNITS; 00120 //debugLog<<"Theora sets End Gran : "<<mLastEndGranulePos<<endl; 00121 } 00122 BYTE* TheoraStream::getFormatBlock() { 00123 00124 return (BYTE*)mTheoraFormatBlock; 00125 } 00126 00127 GUID TheoraStream::getMajorTypeGUID() { 00128 return MEDIATYPE_Video; 00129 } 00130 unsigned long TheoraStream::getFormatBlockSize() { 00131 //Do something 00132 return sizeof(sTheoraFormatBlock); 00133 } 00134 GUID TheoraStream::getFormatGUID() { 00135 return FORMAT_Theora; 00136 } 00137 GUID TheoraStream::getSubtypeGUID() { 00138 return MEDIASUBTYPE_Theora; 00139 } 00140 00141 LONGLONG TheoraStream::getCurrentPos() { 00142 return 0; //(mLastGranulePos * UNITS) / mVorbisFormatBlock->samplesPerSec; 00143 } 00144 00145 unsigned long TheoraStream::getNumBuffers() { 00146 return THEORA_NUM_BUFFERS; 00147 } 00148 unsigned long TheoraStream::getBufferSize() { 00149 unsigned long locBuffSize = ((unsigned long)mTheoraFormatBlock->outerFrameHeight * (unsigned long)mTheoraFormatBlock->outerFrameWidth * 3) >> 3; 00150 if (locBuffSize < 65536) { 00151 locBuffSize = 65536; 00152 } 00153 return locBuffSize; 00154 }