TheoraDecodeFilter.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 
00034 #include "TheoraDecodeFilter.h"
00035 
00036 
00037 
00038 //COM Factory Template
00039 CFactoryTemplate g_Templates[] = 
00040 {
00041     { 
00042                 L"Theora Decode Filter",                                        // Name
00043             &CLSID_TheoraDecodeFilter,                          // CLSID
00044             TheoraDecodeFilter::CreateInstance,         // Method to create an instance of Theora Decoder
00045         NULL,                                                                   // Initialization function
00046         NULL                                                                    // Set-up information (for filters)
00047     }
00048 
00049 };
00050 
00051 // Generic way of determining the number of items in the template
00052 int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]); 
00053 
00054 
00055 
00056 TheoraDecodeFilter::TheoraDecodeFilter() 
00057         :       CTransformFilter( NAME("Theora Decode Filter"), NULL, CLSID_TheoraDecodeFilter)
00058         ,       mHeight(0)
00059         ,       mWidth(0)
00060         ,       mFrameSize(0)
00061         ,       mFrameCount(0)
00062         ,       mYOffset(0)
00063         ,       mXOffset(0)
00064         ,       mFrameDuration(0)
00065         ,       mBegun(false)
00066         ,       mSeekTimeBase(0)
00067         ,       mLastSeenStartGranPos(0)
00068         ,       mTheoraFormatInfo(NULL)
00069 {
00070 #ifdef OGGCODECS_LOGGING
00071         debugLog.open("G:\\logs\\newtheofilter.log", ios_base::out);
00072 #endif
00073         mTheoraDecoder = new TheoraDecoder;
00074         mTheoraDecoder->initCodec();
00075 
00076 }
00077 
00078 TheoraDecodeFilter::~TheoraDecodeFilter() {
00079         delete mTheoraDecoder;
00080         mTheoraDecoder = NULL;
00081 
00082         delete mTheoraFormatInfo;
00083         mTheoraFormatInfo = NULL;
00084         debugLog.close();
00085 
00086 }
00087 
00088 CUnknown* WINAPI TheoraDecodeFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr) 
00089 {
00090         //This routine is the COM implementation to create a new Filter
00091         TheoraDecodeFilter *pNewObject = new TheoraDecodeFilter();
00092     if (pNewObject == NULL) {
00093         *pHr = E_OUTOFMEMORY;
00094     }
00095         return pNewObject;
00096 } 
00097 void TheoraDecodeFilter::FillMediaType(CMediaType* outMediaType, unsigned long inSampleSize) {
00098         outMediaType->SetType(&MEDIATYPE_Video);
00099         outMediaType->SetSubtype(&MEDIASUBTYPE_YV12);
00100         outMediaType->SetFormatType(&FORMAT_VideoInfo);
00101         outMediaType->SetTemporalCompression(FALSE);
00102         outMediaType->SetSampleSize(inSampleSize);              
00103 
00104 }
00105 bool TheoraDecodeFilter::FillVideoInfoHeader(VIDEOINFOHEADER* inFormatBuffer) {
00106         TheoraDecodeFilter* locFilter = this;
00107 
00108         inFormatBuffer->AvgTimePerFrame = (UNITS * locFilter->mTheoraFormatInfo->frameRateDenominator) / locFilter->mTheoraFormatInfo->frameRateNumerator;
00109         inFormatBuffer->dwBitRate = locFilter->mTheoraFormatInfo->targetBitrate;
00110         
00111         inFormatBuffer->bmiHeader.biBitCount = 12;   //12 bits per pixel
00112         inFormatBuffer->bmiHeader.biClrImportant = 0;   //All colours important
00113         inFormatBuffer->bmiHeader.biClrUsed = 0;        //Use max colour depth
00114         inFormatBuffer->bmiHeader.biCompression = MAKEFOURCC('Y','V','1','2');
00115         inFormatBuffer->bmiHeader.biHeight = locFilter->mTheoraFormatInfo->pictureHeight;   //Not sure
00116         inFormatBuffer->bmiHeader.biPlanes = 1;    //Must be 1
00117         inFormatBuffer->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);    //????? Size of what ?
00118         inFormatBuffer->bmiHeader.biSizeImage = ((locFilter->mTheoraFormatInfo->pictureHeight * locFilter->mTheoraFormatInfo->pictureWidth) * 3)/2;    //Size in bytes of image ??
00119         inFormatBuffer->bmiHeader.biWidth = locFilter->mTheoraFormatInfo->pictureWidth;
00120         inFormatBuffer->bmiHeader.biXPelsPerMeter = 2000;   //Fuck knows
00121         inFormatBuffer->bmiHeader.biYPelsPerMeter = 2000;   //" " " " " 
00122         
00123         inFormatBuffer->rcSource.top = 0;
00124         inFormatBuffer->rcSource.bottom = locFilter->mTheoraFormatInfo->pictureHeight;
00125         inFormatBuffer->rcSource.left = 0;
00126         inFormatBuffer->rcSource.right = locFilter->mTheoraFormatInfo->pictureWidth;
00127 
00128         inFormatBuffer->rcTarget.top = 0;
00129         inFormatBuffer->rcTarget.bottom = locFilter->mTheoraFormatInfo->pictureHeight;
00130         inFormatBuffer->rcTarget.left = 0;
00131         inFormatBuffer->rcTarget.right = locFilter->mTheoraFormatInfo->pictureWidth;
00132 
00133         inFormatBuffer->dwBitErrorRate=0;
00134         return true;
00135 }
00136 
00137 HRESULT TheoraDecodeFilter::CheckInputType(const CMediaType* inMediaType) {
00138         
00139         if      ( (inMediaType->majortype == MEDIATYPE_Video) &&
00140                         (inMediaType->subtype == MEDIASUBTYPE_Theora) && (inMediaType->formattype == FORMAT_Theora)
00141                 )
00142         {
00143                 return S_OK;
00144         } else {
00145                 return S_FALSE;
00146         }
00147 }
00148 HRESULT TheoraDecodeFilter::CheckTransform(const CMediaType* inInputMediaType, const CMediaType* inOutputMediaType) {
00149         if ((CheckInputType(inInputMediaType) == S_OK) &&
00150                 ((inOutputMediaType->majortype == MEDIATYPE_Video) && (inOutputMediaType->subtype == MEDIASUBTYPE_YV12) && (inOutputMediaType->formattype == FORMAT_VideoInfo)
00151                 )) {
00152                 VIDEOINFOHEADER* locVideoHeader = (VIDEOINFOHEADER*)inOutputMediaType->Format();
00153 
00154         //      if ((locVideoHeader->bmiHeader.biHeight == mTheoraFormatInfo->pictureHeight) && (locVideoHeader->bmiHeader.biWidth == mTheoraFormatInfo->pictureWidth)) {
00155 
00156                         mHeight = (unsigned long)abs(locVideoHeader->bmiHeader.biHeight);
00157                         mWidth = (unsigned long)abs(locVideoHeader->bmiHeader.biWidth);
00158                         return S_OK;
00159         //      } else {
00160         //              return S_FALSE;
00161         //      }
00162         } else {
00163                 return S_FALSE;
00164         }
00165 }
00166 HRESULT TheoraDecodeFilter::DecideBufferSize(IMemAllocator* inAllocator, ALLOCATOR_PROPERTIES* inPropertyRequest) {
00167         //debugLog<<endl;
00168         //debugLog<<"DecideBufferSize :"<<endl;
00169         //FIX::: Abstract this out properly     
00170 
00171         //debugLog<<"Allocator is "<<(unsigned long)inAllocator<<endl;
00172         //Our error variable
00173         HRESULT locHR = S_OK;
00174 
00175         //Create the structures for setproperties to use
00176         ALLOCATOR_PROPERTIES locReqAlloc;
00177         ALLOCATOR_PROPERTIES locActualAlloc;
00178 
00179         //debugLog<<"DecideBufferSize : Requested :"<<endl;
00180         //debugLog<<"DecideBufferSize : Align     : "<<inPropertyRequest->cbAlign<<endl;
00181         //debugLog<<"DecideBufferSize : BuffSize  : "<<inPropertyRequest->cbBuffer<<endl;
00182         //debugLog<<"DecideBufferSize : Prefix    : "<<inPropertyRequest->cbPrefix<<endl;
00183         //debugLog<<"DecideBufferSize : NumBuffs  : "<<inPropertyRequest->cBuffers<<endl;
00184 
00185 
00186         const unsigned long MIN_BUFFER_SIZE = 16*16;                    //What should this be ????
00187         const unsigned long DEFAULT_BUFFER_SIZE = 1024*1024 * 2;
00188         const unsigned long MIN_NUM_BUFFERS = 1;
00189         const unsigned long DEFAULT_NUM_BUFFERS = 1;
00190 
00191         
00192         //Validate and change what we have been requested to do.
00193         //Allignment of data
00194         if (inPropertyRequest->cbAlign <= 0) {
00195                 locReqAlloc.cbAlign = 1;
00196         } else {
00197                 locReqAlloc.cbAlign = inPropertyRequest->cbAlign;
00198         }
00199 
00200         //Size of each buffer
00201         if (inPropertyRequest->cbBuffer < MIN_BUFFER_SIZE) {
00202                 locReqAlloc.cbBuffer = DEFAULT_BUFFER_SIZE;
00203         } else {
00204                 locReqAlloc.cbBuffer = inPropertyRequest->cbBuffer;
00205         }
00206 
00207         //How many prefeixed bytes
00208         if (inPropertyRequest->cbPrefix < 0) {
00209                         locReqAlloc.cbPrefix = 0;
00210         } else {
00211                 locReqAlloc.cbPrefix = inPropertyRequest->cbPrefix;
00212         }
00213 
00214         //Number of buffers in the allcoator
00215         if (inPropertyRequest->cBuffers < MIN_NUM_BUFFERS) {
00216                 locReqAlloc.cBuffers = DEFAULT_NUM_BUFFERS;
00217         } else {
00218 
00219                 locReqAlloc.cBuffers = inPropertyRequest->cBuffers;
00220         }
00221 
00222         //debugLog<<"DecideBufferSize : Modified Request :"<<endl;
00223         //debugLog<<"DecideBufferSize : Align     : "<<locReqAlloc.cbAlign<<endl;
00224         //debugLog<<"DecideBufferSize : BuffSize  : "<<locReqAlloc.cbBuffer<<endl;
00225         //debugLog<<"DecideBufferSize : Prefix    : "<<locReqAlloc.cbPrefix<<endl;
00226         //debugLog<<"DecideBufferSize : NumBuffs  : "<<locReqAlloc.cBuffers<<endl;
00227 
00228 
00229         //Set the properties in the allocator
00230         locHR = inAllocator->SetProperties(&locReqAlloc, &locActualAlloc);
00231 
00232         //debugLog<<"DecideBufferSize : SetProperties returns "<<locHR<<endl;
00233         //debugLog<<"DecideBufferSize : Actual Params :"<<endl;
00234         //debugLog<<"DecideBufferSize : Align     : "<<locActualAlloc.cbAlign<<endl;
00235         //debugLog<<"DecideBufferSize : BuffSize  : "<<locActualAlloc.cbBuffer<<endl;
00236         //debugLog<<"DecideBufferSize : Prefix    : "<<locActualAlloc.cbPrefix<<endl;
00237         //debugLog<<"DecideBufferSize : NumBuffs  : "<<locActualAlloc.cBuffers<<endl;
00238 
00239         //Check the response
00240         switch (locHR) {
00241                 case E_POINTER:
00242                         //debugLog<<"DecideBufferSize : SetProperties - NULL POINTER"<<endl;
00243                         return locHR;
00244                         
00245 
00246                 case VFW_E_ALREADY_COMMITTED:
00247                         //debugLog<<"DecideBufferSize : SetProperties - Already COMMITED"<<endl;
00248                         return locHR;
00249                         
00250                 case VFW_E_BADALIGN:
00251                         //debugLog<<"DecideBufferSize : SetProperties - Bad ALIGN"<<endl;
00252                         return locHR;
00253                         
00254                 case VFW_E_BUFFERS_OUTSTANDING:
00255                         //debugLog<<"DecideBufferSize : SetProperties - BUFFS OUTSTANDING"<<endl;
00256                         return locHR;
00257                         
00258 
00259                 case S_OK:
00260 
00261                         break;
00262                 default:
00263                         //debugLog<<"DecideBufferSize : SetProperties - UNKNOWN ERROR"<<endl;
00264                         break;
00265 
00266         }
00267 
00268         
00269         //TO DO::: Do we commit ?
00270         //RESOLVED ::: Yep !
00271         
00272         locHR = inAllocator->Commit();
00273         //debugLog<<"DecideBufferSize : Commit Returned "<<locHR<<endl;
00274 
00275 
00276         switch (locHR) {
00277                 case E_FAIL:
00278                         //debugLog<<"DecideBufferSize : Commit - FAILED "<<endl;
00279                         return locHR;
00280                 case E_POINTER:
00281                         //debugLog<<"DecideBufferSize : Commit - NULL POINTER "<<endl;
00282                         return locHR;
00283                 case E_INVALIDARG:
00284                         //debugLog<<"DecideBufferSize : Commit - INVALID ARG "<<endl;
00285                         return locHR;
00286                 case E_NOTIMPL:
00287                         //debugLog<<"DecideBufferSize : Commit - NOT IMPL"<<endl;
00288                         return locHR;
00289                 case S_OK:
00290                         //debugLog<<"DecideBufferSize : Commit - ** SUCCESS **"<<endl;
00291                         break;
00292                 default:
00293                         //debugLog<<"DecideBufferSize : Commit - UNKNOWN ERROR "<<endl;
00294                         return locHR;
00295         }
00296 
00297 
00298         return S_OK;
00299 }
00300 HRESULT TheoraDecodeFilter::GetMediaType(int inPosition, CMediaType* outOutputMediaType) {
00301         if (inPosition < 0) {
00302                 return E_INVALIDARG;
00303         }
00304         
00305         if (inPosition == 0) {
00306                 
00307                 VIDEOINFOHEADER* locVideoFormat = (VIDEOINFOHEADER*)outOutputMediaType->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
00308                 FillVideoInfoHeader(locVideoFormat);
00309                 FillMediaType(outOutputMediaType, locVideoFormat->bmiHeader.biSizeImage);
00310                 //debugLog<<"Vid format size "<<locVideoFormat->bmiHeader.biSizeImage<<endl;
00311                 //outMediaType->SetSampleSize(locVideoFormat->bmiHeader.biSizeImage);
00312                 //debugLog<<"Returning from GetMediaType"<<endl;
00313                 return S_OK;
00314         } else {
00315                 return VFW_S_NO_MORE_ITEMS;
00316         }
00317 }
00318 
00319 void TheoraDecodeFilter::ResetFrameCount() {
00320         mFrameCount = 0;
00321         
00322 }
00323 
00324 HRESULT TheoraDecodeFilter::NewSegment(REFERENCE_TIME inStart, REFERENCE_TIME inEnd, double inRate) 
00325 {
00326         debugLog<<"Resetting frame count"<<endl;
00327         ResetFrameCount();
00328         return CTransformFilter::NewSegment(inStart, inEnd, inRate);
00329 
00330 }
00331 HRESULT TheoraDecodeFilter::Transform(IMediaSample* inInputSample, IMediaSample* outOutputSample) {
00332 
00333         //CAutoLock locLock(mStreamLock);
00334         //debugLog<<endl<<"Transform "<<endl;
00335         //debugLog<<"outOutputSample Size = "<<outOutputSample->
00336         HRESULT locHR;
00337         BYTE* locBuff = NULL;
00338         //Get a source poitner into the input buffer
00339         locHR = inInputSample->GetPointer(&locBuff);
00340 
00341         //TODO::: This should be after the return value check !!
00342         BYTE* locNewBuff = new unsigned char[inInputSample->GetActualDataLength()];             //This gets put into a packet.
00343         memcpy((void*)locNewBuff, (const void*)locBuff, inInputSample->GetActualDataLength());
00344 
00345 
00346         if (locHR != S_OK) {
00347                 //debugLog<<"Receive : Get pointer failed..."<<locHR<<endl;     
00348                 return S_FALSE;
00349         } else {
00350                 //debugLog<<"Receive : Get pointer succeeds..."<<endl;  
00351                 //New start time hacks
00352                 REFERENCE_TIME locStart = 0;
00353                 REFERENCE_TIME locEnd = 0;
00354                 inInputSample->GetTime(&locStart, &locEnd);
00355                 //Error chacks needed here
00356                 //debugLog<<"Input Sample Time - "<<locStart<<" to "<<locEnd<<endl;
00357                 
00358                 //More work arounds for that stupid granule pos scheme in theora!
00359                 REFERENCE_TIME locTimeBase = 0;
00360                 REFERENCE_TIME locDummy = 0;
00361                 inInputSample->GetMediaTime(&locTimeBase, &locDummy);
00362                 mSeekTimeBase = locTimeBase;
00363                 //
00364 
00365                 //debugLog<<"SeekTimeBase = "<<mSeekTimeBase<<endl;
00366                 
00367                 if ((mLastSeenStartGranPos != locStart) && (locStart != -1)) {
00368                         //debugLog<<"Resetting frame count"<<endl;
00369 
00370                         //FIXXX:::
00371                         //ResetFrameCount();
00372                         //
00373 
00374                         mLastSeenStartGranPos = locStart;
00375                         //debugLog<<"Setting base gran pos to "<<locStart<<endl;
00376                 }
00377                 
00378                 //End of additions
00379 
00380 
00381 
00382                 AM_MEDIA_TYPE* locMediaType = NULL;
00383                 inInputSample->GetMediaType(&locMediaType);
00384                 if (locMediaType == NULL) {
00385                         //debugLog<<"No dynamic change..."<<endl;
00386                 } else {
00387                         //debugLog<<"Attempting dynamic change..."<<endl;
00388                 }
00389                 
00390                 //This packet is given to the decoder.
00391                 StampedOggPacket* locPacket = new StampedOggPacket(locNewBuff, inInputSample->GetActualDataLength(), false, false, locStart, locEnd, StampedOggPacket::OGG_END_ONLY);
00392 
00393                 bool locIsKeyFrame = mTheoraDecoder->isKeyFrame(locPacket);
00394                 yuv_buffer* locYUV = mTheoraDecoder->decodeTheora(locPacket);           //This accept the packet and deletes it
00395                 if (locYUV != NULL) {
00396                         if (TheoraDecoded(locYUV, outOutputSample, locIsKeyFrame) != 0) {
00397                                 //debugLog<<"Decoded *** FALSE ***"<<endl;
00398                                 return S_FALSE;
00399                         }
00400                 } else {
00401                         //debugLog<<"!@&#^()!&@#!()*@#&)!(*@#&()!*@# NULL Decode"<<endl;
00402                         return S_FALSE;
00403                 }
00404 
00405                 return S_OK;
00406                 
00407         }
00408         
00409 }
00410 
00411 int TheoraDecodeFilter::TheoraDecoded (yuv_buffer* inYUVBuffer, IMediaSample* outSample, bool inIsKeyFrame) 
00412 {
00413         //debugLog<<"TheoraDecoded... #################### "<<endl;
00414         
00415                 
00416         if (!mBegun) {
00417                 //debugLog<<"First time..."<<endl;
00418                 mBegun = true;
00419                 
00420                 //How many UNITS does one frame take.
00421                 mFrameDuration = (UNITS * mTheoraFormatInfo->frameRateDenominator) / (mTheoraFormatInfo->frameRateNumerator);
00422 
00423                 mFrameSize = (mHeight * mWidth * 3) / 2;
00424                 mFrameCount = 0;
00425                 //debugLog<<"Frame Durn = "<<mFrameDuration<<endl;
00426                 //debugLog<<"FrameSize = "<<mFrameSize<<endl;
00427                 
00428                 
00429         }
00430 
00431 
00433 
00434 
00435         //-----------------------
00436         //OLD CODE... FIXXX:::
00437         //Timestamp hacks start here...
00438                         //unsigned long locMod = (unsigned long)pow(2, mTheoraFormatInfo->maxKeyframeInterval);
00439                         //unsigned long locInterFrameNo = (mLastSeenStartGranPos) % locMod;
00440                         //LONGLONG locAbsFramePos = ((mLastSeenStartGranPos >> mTheoraFormatInfo->maxKeyframeInterval)) + locInterFrameNo;
00441                         //REFERENCE_TIME locTimeBase = (locAbsFramePos * mFrameDuration) - mSeekTimeBase;
00442                         //REFERENCE_TIME locFrameStart = locTimeBase + (mFrameCount * mFrameDuration);
00444                         //mFrameCount++;
00446                         //REFERENCE_TIME locFrameEnd = locTimeBase + (mFrameCount * mFrameDuration);
00447         //------------------------
00448 
00449 
00450         REFERENCE_TIME locFrameStart = (mFrameCount * mFrameDuration);
00451         mFrameCount++;
00452         REFERENCE_TIME locFrameEnd = (mFrameCount * mFrameDuration);
00453 
00454         
00455         debugLog<<"Sample times = "<<locFrameStart<<" to "<<locFrameEnd<<"  frame "<<mFrameCount<<" KF = "<<((inIsKeyFrame) ? "YES" : "NO")<<endl;
00456         
00457         //FILTER_STATE locFS;
00458         //GetState(0, &locFS);
00459         //debugLog<<"State Before = "<<locFS<<endl;
00460         //HRESULT locHR = mOutputPin->GetDeliveryBuffer(&locSample, &locFrameStart, &locFrameEnd, locFlags);
00461         //GetState(0, &locFS);
00462         //debugLog<<"State After = "<<locFS<<endl;
00463         
00464         
00465 
00466         //Debuggin code
00467         AM_MEDIA_TYPE* locMediaType = NULL;
00468         outSample->GetMediaType(&locMediaType);
00469         if (locMediaType == NULL) {
00470                 //debugLog<<"No dynamic change..."<<endl;
00471         } else {
00472                 //debugLog<<"Attempting dynamic change..."<<endl;
00473                 if (locMediaType->majortype == MEDIATYPE_Video) {
00474                         //debugLog<<"Still MEDIATYPE_Video"<<endl;
00475                 }
00476 
00477                 if (locMediaType->subtype == MEDIASUBTYPE_YV12) {
00478                         //debugLog<<"Still MEDIASUBTYPE_YV12"<<endl;
00479                 }
00480 
00481                 if (locMediaType->formattype == FORMAT_VideoInfo) {
00482                         //debugLog<<"Still FORMAT_VideoInfo"<<endl;
00483                         VIDEOINFOHEADER* locVF = (VIDEOINFOHEADER*)locMediaType->pbFormat;
00484                         //debugLog<<"Size = "<<locVF->bmiHeader.biSizeImage<<endl;
00485                         //debugLog<<"Dim   = "<<locVF->bmiHeader.biWidth<<" x " <<locVF->bmiHeader.biHeight<<endl;
00486                 }
00487 
00488                 //debugLog<<"Major  : "<<DSStringer::GUID2String(&locMediaType->majortype);
00489                 //debugLog<<"Minor  : "<<DSStringer::GUID2String(&locMediaType->subtype);
00490                 //debugLog<<"Format : "<<DSStringer::GUID2String(&locMediaType->formattype);
00491                 //debugLog<<"Form Sz: "<<locMediaType->cbFormat;
00492 
00493 
00494         }
00495         //
00496 
00498         BYTE* locBuffer = NULL;
00499         
00500         //
00502         outSample->GetPointer(&locBuffer);
00503         
00504         
00505 
00506 
00507         //Fill the buffer with yuv data...
00508         //      
00509 
00510 
00511 
00512         //Set up the pointers
00513         unsigned char* locDestUptoPtr = locBuffer;
00514         char* locSourceUptoPtr = inYUVBuffer->y;
00515 
00516         //Strides from theora are generally -'ve
00517         long locYStride = inYUVBuffer->y_stride;
00518         long locUVStride = inYUVBuffer->uv_stride;
00519 
00520         //debugLog<<"Y Stride = "<<locYStride<<endl;
00521         //debugLog<<"UV Stride = "<<locUVStride<<endl;
00522         //
00523         //Y DATA
00524         //
00525 
00526         //NEW WAY with offsets Y Data
00527         long locTopPad = inYUVBuffer->y_height - mHeight - mYOffset;
00528         //debugLog<<"--------- PAD = "<<locTopPad<<endl;
00529         ASSERT(locTopPad >= 0);
00530         if (locTopPad < 0) {
00531                 locTopPad = 0;
00532         } else {
00533                 
00534         }
00535 
00536         //Skip the top padding
00537         locSourceUptoPtr += (mYOffset * locYStride);
00538 
00539         for (unsigned long line = 0; line < mHeight; line++) {
00540                 memcpy((void*)(locDestUptoPtr), (const void*)(locSourceUptoPtr + mXOffset), mWidth);
00541                 locSourceUptoPtr += locYStride;
00542                 locDestUptoPtr += mWidth;
00543         }
00544 
00545         locSourceUptoPtr += (locTopPad * locYStride);
00546 
00547         //debugLog<<"Dest Distance(y) = "<<(unsigned long)(locDestUptoPtr - locBuffer)<<endl;
00548 
00549         //Source advances by (y_height * y_stride)
00550         //Dest advances by (mHeight * mWidth)
00551 
00552         //
00553         //V DATA
00554         //
00555 
00556         //Half the padding for uv planes... is this correct ? 
00557         locTopPad = locTopPad /2;
00558         
00559         locSourceUptoPtr = inYUVBuffer->v;
00560 
00561         //Skip the top padding
00562         locSourceUptoPtr += ((mYOffset/2) * locYStride);
00563 
00564         for (unsigned long line = 0; line < mHeight / 2; line++) {
00565                 memcpy((void*)(locDestUptoPtr), (const void*)(locSourceUptoPtr + (mXOffset / 2)), mWidth / 2);
00566                 locSourceUptoPtr += locUVStride;
00567                 locDestUptoPtr += (mWidth / 2);
00568         }
00569         locSourceUptoPtr += (locTopPad * locUVStride);
00570 
00571         //Source advances by (locTopPad + mYOffset/2 + mHeight /2) * uv_stride
00572         //where locTopPad for uv = (inYUVBuffer->y_height - mHeight - mYOffset) / 2
00573         //                                              =       (inYUVBuffer->yheight/2 - mHeight/2 - mYOffset/2)
00574         // so source advances by (y_height/2) * uv_stride
00575         //Dest advances by (mHeight * mWidth) /4
00576 
00577 
00578         //debugLog<<"Dest Distance(V) = "<<(unsigned long)(locDestUptoPtr - locBuffer)<<endl;
00579         //
00580         //U DATA
00581         //
00582 
00583         locSourceUptoPtr = inYUVBuffer->u;
00584 
00585         //Skip the top padding
00586         locSourceUptoPtr += ((mYOffset/2) * locYStride);
00587 
00588         for (unsigned long line = 0; line < mHeight / 2; line++) {
00589                 memcpy((void*)(locDestUptoPtr), (const void*)(locSourceUptoPtr + (mXOffset / 2)), mWidth / 2);
00590                 locSourceUptoPtr += locUVStride;
00591                 locDestUptoPtr += (mWidth / 2);
00592         }
00593         locSourceUptoPtr += (locTopPad * locUVStride);
00594 
00595         //debugLog<<"Dest Distance(U) = "<<(unsigned long)(locDestUptoPtr - locBuffer)<<endl;
00596         //debugLog<<"Frame Size = "<<mFrameSize<<endl;
00597 
00598         //Set the sample parameters.
00599         //BOOL locIsKeyFrame = (locInterFrameNo == 0);
00600         BOOL locIsKeyFrame = FALSE;
00601         if (inIsKeyFrame) {
00602                 locIsKeyFrame = TRUE;
00603         };
00604         SetSampleParams(outSample, mFrameSize, &locFrameStart, &locFrameEnd, locIsKeyFrame);
00605 
00606         
00607         
00608         return 0;
00609 
00610 
00611 }
00612 
00613 
00614 HRESULT TheoraDecodeFilter::SetMediaType(PIN_DIRECTION inDirection, const CMediaType* inMediaType) {
00615 
00616         if (inDirection == PINDIR_INPUT) {
00617                 if (inMediaType->subtype == MEDIASUBTYPE_Theora) {
00618                         //debugLog<<"Setting format block"<<endl;
00619                         setTheoraFormat((sTheoraFormatBlock*)inMediaType->pbFormat);
00620                         
00621                         //Set some other stuff here too...
00622                         mXOffset = ((sTheoraFormatBlock*)inMediaType->pbFormat)->xOffset;
00623                         mYOffset = ((sTheoraFormatBlock*)inMediaType->pbFormat)->yOffset;
00624                         //mHeight = ((sTheoraFormatBlock*)inMediaType->pbFormat)->frameHeight;
00625                         //mWidth = ((sTheoraFormatBlock*)inMediaType->pbFormat)->frameWidth;
00626                         //debugLog<<"Setting height width to "<<mWidth<<" x "<<mHeight<<endl;
00627                         //debugLog<<"Frame Dims were "<<((sTheoraFormatBlock*)inMediaType->pbFormat)->frameWidth<<" x "<<((sTheoraFormatBlock*)inMediaType->pbFormat)->frameHeight<<endl;
00628 
00629                 } else {
00630                         //Failed... should never be here !
00631                         throw 0;
00632                 }
00633                 return CTransformFilter::SetMediaType(PINDIR_INPUT, inMediaType);//CVideoTransformFilter::SetMediaType(PINDIR_INPUT, inMediaType);
00634         } else {
00635                 //debugLog<<"Setting Output Stuff"<<endl;
00636                 //Output pin SetMediaType
00637                 //VIDEOINFOHEADER* locVideoHeader = (VIDEOINFOHEADER*)inMediaType->Format();
00638                 //mHeight = (unsigned long)abs(locVideoHeader->bmiHeader.biHeight);
00639                 //mWidth = (unsigned long)abs(locVideoHeader->bmiHeader.biWidth);
00640 
00641 
00642                 //mFrameSize = (unsigned long)locVideoHeader->bmiHeader.biSizeImage;
00643 
00644                 //debugLog<<"Size = "<<mWidth<<" x "<<mHeight<<" ("<<mFrameSize<<")"<<endl;
00645                 //debugLog<<"Size in Format = "<<locVideoHeader->bmiHeader.biWidth<<" x "<<locVideoHeader->bmiHeader.biHeight<<endl;
00646                 return CTransformFilter::SetMediaType(PINDIR_OUTPUT, inMediaType);//CVideoTransformFilter::SetMediaType(PINDIR_OUTPUT, inMediaType);
00647         }
00648 }
00649 
00650 
00651 bool TheoraDecodeFilter::SetSampleParams(IMediaSample* outMediaSample, unsigned long inDataSize, REFERENCE_TIME* inStartTime, REFERENCE_TIME* inEndTime, BOOL inIsSync) 
00652 {
00653         outMediaSample->SetTime(inStartTime, inEndTime);
00654         outMediaSample->SetMediaTime(NULL, NULL);
00655         outMediaSample->SetActualDataLength(inDataSize);
00656         outMediaSample->SetPreroll(FALSE);
00657         outMediaSample->SetDiscontinuity(FALSE);
00658         outMediaSample->SetSyncPoint(inIsSync);
00659         return true;
00660 }
00661 //BOOL TheoraDecodeFilter::ShouldSkipFrame(IMediaSample* inSample) {
00662 //      //m_bSkipping = FALSE;
00663 //      debugLog<<"Don't skip"<<endl;
00664 //      return FALSE;
00665 //}
00666 
00667 sTheoraFormatBlock* TheoraDecodeFilter::getTheoraFormatBlock() 
00668 {
00669         return mTheoraFormatInfo;
00670 }
00671 void TheoraDecodeFilter::setTheoraFormat(sTheoraFormatBlock* inFormatBlock) 
00672 {
00673         delete mTheoraFormatInfo;
00674         mTheoraFormatInfo = new sTheoraFormatBlock;                     //Deelted in destructor.
00675         *mTheoraFormatInfo = *inFormatBlock;
00676 }
00677 
00678 CBasePin* TheoraDecodeFilter::GetPin(int inPinNo)
00679 {
00680     HRESULT locHR = S_OK;
00681 
00682     // Create an input pin if necessary
00683 
00684     if (m_pInput == NULL) {
00685 
00686         m_pInput = new TheoraDecodeInputPin(this, &locHR);              //Deleted in base destructor
00687 
00688         
00689         if (m_pInput == NULL) {
00690             return NULL;
00691         }
00692         m_pOutput = new TheoraDecodeOutputPin(this, &locHR);    //Deleted in base destructor
00693                         
00694 
00695         if (m_pOutput == NULL) {
00696             delete m_pInput;
00697             m_pInput = NULL;
00698         }
00699     }
00700 
00701     // Return the pin
00702 
00703     if (inPinNo == 0) {
00704         return m_pInput;
00705     } else if (inPinNo == 1) {
00706         return m_pOutput;
00707     } else {
00708         return NULL;
00709     }
00710 }
00711 //---------------------------------------
00712 //OLD IMPLOEMENTATION....
00713 //---------------------------------------
00714 //#include "theoradecodefilter.h"
00715 //
00716 //
00717 //
00719 //CFactoryTemplate g_Templates[] = 
00720 //{
00721 //    { 
00722 //              L"Theora Decode Filter",                                        // Name
00723 //          &CLSID_TheoraDecodeFilter,                          // CLSID
00724 //          TheoraDecodeFilter::CreateInstance,         // Method to create an instance of Theora Decoder
00725 //        NULL,                                                                 // Initialization function
00726 //        NULL                                                                  // Set-up information (for filters)
00727 //    }
00728 //
00729 //};
00730 //
00732 //int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]); 
00733 //
00734 //
00735 //
00738 //TheoraDecodeFilter::TheoraDecodeFilter()
00739 //      :       AbstractVideoDecodeFilter(NAME("Ogg Video Decoder"), CLSID_TheoraDecodeFilter, THEORA)
00740 //      ,       mTheoraFormatInfo(NULL)
00741 //{
00742 //
00743 //      bool locWasConstructed = ConstructPins();
00744 //}
00745 //
00746 //bool TheoraDecodeFilter::ConstructPins() 
00747 //{
00748 //      
00749 //      //Output pin must be done first because it's passed to the input pin.
00750 //      mOutputPin = new TheoraDecodeOutputPin(this, m_pLock);
00751 //
00752 //      CMediaType* locAcceptMediaType = new CMediaType(&MEDIATYPE_Video);
00753 //      locAcceptMediaType->subtype = MEDIASUBTYPE_Theora;
00754 //      locAcceptMediaType->formattype = FORMAT_Theora;
00755 //      mInputPin = new TheoraDecodeInputPin(this, m_pLock, mOutputPin, locAcceptMediaType);
00756 //      return true;
00757 //}
00758 //
00759 //TheoraDecodeFilter::~TheoraDecodeFilter(void)
00760 //{
00761 //      //DestroyPins();
00762 //      delete mTheoraFormatInfo;
00763 //}
00764 //
00765 //CUnknown* WINAPI TheoraDecodeFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr) 
00766 //{
00767 //      //This routine is the COM implementation to create a new Filter
00768 //      TheoraDecodeFilter *pNewObject = new TheoraDecodeFilter();
00769 //    if (pNewObject == NULL) {
00770 //        *pHr = E_OUTOFMEMORY;
00771 //    }
00772 //      return pNewObject;
00773 //} 
00774 //
00775 //STDMETHODIMP TheoraDecodeFilter::GetState(DWORD dw, FILTER_STATE *pState)
00776 //{
00777 //    CheckPointer(pState, E_POINTER);
00778 //    *pState = m_State;
00779 //      if (m_State == State_Paused) {
00780 //        return VFW_S_CANT_CUE;
00781 //      } else {
00782 //        return S_OK;
00783 //      }
00784 //}
00785 //
00788 //sTheoraFormatBlock* TheoraDecodeFilter::getTheoraFormatBlock() 
00789 //{
00790 //      return mTheoraFormatInfo;
00791 //}
00792 //void TheoraDecodeFilter::setTheoraFormat(sTheoraFormatBlock* inFormatBlock) 
00793 //{
00794 //      delete mTheoraFormatInfo;
00795 //      mTheoraFormatInfo = new sTheoraFormatBlock;
00796 //      *mTheoraFormatInfo = *inFormatBlock;
00797 //}

Generated on Tue Feb 15 14:54:16 2005 for oggdsf by  doxygen 1.3.9