FFDShowVideoStream.cpp

Go to the documentation of this file.
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 
00032 #include "stdafx.h"
00033 #include "ffdshowvideostream.h"
00034 
00035 
00036 
00037 FFDShowVideoStream::FFDShowVideoStream(OggPage* inBOSPage, OggDemuxSourceFilter* inOwningFilter, bool inAllowSeek)
00038         :       OggStream(inBOSPage, inOwningFilter, inAllowSeek)
00039         ,       mFFDShowVideoFormatBlock(NULL)
00040         ,       mLastTimeStamp(0)
00041         ,       mLastKnownTimeBase(0)
00042         ,       mGranuleOffset(0)
00043 {
00044         InitCodec(inBOSPage->getStampedPacket(0));
00045         //debugLog.open("g:\\logs\\ffd_dump.out", ios_base::out);
00046 }
00047 
00048 FFDShowVideoStream::~FFDShowVideoStream(void)
00049 {
00050         //debugLog.close();
00051         delete mFFDShowVideoFormatBlock;
00052 }
00053 
00054 bool FFDShowVideoStream::InitCodec(StampedOggPacket* inOggPacket) {
00055         //Can probably abstract this out of here too !
00056         mCodecHeaders = new StreamHeaders;
00057         mCodecHeaders->mCodecType = StreamHeaders::FFDSHOW_VIDEO;
00058         mCodecHeaders->addPacket((StampedOggPacket*)inOggPacket->clone());
00059         mHeaderPack = (StampedOggPacket*)inOggPacket->clone();
00060 
00061         unsigned char* locPackData = inOggPacket->packetData();
00062         mFourCCCode = MAKEFOURCC(locPackData[9], locPackData[10], locPackData[11], locPackData[12]);
00063         mMediaSubTypeGUID = (GUID)(FOURCCMap(mFourCCCode));
00064 
00065         unsigned char* locFourCCString = new unsigned char[5];
00066         for (int i = 0; i < 4; i++) {
00067                 locFourCCString[i] = locPackData[9+i];
00068         }
00069         locFourCCString[4] = 0;
00070 
00071         string locPinName = (char*)locFourCCString;
00072         locPinName = "FOURCC( " + locPinName + " ) out";
00073         mPinName = StringHelper::toWStr(locPinName);
00074 
00075         //What to do with commment fields ??
00076         mNumHeadersNeeded = 1;
00077         //mFirstRun = false;
00078         return true;
00079 }
00080 
00081 
00082 bool FFDShowVideoStream::deliverCodecHeaders() {
00083         StampedOggPacket* locPacket = NULL;
00084 
00085         //TODO::: Why 2 ? - there is a comment header
00086         for (unsigned long i = 2; i < mCodecHeaders->numPackets(); i++) {
00087                 locPacket = mCodecHeaders->getPacket(i);
00088 
00089                 dispatchPacket(locPacket);
00090         }
00091         return true;
00092 
00093 }
00094 wstring FFDShowVideoStream::getPinName() {
00095         
00096         return mPinName;
00097 }
00098 
00099 bool FFDShowVideoStream::createFormatBlock() {
00100         mFFDShowVideoFormatBlock = new VIDEOINFOHEADER;
00101 
00102 
00103 
00104         //FORMAT OF HEADER IN OGG BOS
00105         //-----------------------------------------
00106         //0             -               8               =               STRING          Stream Type (char[8] is NULL)
00107         //9             -               12              =               STRING          Sub Type (FOURCC)
00108         //13    -               16              =               INT32           Size of structure ???
00109         //17    -               24              =               INT64           Time per "unit" in DSHOW UNITS
00110         //25    -               32              =               INT64           Samples per "unit"
00111         //33    -               36              =               INT32           Deefault length ????? in media type ?? WTF ?
00112         //37    -               40              =               INT32           Buffer Size
00113         //41    -               42              =               INT16           Bits per sample
00114         //43    -               44              =               -----           HOLE IN DATA
00115         //45    -               48              =               INT32           Video Width
00116         //49    -               52              =               INT32           Video Height
00117 
00118 
00119  
00120 
00121         //------------------------------------------
00122 
00123         
00124         __int64 locTimePerBlock = iLE_Math::CharArrToInt64(mHeaderPack->packetData() + 17);
00125 
00126         
00127         __int64 locSamplesPerBlock = iLE_Math::CharArrToInt64(mHeaderPack->packetData() + 25);
00128 
00129         //debugLog<<"t/block = "<<locTimePerBlock<<"        Sam/block = "<<locSamplesPerBlock<<endl;
00130 
00131         mFFDShowVideoFormatBlock->AvgTimePerFrame = locTimePerBlock / locSamplesPerBlock;
00132 
00133         //debugLog<<"Time per frame = "<<mFFDShowVideoFormatBlock->AvgTimePerFrame<<endl;
00134 
00135         __int64 locFPSec = (UNITS / locTimePerBlock) * locSamplesPerBlock;
00136 
00137         //debugLog<<"Rate = "<<locFPSec<<" fps"<<endl;
00138         unsigned short locBPSample = ((unsigned char)(mHeaderPack->packetData()[41])) + (((unsigned short)(mHeaderPack->packetData()[42])) * 256);
00139 
00140         
00141         
00142         mFFDShowVideoFormatBlock->bmiHeader.biBitCount = locBPSample;
00143         mFFDShowVideoFormatBlock->bmiHeader.biClrImportant = 0;   //All colours important
00144         mFFDShowVideoFormatBlock->bmiHeader.biClrUsed = 0;        //Use max colour depth
00145         mFFDShowVideoFormatBlock->bmiHeader.biCompression = mFourCCCode;
00146 
00147         unsigned long locHeight = iLE_Math::charArrToULong(mHeaderPack->packetData() + 49);
00148         unsigned long locWidth =  iLE_Math::charArrToULong(mHeaderPack->packetData() + 45);
00149 
00150         mFFDShowVideoFormatBlock->dwBitRate = 0;
00151 
00152         mFFDShowVideoFormatBlock->bmiHeader.biHeight = locHeight;
00153         mFFDShowVideoFormatBlock->bmiHeader.biPlanes = 1;    //Must be 1
00154         mFFDShowVideoFormatBlock->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);    //????? Size of what ?
00155         mFFDShowVideoFormatBlock->bmiHeader.biSizeImage = (locHeight * locWidth * locBPSample) / 8;    //Size in bytes of image ??
00156         mFFDShowVideoFormatBlock->bmiHeader.biWidth = locWidth;
00157         mFFDShowVideoFormatBlock->bmiHeader.biXPelsPerMeter = 2000;   //Fuck knows
00158         mFFDShowVideoFormatBlock->bmiHeader.biYPelsPerMeter = 2000;   //" " " " " 
00159         
00160         mFFDShowVideoFormatBlock->rcSource.top = 0;
00161         mFFDShowVideoFormatBlock->rcSource.bottom = locHeight;
00162         mFFDShowVideoFormatBlock->rcSource.left = 0;
00163         mFFDShowVideoFormatBlock->rcSource.right = locWidth;
00164 
00165         mFFDShowVideoFormatBlock->rcTarget.top = 0;
00166         mFFDShowVideoFormatBlock->rcTarget.bottom = locHeight;
00167         mFFDShowVideoFormatBlock->rcTarget.left = 0;
00168         mFFDShowVideoFormatBlock->rcTarget.right = locWidth;
00169 
00170         mFFDShowVideoFormatBlock->dwBitErrorRate=0;
00171         return true;
00172 }
00173 
00174 
00175 bool FFDShowVideoStream::dispatchPacket(StampedOggPacket* inPacket) {
00176         //This is to get aroudn the extra mystery byte that ogg encapsulated divx gets at the start :|
00177         unsigned long locLenBytes = ((((unsigned long)inPacket->packetData()[0]) >> 4) | (inPacket->packetData()[0] & 2)) >> 1;
00178         unsigned char* locBuff = new unsigned char[inPacket->packetSize() - 1];
00179         memcpy((void*)locBuff, (const void*) (inPacket->packetData() + locLenBytes), inPacket->packetSize() - locLenBytes);
00180         
00181 
00182         //This is to help ffdshow handle timestamps the way it likes them.
00183         //Everytime, the start time changes, we record it and reset the granule counter (frame count)
00184         //This lets ogm stuff be seekable cleanly.
00185         if ((mLastKnownTimeBase != inPacket->startTime()) && (inPacket->startTime() != -1)) {
00186                 mLastKnownTimeBase = inPacket->startTime();
00187                 mLastTimeStamp = mLastKnownTimeBase * mFFDShowVideoFormatBlock->AvgTimePerFrame;
00188                 //debugLog<<"Last Time base set  to  "<<mLastKnownTimeBase<<endl;
00189                 //debugLog<<"Last time stamp set to "<<mLastTimeStamp<<endl;
00190 
00191                 //Granule Offset may not be needed any more.
00192                 mGranuleOffset = 0;
00193         }
00194 
00195         //debugLog<<"Packet stamps = "<<inPacket->startTime() << " - "<<inPacket->endTime()<<endl;
00196 
00197         //debugLog<<"m_tStart = "<<mSourcePin->CurrentStartTime()<<endl;
00198         LONGLONG locStart = mLastTimeStamp - mSourcePin->CurrentStartTime();
00199         LONGLONG locEnd = locStart + mFFDShowVideoFormatBlock->AvgTimePerFrame;
00200         mGranuleOffset++;
00201 
00202         //debugLog<<"Time Stamps = "<<locStart<<" - "<<locEnd<<endl;
00203         //debugLog<<"Granule offset " << mGranuleOffset<<endl;
00204         
00205         mLastTimeStamp = (locEnd >= mLastTimeStamp)             ?       locEnd
00206                                                                                                         :       mLastTimeStamp;
00207 
00208         //debugLog << "Packet :    Start   =   "<<locStart<<"     -   End   =   "<<locEnd<<endl;
00209                                                                                                                                                                         //We should only be delivering full packets here.
00210         StampedOggPacket* locPack = new StampedOggPacket(locBuff, inPacket->packetSize() - locLenBytes, false, false, locStart, locEnd, StampedOggPacket::DIRECTSHOW);
00211         return OggStream::dispatchPacket(locPack);
00212 }
00213 BYTE* FFDShowVideoStream::getFormatBlock() {
00214 
00215         return (BYTE*)mFFDShowVideoFormatBlock;
00216 }
00217 
00218 GUID FFDShowVideoStream::getMajorTypeGUID() {
00219         return MEDIATYPE_Video;
00220 }
00221 unsigned long FFDShowVideoStream::getFormatBlockSize() {
00222         //Do something
00223         return sizeof(VIDEOINFOHEADER);
00224 }
00225 GUID FFDShowVideoStream::getFormatGUID() {
00226         return FORMAT_VideoInfo;
00227 }
00228 GUID FFDShowVideoStream::getSubtypeGUID() {
00229         return mMediaSubTypeGUID;
00230 }
00231 
00232 LONGLONG FFDShowVideoStream::getCurrentPos() {
00233         return 0;
00234 }
00235 
00236 unsigned long FFDShowVideoStream::getNumBuffers() {
00237         return FFDSHOW_VIDEO_NUM_BUFFERS;
00238 }
00239 unsigned long FFDShowVideoStream::getBufferSize() {
00240         return FFDSHOW_VIDEO_BUFFER_SIZE;
00241 }

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