00001 //=========================================================================== 00002 //Copyright (C) 2003, 2004 Zentaro Kavanagh 00003 // 00004 //Redistribution and use in source and binary forms, with or without 00005 //modification, are permitted provided that the following conditions 00006 //are met: 00007 // 00008 //- Redistributions of source code must retain the above copyright 00009 // notice, this list of conditions and the following disclaimer. 00010 // 00011 //- Redistributions in binary form must reproduce the above copyright 00012 // notice, this list of conditions and the following disclaimer in the 00013 // documentation and/or other materials provided with the distribution. 00014 // 00015 //- Neither the name of Zentaro Kavanagh nor the names of contributors 00016 // may be used to endorse or promote products derived from this software 00017 // without specific prior written permission. 00018 // 00019 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00020 //``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00021 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00022 //PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR 00023 //CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00024 //EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00025 //PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00026 //PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00027 //LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00028 //NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00029 //SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00030 //=========================================================================== 00031 00032 #include "stdafx.h" 00033 #include "theoradecodeinputpin.h" 00034 00035 00036 TheoraDecodeInputPin::TheoraDecodeInputPin(CTransformFilter* inParentFilter, HRESULT* outHR) 00037 : CTransformInputPin(NAME("Theora Input Pin"), inParentFilter, outHR, L"Theora In") 00038 { 00039 //debugLog.open("G:\\logs\\theoinput.log", ios_base::out); 00040 } 00041 TheoraDecodeInputPin::~TheoraDecodeInputPin() { 00042 //debugLog.close(); 00043 } 00044 00045 STDMETHODIMP TheoraDecodeInputPin::NonDelegatingQueryInterface(REFIID riid, void **ppv) { 00046 //debugLog<<"Querying interface"<<endl; 00047 if (riid == IID_IMediaSeeking) { 00048 //debugLog<<"Got Seeker"<<endl; 00049 *ppv = (IMediaSeeking*)this; 00050 ((IUnknown*)*ppv)->AddRef(); 00051 00052 return NOERROR; 00053 } 00054 00055 return CBaseInputPin::NonDelegatingQueryInterface(riid, ppv); 00056 } 00057 00058 HRESULT TheoraDecodeInputPin::BreakConnect() { 00059 CAutoLock locLock(m_pLock); 00060 //debugLog<<"Break conenct"<<endl; 00061 //Need a lock ?? 00062 ReleaseDelegate(); 00063 return CTransformInputPin::BreakConnect(); 00064 } 00065 HRESULT TheoraDecodeInputPin::CompleteConnect (IPin *inReceivePin) { 00066 CAutoLock locLock(m_pLock); 00067 //debugLog<<"Complete conenct"<<endl; 00068 IMediaSeeking* locSeeker = NULL; 00069 inReceivePin->QueryInterface(IID_IMediaSeeking, (void**)&locSeeker); 00070 if (locSeeker == NULL) { 00071 //debugLog<<"Seeker is null"<<endl; 00072 } 00073 SetDelegate(locSeeker); 00074 return CTransformInputPin::CompleteConnect(inReceivePin); 00075 } 00076 00077 //---------------------- 00078 //OLD IMPLEMENTATION 00079 //---------------------- 00080 //TheoraDecodeInputPin::TheoraDecodeInputPin(AbstractVideoDecodeFilter* inFilter, CCritSec* inFilterLock, AbstractVideoDecodeOutputPin* inOutputPin, CMediaType* inAcceptMediaType) 00081 // : AbstractVideoDecodeInputPin(inFilter, inFilterLock, inOutputPin, NAME("TheoraDecodeInputPin"), L"Theora In", inAcceptMediaType) 00082 // , mXOffset(0) 00083 // , mYOffset(0) 00084 // 00085 //{ 00086 // debugLog.open("G:\\logs\\theoInputPin.log", ios_base::out); 00087 // ConstructCodec(); 00088 //} 00089 // 00090 //STDMETHODIMP TheoraDecodeInputPin::NonDelegatingQueryInterface(REFIID riid, void **ppv) 00091 //{ 00092 // if (riid == IID_IMediaSeeking) { 00093 // *ppv = (IMediaSeeking*)this; 00094 // ((IUnknown*)*ppv)->AddRef(); 00095 // return NOERROR; 00096 // } 00097 // 00098 // return CBaseInputPin::NonDelegatingQueryInterface(riid, ppv); 00099 //} 00100 //bool TheoraDecodeInputPin::ConstructCodec() { 00101 // 00102 // 00103 // mTheoraDecoder = new TheoraDecoder; 00104 // mTheoraDecoder->initCodec(); 00105 // return true; 00106 //} 00107 //void TheoraDecodeInputPin::DestroyCodec() { 00108 // delete mTheoraDecoder; 00109 //} 00110 //TheoraDecodeInputPin::~TheoraDecodeInputPin(void) 00111 //{ 00112 // debugLog.close(); 00113 // DestroyCodec(); 00114 // 00115 //} 00116 // 00117 // 00118 // 00119 //int TheoraDecodeInputPin::TheoraDecoded (yuv_buffer* inYUVBuffer) 00120 //{ 00121 // DbgLog((LOG_TRACE,1,TEXT("Decoded... Sending..."))); 00122 // 00123 // debugLog<<"TheoraDecoded... "<<endl; 00124 // 00125 // TheoraDecodeFilter* locFilter = reinterpret_cast<TheoraDecodeFilter*>(m_pFilter); 00126 // // 00127 // if (!mBegun) { 00128 // 00129 // 00130 // 00131 // mBegun = true; 00132 // 00133 // //How many UNITS does one frame take. 00134 // mFrameDuration = (UNITS * locFilter->mTheoraFormatInfo->frameRateDenominator) / (locFilter->mTheoraFormatInfo->frameRateNumerator); 00135 // mFrameSize = (mHeight * mWidth * 3) / 2; 00136 // mFrameCount = 0; 00137 // } 00138 // 00139 // 00140 // 00141 // ////FIX::: Most of this will be obselete... the demux does it all. 00142 // // 00143 // 00144 // ////TO DO::: Fix this up... needs to move around order and some only needs to be done once, move it into the block aboce and use member data 00145 // 00146 // ////Make the start timestamp 00147 // ////FIX:::Abstract this calculation 00148 // DbgLog((LOG_TRACE,1,TEXT("Frame Count = %d"), mFrameCount)); 00149 // //REFERENCE_TIME locFrameStart = CurrentStartTime() + (mFrameCount * mFrameDuration); 00150 // 00151 // //Timestamp hacks start here... 00152 // unsigned long locMod = (unsigned long)pow(2, locFilter->mTheoraFormatInfo->maxKeyframeInterval); 00153 // DbgLog((LOG_TRACE,1,TEXT("locSeenGranPos = %d"), mLastSeenStartGranPos)); 00154 // DbgLog((LOG_TRACE,1,TEXT("locMod = %d"), locMod)); 00155 // unsigned long locInterFrameNo = (mLastSeenStartGranPos) % locMod; 00156 // DbgLog((LOG_TRACE,1,TEXT("InterFrameNo = %d"), locInterFrameNo)); 00157 // LONGLONG locAbsFramePos = ((mLastSeenStartGranPos >> locFilter->mTheoraFormatInfo->maxKeyframeInterval)) + locInterFrameNo; 00158 // DbgLog((LOG_TRACE,1,TEXT("AbsFrameNo = %d"), locAbsFramePos)); 00159 // DbgLog((LOG_TRACE,1,TEXT("mSeekTimeBase = %d"), mSeekTimeBase)); 00160 // REFERENCE_TIME locTimeBase = (locAbsFramePos * mFrameDuration) - mSeekTimeBase; 00161 // DbgLog((LOG_TRACE,1,TEXT("locTimeBase = %d"), locTimeBase)); 00162 // // 00163 // // 00164 // 00165 // REFERENCE_TIME locFrameStart = locTimeBase + (mFrameCount * mFrameDuration); 00166 // //Increment the frame counter 00167 // mFrameCount++; 00168 // 00169 // //Make the end frame counter 00170 // //REFERENCE_TIME locFrameEnd = CurrentStartTime() + (mFrameCount * mFrameDuration); 00171 // REFERENCE_TIME locFrameEnd = locTimeBase + (mFrameCount * mFrameDuration); 00172 // 00173 // DbgLog((LOG_TRACE,1,TEXT("Frame Runs From %d"), locFrameStart)); 00174 // DbgLog((LOG_TRACE,1,TEXT("Frame Runs To %d"), locFrameEnd)); 00175 // 00176 // IMediaSample* locSample = NULL; 00177 // debugLog<<"Sample times = "<<locFrameStart<<" to "<<locFrameEnd<<endl; 00178 // DWORD locFlags = 0;//AM_GBF_PREVFRAMESKIPPED | AM_GBF_NOTASYNCPOINT; 00179 // 00180 // FILTER_STATE locFS; 00181 // mParentFilter->GetState(0, &locFS); 00182 // debugLog<<"State Before = "<<locFS<<endl; 00183 // HRESULT locHR = mOutputPin->GetDeliveryBuffer(&locSample, &locFrameStart, &locFrameEnd, locFlags); 00184 // mParentFilter->GetState(0, &locFS); 00185 // debugLog<<"State After = "<<locFS<<endl; 00186 // if (locHR != S_OK) { 00187 // debugLog<<"Get DeliveryBuffer FAILED with "<<locHR<<endl; 00188 // debugLog<<"locSample is "<<(unsigned long)locSample<<endl; 00189 // //We get here when the application goes into stop mode usually. 00190 // 00191 // switch (locHR) { 00192 // case VFW_E_SIZENOTSET: 00193 // debugLog<<"SIZE NOT SET"<<endl; 00194 // break; 00195 // case VFW_E_NOT_COMMITTED: 00196 // debugLog<<"NOT COMMITTED"<<endl; 00197 // break; 00198 // case VFW_E_TIMEOUT: 00199 // debugLog<<"TIMEOUT"<<endl; 00200 // break; 00201 // case VFW_E_STATE_CHANGED: 00202 // debugLog<<"STATE CHANGED"<<endl; 00203 // return S_OK; 00204 // default: 00205 // debugLog<<"SOMETHING ELSE !!!"<<endl; 00206 // break; 00207 // } 00208 // return locHR; 00209 // } 00210 // 00211 // debugLog<<"GetDeliveryBuffer &** SUCCEEDED **"<<endl; 00212 // 00213 // //Debuggin code 00214 // AM_MEDIA_TYPE* locMediaType = NULL; 00215 // locSample->GetMediaType(&locMediaType); 00216 // if (locMediaType == NULL) { 00217 // debugLog<<"No dynamic change..."<<endl; 00218 // } else { 00219 // debugLog<<"Attempting dynamic change..."<<endl; 00220 // if (locMediaType->majortype == MEDIATYPE_Video) { 00221 // debugLog<<"Still MEDIATYPE_Video"<<endl; 00222 // } 00223 // 00224 // if (locMediaType->subtype == MEDIASUBTYPE_YV12) { 00225 // debugLog<<"Still MEDIASUBTYPE_YV12"<<endl; 00226 // } 00227 // 00228 // if (locMediaType->formattype == FORMAT_VideoInfo) { 00229 // debugLog<<"Still FORMAT_VideoInfo"<<endl; 00230 // VIDEOINFOHEADER* locVF = (VIDEOINFOHEADER*)locMediaType->pbFormat; 00231 // debugLog<<"Size = "<<locVF->bmiHeader.biSizeImage<<endl; 00232 // debugLog<<"Dim = "<<locVF->bmiHeader.biWidth<<" x " <<locVF->bmiHeader.biHeight<<endl; 00233 // } 00234 // 00235 // debugLog<<"Major : "<<DSStringer::GUID2String(&locMediaType->majortype); 00236 // debugLog<<"Minor : "<<DSStringer::GUID2String(&locMediaType->subtype); 00237 // debugLog<<"Format : "<<DSStringer::GUID2String(&locMediaType->formattype); 00238 // debugLog<<"Form Sz: "<<locMediaType->cbFormat; 00239 // 00240 // 00241 // } 00242 // // 00243 // 00244 // ////Create pointers for the samples buffer to be assigned to 00245 // BYTE* locBuffer = NULL; 00246 // 00247 // // 00248 // ////Make our pointers set to point to the samples buffer 00249 // locSample->GetPointer(&locBuffer); 00250 // 00251 // 00252 // 00253 // //Fill the buffer with yuv data... 00254 // // 00255 // 00256 // 00257 // 00258 // //Set up the pointers 00259 // unsigned char* locDestUptoPtr = locBuffer; 00260 // char* locSourceUptoPtr = inYUVBuffer->y; 00261 // 00262 // // 00263 // //Y DATA 00264 // // 00265 // 00266 // //NEW WAY with offsets Y Data 00267 // long locTopPad = inYUVBuffer->y_height - mHeight - mYOffset; 00268 // ASSERT(locTopPad >= 0); 00269 // if (locTopPad < 0) { 00270 // locTopPad = 0; 00271 // } 00272 // 00273 // //Skip the top padding 00274 // locSourceUptoPtr += (locTopPad * inYUVBuffer->y_stride); 00275 // 00276 // for (long line = 0; line < mHeight; line++) { 00277 // memcpy((void*)(locDestUptoPtr), (const void*)(locSourceUptoPtr + mXOffset), mWidth); 00278 // locSourceUptoPtr += inYUVBuffer->y_stride; 00279 // locDestUptoPtr += mWidth; 00280 // } 00281 // 00282 // locSourceUptoPtr += (mYOffset * inYUVBuffer->y_stride); 00283 // 00284 // //Source advances by (y_height * y_stride) 00285 // //Dest advances by (mHeight * mWidth) 00286 // 00287 // // 00288 // //V DATA 00289 // // 00290 // 00291 // //Half the padding for uv planes... is this correct ? 00292 // locTopPad = locTopPad /2; 00293 // 00294 // locSourceUptoPtr = inYUVBuffer->v; 00295 // 00296 // //Skip the top padding 00297 // locSourceUptoPtr += (locTopPad * inYUVBuffer->y_stride); 00298 // 00299 // for (long line = 0; line < mHeight / 2; line++) { 00300 // memcpy((void*)(locDestUptoPtr), (const void*)(locSourceUptoPtr + (mXOffset / 2)), mWidth / 2); 00301 // locSourceUptoPtr += inYUVBuffer->uv_stride; 00302 // locDestUptoPtr += (mWidth / 2); 00303 // } 00304 // locSourceUptoPtr += ((mYOffset/2) * inYUVBuffer->uv_stride); 00305 // 00306 // //Source advances by (locTopPad + mYOffset/2 + mHeight /2) * uv_stride 00307 // //where locTopPad for uv = (inYUVBuffer->y_height - mHeight - mYOffset) / 2 00308 // // = (inYUVBuffer->yheight/2 - mHeight/2 - mYOffset/2) 00309 // // so source advances by (y_height/2) * uv_stride 00310 // //Dest advances by (mHeight * mWidth) /4 00311 // 00312 // 00313 // // 00314 // //U DATA 00315 // // 00316 // 00317 // locSourceUptoPtr = inYUVBuffer->u; 00318 // 00319 // //Skip the top padding 00320 // locSourceUptoPtr += (locTopPad * inYUVBuffer->y_stride); 00321 // 00322 // for (long line = 0; line < mHeight / 2; line++) { 00323 // memcpy((void*)(locDestUptoPtr), (const void*)(locSourceUptoPtr + (mXOffset / 2)), mWidth / 2); 00324 // locSourceUptoPtr += inYUVBuffer->uv_stride; 00325 // locDestUptoPtr += (mWidth / 2); 00326 // } 00327 // locSourceUptoPtr += ((mYOffset/2) * inYUVBuffer->uv_stride); 00328 // 00329 // 00330 // ////Y Data. 00331 // //for ( long line = 0; line < inYUVBuffer->y_height; line++) { 00332 // // memcpy((void*)locBuffer, (const void*)(inYUVBuffer->y + (inYUVBuffer->y_stride * (line))), inYUVBuffer->y_width); 00333 // // locBuffer += inYUVBuffer->y_width; 00334 // 00335 // // if (mWidth > inYUVBuffer->y_width) { 00336 // // memset((void*)locBuffer, 0, mWidth - inYUVBuffer->y_width); 00337 // // } 00338 // // locBuffer += mWidth - inYUVBuffer->y_width; 00339 // //} 00340 // 00341 // ////Pad height... 00342 // //for ( long line = 0; line < mHeight - inYUVBuffer->y_height; line++) { 00343 // // memset((void*)locBuffer, 0, mWidth); 00344 // // locBuffer += mWidth; 00345 // //} 00346 // 00347 // ////V Data 00348 // //for ( long line = 0; line < inYUVBuffer->uv_height; line++) { 00349 // // memcpy((void*)locBuffer, (const void*)(inYUVBuffer->v + (inYUVBuffer->uv_stride * (line))), inYUVBuffer->uv_width); 00350 // // locBuffer += inYUVBuffer->uv_width; 00351 // 00352 // // if (mWidth/2 > inYUVBuffer->uv_width) { 00353 // // memset((void*)locBuffer, 0, (mWidth/2) - inYUVBuffer->uv_width); 00354 // // } 00355 // // locBuffer += (mWidth/2) - inYUVBuffer->uv_width; 00356 // //} 00357 // 00358 // ////Pad height... 00359 // //for ( long line = 0; line < (mHeight/2) - inYUVBuffer->uv_height; line++) { 00360 // // memset((void*)locBuffer, 0, mWidth/2); 00361 // // locBuffer += mWidth/2; 00362 // //} 00363 // 00364 // ////U Data 00365 // //for (long line = 0; line < inYUVBuffer->uv_height; line++) { 00366 // // memcpy((void*)locBuffer, (const void*)(inYUVBuffer->u + (inYUVBuffer->uv_stride * (line))), inYUVBuffer->uv_width); 00367 // // locBuffer += inYUVBuffer->uv_width; 00368 // 00369 // // if (mWidth/2 > inYUVBuffer->uv_width) { 00370 // // memset((void*)locBuffer, 0, (mWidth/2) - inYUVBuffer->uv_width); 00371 // // } 00372 // // locBuffer += (mWidth/2) - inYUVBuffer->uv_width; 00373 // //} 00374 // 00375 // ////Pad height... 00376 // //for ( long line = 0; line < (mHeight/2) - inYUVBuffer->uv_height; line++) { 00377 // // memset((void*)locBuffer, 0, mWidth/2); 00378 // // locBuffer += mWidth/2; 00379 // //} 00380 // 00381 // 00382 // 00383 // 00384 // 00385 // //Set the sample parameters. 00386 // SetSampleParams(locSample, mFrameSize, &locFrameStart, &locFrameEnd); 00387 // 00388 // { 00389 // 00390 // //Add a reerence to the sample so it isn't deleted in the queue. 00391 // //locSample->AddRef(); 00392 // HRESULT locHR = mOutputPin->mDataQueue->Receive(locSample); //->DownstreamFilter()->Receive(locSample); 00393 // if (locHR != S_OK) { 00394 // debugLog<<"Data Q rejects sample... with "<<locHR<<endl; 00395 // return -1; 00396 // 00397 // } 00398 // } 00399 // 00400 // 00401 // return 0; 00402 // 00403 // 00404 //} 00405 // 00406 // 00407 // 00408 //long TheoraDecodeInputPin::decodeData(BYTE* inBuf, long inNumBytes, LONGLONG inStart, LONGLONG inEnd) 00409 //{ 00410 // DbgLog((LOG_TRACE,1,TEXT("decodeData"))); 00411 // //Not truncated or continued... it's a full packet 00412 // StampedOggPacket* locPacket = new StampedOggPacket(inBuf, inNumBytes, false, false, inStart, inEnd, StampedOggPacket::OGG_END_ONLY); 00413 // yuv_buffer* locYUV = mTheoraDecoder->decodeTheora(locPacket); 00414 // if (locYUV != NULL) { 00415 // if (TheoraDecoded(locYUV) != 0) { 00416 // return -1; 00417 // } 00418 // } 00419 // 00420 // return 0; 00421 //} 00422 // 00423 // 00424 // 00425 //HRESULT TheoraDecodeInputPin::SetMediaType(const CMediaType* inMediaType) { 00426 // 00427 // if (inMediaType->subtype == MEDIASUBTYPE_Theora) { 00428 // ((TheoraDecodeFilter*)mParentFilter)->setTheoraFormat((sTheoraFormatBlock*)inMediaType->pbFormat); 00429 // mParentFilter->mVideoFormat = AbstractVideoDecodeFilter::THEORA; 00430 // //Set some other stuff here too... 00431 // mXOffset = ((sTheoraFormatBlock*)inMediaType->pbFormat)->xOffset; 00432 // mYOffset = ((sTheoraFormatBlock*)inMediaType->pbFormat)->yOffset; 00433 // 00434 // } else { 00435 // //Failed... should never be here ! 00436 // throw 0; 00437 // } 00438 // return CBaseInputPin::SetMediaType(inMediaType); 00439 //} 00440 //