VorbisDecodeInputPin.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 "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         ,       mSetupState(VSS_SEEN_NOTHING)
00057         ,       mDecodedBuffer(NULL)
00058         ,       mDecodedByteCount(0)
00059         ,       mRateNumerator(RATE_DENOMINATOR)
00060         ,       mOggOutputPinInterface(NULL)
00061         ,       mSentStreamOffset(false)
00062                 
00063 {
00064         //debugLog.open("g:\\logs\\vorbislog.log", ios_base::out);
00065         ConstructCodec();
00066 
00067         mDecodedBuffer = new unsigned char[DECODED_BUFFER_SIZE];
00068 }
00069 
00070 VorbisDecodeInputPin::~VorbisDecodeInputPin(void)
00071 {
00072         //debugLog.close();
00073         DestroyCodec();
00074         delete[] mDecodedBuffer;
00075 
00076 }
00077 //Is this needed ??
00078 STDMETHODIMP VorbisDecodeInputPin::NonDelegatingQueryInterface(REFIID riid, void **ppv)
00079 {
00080         if (riid == IID_IMediaSeeking) {
00081                 *ppv = (IMediaSeeking*)this;
00082                 ((IUnknown*)*ppv)->AddRef();
00083                 return NOERROR;
00084         } else if (riid == IID_IOggDecoder) {
00085                 *ppv = (IOggDecoder*)this;
00086                 //((IUnknown*)*ppv)->AddRef();
00087                 return NOERROR;
00088 
00089         }
00090 
00091         return AbstractTransformInputPin::NonDelegatingQueryInterface(riid, ppv); 
00092 }
00093 bool VorbisDecodeInputPin::ConstructCodec() 
00094 {
00095         mFishSound = fish_sound_new (FISH_SOUND_DECODE, &mFishInfo);                    //Deleted by destroycodec from destructor.
00096 
00097         int i = 1;
00098         //FIX::: Use new API for interleave setting
00099         fish_sound_command(mFishSound, FISH_SOUND_SET_INTERLEAVE, &i, sizeof(int));
00100 
00101         fish_sound_set_decoded_callback (mFishSound, VorbisDecodeInputPin::VorbisDecoded, this);
00102         //FIX::: Proper return value
00103         return true;
00104 }
00105 void VorbisDecodeInputPin::DestroyCodec() 
00106 {
00107         fish_sound_delete(mFishSound);
00108         mFishSound = NULL;
00109 }
00110 
00111 
00112 STDMETHODIMP VorbisDecodeInputPin::NewSegment(REFERENCE_TIME inStartTime, REFERENCE_TIME inStopTime, double inRate) 
00113 {
00114         CAutoLock locLock(mStreamLock);
00115         //debugLog<<"New segment "<<inStartTime<<" - "<<inStopTime<<endl;
00116         mUptoFrame = 0;
00117         mRateNumerator = RATE_DENOMINATOR * inRate;
00118         if (mRateNumerator > RATE_DENOMINATOR) {
00119                 mRateNumerator = RATE_DENOMINATOR;
00120         }
00121         return AbstractTransformInputPin::NewSegment(inStartTime, inStopTime, inRate);
00122         
00123 }
00124 
00125 STDMETHODIMP VorbisDecodeInputPin::EndFlush()
00126 {
00127         CAutoLock locLock(m_pLock);
00128         
00129         HRESULT locHR = AbstractTransformInputPin::EndFlush();
00130         mDecodedByteCount = 0;
00131         return locHR;
00132 }
00133 
00134 int __cdecl VorbisDecodeInputPin::VorbisDecoded (FishSound* inFishSound, float** inPCM, long inFrames, void* inThisPointer) 
00135 {
00136         
00137         VorbisDecodeInputPin* locThis = reinterpret_cast<VorbisDecodeInputPin*> (inThisPointer);
00138         VorbisDecodeFilter* locFilter = reinterpret_cast<VorbisDecodeFilter*>(locThis->m_pFilter);
00139 
00140         if (locThis->CheckStreaming() == S_OK) {
00141 
00142                 unsigned long locActualSize = inFrames * locThis->mFrameSize;
00143                 unsigned long locTotalFrameCount = inFrames * locThis->mNumChannels;
00144                 unsigned long locBufferRemaining = DECODED_BUFFER_SIZE - locThis->mDecodedByteCount;
00145                 
00146 
00147 
00148                 //Create a pointer into the buffer              
00149                 signed short* locShortBuffer = (signed short*)&locThis->mDecodedBuffer[locThis->mDecodedByteCount];
00150                 
00151                 
00152                 signed short tempInt = 0;
00153                 float tempFloat = 0;
00154                 
00155                 //FIX:::Move the clipping to the abstract function
00156 
00157                 if (locBufferRemaining >= locActualSize) {
00158                         //Do float to int conversion with clipping
00159                         const float SINT_MAX_AS_FLOAT = 32767.0f;
00160                         for (unsigned long i = 0; i < locTotalFrameCount; i++) {
00161                                 //Clipping because vorbis puts out floats out of range -1 to 1
00162                                 if (((float*)inPCM)[i] <= -1.0f) {
00163                                         tempInt = SINT_MIN;     
00164                                 } else if (((float*)inPCM)[i] >= 1.0f) {
00165                                         tempInt = SINT_MAX;
00166                                 } else {
00167                                         //FIX:::Take out the unnescessary variable.
00168                                         tempFloat = ((( (float*) inPCM )[i]) * SINT_MAX_AS_FLOAT);
00169                                         //ASSERT((tempFloat <= 32767.0f) && (tempFloat >= -32786.0f));
00170                                         tempInt = (signed short)(tempFloat);
00171                                         //tempInt = (signed short) ((( (float*) inPCM )[i]) * SINT_MAX_AS_FLOAT);
00172                                 }
00173                                 
00174                                 *locShortBuffer = tempInt;
00175                                 locShortBuffer++;
00176                         }
00177 
00178                         locThis->mDecodedByteCount += locActualSize;
00179                         
00180                         return 0;
00181                 } else {
00182                         throw 0;
00183                 }
00184         } else {
00185                 DbgLog((LOG_TRACE,1,TEXT("Fishsound sending stuff we aren't ready for...")));
00186                 return -1;
00187         }
00188 
00189 }
00190 
00191 STDMETHODIMP VorbisDecodeInputPin::Receive(IMediaSample* inSample) 
00192 {
00193         CAutoLock locLock(mStreamLock);
00194 
00195         HRESULT locHR = CheckStreaming();
00196 
00197         if (locHR == S_OK) {
00198 
00199 
00200                 BYTE* locBuff = NULL;
00201                 locHR = inSample->GetPointer(&locBuff);
00202 
00203                 if (locHR != S_OK) {
00204                         //TODO::: Do a debug dump or something here with specific error info.
00205                         return locHR;
00206                 } else {
00207                         REFERENCE_TIME locStart = -1;
00208                         REFERENCE_TIME locEnd = -1;
00209                         __int64 locSampleDuration = 0;
00210                         inSample->GetTime(&locStart, &locEnd);
00211 
00212                         HRESULT locResult = TransformData(locBuff, inSample->GetActualDataLength());
00213                         if (locResult != S_OK) {
00214                                 return S_FALSE;
00215                         }
00216                         if (locEnd > 0) {
00217                                 //Can dump it all downstream now        
00218                                 IMediaSample* locSample;
00219                                 unsigned long locBytesCopied = 0;
00220                                 unsigned long locBytesToCopy = 0;
00221 
00222                                 locStart = convertGranuleToTime(locEnd) - (((mDecodedByteCount / mFrameSize) * UNITS) / mSampleRate);
00223 
00224                                 REFERENCE_TIME locGlobalOffset = 0;
00225                                 //Handle stream offsetting
00226                                 if (!mSentStreamOffset && (mOggOutputPinInterface != NULL)) {
00227                                         mOggOutputPinInterface->notifyStreamBaseTime(locStart);
00228                                         mSentStreamOffset = true;
00229                                         
00230                                 }
00231 
00232                                 if (mOggOutputPinInterface != NULL) {
00233                                         locGlobalOffset = mOggOutputPinInterface->getGlobalBaseTime();
00234                                 }
00235 
00236                                 do {
00237                                         HRESULT locHR = mOutputPin->GetDeliveryBuffer(&locSample, NULL, NULL, NULL);
00238                                         if (locHR != S_OK) {
00239                                                 return locHR;
00240                                         }
00241 
00242                                         BYTE* locBuffer = NULL;
00243                                         locHR = locSample->GetPointer(&locBuffer);
00244                                 
00245                                         if (locHR != S_OK) {
00246                                                 return locHR;
00247                                         }
00248 
00249                                         locBytesToCopy = ((mDecodedByteCount - locBytesCopied) <= locSample->GetSize()) ? (mDecodedByteCount - locBytesCopied) : locSample->GetSize();
00250                                         //locBytesCopied += locBytesToCopy;
00251 
00252                                         locSampleDuration = (((locBytesToCopy/mFrameSize) * UNITS) / mSampleRate);
00253                                         locEnd = locStart + locSampleDuration;
00254 
00255                                         //Adjust the time stamps for rate and seeking
00256                                         REFERENCE_TIME locAdjustedStart = (locStart * RATE_DENOMINATOR) / mRateNumerator;
00257                                         REFERENCE_TIME locAdjustedEnd = (locEnd * RATE_DENOMINATOR) / mRateNumerator;
00258                                         locAdjustedStart -= (m_tStart + locGlobalOffset);
00259                                         locAdjustedEnd -= (m_tStart + locGlobalOffset);
00260 
00261                                         __int64 locSeekStripOffset = 0;
00262                                         if (locAdjustedEnd < 0) {
00263                                                 locSample->Release();
00264                                         } else {
00265                                                 if (locAdjustedStart < 0) {
00266                                                         locSeekStripOffset = (-locAdjustedStart) * mSampleRate;
00267                                                         locSeekStripOffset *= mFrameSize;
00268                                                         locSeekStripOffset /= UNITS;
00269                                                         locSeekStripOffset += (mFrameSize - (locSeekStripOffset % mFrameSize));
00270                                                         __int64 locStrippedDuration = (((locSeekStripOffset/mFrameSize) * UNITS) / mSampleRate);
00271                                                         locAdjustedStart += locStrippedDuration;
00272                                                 }
00273                                                         
00274 
00275                                         
00276 
00277                                                 memcpy((void*)locBuffer, (const void*)&mDecodedBuffer[locBytesCopied + locSeekStripOffset], locBytesToCopy - locSeekStripOffset);
00278 
00279                                                 locSample->SetTime(&locAdjustedStart, &locAdjustedEnd);
00280                                                 locSample->SetMediaTime(&locStart, &locEnd);
00281                                                 locSample->SetSyncPoint(TRUE);
00282                                                 locSample->SetActualDataLength(locBytesToCopy - locSeekStripOffset);
00283                                                 locHR = ((VorbisDecodeOutputPin*)(mOutputPin))->mDataQueue->Receive(locSample);
00284                                                 if (locHR != S_OK) {
00285                                                         return locHR;
00286                                                 }
00287                                                 locStart += locSampleDuration;
00288 
00289                                         }
00290                                         locBytesCopied += locBytesToCopy;
00291 
00292                                 
00293                                 } while(locBytesCopied < mDecodedByteCount);
00294 
00295                                 mDecodedByteCount = 0;
00296                                 
00297                         }
00298                         return S_OK;
00299 
00300                 }
00301         } else {
00302                 //Not streaming - Bail out.
00303                 return S_FALSE;
00304         }
00305 }
00306 
00307 HRESULT VorbisDecodeInputPin::TransformData(BYTE* inBuf, long inNumBytes) 
00308 {
00309         //TODO::: Return types !!!
00310 
00311         //debugLog << "Decode called... Last Gran Pos : "<<mLastSeenStartGranPos<<endl;
00312         DbgLog((LOG_TRACE,1,TEXT("decodeData")));
00313         long locErr = fish_sound_decode(mFishSound, inBuf, inNumBytes);
00314         //FIX::: Do something here ?
00315         if (locErr < 0) {
00316                 DbgLog((LOG_TRACE,1,TEXT("decodeData : fishsound returns < 0")));
00317                 return S_FALSE;
00318                 //debugLog <<"** Fish Sound error **"<<endl;
00319         } else {
00320                 return S_OK;
00321                 //debugLog << "Fish Sound OK >=0 "<<endl;
00322         }
00323         //return locErr;
00324 }
00325 
00326 
00327 HRESULT VorbisDecodeInputPin::SetMediaType(const CMediaType* inMediaType) 
00328 {
00329         //FIX:::Error checking
00330 
00331         if (CheckMediaType(inMediaType) == S_OK) {
00332                 ((VorbisDecodeFilter*)mParentFilter)->setVorbisFormat(inMediaType->pbFormat);
00333                 
00334         } else {
00335                 throw 0;
00336         }
00337         return CBaseInputPin::SetMediaType(inMediaType);
00338 }
00339 HRESULT VorbisDecodeInputPin::CheckMediaType(const CMediaType *inMediaType)
00340 {
00341         if (AbstractTransformInputPin::CheckMediaType(inMediaType) == S_OK) {
00342                 if (inMediaType->cbFormat == VORBIS_IDENT_HEADER_SIZE) {
00343                         if (strncmp((char*)inMediaType->pbFormat, "\001vorbis", 7) == 0) {
00344                                 //TODO::: Possibly verify version
00345                                 return S_OK;
00346                         }
00347                 }
00348         }
00349         return S_FALSE;
00350         
00351 }
00352 
00353 HRESULT VorbisDecodeInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *outRequestedProps)
00354 {
00355         outRequestedProps->cbBuffer = VORBIS_BUFFER_SIZE;
00356         outRequestedProps->cBuffers = VORBIS_NUM_BUFFERS;
00357         outRequestedProps->cbAlign = 1;
00358         outRequestedProps->cbPrefix = 0;
00359 
00360         return S_OK;
00361 }
00362 
00363 LOOG_INT64 VorbisDecodeInputPin::convertGranuleToTime(LOOG_INT64 inGranule)
00364 {
00365         if (mBegun) {   
00366                 return (inGranule * UNITS) / mSampleRate;
00367         } else {
00368                 return -1;
00369         }
00370 }
00371 
00372 LOOG_INT64 VorbisDecodeInputPin::mustSeekBefore(LOOG_INT64 inGranule)
00373 {
00374         //TODO::: Get adjustment from block size info... for now, it doesn't matter if no preroll
00375         return inGranule;
00376 }
00377 IOggDecoder::eAcceptHeaderResult VorbisDecodeInputPin::showHeaderPacket(OggPacket* inCodecHeaderPacket)
00378 {
00379         switch (mSetupState) {
00380                 case VSS_SEEN_NOTHING:
00381                         if (strncmp((char*)inCodecHeaderPacket->packetData(), "\001vorbis", 7) == 0) {
00382                                 //TODO::: Possibly verify version
00383                                 if (fish_sound_decode(mFishSound, inCodecHeaderPacket->packetData(), inCodecHeaderPacket->packetSize()) >= 0) {
00384                                         mSetupState = VSS_SEEN_BOS;
00385                                         return IOggDecoder::AHR_MORE_HEADERS_TO_COME;
00386                                 }
00387                         }
00388                         return IOggDecoder::AHR_INVALID_HEADER;
00389                         
00390                         
00391                 case VSS_SEEN_BOS:
00392                         if (strncmp((char*)inCodecHeaderPacket->packetData(), "\003vorbis", 7) == 0) {
00393                                 if (fish_sound_decode(mFishSound, inCodecHeaderPacket->packetData(), inCodecHeaderPacket->packetSize()) >= 0) {
00394                                         mSetupState = VSS_SEEN_COMMENT;
00395                                         return IOggDecoder::AHR_MORE_HEADERS_TO_COME;
00396                                 }
00397                                 
00398                                 
00399                         }
00400                         return IOggDecoder::AHR_INVALID_HEADER;
00401                         
00402                         
00403                 case VSS_SEEN_COMMENT:
00404                         if (strncmp((char*)inCodecHeaderPacket->packetData(), "\005vorbis", 7) == 0) {
00405                                 if (fish_sound_decode(mFishSound, inCodecHeaderPacket->packetData(), inCodecHeaderPacket->packetSize()) >= 0) {
00406                 
00407                                         fish_sound_command (mFishSound, FISH_SOUND_GET_INFO, &(mFishInfo), sizeof (FishSoundInfo)); 
00408                                         //Is mBegun useful ?
00409                                         mBegun = true;
00410                         
00411                                         mNumChannels = mFishInfo.channels;
00412                                         mFrameSize = mNumChannels * SIZE_16_BITS;
00413                                         mSampleRate = mFishInfo.samplerate;
00414 
00415                 
00416                                         mSetupState = VSS_ALL_HEADERS_SEEN;
00417                                         return IOggDecoder::AHR_ALL_HEADERS_RECEIVED;
00418                                 }
00419                                 
00420                         }
00421                         return IOggDecoder::AHR_INVALID_HEADER;
00422                         
00423                 case VSS_ALL_HEADERS_SEEN:
00424                 case VSS_ERROR:
00425                 default:
00426                         return IOggDecoder::AHR_UNEXPECTED;
00427         }
00428 }
00429 string VorbisDecodeInputPin::getCodecShortName()
00430 {
00431         return "vorbis";
00432 }
00433 string VorbisDecodeInputPin::getCodecIdentString()
00434 {
00435         //TODO:::
00436         return "vorbis";
00437 }
00438 
00439 HRESULT VorbisDecodeInputPin::CompleteConnect(IPin *inReceivePin)
00440 {
00441         IOggOutputPin* locOggOutput = NULL;
00442         mSentStreamOffset = false;
00443         HRESULT locHR = inReceivePin->QueryInterface(IID_IOggOutputPin, (void**)&locOggOutput);
00444         if (locHR == S_OK) {
00445                 mOggOutputPinInterface = locOggOutput;
00446                 
00447         } else {
00448                 mOggOutputPinInterface = NULL;
00449         }
00450         return AbstractTransformInputPin::CompleteConnect(inReceivePin);
00451         
00452 }

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