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 "VorbisDecodeInputPin.h" 00035 00036 00037 VorbisDecodeInputPin::VorbisDecodeInputPin ( AbstractTransformFilter* inFilter 00038 , CCritSec* inFilterLock 00039 , AbstractTransformOutputPin* inOutputPin 00040 , vector<CMediaType*> inAcceptableMediaTypes 00041 ) 00042 00043 : AbstractTransformInputPin ( inFilter 00044 , inFilterLock 00045 , inOutputPin 00046 , NAME("VorbisDecodeInputPin") 00047 , L"Vorbis In", inAcceptableMediaTypes 00048 ) 00049 , mBegun(false) 00050 , mFishSound(NULL) 00051 00052 , mNumChannels(0) 00053 , mFrameSize(0) 00054 , mSampleRate(0) 00055 , mUptoFrame(0) 00056 00057 { 00058 //debugLog.open("g:\\logs\\vorbislog.log", ios_base::out); 00059 ConstructCodec(); 00060 } 00061 00062 VorbisDecodeInputPin::~VorbisDecodeInputPin(void) 00063 { 00064 //debugLog.close(); 00065 DestroyCodec(); 00066 } 00067 //Is this needed ?? 00068 STDMETHODIMP VorbisDecodeInputPin::NonDelegatingQueryInterface(REFIID riid, void **ppv) 00069 { 00070 if (riid == IID_IMediaSeeking) { 00071 *ppv = (IMediaSeeking*)this; 00072 ((IUnknown*)*ppv)->AddRef(); 00073 return NOERROR; 00074 } 00075 00076 return AbstractTransformInputPin::NonDelegatingQueryInterface(riid, ppv); 00077 } 00078 bool VorbisDecodeInputPin::ConstructCodec() 00079 { 00080 mFishSound = fish_sound_new (FISH_SOUND_DECODE, &mFishInfo); //Deleted by destroycodec from destructor. 00081 00082 int i = 1; 00083 //FIX::: Use new API for interleave setting 00084 fish_sound_command(mFishSound, FISH_SOUND_SET_INTERLEAVE, &i, sizeof(int)); 00085 00086 fish_sound_set_decoded_callback (mFishSound, VorbisDecodeInputPin::VorbisDecoded, this); 00087 //FIX::: Proper return value 00088 return true; 00089 } 00090 void VorbisDecodeInputPin::DestroyCodec() 00091 { 00092 fish_sound_delete(mFishSound); 00093 mFishSound = NULL; 00094 } 00095 00096 00097 STDMETHODIMP VorbisDecodeInputPin::NewSegment(REFERENCE_TIME inStartTime, REFERENCE_TIME inStopTime, double inRate) 00098 { 00099 CAutoLock locLock(mStreamLock); 00100 //debugLog<<"New segment "<<inStartTime<<" - "<<inStopTime<<endl; 00101 mUptoFrame = 0; 00102 return AbstractTransformInputPin::NewSegment(inStartTime, inStopTime, inRate); 00103 00104 } 00105 00106 int __cdecl VorbisDecodeInputPin::VorbisDecoded (FishSound* inFishSound, float** inPCM, long inFrames, void* inThisPointer) 00107 { 00108 00109 VorbisDecodeInputPin* locThis = reinterpret_cast<VorbisDecodeInputPin*> (inThisPointer); 00110 VorbisDecodeFilter* locFilter = reinterpret_cast<VorbisDecodeFilter*>(locThis->m_pFilter); 00111 00112 if (locThis->CheckStreaming() == S_OK) { 00113 if (! locThis->mBegun) { 00114 //locThis->debugLog<<"First Time"<<endl; 00115 //Set up fishsound 00116 fish_sound_command (locThis->mFishSound, FISH_SOUND_GET_INFO, &(locThis->mFishInfo), sizeof (FishSoundInfo)); 00117 locThis->mBegun = true; 00118 00119 locThis->mNumChannels = locThis->mFishInfo.channels; 00120 locThis->mFrameSize = locThis->mNumChannels * SIZE_16_BITS; 00121 locThis->mSampleRate = locThis->mFishInfo.samplerate; 00122 00123 } 00124 00125 00126 unsigned long locActualSize = inFrames * locThis->mFrameSize; 00127 unsigned long locTotalFrameCount = inFrames * locThis->mNumChannels; 00128 00129 //locThis->debugLog<<"m_tStart = "<<locThis->m_tStart<<endl; 00130 //locThis->debugLog<<"mUptoFrame = "<<locThis->mUptoFrame<<endl; 00131 //Make the start presentation time 00132 REFERENCE_TIME locFrameStart = (((__int64)(locThis->mUptoFrame * UNITS)) / locThis->mSampleRate); 00133 00134 //Increment the frame counter 00135 locThis->mUptoFrame += inFrames; 00136 00137 //Make the end presentation time 00138 REFERENCE_TIME locFrameEnd = (((__int64)(locThis->mUptoFrame * UNITS)) / locThis->mSampleRate); 00139 00140 //locThis->debugLog<<"Sample time = "<<locFrameStart<<" - "<<locFrameEnd<<endl; 00141 IMediaSample* locSample; 00142 HRESULT locHR = locThis->mOutputPin->GetDeliveryBuffer(&locSample, &locFrameStart, &locFrameEnd, NULL); 00143 00144 if (locHR != S_OK) { 00145 return -1; 00146 } 00147 00148 00149 //Create pointers for the samples buffer to be assigned to 00150 BYTE* locBuffer = NULL; 00151 signed short* locShortBuffer = NULL; 00152 00153 locSample->GetPointer(&locBuffer); 00154 locShortBuffer = (short *) locBuffer; 00155 00156 signed short tempInt = 0; 00157 float tempFloat = 0; 00158 00159 //FIX:::Move the clipping to the abstract function 00160 00161 if (locSample->GetSize() >= locActualSize) { 00162 //Do float to int conversion with clipping 00163 const float SINT_MAX_AS_FLOAT = 32767.0f; 00164 for (unsigned long i = 0; i < locTotalFrameCount; i++) { 00165 //Clipping because vorbis puts out floats out of range -1 to 1 00166 if (((float*)inPCM)[i] <= -1.0f) { 00167 tempInt = SINT_MIN; 00168 } else if (((float*)inPCM)[i] >= 1.0f) { 00169 tempInt = SINT_MAX; 00170 } else { 00171 //FIX:::Take out the unnescessary variable. 00172 tempFloat = ((( (float*) inPCM )[i]) * SINT_MAX_AS_FLOAT); 00173 //ASSERT((tempFloat <= 32767.0f) && (tempFloat >= -32786.0f)); 00174 tempInt = (signed short)(tempFloat); 00175 //tempInt = (signed short) ((( (float*) inPCM )[i]) * SINT_MAX_AS_FLOAT); 00176 } 00177 00178 *locShortBuffer = tempInt; 00179 locShortBuffer++; 00180 } 00181 00182 //Set the sample parameters. 00183 locThis->SetSampleParams(locSample, locActualSize, &locFrameStart, &locFrameEnd); 00184 00185 { 00186 00187 CAutoLock locLock(locThis->m_pLock); 00188 00189 //TODO::: Explain why we don't addref or release. 00190 HRESULT locHR = ((VorbisDecodeOutputPin*)(locThis->mOutputPin))->mDataQueue->Receive(locSample); 00191 if (locHR != S_OK) { 00192 DbgLog((LOG_TRACE,1,TEXT("Queue rejected us..."))); 00193 return -1; 00194 } 00195 } 00196 00197 00198 return 0; 00199 } else { 00200 throw 0; 00201 } 00202 } else { 00203 DbgLog((LOG_TRACE,1,TEXT("Fishsound sending stuff we aren't ready for..."))); 00204 return -1; 00205 } 00206 00207 } 00208 00209 00210 00211 HRESULT VorbisDecodeInputPin::TransformData(BYTE* inBuf, long inNumBytes) 00212 { 00213 //TODO::: Return types !!! 00214 00215 //debugLog << "Decode called... Last Gran Pos : "<<mLastSeenStartGranPos<<endl; 00216 DbgLog((LOG_TRACE,1,TEXT("decodeData"))); 00217 long locErr = fish_sound_decode(mFishSound, inBuf, inNumBytes); 00218 //FIX::: Do something here ? 00219 if (locErr < 0) { 00220 DbgLog((LOG_TRACE,1,TEXT("decodeData : fishsound returns < 0"))); 00221 return S_FALSE; 00222 //debugLog <<"** Fish Sound error **"<<endl; 00223 } else { 00224 return S_OK; 00225 //debugLog << "Fish Sound OK >=0 "<<endl; 00226 } 00227 //return locErr; 00228 } 00229 00230 00231 HRESULT VorbisDecodeInputPin::SetMediaType(const CMediaType* inMediaType) { 00232 //FIX:::Error checking 00233 //RESOLVED::: Bit better. 00234 00235 if (inMediaType->subtype == MEDIASUBTYPE_Vorbis) { 00236 ((VorbisDecodeFilter*)mParentFilter)->setVorbisFormat((sVorbisFormatBlock*)inMediaType->pbFormat); 00237 00238 } else { 00239 throw 0; 00240 } 00241 return CBaseInputPin::SetMediaType(inMediaType); 00242 } 00243 00244 00245 00246 00247 //Old imp 00248 //************************************************* 00249 //#include "stdafx.h" 00250 // 00251 //#include "VorbisDecodeInputPin.h" 00252 // 00253 // 00254 //VorbisDecodeInputPin::VorbisDecodeInputPin(AbstractAudioDecodeFilter* inFilter, CCritSec* inFilterLock, AbstractAudioDecodeOutputPin* inOutputPin, CMediaType* inAcceptMediaType) 00255 // : AbstractAudioDecodeInputPin(inFilter, inFilterLock, inOutputPin, NAME("VorbisDecodeInputPin"), L"Vorbis In", inAcceptMediaType), 00256 // mBegun(false) 00257 // , mFishSound(NULL) 00258 // 00259 //{ 00260 // //debugLog.open("g:\\logs\\vorbislog.log", ios_base::out); 00261 // ConstructCodec(); 00262 //} 00263 // 00264 //STDMETHODIMP VorbisDecodeInputPin::NonDelegatingQueryInterface(REFIID riid, void **ppv) 00265 //{ 00266 // if (riid == IID_IMediaSeeking) { 00267 // *ppv = (IMediaSeeking*)this; 00268 // ((IUnknown*)*ppv)->AddRef(); 00269 // return NOERROR; 00270 // } 00271 // 00272 // return CBaseInputPin::NonDelegatingQueryInterface(riid, ppv); 00273 //} 00274 //bool VorbisDecodeInputPin::ConstructCodec() { 00275 // mFishSound = fish_sound_new (FISH_SOUND_DECODE, &mFishInfo); //Deleted by destroycodec from destructor. 00276 // 00277 // int i = 1; 00278 // //FIX::: Use new API for interleave setting 00279 // fish_sound_command(mFishSound, FISH_SOUND_SET_INTERLEAVE, &i, sizeof(int)); 00280 // 00281 // fish_sound_set_decoded_callback (mFishSound, VorbisDecodeInputPin::VorbisDecoded, this); 00282 // //FIX::: Proper return value 00283 // return true; 00284 //} 00285 //void VorbisDecodeInputPin::DestroyCodec() { 00286 // fish_sound_delete(mFishSound); 00287 // mFishSound = NULL; 00288 //} 00289 //VorbisDecodeInputPin::~VorbisDecodeInputPin(void) 00290 //{ 00291 // //debugLog.close(); 00292 // DestroyCodec(); 00293 //} 00294 // 00295 // 00296 // 00297 //int __cdecl VorbisDecodeInputPin::VorbisDecoded (FishSound* inFishSound, float** inPCM, long inFrames, void* inThisPointer) 00298 //{ 00299 // 00300 // DbgLog((LOG_TRACE,1,TEXT("Decoded... Sending..."))); 00301 // //Do we need to delete the pcm structure ???? 00302 // //More of this can go to the abstract class. 00303 // 00304 // //For convenience we do all these cast once and for all here. 00305 // VorbisDecodeInputPin* locThis = reinterpret_cast<VorbisDecodeInputPin*> (inThisPointer); 00306 // VorbisDecodeFilter* locFilter = reinterpret_cast<VorbisDecodeFilter*>(locThis->m_pFilter); 00307 // 00308 // 00309 // if (locThis->CheckStreaming() == S_OK) { 00310 // if (! locThis->mBegun) { 00311 // 00312 // 00313 // fish_sound_command (locThis->mFishSound, FISH_SOUND_GET_INFO, &(locThis->mFishInfo), sizeof (FishSoundInfo)); 00314 // locThis->mBegun = true; 00315 // 00316 // locThis->mNumChannels = locThis->mFishInfo.channels; 00317 // locThis->mFrameSize = locThis->mNumChannels * SIZE_16_BITS; 00318 // locThis->mSampleRate = locThis->mFishInfo.samplerate; 00319 // 00320 // } 00321 // 00322 // //FIX::: Most of this will be obselete... the demux does it all. 00323 // 00324 // 00325 // unsigned long locActualSize = inFrames * locThis->mFrameSize; 00326 // unsigned long locTotalFrameCount = inFrames * locThis->mNumChannels; 00327 // 00328 // //REFERENCE_TIME locFrameStart = locThis->CurrentStartTime() + (((__int64)(locThis->mUptoFrame * UNITS)) / locThis->mSampleRate); 00329 // 00330 // 00331 // //New hacks for chaining. 00332 // if (locThis->mSeekTimeBase == -1) { 00333 // //locThis->debugLog<<"Chaining was detected... setting chain time base to : "<<locThis->mPreviousEndTime<<endl; 00334 // //This is our signal this is the start of a chain... 00335 // // This can only happen on non-seekable streams. 00336 // locThis->mChainTimeBase = locThis->mPreviousEndTime; 00337 // 00338 // locThis->mSeekTimeBase = 0; 00339 // } 00340 // 00341 // //Start time hacks 00342 // REFERENCE_TIME locTimeBase = ((locThis->mLastSeenStartGranPos * UNITS) / locThis->mSampleRate) - locThis->mSeekTimeBase + locThis->mChainTimeBase; 00343 // 00344 // 00345 // 00346 // //locThis->aadDebug<<"Last Seen : " <<locThis->mLastSeenStartGranPos<<endl; 00347 // //locThis->debugLog<<"Last Seen : " << locThis->mLastSeenStartGranPos<<endl; 00348 // //locThis->debugLog<<"Time Base : " << locTimeBase << endl; 00349 // //locThis->debugLog<<"FrameCount : " <<locThis->mUptoFrame<<endl; 00350 // //locThis->debugLog<<"Seek TB : " <<locThis->mSeekTimeBase<<endl; 00351 // 00352 // //Temp - this will break seeking 00353 // REFERENCE_TIME locFrameStart = locTimeBase + (((__int64)(locThis->mUptoFrame * UNITS)) / locThis->mSampleRate); 00354 // //Increment the frame counter 00355 // locThis->mUptoFrame += inFrames; 00356 // //Make the end frame counter 00357 // 00358 // //REFERENCE_TIME locFrameEnd = locThis->CurrentStartTime() + (((__int64)(locThis->mUptoFrame * UNITS)) / locThis->mSampleRate); 00359 // REFERENCE_TIME locFrameEnd = locTimeBase + (((__int64)(locThis->mUptoFrame * UNITS)) / locThis->mSampleRate); 00360 // locThis->mPreviousEndTime = locFrameEnd; 00361 // 00362 // 00363 // 00364 // //locThis->debugLog<<"Start : "<<locFrameStart<<endl; 00365 // //locThis->debugLog<<"End : "<<locFrameEnd<<endl; 00366 // //locThis->debugLog<<"=================================================="<<endl; 00367 // IMediaSample* locSample; 00368 // HRESULT locHR = locThis->mOutputPin->GetDeliveryBuffer(&locSample, &locFrameStart, &locFrameEnd, NULL); 00369 // 00370 // if (locHR != S_OK) { 00371 // return -1; 00372 // } 00373 // 00374 // 00375 // //Create pointers for the samples buffer to be assigned to 00376 // BYTE* locBuffer = NULL; 00377 // signed short* locShortBuffer = NULL; 00378 // 00379 // locSample->GetPointer(&locBuffer); 00380 // locShortBuffer = (short *) locBuffer; 00381 // 00382 // signed short tempInt = 0; 00383 // float tempFloat = 0; 00384 // 00385 // //FIX:::Move the clipping to the abstract function 00386 // 00387 // if (locSample->GetSize() >= locActualSize) { 00388 // //Do float to int conversion with clipping 00389 // const float SINT_MAX_AS_FLOAT = 32767.0f; 00390 // for (unsigned long i = 0; i < locTotalFrameCount; i++) { 00391 // //Clipping because vorbis puts out floats out of range -1 to 1 00392 // if (((float*)inPCM)[i] <= -1.0f) { 00393 // tempInt = SINT_MIN; 00394 // } else if (((float*)inPCM)[i] >= 1.0f) { 00395 // tempInt = SINT_MAX; 00396 // } else { 00397 // //FIX:::Take out the unnescessary variable. 00398 // tempFloat = ((( (float*) inPCM )[i]) * SINT_MAX_AS_FLOAT); 00399 // //ASSERT((tempFloat <= 32767.0f) && (tempFloat >= -32786.0f)); 00400 // tempInt = (signed short)(tempFloat); 00401 // //tempInt = (signed short) ((( (float*) inPCM )[i]) * SINT_MAX_AS_FLOAT); 00402 // } 00403 // 00404 // *locShortBuffer = tempInt; 00405 // locShortBuffer++; 00406 // } 00407 // 00408 // //Set the sample parameters. 00409 // locThis->SetSampleParams(locSample, locActualSize, &locFrameStart, &locFrameEnd); 00410 // 00411 // { 00412 // 00413 // CAutoLock locLock(locThis->m_pLock); 00414 // 00415 // //Add a reference so it isn't deleted en route.... or not 00416 // //locSample->AddRef(); 00417 // HRESULT lHR = locThis->mOutputPin->mDataQueue->Receive(locSample); 00418 // if (lHR != S_OK) { 00419 // DbgLog((LOG_TRACE,1,TEXT("Queue rejected us..."))); 00420 // return -1; 00421 // } 00422 // } 00423 // 00424 // //Don't Release the sample it gets done for us ! 00425 // //locSample->Release(); 00426 // 00427 // return 0; 00428 // } else { 00429 // throw 0; 00430 // } 00431 // } else { 00432 // DbgLog((LOG_TRACE,1,TEXT("Fishsound sending stuff we aren't ready for..."))); 00433 // return -1; 00434 // } 00435 // 00436 //} 00437 // 00438 // 00439 // 00440 //long VorbisDecodeInputPin::decodeData(BYTE* inBuf, long inNumBytes) 00441 //{ 00442 // //debugLog << "Decode called... Last Gran Pos : "<<mLastSeenStartGranPos<<endl; 00443 // DbgLog((LOG_TRACE,1,TEXT("decodeData"))); 00444 // long locErr = fish_sound_decode(mFishSound, inBuf, inNumBytes); 00445 // //FIX::: Do something here ? 00446 // if (locErr < 0) { 00447 // //debugLog <<"** Fish Sound error **"<<endl; 00448 // } else { 00449 // //debugLog << "Fish Sound OK >=0 "<<endl; 00450 // } 00451 // return locErr; 00452 //} 00453 // 00454 // 00455 //HRESULT VorbisDecodeInputPin::SetMediaType(const CMediaType* inMediaType) { 00456 // //FIX:::Error checking 00457 // //RESOLVED::: Bit better. 00458 // 00459 // if (inMediaType->subtype == MEDIASUBTYPE_Vorbis) { 00460 // ((VorbisDecodeFilter*)mParentFilter)->setVorbisFormat((sVorbisFormatBlock*)inMediaType->pbFormat); 00461 // mParentFilter->mAudioFormat = AbstractAudioDecodeFilter::VORBIS; 00462 // } else { 00463 // throw 0; 00464 // } 00465 // return CBaseInputPin::SetMediaType(inMediaType); 00466 //} 00467 //