SpeexDecodeInputPin.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 #include "SpeexDecodeInputPin.h"
00034 
00035 
00036 SpeexDecodeInputPin::SpeexDecodeInputPin(AbstractTransformFilter* inFilter, CCritSec* inFilterLock, AbstractTransformOutputPin* inOutputPin, vector<CMediaType*> inAcceptableMediaTypes)
00037         :       AbstractTransformInputPin(inFilter, inFilterLock, inOutputPin, NAME("SpeexDecodeInputPin"), L"Speex In", inAcceptableMediaTypes)
00038         ,       mFishSound(NULL)
00039 
00040         ,       mNumChannels(0)
00041         ,       mFrameSize(0)
00042         ,       mSampleRate(0)
00043         ,       mUptoFrame(0)
00044 
00045         ,       mDecodedByteCount(0)
00046         ,       mDecodedBuffer(NULL)
00047         ,       mRateNumerator(RATE_DENOMINATOR)
00048 
00049         ,       mSetupState(VSS_SEEN_NOTHING)
00050 
00051         ,       mBegun(false)
00052 {
00053         ConstructCodec();
00054 
00055         mDecodedBuffer = new unsigned char[DECODED_BUFFER_SIZE];
00056 }
00057 
00058 bool SpeexDecodeInputPin::ConstructCodec() {
00059         mFishSound = fish_sound_new (FISH_SOUND_DECODE, &mFishInfo);
00060 
00061         int i = 1;
00062         //FIX::: Use new API for interleave setting
00063         fish_sound_command(mFishSound, FISH_SOUND_SET_INTERLEAVE, &i, sizeof(int));
00064 
00065         fish_sound_set_decoded_callback (mFishSound, SpeexDecodeInputPin::SpeexDecoded, this);
00066         //FIX::: Proper return value
00067         return true;
00068 }
00069 void SpeexDecodeInputPin::DestroyCodec() {
00070         fish_sound_delete(mFishSound);
00071         mFishSound = NULL;
00072 }
00073 SpeexDecodeInputPin::~SpeexDecodeInputPin(void)
00074 {
00075         DestroyCodec();
00076 
00077         delete mDecodedBuffer;
00078 }
00079 
00080 STDMETHODIMP SpeexDecodeInputPin::NonDelegatingQueryInterface(REFIID riid, void **ppv)
00081 {
00082         if (riid == IID_IMediaSeeking) {
00083                 *ppv = (IMediaSeeking*)this;
00084                 ((IUnknown*)*ppv)->AddRef();
00085                 return NOERROR;
00086         } else if (riid == IID_IOggDecoder) {
00087                 *ppv = (IOggDecoder*)this;
00088                 //((IUnknown*)*ppv)->AddRef();
00089                 return NOERROR;
00090 
00091         }
00092 
00093         return CBaseInputPin::NonDelegatingQueryInterface(riid, ppv); 
00094 }
00095 STDMETHODIMP SpeexDecodeInputPin::NewSegment(REFERENCE_TIME inStartTime, REFERENCE_TIME inStopTime, double inRate) 
00096 {
00097         CAutoLock locLock(mStreamLock);
00098         //debugLog<<"New segment "<<inStartTime<<" - "<<inStopTime<<endl;
00099         mUptoFrame = 0;
00100 
00101         mRateNumerator = RATE_DENOMINATOR * inRate;
00102         if (mRateNumerator > RATE_DENOMINATOR) {
00103                 mRateNumerator = RATE_DENOMINATOR;
00104         }
00105         return AbstractTransformInputPin::NewSegment(inStartTime, inStopTime, inRate);  
00106 }
00107 
00108 STDMETHODIMP SpeexDecodeInputPin::EndFlush()
00109 {
00110         CAutoLock locLock(m_pLock);
00111         
00112         HRESULT locHR = AbstractTransformInputPin::EndFlush();
00113         mDecodedByteCount = 0;
00114         return locHR;
00115 }
00116 HRESULT SpeexDecodeInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *outRequestedProps)
00117 {
00118         outRequestedProps->cbBuffer = SPEEX_BUFFER_SIZE;
00119         outRequestedProps->cBuffers = SPEEX_NUM_BUFFERS;
00120         outRequestedProps->cbAlign = 1;
00121         outRequestedProps->cbPrefix = 0;
00122 
00123         return S_OK;
00124 }
00125 int SpeexDecodeInputPin::SpeexDecoded (FishSound* inFishSound, float** inPCM, long inFrames, void* inThisPointer) 
00126 {
00127 
00128         SpeexDecodeInputPin* locThis = reinterpret_cast<SpeexDecodeInputPin*> (inThisPointer);
00129         SpeexDecodeFilter* locFilter = reinterpret_cast<SpeexDecodeFilter*>(locThis->m_pFilter);
00130 
00131         if (locThis->CheckStreaming() == S_OK) {
00132 
00133                 unsigned long locActualSize = inFrames * locThis->mFrameSize;
00134                 unsigned long locTotalFrameCount = inFrames * locThis->mNumChannels;
00135                 unsigned long locBufferRemaining = DECODED_BUFFER_SIZE - locThis->mDecodedByteCount;
00136                 
00137 
00138 
00139                 //Create a pointer into the buffer              
00140                 signed short* locShortBuffer = (signed short*)&locThis->mDecodedBuffer[locThis->mDecodedByteCount];
00141                 
00142                 
00143                 signed short tempInt = 0;
00144                 float tempFloat = 0;
00145                 
00146                 //FIX:::Move the clipping to the abstract function
00147 
00148                 if (locBufferRemaining >= locActualSize) {
00149                         //Do float to int conversion with clipping
00150                         const float SINT_MAX_AS_FLOAT = 32767.0f;
00151                         for (unsigned long i = 0; i < locTotalFrameCount; i++) {
00152                                 //Clipping because vorbis puts out floats out of range -1 to 1
00153                                 if (((float*)inPCM)[i] <= -1.0f) {
00154                                         tempInt = SINT_MIN;     
00155                                 } else if (((float*)inPCM)[i] >= 1.0f) {
00156                                         tempInt = SINT_MAX;
00157                                 } else {
00158                                         //FIX:::Take out the unnescessary variable.
00159                                         tempFloat = ((( (float*) inPCM )[i]) * SINT_MAX_AS_FLOAT);
00160                                         //ASSERT((tempFloat <= 32767.0f) && (tempFloat >= -32786.0f));
00161                                         tempInt = (signed short)(tempFloat);
00162                                         //tempInt = (signed short) ((( (float*) inPCM )[i]) * SINT_MAX_AS_FLOAT);
00163                                 }
00164                                 
00165                                 *locShortBuffer = tempInt;
00166                                 locShortBuffer++;
00167                         }
00168 
00169                         locThis->mDecodedByteCount += locActualSize;
00170                         
00171                         return 0;
00172                 } else {
00173                         throw 0;
00174                 }
00175         } else {
00176                 DbgLog((LOG_TRACE,1,TEXT("Fishsound sending stuff we aren't ready for...")));
00177                 return -1;
00178         }
00179 
00180 
00181 
00182 
00183 
00184 
00185 
00186 
00187 
00188 
00189 
00190 
00191 
00194 
00196         //SpeexDecodeInputPin* locThis = reinterpret_cast<SpeexDecodeInputPin*> (inThisPointer);
00197         //SpeexDecodeFilter* locFilter = reinterpret_cast<SpeexDecodeFilter*>(locThis->m_pFilter);
00198         //
00199 
00200         //if (! locThis->mBegun) {
00201         //
00202         //      fish_sound_command (locThis->mFishSound, FISH_SOUND_GET_INFO, &(locThis->mFishInfo), sizeof (FishSoundInfo)); 
00203         //      locThis->mBegun = true;
00204         //      
00205         //      locThis->mNumChannels = locThis->mFishInfo.channels;
00206         //      locThis->mFrameSize = locThis->mNumChannels * SIZE_16_BITS;
00207         //      locThis->mSampleRate = locThis->mFishInfo.samplerate;
00208 
00209         //}
00210         //
00212         //unsigned long locActualSize = inFrames * locThis->mFrameSize;
00213         //unsigned long locTotalFrameCount = inFrames * locThis->mNumChannels;
00214 
00215         //REFERENCE_TIME locFrameStart = (((__int64)(locThis->mUptoFrame * UNITS)) / locThis->mSampleRate);
00217         //locThis->mUptoFrame += inFrames;
00219 
00220         //
00221         //REFERENCE_TIME locFrameEnd = (((__int64)(locThis->mUptoFrame * UNITS)) / locThis->mSampleRate);
00222 
00223 
00224         //IMediaSample* locSample;
00225         //HRESULT locHR = locThis->mOutputPin->GetDeliveryBuffer(&locSample, &locFrameStart, &locFrameEnd, NULL);
00226 
00227         //if (locHR != S_OK) {
00228         //      return locHR;
00229         //}     
00230         //
00232         //BYTE* locBuffer = NULL;
00233         //signed short* locShortBuffer = NULL;
00234         //
00236         //locSample->GetPointer(&locBuffer);
00237         //locShortBuffer = (short *) locBuffer;
00238         //
00239         //signed short tempInt = 0;
00240         //float tempFloat = 0;
00241         //
00243 
00244         //if (locSample->GetSize() >= locActualSize) {
00245         //      //Do float to int conversion with clipping
00246         //      float SINT_MAX_AS_FLOAT = 32767.0f;
00247         //      for (unsigned long i = 0; i < locTotalFrameCount; i++) {
00248         //              //Clipping because vorbis puts out floats out of range -1 to 1
00249         //              if (((float*)inPCM)[i] <= -1.0f) {
00250         //                      tempInt = SINT_MIN;     
00251         //              } else if (((float*)inPCM)[i] >= 1.0f) {
00252         //                      tempInt = SINT_MAX;
00253         //              } else {
00254         //                      //FIX:::Take out the unnescessary variable.
00255         //                      tempFloat = ((( (float*) inPCM )[i]) * SINT_MAX_AS_FLOAT);
00256         //                      //ASSERT((tempFloat <= 32767.0f) && (tempFloat >= -32786.0f));
00257         //                      tempInt = (signed short)(tempFloat);
00258         //                      //tempInt = (signed short) ((( (float*) inPCM )[i]) * SINT_MAX_AS_FLOAT);
00259         //              }
00260         //              
00261         //              *locShortBuffer = tempInt;
00262         //              locShortBuffer++;
00263         //      }
00264         //      
00265         //      //Set the sample parameters.
00266         //      locThis->SetSampleParams(locSample, locActualSize, &locFrameStart, &locFrameEnd);
00267 
00268         //      {
00269         //              CAutoLock locLock(locThis->m_pLock);
00270         //              HRESULT locHR = ((SpeexDecodeOutputPin*)(locThis->mOutputPin))->mDataQueue->Receive(locSample);
00271         //              if (locHR != S_OK) {
00272         //                      return locHR;                           
00273         //              }
00274         //      }
00275 
00276         //      
00277         //      return 0;
00278         //} else {
00279         //      throw 0;
00280         //}
00281 
00282 }
00283 
00284 STDMETHODIMP SpeexDecodeInputPin::Receive(IMediaSample* inSample) 
00285 {
00286         CAutoLock locLock(mStreamLock);
00287 
00288         HRESULT locHR = CheckStreaming();
00289 
00290         if (locHR == S_OK) {
00291 
00292 
00293                 BYTE* locBuff = NULL;
00294                 locHR = inSample->GetPointer(&locBuff);
00295 
00296                 if (locHR != S_OK) {
00297                         //TODO::: Do a debug dump or something here with specific error info.
00298                         return locHR;
00299                 } else {
00300                         REFERENCE_TIME locStart = -1;
00301                         REFERENCE_TIME locEnd = -1;
00302                         __int64 locSampleDuration = 0;
00303                         inSample->GetTime(&locStart, &locEnd);
00304 
00305                         HRESULT locResult = TransformData(locBuff, inSample->GetActualDataLength());
00306                         if (locResult != S_OK) {
00307                                 return S_FALSE;
00308                         }
00309                         if (locEnd > 0) {
00310                                 //Can dump it all downstream now        
00311                                 IMediaSample* locSample;
00312                                 unsigned long locBytesCopied = 0;
00313                                 unsigned long locBytesToCopy = 0;
00314 
00315                                 locStart = convertGranuleToTime(locEnd) - (((mDecodedByteCount / mFrameSize) * UNITS) / mSampleRate);
00316                                 do {
00317                                         HRESULT locHR = mOutputPin->GetDeliveryBuffer(&locSample, NULL, NULL, NULL);
00318                                         if (locHR != S_OK) {
00319                                                 return locHR;
00320                                         }
00321 
00322                                         BYTE* locBuffer = NULL;
00323                                         locHR = locSample->GetPointer(&locBuffer);
00324                                 
00325                                         if (locHR != S_OK) {
00326                                                 return locHR;
00327                                         }
00328 
00329                                         locBytesToCopy = ((mDecodedByteCount - locBytesCopied) <= locSample->GetSize()) ? (mDecodedByteCount - locBytesCopied) : locSample->GetSize();
00330                                         //locBytesCopied += locBytesToCopy;
00331 
00332                                         locSampleDuration = (((locBytesToCopy/mFrameSize) * UNITS) / mSampleRate);
00333                                         locEnd = locStart + locSampleDuration;
00334 
00335                                         //Adjust the time stamps for rate and seeking
00336                                         REFERENCE_TIME locAdjustedStart = (locStart * RATE_DENOMINATOR) / mRateNumerator;
00337                                         REFERENCE_TIME locAdjustedEnd = (locEnd * RATE_DENOMINATOR) / mRateNumerator;
00338                                         locAdjustedStart -= m_tStart;
00339                                         locAdjustedEnd -= m_tStart;
00340 
00341                                         __int64 locSeekStripOffset = 0;
00342                                         if (locAdjustedEnd < 0) {
00343                                                 locSample->Release();
00344                                         } else {
00345                                                 if (locAdjustedStart < 0) {
00346                                                         locSeekStripOffset = (-locAdjustedStart) * mSampleRate;
00347                                                         locSeekStripOffset *= mFrameSize;
00348                                                         locSeekStripOffset /= UNITS;
00349                                                         locSeekStripOffset += (mFrameSize - (locSeekStripOffset % mFrameSize));
00350                                                         __int64 locStrippedDuration = (((locSeekStripOffset/mFrameSize) * UNITS) / mSampleRate);
00351                                                         locAdjustedStart += locStrippedDuration;
00352                                                 }
00353                                                         
00354 
00355                                         
00356 
00357                                                 memcpy((void*)locBuffer, (const void*)&mDecodedBuffer[locBytesCopied + locSeekStripOffset], locBytesToCopy - locSeekStripOffset);
00358 
00359                                                 locSample->SetTime(&locAdjustedStart, &locAdjustedEnd);
00360                                                 locSample->SetMediaTime(&locStart, &locEnd);
00361                                                 locSample->SetSyncPoint(TRUE);
00362                                                 locSample->SetActualDataLength(locBytesToCopy - locSeekStripOffset);
00363                                                 locHR = ((SpeexDecodeOutputPin*)(mOutputPin))->mDataQueue->Receive(locSample);
00364                                                 if (locHR != S_OK) {
00365                                                         return locHR;
00366                                                 }
00367                                                 locStart += locSampleDuration;
00368 
00369                                         }
00370                                         locBytesCopied += locBytesToCopy;
00371 
00372                                 
00373                                 } while(locBytesCopied < mDecodedByteCount);
00374 
00375                                 mDecodedByteCount = 0;
00376                                 
00377                         }
00378                         return S_OK;
00379 
00380                 }
00381         } else {
00382                 //Not streaming - Bail out.
00383                 return S_FALSE;
00384         }
00385 }
00386 
00387 
00388 HRESULT SpeexDecodeInputPin::TransformData(BYTE* inBuf, long inNumBytes) 
00389 {
00390         long locErr = fish_sound_decode(mFishSound, inBuf, inNumBytes);
00391         if (locErr == 0) {
00392                 return S_OK;
00393         } else {
00394                 return S_FALSE;
00395         }
00396 }
00397 
00398 
00399 
00400 HRESULT SpeexDecodeInputPin::SetMediaType(const CMediaType* inMediaType) 
00401 {
00402         //FIX:::Error checking
00403         //RESOLVED::: Bit better.
00404         if (CheckMediaType(inMediaType) == S_OK) {
00405                 ((SpeexDecodeFilter*)mParentFilter)->setSpeexFormat(inMediaType->pbFormat);
00406                 
00407         } else {
00408                 throw 0;
00409         }
00410         return CBaseInputPin::SetMediaType(inMediaType);
00411 
00412         //if (inMediaType->subtype == MEDIASUBTYPE_Speex) {
00413         //      ((SpeexDecodeFilter*)mParentFilter)->setSpeexFormat((sSpeexFormatBlock*)inMediaType->pbFormat);
00414 
00415         //} else {
00416         //      throw 0;
00417         //}
00418         //return CBaseInputPin::SetMediaType(inMediaType);
00419 }
00420 
00421 HRESULT SpeexDecodeInputPin::CheckMediaType(const CMediaType *inMediaType)
00422 {
00423         if (AbstractTransformInputPin::CheckMediaType(inMediaType) == S_OK) {
00424                 if (inMediaType->cbFormat == SPEEX_IDENT_HEADER_SIZE) {
00425                         if (strncmp((char*)inMediaType->pbFormat, "Speex   ", 8) == 0) {
00426                                 //TODO::: Possibly verify version
00427                                 return S_OK;
00428                         }
00429                 }
00430         }
00431         return S_FALSE;
00432         
00433 }
00434 
00435 LOOG_INT64 SpeexDecodeInputPin::convertGranuleToTime(LOOG_INT64 inGranule)
00436 {
00437         if (mBegun) {   
00438                 return (inGranule * UNITS) / mSampleRate;
00439         } else {
00440                 return -1;
00441         }
00442 }
00443 
00444 LOOG_INT64 SpeexDecodeInputPin::mustSeekBefore(LOOG_INT64 inGranule)
00445 {
00446         //TODO::: Get adjustment from block size info... for now, it doesn't matter if no preroll
00447         return inGranule;
00448 }
00449 IOggDecoder::eAcceptHeaderResult SpeexDecodeInputPin::showHeaderPacket(OggPacket* inCodecHeaderPacket)
00450 {
00451         switch (mSetupState) {
00452                 case VSS_SEEN_NOTHING:
00453                         if (strncmp((char*)inCodecHeaderPacket->packetData(), "Speex   ", 8) == 0) {
00454                                 //TODO::: Possibly verify version
00455                                 if (fish_sound_decode(mFishSound, inCodecHeaderPacket->packetData(), inCodecHeaderPacket->packetSize()) >= 0) {
00456                                         mSetupState = VSS_SEEN_BOS;
00457                                         return IOggDecoder::AHR_MORE_HEADERS_TO_COME;
00458                                 }
00459                         }
00460                         return IOggDecoder::AHR_INVALID_HEADER;
00461                         
00462                         
00463                 case VSS_SEEN_BOS:
00464                         //The comment packet can't be easily identified in speex.
00465                         //Just ignore the second packet we see, and hope fishsound does better.
00466 
00467                         //if (strncmp((char*)inCodecHeaderPacket->packetData(), "\003vorbis", 7) == 0) {
00468                                 if (fish_sound_decode(mFishSound, inCodecHeaderPacket->packetData(), inCodecHeaderPacket->packetSize()) >= 0) {
00469                                         mSetupState = VSS_ALL_HEADERS_SEEN;
00470 
00471                                         fish_sound_command (mFishSound, FISH_SOUND_GET_INFO, &(mFishInfo), sizeof (FishSoundInfo)); 
00472                                         mBegun = true;
00473                         
00474                                         mNumChannels = mFishInfo.channels;
00475                                         mFrameSize = mNumChannels * SIZE_16_BITS;
00476                                         mSampleRate = mFishInfo.samplerate;
00477 
00478                                         return IOggDecoder::AHR_ALL_HEADERS_RECEIVED;
00479                                 }
00480                                 
00481                                 
00482                         //}
00483                         return IOggDecoder::AHR_INVALID_HEADER;
00484                         
00485                         
00486         
00487                 case VSS_ALL_HEADERS_SEEN:
00488                 case VSS_ERROR:
00489                 default:
00490                         return IOggDecoder::AHR_UNEXPECTED;
00491         }
00492 }
00493 string SpeexDecodeInputPin::getCodecShortName()
00494 {
00495         return "speex";
00496 }
00497 string SpeexDecodeInputPin::getCodecIdentString()
00498 {
00499         //TODO:::
00500         return "speex";
00501 }
00502 

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