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 
00069         ,       mSegStart(0)
00070         ,       mSegEnd(0)
00071         ,       mPlaybackRate(0.0)
00072         ,       mTheoraFormatInfo(NULL)
00073 {
00074 #ifdef OGGCODECS_LOGGING
00075         debugLog.open("G:\\logs\\newtheofilter.log", ios_base::out);
00076 #endif
00077         mTheoraDecoder = new TheoraDecoder;
00078         mTheoraDecoder->initCodec();
00079 
00080 }
00081 
00082 TheoraDecodeFilter::~TheoraDecodeFilter() {
00083         delete mTheoraDecoder;
00084         mTheoraDecoder = NULL;
00085 
00086         delete mTheoraFormatInfo;
00087         mTheoraFormatInfo = NULL;
00088         debugLog.close();
00089 
00090 }
00091 
00092 CUnknown* WINAPI TheoraDecodeFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr) 
00093 {
00094         //This routine is the COM implementation to create a new Filter
00095         TheoraDecodeFilter *pNewObject = new TheoraDecodeFilter();
00096     if (pNewObject == NULL) {
00097         *pHr = E_OUTOFMEMORY;
00098     }
00099         return pNewObject;
00100 } 
00101 void TheoraDecodeFilter::FillMediaType(CMediaType* outMediaType, unsigned long inSampleSize) {
00102         outMediaType->SetType(&MEDIATYPE_Video);
00103         outMediaType->SetSubtype(&MEDIASUBTYPE_YV12);
00104         outMediaType->SetFormatType(&FORMAT_VideoInfo);
00105         outMediaType->SetTemporalCompression(FALSE);
00106         outMediaType->SetSampleSize(inSampleSize);              
00107 
00108 }
00109 bool TheoraDecodeFilter::FillVideoInfoHeader(VIDEOINFOHEADER* inFormatBuffer) {
00110         TheoraDecodeFilter* locFilter = this;
00111 
00112         inFormatBuffer->AvgTimePerFrame = (UNITS * locFilter->mTheoraFormatInfo->frameRateDenominator) / locFilter->mTheoraFormatInfo->frameRateNumerator;
00113         inFormatBuffer->dwBitRate = locFilter->mTheoraFormatInfo->targetBitrate;
00114         
00115         inFormatBuffer->bmiHeader.biBitCount = 12;   //12 bits per pixel
00116         inFormatBuffer->bmiHeader.biClrImportant = 0;   //All colours important
00117         inFormatBuffer->bmiHeader.biClrUsed = 0;        //Use max colour depth
00118         inFormatBuffer->bmiHeader.biCompression = MAKEFOURCC('Y','V','1','2');
00119         inFormatBuffer->bmiHeader.biHeight = locFilter->mTheoraFormatInfo->pictureHeight;   //Not sure
00120         inFormatBuffer->bmiHeader.biPlanes = 1;    //Must be 1
00121         inFormatBuffer->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);    //????? Size of what ?
00122         inFormatBuffer->bmiHeader.biSizeImage = ((locFilter->mTheoraFormatInfo->pictureHeight * locFilter->mTheoraFormatInfo->pictureWidth) * 3)/2;    //Size in bytes of image ??
00123         inFormatBuffer->bmiHeader.biWidth = locFilter->mTheoraFormatInfo->pictureWidth;
00124         inFormatBuffer->bmiHeader.biXPelsPerMeter = 2000;   //Fuck knows
00125         inFormatBuffer->bmiHeader.biYPelsPerMeter = 2000;   //" " " " " 
00126         
00127         inFormatBuffer->rcSource.top = 0;
00128         inFormatBuffer->rcSource.bottom = locFilter->mTheoraFormatInfo->pictureHeight;
00129         inFormatBuffer->rcSource.left = 0;
00130         inFormatBuffer->rcSource.right = locFilter->mTheoraFormatInfo->pictureWidth;
00131 
00132         inFormatBuffer->rcTarget.top = 0;
00133         inFormatBuffer->rcTarget.bottom = locFilter->mTheoraFormatInfo->pictureHeight;
00134         inFormatBuffer->rcTarget.left = 0;
00135         inFormatBuffer->rcTarget.right = locFilter->mTheoraFormatInfo->pictureWidth;
00136 
00137         inFormatBuffer->dwBitErrorRate=0;
00138         return true;
00139 }
00140 
00141 HRESULT TheoraDecodeFilter::CheckInputType(const CMediaType* inMediaType) 
00142 {
00143 
00144         
00145         if      ( (inMediaType->majortype == MEDIATYPE_OggPacketStream) &&
00146                         (inMediaType->subtype == MEDIASUBTYPE_None) && (inMediaType->formattype == FORMAT_OggIdentHeader)
00147                 )
00148         {
00149                 if (inMediaType->cbFormat == THEORA_IDENT_HEADER_SIZE) {
00150                         if (strncmp((char*)inMediaType->pbFormat, "\200theora", 7) == 0) {
00151                                 //TODO::: Possibly verify version
00152                                 return S_OK;
00153                         }
00154                 }
00155 
00156         }
00157         return S_FALSE;
00158         
00159 }
00160 HRESULT TheoraDecodeFilter::CheckTransform(const CMediaType* inInputMediaType, const CMediaType* inOutputMediaType) {
00161         if ((CheckInputType(inInputMediaType) == S_OK) &&
00162                 ((inOutputMediaType->majortype == MEDIATYPE_Video) && (inOutputMediaType->subtype == MEDIASUBTYPE_YV12) && (inOutputMediaType->formattype == FORMAT_VideoInfo)
00163                 )) {
00164                 VIDEOINFOHEADER* locVideoHeader = (VIDEOINFOHEADER*)inOutputMediaType->Format();
00165 
00166         //      if ((locVideoHeader->bmiHeader.biHeight == mTheoraFormatInfo->pictureHeight) && (locVideoHeader->bmiHeader.biWidth == mTheoraFormatInfo->pictureWidth)) {
00167 
00168                         mHeight = (unsigned long)abs(locVideoHeader->bmiHeader.biHeight);
00169                         mWidth = (unsigned long)abs(locVideoHeader->bmiHeader.biWidth);
00170                         return S_OK;
00171         //      } else {
00172         //              return S_FALSE;
00173         //      }
00174         } else {
00175                 return S_FALSE;
00176         }
00177 }
00178 HRESULT TheoraDecodeFilter::DecideBufferSize(IMemAllocator* inAllocator, ALLOCATOR_PROPERTIES* inPropertyRequest) {
00179         //debugLog<<endl;
00180         //debugLog<<"DecideBufferSize :"<<endl;
00181         //FIX::: Abstract this out properly     
00182 
00183         //debugLog<<"Allocator is "<<(unsigned long)inAllocator<<endl;
00184         //Our error variable
00185         HRESULT locHR = S_OK;
00186 
00187         //Create the structures for setproperties to use
00188         ALLOCATOR_PROPERTIES locReqAlloc;
00189         ALLOCATOR_PROPERTIES locActualAlloc;
00190 
00191         //debugLog<<"DecideBufferSize : Requested :"<<endl;
00192         //debugLog<<"DecideBufferSize : Align     : "<<inPropertyRequest->cbAlign<<endl;
00193         //debugLog<<"DecideBufferSize : BuffSize  : "<<inPropertyRequest->cbBuffer<<endl;
00194         //debugLog<<"DecideBufferSize : Prefix    : "<<inPropertyRequest->cbPrefix<<endl;
00195         //debugLog<<"DecideBufferSize : NumBuffs  : "<<inPropertyRequest->cBuffers<<endl;
00196 
00197 
00198         const unsigned long MIN_BUFFER_SIZE = 16*16;                    //What should this be ????
00199         const unsigned long DEFAULT_BUFFER_SIZE = 1024*1024 * 2;
00200         const unsigned long MIN_NUM_BUFFERS = 1;
00201         const unsigned long DEFAULT_NUM_BUFFERS = 1;
00202 
00203         
00204         //Validate and change what we have been requested to do.
00205         //Allignment of data
00206         if (inPropertyRequest->cbAlign <= 0) {
00207                 locReqAlloc.cbAlign = 1;
00208         } else {
00209                 locReqAlloc.cbAlign = inPropertyRequest->cbAlign;
00210         }
00211 
00212         //Size of each buffer
00213         if (inPropertyRequest->cbBuffer < MIN_BUFFER_SIZE) {
00214                 locReqAlloc.cbBuffer = DEFAULT_BUFFER_SIZE;
00215         } else {
00216                 locReqAlloc.cbBuffer = inPropertyRequest->cbBuffer;
00217         }
00218 
00219         //How many prefeixed bytes
00220         if (inPropertyRequest->cbPrefix < 0) {
00221                         locReqAlloc.cbPrefix = 0;
00222         } else {
00223                 locReqAlloc.cbPrefix = inPropertyRequest->cbPrefix;
00224         }
00225 
00226         //Number of buffers in the allcoator
00227         if (inPropertyRequest->cBuffers < MIN_NUM_BUFFERS) {
00228                 locReqAlloc.cBuffers = DEFAULT_NUM_BUFFERS;
00229         } else {
00230 
00231                 locReqAlloc.cBuffers = inPropertyRequest->cBuffers;
00232         }
00233 
00234         //debugLog<<"DecideBufferSize : Modified Request :"<<endl;
00235         //debugLog<<"DecideBufferSize : Align     : "<<locReqAlloc.cbAlign<<endl;
00236         //debugLog<<"DecideBufferSize : BuffSize  : "<<locReqAlloc.cbBuffer<<endl;
00237         //debugLog<<"DecideBufferSize : Prefix    : "<<locReqAlloc.cbPrefix<<endl;
00238         //debugLog<<"DecideBufferSize : NumBuffs  : "<<locReqAlloc.cBuffers<<endl;
00239 
00240 
00241         //Set the properties in the allocator
00242         locHR = inAllocator->SetProperties(&locReqAlloc, &locActualAlloc);
00243 
00244         //debugLog<<"DecideBufferSize : SetProperties returns "<<locHR<<endl;
00245         //debugLog<<"DecideBufferSize : Actual Params :"<<endl;
00246         //debugLog<<"DecideBufferSize : Align     : "<<locActualAlloc.cbAlign<<endl;
00247         //debugLog<<"DecideBufferSize : BuffSize  : "<<locActualAlloc.cbBuffer<<endl;
00248         //debugLog<<"DecideBufferSize : Prefix    : "<<locActualAlloc.cbPrefix<<endl;
00249         //debugLog<<"DecideBufferSize : NumBuffs  : "<<locActualAlloc.cBuffers<<endl;
00250 
00251         //Check the response
00252         switch (locHR) {
00253                 case E_POINTER:
00254                         //debugLog<<"DecideBufferSize : SetProperties - NULL POINTER"<<endl;
00255                         return locHR;
00256                         
00257 
00258                 case VFW_E_ALREADY_COMMITTED:
00259                         //debugLog<<"DecideBufferSize : SetProperties - Already COMMITED"<<endl;
00260                         return locHR;
00261                         
00262                 case VFW_E_BADALIGN:
00263                         //debugLog<<"DecideBufferSize : SetProperties - Bad ALIGN"<<endl;
00264                         return locHR;
00265                         
00266                 case VFW_E_BUFFERS_OUTSTANDING:
00267                         //debugLog<<"DecideBufferSize : SetProperties - BUFFS OUTSTANDING"<<endl;
00268                         return locHR;
00269                         
00270 
00271                 case S_OK:
00272 
00273                         break;
00274                 default:
00275                         //debugLog<<"DecideBufferSize : SetProperties - UNKNOWN ERROR"<<endl;
00276                         break;
00277 
00278         }
00279 
00280         
00281         //TO DO::: Do we commit ?
00282         //RESOLVED ::: Yep !
00283         
00284         locHR = inAllocator->Commit();
00285         //debugLog<<"DecideBufferSize : Commit Returned "<<locHR<<endl;
00286 
00287 
00288         switch (locHR) {
00289                 case E_FAIL:
00290                         //debugLog<<"DecideBufferSize : Commit - FAILED "<<endl;
00291                         return locHR;
00292                 case E_POINTER:
00293                         //debugLog<<"DecideBufferSize : Commit - NULL POINTER "<<endl;
00294                         return locHR;
00295                 case E_INVALIDARG:
00296                         //debugLog<<"DecideBufferSize : Commit - INVALID ARG "<<endl;
00297                         return locHR;
00298                 case E_NOTIMPL:
00299                         //debugLog<<"DecideBufferSize : Commit - NOT IMPL"<<endl;
00300                         return locHR;
00301                 case S_OK:
00302                         //debugLog<<"DecideBufferSize : Commit - ** SUCCESS **"<<endl;
00303                         break;
00304                 default:
00305                         //debugLog<<"DecideBufferSize : Commit - UNKNOWN ERROR "<<endl;
00306                         return locHR;
00307         }
00308 
00309 
00310         return S_OK;
00311 }
00312 HRESULT TheoraDecodeFilter::GetMediaType(int inPosition, CMediaType* outOutputMediaType) {
00313         if (inPosition < 0) {
00314                 return E_INVALIDARG;
00315         }
00316         
00317         if (inPosition == 0) {
00318                 
00319                 VIDEOINFOHEADER* locVideoFormat = (VIDEOINFOHEADER*)outOutputMediaType->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
00320                 FillVideoInfoHeader(locVideoFormat);
00321                 FillMediaType(outOutputMediaType, locVideoFormat->bmiHeader.biSizeImage);
00322                 //debugLog<<"Vid format size "<<locVideoFormat->bmiHeader.biSizeImage<<endl;
00323                 //outMediaType->SetSampleSize(locVideoFormat->bmiHeader.biSizeImage);
00324                 //debugLog<<"Returning from GetMediaType"<<endl;
00325                 return S_OK;
00326         } else {
00327                 return VFW_S_NO_MORE_ITEMS;
00328         }
00329 }
00330 
00331 void TheoraDecodeFilter::ResetFrameCount() 
00332 {
00333         //XTODO::: Maybe not needed
00334         mFrameCount = 0;
00335         
00336 }
00337 
00338 HRESULT TheoraDecodeFilter::NewSegment(REFERENCE_TIME inStart, REFERENCE_TIME inEnd, double inRate) 
00339 {
00340         debugLog<<"Resetting frame count"<<endl;
00341         ResetFrameCount();
00342         mSegStart = inStart;
00343         mSegEnd = inEnd;
00344         mPlaybackRate = inRate;
00345         return CTransformFilter::NewSegment(inStart, inEnd, inRate);
00346 
00347 }
00348 
00349 HRESULT TheoraDecodeFilter::Receive(IMediaSample* inInputSample)
00350 {
00351 
00352 
00353         BYTE* locBuff = NULL;
00354         //Get a source poitner into the input buffer
00355         HRESULT locHR = inInputSample->GetPointer(&locBuff);
00356 
00357         if (locHR != S_OK) {
00358                 //debugLog<<"Receive : Get pointer failed..."<<locHR<<endl;     
00359                 return S_FALSE;
00360         } else {
00361 
00362                 if ((inInputSample->GetActualDataLength() > 0) && ((locBuff[0] & 128) != 0)) {
00363                         //inInputSample->Release();
00364 
00365                         //This is a header, so ignore it
00366                         return S_OK;
00367                 }
00368                 //Make a copy of the packet buffer
00369                 BYTE* locNewBuff = new unsigned char[inInputSample->GetActualDataLength()];             //This gets put into a packet.
00370                 memcpy((void*)locNewBuff, (const void*)locBuff, inInputSample->GetActualDataLength());
00371 
00372 
00373                 REFERENCE_TIME locStart = 0;
00374                 REFERENCE_TIME locEnd = 0;
00375                 inInputSample->GetTime(&locStart, &locEnd);
00376 
00377                 debugLog<<"Theora::Receive - Sample: Size = "<<inInputSample->GetActualDataLength()<<" Time: "<<locStart<<" - "<<locEnd<<endl;
00378 
00379                 //This packet is given to the decoder or buffered for later
00380                 StampedOggPacket* locPacket = new StampedOggPacket(locNewBuff, inInputSample->GetActualDataLength(), false, false, locStart, locEnd, StampedOggPacket::OGG_END_ONLY);
00381 
00382                 //Buffer all packets, even if we are about to send them anyway
00383                 mBufferedPackets.push_back(locPacket);
00384 
00385                 if (locEnd < 0) {
00386 
00387                         //The packet was ok, but we just aren't going to deliver it yet
00388                         return S_OK;
00389                 } else {
00390                         //Now we have one with a stamp, we can send all the previous ones.
00391                         TheoraDecodeInputPin* locInputPin = (TheoraDecodeInputPin*)m_pInput;
00392                         REFERENCE_TIME locGlobalEnd = locInputPin->convertGranuleToTime(locEnd);
00393                         unsigned long locNumBufferedFrames = mBufferedPackets.size();
00394                         REFERENCE_TIME locGlobalStart = locGlobalEnd - (locNumBufferedFrames * mFrameDuration);
00395 
00396                         locStart = locGlobalStart;
00397 
00398 
00399                         //Offsetting
00400                         REFERENCE_TIME locGlobalOffset = 0;
00401                         //Handle stream offsetting
00402                         if (!locInputPin->getSentStreamOffset() && (locInputPin->getOutputPinInterface() != NULL)) {
00403                                 locInputPin->getOutputPinInterface()->notifyStreamBaseTime(locStart);
00404                                 locInputPin->setSentStreamOffset(true);
00405                                 
00406                         }
00407 
00408                         if (locInputPin->getOutputPinInterface() != NULL) {
00409                                 locGlobalOffset = locInputPin->getOutputPinInterface()->getGlobalBaseTime();
00410                         }
00411                         
00412                         debugLog<<"Theora::Receive - "<<locNumBufferedFrames<<" frames buffered"<<endl;
00413                         for (unsigned long i = 0; i < locNumBufferedFrames; i++) {
00414                                 debugLog<<"Theora::Receive - Processing buffered frame "<<i<<endl;
00415                                 bool locIsKeyFrame = mTheoraDecoder->isKeyFrame(mBufferedPackets[i]);
00416                                 yuv_buffer* locYUV = mTheoraDecoder->decodeTheora(mBufferedPackets[i]);         //This accept the packet and deletes it
00417                                 locEnd = locStart + mFrameDuration;
00418                                 REFERENCE_TIME locAdjustedStart = locStart - mSegStart - locGlobalOffset;
00419                                 REFERENCE_TIME locAdjustedEnd = locEnd - mSegStart - locGlobalOffset;
00420 
00421                                 if (locAdjustedStart < 0) {
00422                                         locAdjustedStart = 0;
00423                                 }
00424 
00425                                 if (locAdjustedEnd >= 0) { 
00426                                         if (locYUV != NULL) {
00427                                                 IMediaSample* locOutSample = NULL;
00428                                                 debugLog<<"Theora::Receive - Pre output sample initialisation"<<endl;
00429                                                 locHR = InitializeOutputSample(inInputSample, &locOutSample);
00430                                                 if (locHR != S_OK) {
00431                                                         //XTODO::: We need to trash our buffered packets
00432                                                         debugLog<<"Theora::Receive - Output sample initialisation failed"<<endl;
00433                                                         
00434                                                         deleteBufferedPacketsAfter(i);
00435                                                         
00436                                                         return S_FALSE;
00437                                                 }
00438                                                 debugLog<<"Theora::Receive - Output sample initialisation suceeded"<<endl;
00439 
00440                                                 //REFERENCE_TIME locAdjustedStart = (locStart * RATE_DENOMINATOR) / mRateNumerator;
00441                                                 //REFERENCE_TIME locAdjustedEnd = (locEnd * RATE_DENOMINATOR) / mRateNumerator;
00442 
00443 
00444                                                 //Fill the sample info
00445                                                 if (TheoraDecoded(locYUV, locOutSample, locIsKeyFrame, locAdjustedStart, locAdjustedEnd) != S_OK) {
00446                                                         
00447                                                         //XTODO::: We need to trash our buffered packets
00448                                                         locOutSample->Release();
00449                                                         deleteBufferedPacketsAfter(i);
00450                                                         return S_FALSE;
00451                                                 } else {
00452                                                         //Deliver the sample
00453                                                         debugLog<<"Theora::Receive - Delivering: "<<locAdjustedStart<<" to "<<locAdjustedEnd<<(locIsKeyFrame ? "KEYFRAME": " ")<<endl;
00454                                                         
00455                                                         locHR = m_pOutput->Deliver(locOutSample);
00456                                                         locOutSample->Release();
00457                                                         debugLog<<"Theora::Receive - Post delivery"<<endl;
00458                                                         if (locHR != S_OK) {
00459                                                                 //XTODO::: We need to trash our buffered packets
00460                                                                 debugLog<<"Theora::Receive - Delivery failed"<<endl;
00461                                                                 locOutSample->Release();
00462                                                                 deleteBufferedPacketsAfter(i);
00463                                                                 return S_FALSE;
00464                                                         }
00465                                                         debugLog<<"Theora::Receive - Delivery Suceeded"<<endl;
00466 
00467                                                 }
00468                                         } else {
00469                                                 //XTODO::: We need to trash our buffered packets
00470                                                 deleteBufferedPacketsAfter(i);
00471                                                 return S_FALSE;
00472                                         }
00473                                 }
00474                                 locStart = locEnd;
00475                         }
00476 
00477                         mBufferedPackets.clear();
00478 
00479 
00480 
00481                         return S_OK;
00482 
00483                 }
00484                 
00485         }
00486 }
00487 
00488 void TheoraDecodeFilter::deleteBufferedPacketsAfter(unsigned long inPacketIndex)
00489 {
00490         for (size_t i = inPacketIndex + 1; i < mBufferedPackets.size(); i++) {
00491                 delete mBufferedPackets[i];
00492         }
00493 
00494         mBufferedPackets.clear();
00495 }
00496 HRESULT TheoraDecodeFilter::Transform(IMediaSample* inInputSample, IMediaSample* outOutputSample) 
00497 {
00498         //HRESULT locHR;
00499         //BYTE* locBuff = NULL;
00501         //locHR = inInputSample->GetPointer(&locBuff);
00502 
00503         //if (locHR != S_OK) {
00504         //      //debugLog<<"Receive : Get pointer failed..."<<locHR<<endl;     
00505         //      return S_FALSE;
00506         //} else {
00507         //      //Make a copy of the packet buffer
00508         //      BYTE* locNewBuff = new unsigned char[inInputSample->GetActualDataLength()];             //This gets put into a packet.
00509         //      memcpy((void*)locNewBuff, (const void*)locBuff, inInputSample->GetActualDataLength());
00510 
00511 
00512         //      REFERENCE_TIME locStart = 0;
00513         //      REFERENCE_TIME locEnd = 0;
00514         //      inInputSample->GetTime(&locStart, &locEnd);
00515 
00516         //      //This packet is given to the decoder or buffered for later
00517         //      StampedOggPacket* locPacket = new StampedOggPacket(locNewBuff, inInputSample->GetActualDataLength(), false, false, locStart, locEnd, StampedOggPacket::OGG_END_ONLY);
00518 
00519         //      //Buffer all packets, even if we are about to send them anyway
00520         //      mBufferedPackets.push_back(locPacket);
00521 
00522         //      if (locEnd < 0) {
00523 
00524         //              //S_FALSE is an agreement with CTransform filter, to not deliver the presented output sample
00525         //              //XXX::: There may be some problems doing this, since it causes a quality message, and thinks we
00526         //              //              are dropping samples. It also may present a problem when we try to dump many frames
00527         //              //              downstream in one go.
00528         //              return S_FALSE;
00529         //      } else {
00530         //              //Now we have one with a stamp, we can send all the previous ones.
00531         //              TheoraDecodeInputPin* locInputPin = (TheoraDecodeInputPin*)m_pInput;
00532         //              REFERENCE_TIME locGlobalEnd = locInputPin->convertGranuleToTime(locEnd);
00533         //              unsigned long locNumBufferedFrames = mBufferedPackets.size();
00534         //              REFERENCE_TIME locGlobalStart = locGlobalEnd - (locNumBufferedFrames * mFrameDuration);
00535 
00536         //              locStart = locGlobalStart;
00537         //              
00538         //              for (unsigned long i = 0; i < locNumBufferedFrames; i++) {
00539         //                      bool locIsKeyFrame = mTheoraDecoder->isKeyFrame(mBufferedPackets[i]);
00540         //                      yuv_buffer* locYUV = mTheoraDecoder->decodeTheora(mBufferedPackets[i]);         //This accept the packet and deletes it
00541         //                      locEnd = locStart + mFrameDuration;
00542         //                      if (locYUV != NULL) {
00543         //                              if (TheoraDecoded(locYUV, outOutputSample, locIsKeyFrame) != 0) {
00544         //                                      //debugLog<<"Decoded *** FALSE ***"<<endl;
00545         //                                      return S_FALSE;
00546         //                              }
00547         //                      } else {
00548         //                              //debugLog<<"!@&#^()!&@#!()*@#&)!(*@#&()!*@# NULL Decode"<<endl;
00549         //                              return S_FALSE;
00550         //                      }                                       
00551         //              }
00552 
00553 
00554 
00555         //              return S_OK;
00556 
00557         //      }
00558         //      
00559         //}
00560 
00561 
00562 
00563 
00564 
00565 
00566 
00567         //HRESULT locHR;
00568         //BYTE* locBuff = NULL;
00570         //locHR = inInputSample->GetPointer(&locBuff);
00571 
00573         //BYTE* locNewBuff = new unsigned char[inInputSample->GetActualDataLength()];           //This gets put into a packet.
00574         //memcpy((void*)locNewBuff, (const void*)locBuff, inInputSample->GetActualDataLength());
00575 
00576 
00577         //if (locHR != S_OK) {
00578         //      //debugLog<<"Receive : Get pointer failed..."<<locHR<<endl;     
00579         //      return S_FALSE;
00580         //} else {
00581         //      //debugLog<<"Receive : Get pointer succeeds..."<<endl;  
00582         //      //New start time hacks
00583         //      REFERENCE_TIME locStart = 0;
00584         //      REFERENCE_TIME locEnd = 0;
00585         //      inInputSample->GetTime(&locStart, &locEnd);
00586         //      //Error chacks needed here
00587         //      //debugLog<<"Input Sample Time - "<<locStart<<" to "<<locEnd<<endl;
00588         //      
00589         //      //More work arounds for that stupid granule pos scheme in theora!
00590         //      REFERENCE_TIME locTimeBase = 0;
00591         //      REFERENCE_TIME locDummy = 0;
00592         //      inInputSample->GetMediaTime(&locTimeBase, &locDummy);
00593         //      mSeekTimeBase = locTimeBase;
00594         //      //
00595 
00596         //      //debugLog<<"SeekTimeBase = "<<mSeekTimeBase<<endl;
00597         //      
00598         //      if ((mLastSeenStartGranPos != locStart) && (locStart != -1)) {
00599         //              //debugLog<<"Resetting frame count"<<endl;
00600 
00601         //              //FIXXX:::
00602         //              //ResetFrameCount();
00603         //              //
00604 
00605         //              mLastSeenStartGranPos = locStart;
00606         //              //debugLog<<"Setting base gran pos to "<<locStart<<endl;
00607         //      }
00608         //      
00609         //      //End of additions
00610 
00611 
00612 
00613         //      AM_MEDIA_TYPE* locMediaType = NULL;
00614         //      inInputSample->GetMediaType(&locMediaType);
00615         //      if (locMediaType == NULL) {
00616         //              //debugLog<<"No dynamic change..."<<endl;
00617         //      } else {
00618         //              //debugLog<<"Attempting dynamic change..."<<endl;
00619         //      }
00620         //      
00621         //      //This packet is given to the decoder.
00622         //      StampedOggPacket* locPacket = new StampedOggPacket(locNewBuff, inInputSample->GetActualDataLength(), false, false, locStart, locEnd, StampedOggPacket::OGG_END_ONLY);
00623 
00624         //      bool locIsKeyFrame = mTheoraDecoder->isKeyFrame(locPacket);
00625         //      yuv_buffer* locYUV = mTheoraDecoder->decodeTheora(locPacket);           //This accept the packet and deletes it
00626         //      if (locYUV != NULL) {
00627         //              if (TheoraDecoded(locYUV, outOutputSample, locIsKeyFrame) != 0) {
00628         //                      //debugLog<<"Decoded *** FALSE ***"<<endl;
00629         //                      return S_FALSE;
00630         //              }
00631         //      } else {
00632         //              //debugLog<<"!@&#^()!&@#!()*@#&)!(*@#&()!*@# NULL Decode"<<endl;
00633         //              return S_FALSE;
00634         //      }
00635 
00636         //      return S_OK;
00637         //      
00638         //}
00639 
00640         debugLog<<"Theora::Transform NOT IMPLEMENTED"<<endl;
00641 
00642         return E_NOTIMPL;
00643         
00644 }
00645 
00646 HRESULT TheoraDecodeFilter::TheoraDecoded (yuv_buffer* inYUVBuffer, IMediaSample* outSample, bool inIsKeyFrame, REFERENCE_TIME inStart, REFERENCE_TIME inEnd) 
00647 {
00648 
00650         BYTE* locBuffer = NULL;
00651         
00652         //
00654         outSample->GetPointer(&locBuffer);
00655 
00656         //Fill the buffer with yuv data...
00657         //      
00658 
00659         REFERENCE_TIME locStart = inStart;
00660         REFERENCE_TIME locEnd = inEnd;
00661 
00662 
00663         //Set up the pointers
00664         unsigned char* locDestUptoPtr = locBuffer;
00665         char* locSourceUptoPtr = inYUVBuffer->y;
00666 
00667         //Strides from theora are generally -'ve
00668         long locYStride = inYUVBuffer->y_stride;
00669         long locUVStride = inYUVBuffer->uv_stride;
00670 
00671         //debugLog<<"Y Stride = "<<locYStride<<endl;
00672         //debugLog<<"UV Stride = "<<locUVStride<<endl;
00673         //
00674         //Y DATA
00675         //
00676 
00677         //NEW WAY with offsets Y Data
00678         long locTopPad = inYUVBuffer->y_height - mHeight - mYOffset;
00679         //debugLog<<"--------- PAD = "<<locTopPad<<endl;
00680 
00681 
00682         //ASSERT(locTopPad >= 0);
00683         if (locTopPad < 0) {
00684                 locTopPad = 0;
00685         } else {
00686                 
00687         }
00688 
00689         //Skip the top padding
00690         locSourceUptoPtr += (mYOffset * locYStride);
00691 
00692         for (unsigned long line = 0; line < mHeight; line++) {
00693                 memcpy((void*)(locDestUptoPtr), (const void*)(locSourceUptoPtr + mXOffset), mWidth);
00694                 locSourceUptoPtr += locYStride;
00695                 locDestUptoPtr += mWidth;
00696         }
00697 
00698         locSourceUptoPtr += (locTopPad * locYStride);
00699 
00700         //debugLog<<"Dest Distance(y) = "<<(unsigned long)(locDestUptoPtr - locBuffer)<<endl;
00701 
00702         //Source advances by (y_height * y_stride)
00703         //Dest advances by (mHeight * mWidth)
00704 
00705         //
00706         //V DATA
00707         //
00708 
00709         //Half the padding for uv planes... is this correct ? 
00710         locTopPad = locTopPad /2;
00711         
00712         locSourceUptoPtr = inYUVBuffer->v;
00713 
00714         //Skip the top padding
00715         locSourceUptoPtr += ((mYOffset/2) * locYStride);
00716 
00717         for (unsigned long line = 0; line < mHeight / 2; line++) {
00718                 memcpy((void*)(locDestUptoPtr), (const void*)(locSourceUptoPtr + (mXOffset / 2)), mWidth / 2);
00719                 locSourceUptoPtr += locUVStride;
00720                 locDestUptoPtr += (mWidth / 2);
00721         }
00722         locSourceUptoPtr += (locTopPad * locUVStride);
00723 
00724         //Source advances by (locTopPad + mYOffset/2 + mHeight /2) * uv_stride
00725         //where locTopPad for uv = (inYUVBuffer->y_height - mHeight - mYOffset) / 2
00726         //                                              =       (inYUVBuffer->yheight/2 - mHeight/2 - mYOffset/2)
00727         // so source advances by (y_height/2) * uv_stride
00728         //Dest advances by (mHeight * mWidth) /4
00729 
00730 
00731         //debugLog<<"Dest Distance(V) = "<<(unsigned long)(locDestUptoPtr - locBuffer)<<endl;
00732         //
00733         //U DATA
00734         //
00735 
00736         locSourceUptoPtr = inYUVBuffer->u;
00737 
00738         //Skip the top padding
00739         locSourceUptoPtr += ((mYOffset/2) * locYStride);
00740 
00741         for (unsigned long line = 0; line < mHeight / 2; line++) {
00742                 memcpy((void*)(locDestUptoPtr), (const void*)(locSourceUptoPtr + (mXOffset / 2)), mWidth / 2);
00743                 locSourceUptoPtr += locUVStride;
00744                 locDestUptoPtr += (mWidth / 2);
00745         }
00746         locSourceUptoPtr += (locTopPad * locUVStride);
00747 
00748         //debugLog<<"Dest Distance(U) = "<<(unsigned long)(locDestUptoPtr - locBuffer)<<endl;
00749         //debugLog<<"Frame Size = "<<mFrameSize<<endl;
00750 
00751         //Set the sample parameters.
00752         //BOOL locIsKeyFrame = (locInterFrameNo == 0);
00753         BOOL locIsKeyFrame = FALSE;
00754         if (inIsKeyFrame) {
00755                 locIsKeyFrame = TRUE;
00756         };
00757         SetSampleParams(outSample, mFrameSize, &locStart, &locEnd, locIsKeyFrame);
00758 
00759         
00760         
00761         return S_OK;
00762 
00763 
00764 }
00765 
00766 
00767 HRESULT TheoraDecodeFilter::SetMediaType(PIN_DIRECTION inDirection, const CMediaType* inMediaType) {
00768 
00769         if (inDirection == PINDIR_INPUT) {
00770                 if (CheckInputType(inMediaType) == S_OK) {
00771                         //debugLog<<"Setting format block"<<endl;
00772                         setTheoraFormat(inMediaType->pbFormat);
00773                         
00774                         //Set some other stuff here too...
00775                         mXOffset = mTheoraFormatInfo->xOffset;
00776                         mYOffset = mTheoraFormatInfo->xOffset;
00777 
00778                         //How many UNITS does one frame take.
00779                         mFrameDuration = (UNITS * mTheoraFormatInfo->frameRateDenominator) / (mTheoraFormatInfo->frameRateNumerator);
00780 
00781                         mFrameSize = (mHeight * mWidth * 3) / 2;
00782                         mFrameCount = 0;
00783                 } else {
00784                         //Failed... should never be here !
00785                         throw 0;
00786                 }
00787                 return CTransformFilter::SetMediaType(PINDIR_INPUT, inMediaType);//CVideoTransformFilter::SetMediaType(PINDIR_INPUT, inMediaType);
00788         } else {
00789                 //debugLog<<"Setting Output Stuff"<<endl;
00790                 //Output pin SetMediaType
00791                 //VIDEOINFOHEADER* locVideoHeader = (VIDEOINFOHEADER*)inMediaType->Format();
00792                 //mHeight = (unsigned long)abs(locVideoHeader->bmiHeader.biHeight);
00793                 //mWidth = (unsigned long)abs(locVideoHeader->bmiHeader.biWidth);
00794 
00795 
00796                 //mFrameSize = (unsigned long)locVideoHeader->bmiHeader.biSizeImage;
00797 
00798                 //debugLog<<"Size = "<<mWidth<<" x "<<mHeight<<" ("<<mFrameSize<<")"<<endl;
00799                 //debugLog<<"Size in Format = "<<locVideoHeader->bmiHeader.biWidth<<" x "<<locVideoHeader->bmiHeader.biHeight<<endl;
00800                 return CTransformFilter::SetMediaType(PINDIR_OUTPUT, inMediaType);//CVideoTransformFilter::SetMediaType(PINDIR_OUTPUT, inMediaType);
00801         }
00802 }
00803 
00804 
00805 bool TheoraDecodeFilter::SetSampleParams(IMediaSample* outMediaSample, unsigned long inDataSize, REFERENCE_TIME* inStartTime, REFERENCE_TIME* inEndTime, BOOL inIsSync) 
00806 {
00807         outMediaSample->SetTime(inStartTime, inEndTime);
00808         outMediaSample->SetMediaTime(NULL, NULL);
00809         outMediaSample->SetActualDataLength(inDataSize);
00810         outMediaSample->SetPreroll(FALSE);
00811         outMediaSample->SetDiscontinuity(FALSE);
00812         outMediaSample->SetSyncPoint(inIsSync);
00813         return true;
00814 }
00815 //BOOL TheoraDecodeFilter::ShouldSkipFrame(IMediaSample* inSample) {
00816 //      //m_bSkipping = FALSE;
00817 //      debugLog<<"Don't skip"<<endl;
00818 //      return FALSE;
00819 //}
00820 
00821 sTheoraFormatBlock* TheoraDecodeFilter::getTheoraFormatBlock() 
00822 {
00823         return mTheoraFormatInfo;
00824 }
00825 void TheoraDecodeFilter::setTheoraFormat(BYTE* inFormatBlock) 
00826 {
00827 
00828         delete mTheoraFormatInfo;
00829         mTheoraFormatInfo = new sTheoraFormatBlock;                     //Deelted in destructor.
00830 
00831         //0             -       55                      theora ident                                            0       -       6
00832         //56    -       63                      ver major                                                       7       -       7
00833         //64    -       71                      ver minor                                                       8       -       8
00834         //72    -       79                      ver subversion                                          9       =       9
00835         //80    -       95                      width/16                                                        10      -       11
00836         //96    -       111                     height/16                                                       12      -       13
00837         //112   -       135                     framewidth                                                      14      -       16
00838         //136   -       159                     frameheight                                                     17      -       19
00839         //160   -       167                     xoffset                                                         20      -       20
00840         //168   -       175                     yoffset                                                         21      -       21
00841         //176   -       207                     framerateNum                                            22      -       25
00842         //208   -       239                     frameratedenom                                          26      -       29
00843         //240   -       263                     aspectNum                                                       30      -       32
00844         //264   -       287                     aspectdenom                                                     33      -       35
00845         //288   -       295                     colourspace                                                     36      -       36
00846         //296   -       319                     targetbitrate                                           37      -       39
00847         //320   -       325                     targetqual                                                      40      -       40.75
00848         //326   -       330                     keyframintlog                                           40.75-  41.375
00849 
00850         unsigned char* locIdentHeader = inFormatBlock;
00851         mTheoraFormatInfo->theoraVersion = (iBE_Math::charArrToULong(locIdentHeader + 7)) >>8;
00852         mTheoraFormatInfo->outerFrameWidth = (iBE_Math::charArrToUShort(locIdentHeader + 10)) * 16;
00853         mTheoraFormatInfo->outerFrameHeight = (iBE_Math::charArrToUShort(locIdentHeader + 12)) * 16;
00854         mTheoraFormatInfo->pictureWidth = (iBE_Math::charArrToULong(locIdentHeader + 14)) >>8;
00855         mTheoraFormatInfo->pictureHeight = (iBE_Math::charArrToULong(locIdentHeader + 17)) >>8;
00856         mTheoraFormatInfo->xOffset = locIdentHeader[20];
00857         mTheoraFormatInfo->yOffset = locIdentHeader[21];
00858         mTheoraFormatInfo->frameRateNumerator = iBE_Math::charArrToULong(locIdentHeader + 22);
00859         mTheoraFormatInfo->frameRateDenominator = iBE_Math::charArrToULong(locIdentHeader + 26);
00860         mTheoraFormatInfo->aspectNumerator = (iBE_Math::charArrToULong(locIdentHeader + 30)) >>8;
00861         mTheoraFormatInfo->aspectDenominator = (iBE_Math::charArrToULong(locIdentHeader + 33)) >>8;
00862         mTheoraFormatInfo->colourSpace = locIdentHeader[36];
00863         mTheoraFormatInfo->targetBitrate = (iBE_Math::charArrToULong(locIdentHeader + 37)) >>8;
00864         mTheoraFormatInfo->targetQuality = (locIdentHeader[40]) >> 2;
00865 
00866         mTheoraFormatInfo->maxKeyframeInterval= (((locIdentHeader[40]) % 4) << 3) + (locIdentHeader[41] >> 5);
00867 }
00868 
00869 CBasePin* TheoraDecodeFilter::GetPin(int inPinNo)
00870 {
00871     HRESULT locHR = S_OK;
00872 
00873     // Create an input pin if necessary
00874 
00875     if (m_pInput == NULL) {
00876 
00877         m_pInput = new TheoraDecodeInputPin(this, &locHR);              //Deleted in base destructor
00878 
00879         
00880         if (m_pInput == NULL) {
00881             return NULL;
00882         }
00883         m_pOutput = new TheoraDecodeOutputPin(this, &locHR);    //Deleted in base destructor
00884                         
00885 
00886         if (m_pOutput == NULL) {
00887             delete m_pInput;
00888             m_pInput = NULL;
00889         }
00890     }
00891 
00892     // Return the pin
00893 
00894     if (inPinNo == 0) {
00895         return m_pInput;
00896     } else if (inPinNo == 1) {
00897         return m_pOutput;
00898     } else {
00899         return NULL;
00900     }
00901 }

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