FLACDecodeInputPin.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 "flacdecodeinputpin.h"
00034 
00035 FLACDecodeInputPin::FLACDecodeInputPin(AbstractTransformFilter* inParentFilter, CCritSec* inFilterLock, AbstractTransformOutputPin* inOutputPin, vector<CMediaType*> inAcceptableMediaTypes)
00036         :       AbstractTransformInputPin(inParentFilter, inFilterLock, inOutputPin, NAME("FLACDecodeInputPin"), L"FLAC In", inAcceptableMediaTypes)
00037         ,       mGotMetaData(false)
00038         ,       mCodecLock(NULL)
00039         ,       mFLACType(FT_UNKNOWN)
00040         ,       mMetadataPacket(NULL)
00041         ,       mSetupState(VSS_SEEN_NOTHING)
00042         ,       mDecodedByteCount(0)
00043         ,       mDecodedBuffer(NULL)
00044         ,       mRateNumerator(RATE_DENOMINATOR)
00045 
00046         ,       mUptoFrame(0)
00047 
00048 {
00049         //debugLog.open("G:\\logs\\flacfilter.log", ios_base::out);
00050         mCodecLock = new CCritSec;                      //Deleted in destructor.
00051         ConstructCodec();
00052 
00053         mDecodedBuffer = new unsigned char[DECODED_BUFFER_SIZE];
00054 }
00055 
00056 FLACDecodeInputPin::~FLACDecodeInputPin(void)
00057 {
00058         //debugLog.close();
00059         delete mCodecLock;
00060         delete mMetadataPacket;
00061         delete mDecodedBuffer;
00062         
00063 }
00064 
00065 STDMETHODIMP FLACDecodeInputPin::NonDelegatingQueryInterface(REFIID riid, void **ppv)
00066 {
00067         if (riid == IID_IMediaSeeking) {
00068                 *ppv = (IMediaSeeking*)this;
00069                 ((IUnknown*)*ppv)->AddRef();
00070                 return NOERROR;
00071         } else if (riid == IID_IOggDecoder) {
00072                 *ppv = (IOggDecoder*)this;
00073                 //((IUnknown*)*ppv)->AddRef();
00074                 return NOERROR;
00075 
00076         }
00077 
00078         return CBaseInputPin::NonDelegatingQueryInterface(riid, ppv); 
00079 }
00080 bool FLACDecodeInputPin::ConstructCodec() 
00081 {
00082         mFLACDecoder.initCodec();
00083 
00084         return true;
00085 }
00086 void FLACDecodeInputPin::DestroyCodec() 
00087 {
00088 
00089 }
00090 STDMETHODIMP FLACDecodeInputPin::NewSegment(REFERENCE_TIME inStartTime, REFERENCE_TIME inStopTime, double inRate) 
00091 {
00092         CAutoLock locLock(mStreamLock);
00093         //debugLog<<"New segment "<<inStartTime<<" - "<<inStopTime<<endl;
00094         mUptoFrame = 0;
00095         return AbstractTransformInputPin::NewSegment(inStartTime, inStopTime, inRate);
00096         
00097 }
00098 
00099 
00100 
00101 STDMETHODIMP FLACDecodeInputPin::Receive(IMediaSample* inSample) 
00102 {
00103         CAutoLock locLock(mStreamLock);
00104 
00105         HRESULT locHR = CheckStreaming();
00106 
00107         if (locHR == S_OK) {
00108                 BYTE* locBuff = NULL;
00109                 locHR = inSample->GetPointer(&locBuff);
00110 
00111                 if ((inSample->GetActualDataLength() > 1) && ((locBuff[0] != 0xff) || (locBuff[1] != 0xf8))) {
00112                         //inInputSample->Release();
00113 
00114                         //This is a header, so ignore it
00115                         return S_OK;
00116                 }
00117 
00118 
00119 
00120                 if (locHR != S_OK) {
00121                         //TODO::: Do a debug dump or something here with specific error info.
00122                         return locHR;
00123                 } else {
00124                         REFERENCE_TIME locStart = -1;
00125                         REFERENCE_TIME locEnd = -1;
00126                         __int64 locSampleDuration = 0;
00127                         inSample->GetTime(&locStart, &locEnd);
00128 
00129                         HRESULT locResult = TransformData(locBuff, inSample->GetActualDataLength());
00130                         if (locResult != S_OK) {
00131                                 return S_FALSE;
00132                         }
00133                         if (locEnd > 0) {
00134                                 //Can dump it all downstream now        
00135                                 IMediaSample* locSample;
00136                                 unsigned long locBytesCopied = 0;
00137                                 unsigned long locBytesToCopy = 0;
00138 
00139                                 locStart = convertGranuleToTime(locEnd) - (((mDecodedByteCount / mFLACDecoder.frameSize()) * UNITS) / mFLACDecoder.sampleRate());
00140                                 do {
00141                                         HRESULT locHR = mOutputPin->GetDeliveryBuffer(&locSample, NULL, NULL, NULL);
00142                                         if (locHR != S_OK) {
00143                                                 return locHR;
00144                                         }
00145 
00146                                         BYTE* locBuffer = NULL;
00147                                         locHR = locSample->GetPointer(&locBuffer);
00148                                 
00149                                         if (locHR != S_OK) {
00150                                                 return locHR;
00151                                         }
00152 
00153                                         locBytesToCopy = ((mDecodedByteCount - locBytesCopied) <= locSample->GetSize()) ? (mDecodedByteCount - locBytesCopied) : locSample->GetSize();
00154                                         //locBytesCopied += locBytesToCopy;
00155 
00156                                         locSampleDuration = (((locBytesToCopy/mFLACDecoder.frameSize()) * UNITS) / mFLACDecoder.sampleRate());
00157                                         locEnd = locStart + locSampleDuration;
00158 
00159                                         //Adjust the time stamps for rate and seeking
00160                                         REFERENCE_TIME locAdjustedStart = (locStart * RATE_DENOMINATOR) / mRateNumerator;
00161                                         REFERENCE_TIME locAdjustedEnd = (locEnd * RATE_DENOMINATOR) / mRateNumerator;
00162                                         locAdjustedStart -= m_tStart;
00163                                         locAdjustedEnd -= m_tStart;
00164 
00165                                         __int64 locSeekStripOffset = 0;
00166                                         if (locAdjustedEnd < 0) {
00167                                                 locSample->Release();
00168                                         } else {
00169                                                 if (locAdjustedStart < 0) {
00170                                                         locSeekStripOffset = (-locAdjustedStart) * mFLACDecoder.sampleRate();
00171                                                         locSeekStripOffset *= mFLACDecoder.frameSize();
00172                                                         locSeekStripOffset /= UNITS;
00173                                                         locSeekStripOffset += (mFLACDecoder.frameSize() - (locSeekStripOffset % mFLACDecoder.frameSize()));
00174                                                         __int64 locStrippedDuration = (((locSeekStripOffset/mFLACDecoder.frameSize()) * UNITS) / mFLACDecoder.sampleRate());
00175                                                         locAdjustedStart += locStrippedDuration;
00176                                                 }
00177                                                         
00178 
00179                                         
00180 
00181                                                 memcpy((void*)locBuffer, (const void*)&mDecodedBuffer[locBytesCopied + locSeekStripOffset], locBytesToCopy - locSeekStripOffset);
00182 
00183                                                 locSample->SetTime(&locAdjustedStart, &locAdjustedEnd);
00184                                                 locSample->SetMediaTime(&locStart, &locEnd);
00185                                                 locSample->SetSyncPoint(TRUE);
00186                                                 locSample->SetActualDataLength(locBytesToCopy - locSeekStripOffset);
00187                                                 locHR = ((FLACDecodeOutputPin*)(mOutputPin))->mDataQueue->Receive(locSample);
00188                                                 if (locHR != S_OK) {
00189                                                         return locHR;
00190                                                 }
00191                                                 locStart += locSampleDuration;
00192 
00193                                         }
00194                                         locBytesCopied += locBytesToCopy;
00195 
00196                                 
00197                                 } while(locBytesCopied < mDecodedByteCount);
00198 
00199                                 mDecodedByteCount = 0;
00200                                 
00201                         }
00202                         return S_OK;
00203 
00204                 }
00205         } else {
00206                 //Not streaming - Bail out.
00207                 return S_FALSE;
00208         }
00209 }
00210 
00211 
00212 
00213 
00214 HRESULT FLACDecodeInputPin::TransformData(BYTE* inBuf, long inNumBytes) 
00215 {
00216         //TODO::: There is a thread blocking problem here. sometimes the this code
00217         //              inside the checkstream check can be called while the graph is flushing.
00218         //
00219         //              Probably just needs a lock here on the filter, and/or in the begin/end flush method
00220         if (CheckStreaming() == S_OK) {
00221                 unsigned char* locInBuff = new unsigned char[inNumBytes];
00222                 memcpy((void*)locInBuff, (const void*)inBuf, inNumBytes);
00223                 OggPacket* locInputPacket = new OggPacket(locInBuff, inNumBytes, false, false);
00224 
00225         
00226                 StampedOggPacket* locStamped = (StampedOggPacket*)mFLACDecoder.decodeFLAC(locInputPacket)->clone();
00227 
00228                 FLACDecodeFilter* locFilter = reinterpret_cast<FLACDecodeFilter*>(m_pFilter);
00229 
00230         
00231 
00232                 unsigned long locActualSize = locStamped->packetSize();
00233                 //unsigned long locTotalFrameCount = inFrames * locThis->mNumChannels;
00234                 unsigned long locBufferRemaining = DECODED_BUFFER_SIZE - mDecodedByteCount;
00235                 
00236 
00237 
00238                 //Create a pointer into the buffer              
00239                 //signed short* locShortBuffer = (signed short*)&mDecodedBuffer[mDecodedByteCount];
00240                 
00241                 
00242                 //signed short tempInt = 0;
00243                 //float tempFloat = 0;
00244                 
00245                 //FIX:::Move the clipping to the abstract function
00246 
00247                 if (locBufferRemaining >= locActualSize) {
00248                         
00249                         memcpy((void*)&mDecodedBuffer[mDecodedByteCount], (const void*)locStamped->packetData(), locActualSize);
00250 
00251                         mDecodedByteCount += locActualSize;
00252                         delete locStamped;
00253                         return S_OK;
00254                 } else {
00255                         throw 0;
00256                 }
00257         } else {
00258                 DbgLog((LOG_TRACE,1,TEXT("Not streaming")));
00259                 return -1;
00260         }
00261 
00262 }
00263 
00264 
00265 STDMETHODIMP FLACDecodeInputPin::BeginFlush() {
00266         CAutoLock locLock(m_pLock);
00267         
00268         //debugLog<<"BeginFlush : Calling flush on the codec."<<endl;
00269 
00270         HRESULT locHR = AbstractTransformInputPin::BeginFlush();
00271         {       //PROTECT CODEC FROM IMPLODING
00272                 CAutoLock locCodecLock(mCodecLock);
00273                 mFLACDecoder.flushCodec();
00274         }       //END CRITICAL SECTION
00275         return locHR;
00276         
00277 }
00278 
00279 STDMETHODIMP FLACDecodeInputPin::EndFlush()
00280 {
00281         CAutoLock locLock(m_pLock);
00282         
00283         HRESULT locHR = AbstractTransformInputPin::EndFlush();
00284         mDecodedByteCount = 0;
00285         return locHR;
00286 }
00287 
00288 STDMETHODIMP FLACDecodeInputPin::EndOfStream(void) {
00289         CAutoLock locStreamLock(mStreamLock);
00290         {       //PROTECT CODEC FROM IMPLODING
00291                 CAutoLock locCodecLock(mCodecLock);
00292                 mFLACDecoder.flushCodec();
00293         }       //END CRITICAL SECTION
00294 
00295         return AbstractTransformInputPin::EndOfStream();
00296 }
00297 
00298 HRESULT FLACDecodeInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *outRequestedProps)
00299 {
00300         outRequestedProps->cbBuffer = FLAC_BUFFER_SIZE;
00301         outRequestedProps->cBuffers = FLAC_NUM_BUFFERS;
00302         outRequestedProps->cbAlign = 1;
00303         outRequestedProps->cbPrefix = 0;
00304 
00305         return S_OK;
00306 }
00307 HRESULT FLACDecodeInputPin::CheckMediaType(const CMediaType *inMediaType)
00308 {
00309         if (AbstractTransformInputPin::CheckMediaType(inMediaType) == S_OK) {
00310                 if (inMediaType->cbFormat == 4) {
00311                         if (strncmp((char*)inMediaType->pbFormat, "fLaC", 4) == 0) {
00312                                 //TODO::: Possibly verify version
00313                                 return S_OK;
00314                         }
00315                 } else if (inMediaType->cbFormat > 4) {
00316                         if (strncmp((char*)inMediaType->pbFormat, "\177FLAC", 5) == 0) {
00317                                 //TODO::: Possibly verify version
00318                                 return S_OK;
00319                         }
00320                 }
00321         }
00322         return S_FALSE;
00323         
00324 }
00325 HRESULT FLACDecodeInputPin::SetMediaType(const CMediaType* inMediaType) {
00326         //FIX:::Error checking
00327         //RESOLVED::: Bit better.
00328         if (CheckMediaType(inMediaType) == S_OK) {
00329                 //((FLACDecodeFilter*)mParentFilter)->setFLACFormatBlock(inMediaType->pbFormat);
00330                 if (inMediaType->cbFormat == 4) {
00331                         if (strncmp((char*)inMediaType->pbFormat, "fLaC", 4) == 0) {
00332                                 mFLACType = FT_CLASSIC;
00333                                 return S_OK;
00334                         }
00335                 } else if (inMediaType->cbFormat > 4) {
00336                         if (strncmp((char*)inMediaType->pbFormat, "\177FLAC", 5) == 0) {
00337                                 mFLACType = FT_OGG_FLAC_1;
00338                                 return S_OK;
00339                                 
00340                         }
00341                 }
00342                 return S_FALSE;
00343                 
00344         } else {
00345                 throw 0;
00346         }
00347 
00348 
00349         return CBaseInputPin::SetMediaType(inMediaType);
00350 }
00351 
00352 LOOG_INT64 FLACDecodeInputPin::convertGranuleToTime(LOOG_INT64 inGranule)
00353 {
00354                 
00355         return (inGranule * UNITS) / ((FLACDecodeFilter*)mParentFilter)->getFLACFormatBlock()->samplesPerSec;
00356         
00357 }
00358 
00359 LOOG_INT64 FLACDecodeInputPin::mustSeekBefore(LOOG_INT64 inGranule)
00360 {
00361         //TODO::: Get adjustment from block size info... for now, it doesn't matter if no preroll
00362         return inGranule;
00363 }
00364 IOggDecoder::eAcceptHeaderResult FLACDecodeInputPin::showHeaderPacket(OggPacket* inCodecHeaderPacket)
00365 {
00366         const unsigned char MORE_HEADERS_MASK = 128;   //10000000
00367         switch (mFLACType) {
00368                 case FT_CLASSIC:
00369                         switch (mSetupState) {
00370                                 case VSS_SEEN_NOTHING:
00371                                         if (strncmp((char*)inCodecHeaderPacket->packetData(), "fLaC", 4) == 0) {
00372                                                 mSetupState = VSS_SEEN_BOS;
00373                                                 delete mMetadataPacket;
00374                                                 mMetadataPacket = inCodecHeaderPacket->clone();
00375                                                 return IOggDecoder::AHR_MORE_HEADERS_TO_COME;
00376                                         }
00377 
00378                                         //TODO::: new flac format
00379                                         mSetupState = VSS_ERROR;
00380                                         return IOggDecoder::AHR_INVALID_HEADER;
00381                                 case VSS_SEEN_BOS:
00382                                         mMetadataPacket->merge(inCodecHeaderPacket);
00383                                         if ((inCodecHeaderPacket->packetData()[0] & MORE_HEADERS_MASK) != 0) {
00384                                                 //Last packet
00385                                                 mSetupState = VSS_ALL_HEADERS_SEEN; 
00386                                                 ((FLACDecodeFilter*)mParentFilter)->setFLACFormatBlock(mMetadataPacket->packetData());
00387                                                 mFLACDecoder.acceptMetadata(mMetadataPacket);
00388                                                 mMetadataPacket = NULL;
00389                                 
00390                                                 //TODO::: Give it to the codec
00391 
00392                                                 return IOggDecoder::AHR_ALL_HEADERS_RECEIVED;
00393                                         }
00394 
00395                                         return IOggDecoder::AHR_MORE_HEADERS_TO_COME;
00396                                 default:
00397                                         return IOggDecoder::AHR_UNEXPECTED;
00398                         }
00399 
00400                 case FT_OGG_FLAC_1:
00401                         switch(mSetupState) {
00402                                 case VSS_SEEN_NOTHING:
00403                                         if (strncmp((char*)inCodecHeaderPacket->packetData(),  "\177FLAC", 5) == 0) {
00404                                                 mSetupState = VSS_SEEN_BOS;
00405                                                 delete mMetadataPacket;
00406                                                 unsigned char* locBuff = new unsigned char[inCodecHeaderPacket->packetSize() - 9];
00407                                                 memcpy((void*)locBuff, (const void*)(inCodecHeaderPacket->packetData() + 9), inCodecHeaderPacket->packetSize() - 9);
00408                                                 mMetadataPacket = new OggPacket(locBuff, inCodecHeaderPacket->packetSize() - 9,  false, false);
00409                                                 return IOggDecoder::AHR_MORE_HEADERS_TO_COME;
00410                                         }
00411 
00412                                         
00413                                         mSetupState = VSS_ERROR;
00414                                         return IOggDecoder::AHR_INVALID_HEADER;
00415                                 case VSS_SEEN_BOS:
00416                                         mMetadataPacket->merge(inCodecHeaderPacket);
00417                                         if ((inCodecHeaderPacket->packetData()[0] & MORE_HEADERS_MASK) != 0) {
00418                                                 //Last packet
00419                                                 mSetupState = VSS_ALL_HEADERS_SEEN; 
00420                                                 ((FLACDecodeFilter*)mParentFilter)->setFLACFormatBlock(mMetadataPacket->packetData());
00421                                                 mFLACDecoder.acceptMetadata(mMetadataPacket);
00422                                                 mMetadataPacket = NULL;
00423                                 
00424                                                 //TODO::: Give it to the codec
00425 
00426                                                 return IOggDecoder::AHR_ALL_HEADERS_RECEIVED;
00427                                         }
00428 
00429                                         return IOggDecoder::AHR_MORE_HEADERS_TO_COME;
00430                                 default:
00431                                         return IOggDecoder::AHR_UNEXPECTED;
00432 
00433 
00434                         };
00435                 default:
00436                         return IOggDecoder::AHR_INVALID_HEADER;
00437 
00438 
00439         }
00440 
00441 }
00442 string FLACDecodeInputPin::getCodecShortName()
00443 {
00444         return "flac";
00445 }
00446 string FLACDecodeInputPin::getCodecIdentString()
00447 {
00448         //TODO:::
00449         return "flac";
00450 }
00451 

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