OGMDecodeFilter.cpp

Go to the documentation of this file.
00001 //===========================================================================
00002 //Copyright (C) 2003-2006 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 "OGMDecodeFilter.h"
00034 
00035 
00036 
00037 //COM Factory Template
00038 CFactoryTemplate g_Templates[] = 
00039 {
00040     { 
00041                 L"OGM Decode Filter",                                   // Name
00042             &CLSID_OGMDecodeFilter,                             // CLSID
00043             OGMDecodeFilter::CreateInstance,            // Method to create an instance of Speex Decoder
00044         NULL,                                                                   // Initialization function
00045         NULL                                                                    // Set-up information (for filters)
00046     }
00047 
00048 };
00049 
00050 // Generic way of determining the number of items in the template
00051 int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]); 
00052 
00053 OGMDecodeFilter::OGMDecodeFilter()
00054         :       CTransformFilter(NAME("OGM Video Decoder"), NULL, CLSID_OGMDecodeFilter)
00055         ,       mInputPin(NULL)
00056         ,       mOutputPin(NULL)
00057         ,       mOGMGranulesBuffered(0)
00058         ,       mSegStart(0)
00059         ,       mSegEnd(0)
00060         ,       mSegRate(0)
00061         
00062 {
00063 
00064         
00065 }
00066 
00067 
00068 
00069 OGMDecodeFilter::~OGMDecodeFilter(void)
00070 {
00071 
00072 }
00073 
00074 CUnknown* WINAPI OGMDecodeFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr) 
00075 {
00076         //This routine is the COM implementation to create a new Filter
00077         OGMDecodeFilter *pNewObject = new OGMDecodeFilter();
00078     if (pNewObject == NULL) {
00079         *pHr = E_OUTOFMEMORY;
00080     }
00081         return pNewObject;
00082 } 
00083 
00084 HRESULT OGMDecodeFilter::CheckInputType(const CMediaType* inMediaType)
00085 {
00086         return mInputPin->CheckMediaType(inMediaType);
00087 }
00088 HRESULT OGMDecodeFilter::CheckTransform(const CMediaType* inInputMediaType, const CMediaType* inOutputMediaType)
00089 {
00090 
00091         return S_OK;
00092 }
00093 HRESULT OGMDecodeFilter::DecideBufferSize(IMemAllocator* inAllocator, ALLOCATOR_PROPERTIES* inPropertyRequest)
00094 {
00095         HRESULT locHR = S_OK;
00096 
00097         ALLOCATOR_PROPERTIES locReqAlloc;
00098         ALLOCATOR_PROPERTIES locActualAlloc;
00099         
00100         if (inPropertyRequest->cbAlign <= 0) {
00101                 locReqAlloc.cbAlign = 1;
00102         } else {
00103                 locReqAlloc.cbAlign = inPropertyRequest->cbAlign;
00104         }
00105 
00106 
00107         if (inPropertyRequest->cbBuffer == 0) {
00108                 //VIDSPEC::: Smaller for audio and text
00109                 locReqAlloc.cbBuffer = 65536*16;
00110         } else {
00111                 locReqAlloc.cbBuffer = inPropertyRequest->cbBuffer;
00112         }
00113         
00114 
00115         if (inPropertyRequest->cbPrefix < 0) {
00116                         locReqAlloc.cbPrefix = 0;
00117         } else {
00118                 locReqAlloc.cbPrefix = inPropertyRequest->cbPrefix;
00119         }
00120         
00121         if (inPropertyRequest->cBuffers == 0) {
00122                 locReqAlloc.cBuffers = 5;
00123         } else {
00124                 locReqAlloc.cBuffers = inPropertyRequest->cBuffers;
00125         }
00126 
00127         
00128         locHR = inAllocator->SetProperties(&locReqAlloc, &locActualAlloc);
00129 
00130         if (locHR != S_OK) {
00131                 //TODO::: Handle a fail state here.
00132                 return locHR;
00133         } else {
00134                 //TODO::: Need to save this pointer to decommit in destructor ???
00135                 locHR = inAllocator->Commit();
00136 
00137         
00138                 return locHR;
00139         }
00140         
00141 }
00142 
00143 HRESULT OGMDecodeFilter::NewSegment(REFERENCE_TIME inStartTime, REFERENCE_TIME inStopTime, double inRate)
00144 {
00145         mSegStart = inStartTime;
00146         mSegEnd = inStopTime;
00147         mSegRate = inRate;
00148         return CTransformFilter::NewSegment(inStartTime, inStopTime, inRate);
00149 }
00150 HRESULT OGMDecodeFilter::GetMediaType(int inPosition, CMediaType* outMediaType)
00151 {
00152         
00153         if (inPosition < 0) {
00154                 return E_INVALIDARG;
00155         }
00156         
00157         if ((inPosition == 0) && (mInputPin != NULL) && (mInputPin->IsConnected())) {
00158 
00159                 //VIDSPEC:::This needs cases for audio and text
00160                 switch(mInputPin->getOGMMediaType()) {
00161                         case OGMDecodeInputPin::OGM_VIDEO_TYPE:
00162                         {
00163                                 VIDEOINFOHEADER* locVideoFormat = (VIDEOINFOHEADER*)outMediaType->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
00164                                 *locVideoFormat = *mInputPin->getVideoFormatBlock();
00165                                 //FillMediaType(outMediaType, locVideoFormat->bmiHeader.biSizeImage);
00166                                 outMediaType->majortype = MEDIATYPE_Video;
00167                                 outMediaType->subtype = (GUID)(FOURCCMap(locVideoFormat->bmiHeader.biCompression));;
00168                                 outMediaType->formattype = FORMAT_VideoInfo;
00169                                 //TODO:::Handle temproal compression and variable size field
00170 
00171                         }
00172                         break;
00173                                 
00174                         case OGMDecodeInputPin::OGM_AUDIO_TYPE:
00175                         {
00176                                 WAVEFORMATEX* locAudioFormat = (WAVEFORMATEX*)outMediaType->AllocFormatBuffer(sizeof(WAVEFORMATEX));
00177                                 *locAudioFormat = *mInputPin->getAudioFormatBlock();
00178                                 outMediaType->majortype = MEDIATYPE_Audio;
00179                                 outMediaType->subtype = MEDIASUBTYPE_PCM;
00180                                 outMediaType->subtype.Data1 = locAudioFormat->wFormatTag;
00181                                 outMediaType->formattype = FORMAT_WaveFormatEx;
00182                         }
00183 
00184                         break;
00185                         case OGMDecodeInputPin::OGM_TEXT_TYPE:
00186 
00187                                 outMediaType->majortype = MEDIATYPE_Text;
00188                                 outMediaType->subtype = MEDIASUBTYPE_None;
00189                                 outMediaType->formattype = FORMAT_None;
00190                                 break;
00191 
00192                         default:
00193                                 return E_FAIL;
00194 
00195                 }
00196 
00197 
00198                 return S_OK;
00199         } else {
00200                 return VFW_S_NO_MORE_ITEMS;
00201         }
00202 
00203 
00204 }
00205 
00206 HRESULT OGMDecodeFilter::Receive(IMediaSample* inSample)
00207 {
00208         //VIDSPEC:::
00209         BYTE* locInBuff = NULL;
00210         HRESULT locHR = inSample->GetPointer(&locInBuff);
00211 
00212         if (locHR == S_OK) {
00213                 //Get the time input
00214                 REFERENCE_TIME locStart = -1;
00215                 REFERENCE_TIME locEnd = -1;
00216                 inSample->GetTime(&locStart, &locEnd);
00217 
00218                 //Do nothing if it's a header packet
00219                 if ((locInBuff[0] & 1) != 0) {
00220                         return S_OK;
00221                 }
00222 
00223                 //Get the sample length and setup some buffers
00224                 unsigned long locLength = inSample->GetActualDataLength();
00225                 unsigned char* locBuff = new unsigned char[locLength];
00226                 sSimplePack locPack;
00227                 memcpy((void*)locBuff, (const void*)locInBuff, locLength);
00228                 locPack.mBuff = locBuff;
00229                 locPack.mLength = locLength;
00230 
00231                 
00232                 //Find out how many bytes of the header are the length field
00233                 unsigned long locNumLenBytes = locInBuff[0];
00234                 const unsigned char LEN_MASK = 0xC2; //11000010
00235                 locNumLenBytes &= LEN_MASK;
00236                 locNumLenBytes = (locNumLenBytes >> 6) | ((locNumLenBytes&2) << 1);
00237 
00238                 //Find out how many frames this will gnerate
00239                 //locPackTime represents different things for text, audio and video
00240                 //
00241                 //video -       number of frames duration (can be more than 1 frame generated from a packet)
00242                 //audio -       number of samples generated by this packet
00243                 //text  -       duration of text in 1ms units (ie 1000 = 1sec)
00244                 __int64 locPackTime = 0;
00245                 if (locNumLenBytes != 0) {
00246                         for (int i = 0; i <  locNumLenBytes; i++) {
00247                                 locPackTime |= ((__int64)locInBuff[1+i] << (i * 8));
00248                         }
00249                 } else {
00250                         locPackTime = 1;
00251                 }
00252                 
00253                 //Buffer up the packet  -       
00254                 mOGMGranulesBuffered += locPackTime;                    //VS:::
00255                 locPack.mDuration = locPackTime;                //VS:::
00256                 locPack.mHeaderSize = locNumLenBytes + 1;
00257                 locPack.mIsKeyframe = ((locInBuff[0] & (1<<3)) != 0);
00258 
00259                 mPacketBuffer.push_back(locPack);
00260 
00261                 if (locEnd > 0) {
00262                         REFERENCE_TIME locGlobalStart = 0;
00263                         REFERENCE_TIME locGlobalEnd = 0;
00264 
00265                         //__int64 locFrameDuration = mInputPin->getVideoFormatBlock()->AvgTimePerFrame;         //VS:::
00266                         __int64 locNumBuffered = mPacketBuffer.size();
00267 
00268                         locGlobalEnd = mInputPin->convertGranuleToTime(locEnd); //locEnd * locFrameDuration;                                                                                    //VS:::
00269                         locGlobalStart = locGlobalEnd - (mInputPin->convertGranuleToTime(mOGMGranulesBuffered));//locGlobalEnd - (mOGMGranulesBuffered * locFrameDuration);                             //VS:::
00270 
00271                         __int64 locUptoStart = locGlobalStart;
00272                         __int64 locUptoEnd = locGlobalStart;
00273 
00274                         __int64 locAdjustedStart = 0;
00275                         __int64 locAdjustedEnd = 0;
00276                         for (int i = 0; i < locNumBuffered; i++) {
00277                                 IMediaSample* locOutSample = NULL;
00278                                 
00279                                 locHR = InitializeOutputSample(inSample, &locOutSample);
00280                                 if (locHR == S_OK) {
00281                                         locUptoEnd = locUptoStart + (mInputPin->convertGranuleToTime(mPacketBuffer[i].mDuration));//locUptoStart + (mPacketBuffer[i].mDuration * locFrameDuration);             //VS:::
00282 
00283                                         locAdjustedStart = locUptoStart - mSegStart;
00284                                         locAdjustedEnd = locUptoEnd - mSegStart;
00285                                         locOutSample->SetTime(&locAdjustedStart, &locAdjustedEnd);
00286                                         locOutSample->SetMediaTime(&locAdjustedStart, &locAdjustedEnd);
00287                                         locOutSample->SetSyncPoint(mPacketBuffer[i].mIsKeyframe);
00288                                         locOutSample->SetActualDataLength(mPacketBuffer[i].mLength - mPacketBuffer[i].mHeaderSize);
00289                                         BYTE* locOutBuff = NULL;
00290                                         locOutSample->GetPointer(&locOutBuff);
00291                                         memcpy((void*)locOutBuff, (const void*)(mPacketBuffer[i].mBuff + mPacketBuffer[i].mHeaderSize), mPacketBuffer[i].mLength - mPacketBuffer[i].mHeaderSize);
00292                                         locHR = m_pOutput->Deliver(locOutSample);
00293                                         locOutSample->Release();
00294 
00295                                         if (locHR != S_OK) {
00296                                                 deleteBufferedPackets();
00297                                                 return S_FALSE;
00298                                         }
00299 
00300                                         
00301                                         locUptoStart = locUptoEnd;
00302 
00303                                         
00304                                 } else {
00305                                         deleteBufferedPackets();
00306                                         return S_FALSE;
00307                                 }
00308 
00309                         }
00310 
00311                         deleteBufferedPackets();
00312                         return S_OK;
00313 
00314 
00315 
00316 
00317 
00318                 } else {
00319                         return S_OK;
00320                 }
00321 
00322         } else {
00323                 return locHR;
00324         }
00325 }
00326 
00327 void OGMDecodeFilter::deleteBufferedPackets()
00328 {
00329         for (size_t i = 0; i < mPacketBuffer.size(); i++) {
00330                 delete[] mPacketBuffer[i].mBuff;
00331         }
00332         mPacketBuffer.clear();
00333         mOGMGranulesBuffered = 0;
00334 }
00335 HRESULT OGMDecodeFilter::Transform(IMediaSample* inInputSample, IMediaSample* inOutputSample)
00336 {
00337 
00338         //BYTE* locInBuff = NULL;
00339         //HRESULT locHR = inInputSample->GetPointer(&locInBuff);
00340 
00341         //if (locHR == S_OK) {
00342         //      REFERENCE_TIME locStart = -1;
00343         //      REFERENCE_TIME locEnd = -1;
00344         //      inInputSample->GetTime(&locStart, &locEnd);
00345         //      unsigned long locLength = inInputSample->GetActualDataLength();
00346         //      unsigned char* locBuff = new unsigned char[locLength];
00347         //      sSimplePack locPack;
00348         //      memcpy((void*)locBuff, (const void*)locInBuff, locLength);
00349         //      locPack.mBuff = locBuff;
00350         //      locPack.mLength = locLength;
00351         //      mPacketBuffer.push_back(sSimplePack);
00352 
00353 
00354 
00355         //      
00356 
00357         //}
00358 
00359 
00360         return S_OK;
00361 }
00362 
00363 CBasePin* OGMDecodeFilter::GetPin(int inPinNo)
00364 {
00365 
00366     HRESULT locHR = S_OK;
00367 
00368     // Create an input pin if necessary
00369 
00370     if (m_pInput == NULL) {
00371 
00372         m_pInput = new OGMDecodeInputPin(this, &locHR);         //Deleted in base destructor
00373 
00374         
00375         if (m_pInput == NULL) {
00376             return NULL;
00377         }
00378                 //VIDSPEC::: Change the name dynamically if audio or text
00379                 mInputPin = (OGMDecodeInputPin*)m_pInput;
00380         m_pOutput = new CTransformOutputPin(NAME("OGM Out"), this, &locHR, L"Video Out");       //Deleted in base destructor
00381                         
00382 
00383         if (m_pOutput == NULL) {
00384             delete m_pInput;
00385             m_pInput = NULL;
00386         }
00387     }
00388 
00389     // Return the pin
00390 
00391     if (inPinNo == 0) {
00392         return m_pInput;
00393     } else if (inPinNo == 1) {
00394         return m_pOutput;
00395     } else {
00396         return NULL;
00397     }
00398 
00399 }

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