NativeFLACSourceFilter.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 #include "stdafx.h"
00032 #include ".\NativeFLACSourceFilter.h"
00033 
00034 CFactoryTemplate g_Templates[] = 
00035 {
00036     { 
00037                 L"Native FLAC SourceFilter",                                            // Name
00038             &CLSID_NativeFLACSourceFilter,            // CLSID
00039             NativeFLACSourceFilter::CreateInstance,     // Method to create an instance of MyComponent
00040         NULL,                                                                   // Initialization function
00041         NULL                                                                    // Set-up information (for filters)
00042     }
00043 
00044 };
00045 
00046 // Generic way of determining the number of items in the template
00047 int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]); 
00048 
00049 
00050 CUnknown* WINAPI NativeFLACSourceFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr) 
00051 {
00052         NativeFLACSourceFilter *pNewObject = new NativeFLACSourceFilter();
00053     if (pNewObject == NULL) {
00054         *pHr = E_OUTOFMEMORY;
00055     }
00056     return pNewObject;
00057 } 
00058 
00059 NativeFLACSourceFilter::NativeFLACSourceFilter(void)
00060         :       CBaseFilter(NAME("NativeFLACSourceFilter"), NULL, m_pLock, CLSID_NativeFLACSourceFilter)
00061         ,       mNumChannels(0)
00062         ,       mSampleRate(0)
00063         ,       mBitsPerSample(0)
00064         ,       mBegun(false)
00065         ,       mUpto(0)
00066         ,       mJustSeeked(true)
00067         ,       mSeekRequest(0)
00068         ,       mTotalNumSamples(0)
00069         ,       mWasEOF(false)
00070 {
00071         m_pLock = new CCritSec;
00072         mCodecLock = new CCritSec;
00073         mFLACSourcePin = new NativeFLACSourcePin(this, m_pLock);
00074 }
00075 
00076 NativeFLACSourceFilter::~NativeFLACSourceFilter(void)
00077 {
00078         delete mFLACSourcePin;
00079         mFLACSourcePin = NULL;
00080         delete mCodecLock;
00081 }
00082 
00083 //BaseFilter Interface
00084 int NativeFLACSourceFilter::GetPinCount() {
00085         return 1;
00086 }
00087 CBasePin* NativeFLACSourceFilter::GetPin(int inPinNo) {
00088         if (inPinNo == 0) {
00089                 return mFLACSourcePin;
00090         } else {
00091                 return NULL;
00092         }
00093 }
00094 
00095 //IAMFilterMiscFlags Interface
00096 ULONG NativeFLACSourceFilter::GetMiscFlags(void) {
00097         return AM_FILTER_MISC_FLAGS_IS_SOURCE;
00098 }
00099 
00100         //IFileSource Interface
00101 STDMETHODIMP NativeFLACSourceFilter::GetCurFile(LPOLESTR* outFileName, AM_MEDIA_TYPE* outMediaType) {
00102         LPOLESTR x = SysAllocString(mFileName.c_str());
00103         *outFileName = x;
00104         return S_OK;
00105 }
00106 
00107 
00108 STDMETHODIMP NativeFLACSourceFilter::Load(LPCOLESTR inFileName, const AM_MEDIA_TYPE* inMediaType) 
00109 {
00110         //Initialise the file here and setup the stream
00111         CAutoLock locLock(m_pLock);
00112         mFileName = inFileName;
00113 
00114         mInputFile.open(StringHelper::toNarrowStr(mFileName).c_str(), ios_base::in | ios_base::binary);
00115 
00116         //CT> Added header check (for FLAC files with ID3 v1/2 tags in them)
00117         //    We'll look in the first 128kb of the file
00118         unsigned long locStart = 0;
00119         int locHeaderFound = 0;
00120         for(int j = 0; !locHeaderFound && j < 128; j++) {
00121                 unsigned char locTempBuf[1024]={0,};
00122                 mInputFile.read((char*)&locTempBuf, sizeof(locTempBuf));
00123                 unsigned char* locPtr = locTempBuf;
00124                 for(int i = 0; i < 1023; i++) {
00125                         if(locPtr[i]=='f' && locPtr[i+1]=='L' && locPtr[i+2]=='a' && locPtr[i+3]=='C')                  {
00126                                 locHeaderFound = 1;
00127                                 locStart = i + (j * 1024);
00128                                 break;
00129                         }
00130                 }
00131         }
00132         if(!locHeaderFound) {
00133                 return E_FAIL;
00134         }
00135 
00136         mInputFile.seekg(0, ios_base::end);
00137         mFileSize = mInputFile.tellg();
00138         mFileSize -= locStart;
00139         mInputFile.seekg(locStart, ios_base::beg);
00140 
00141         unsigned char locBuff[64];
00142         mInputFile.read((char*)&locBuff, 64);
00143         const unsigned char FLAC_CHANNEL_MASK = 14;  //00001110
00144         const unsigned char FLAC_BPS_START_MASK = 1; //00000001
00145         const unsigned char FLAC_BPS_END_MASK = 240;  //11110000
00146 
00147         mNumChannels = (((locBuff[20]) & FLAC_CHANNEL_MASK) >> 1) + 1;
00148         mSampleRate = (iBE_Math::charArrToULong(&locBuff[18])) >> 12;
00149         mBitsPerSample =        (((locBuff[20] & FLAC_BPS_START_MASK) << 4)     | ((locBuff[21] & FLAC_BPS_END_MASK) >> 4)) + 1;        
00150         mTotalNumSamples = (((__int64)(locBuff[21] % 16)) << 32) + ((__int64)(iBE_Math::charArrToULong(&locBuff[22])));
00151 
00152         //TODO::: NEed to handle the case where the number of samples is zero by making it non-seekable.
00153         mInputFile.seekg(locStart, ios_base::beg);
00154 
00155         init();
00156         bool locResult = process_until_end_of_metadata();
00157 
00158         return (locResult ? S_OK : E_FAIL);
00159 
00160 }
00161 
00162 STDMETHODIMP NativeFLACSourceFilter::NonDelegatingQueryInterface(REFIID riid, void **ppv)
00163 {
00164         if (riid == IID_IFileSourceFilter) {
00165                 *ppv = (IFileSourceFilter*)this;
00166                 ((IUnknown*)*ppv)->AddRef();
00167                 return NOERROR;
00168         }
00169 
00170         return CBaseFilter::NonDelegatingQueryInterface(riid, ppv); 
00171 }
00172 
00173 
00174 //IMEdiaStreaming
00175 STDMETHODIMP NativeFLACSourceFilter::Run(REFERENCE_TIME tStart) {
00176         CAutoLock locLock(m_pLock);
00177         return CBaseFilter::Run(tStart);
00178 }
00179 STDMETHODIMP NativeFLACSourceFilter::Pause(void) {
00180         CAutoLock locLock(m_pLock);
00181         if (m_State == State_Stopped) {
00182                 if (ThreadExists() == FALSE) {
00183                         Create();
00184                 }
00185                 CallWorker(THREAD_RUN);
00186         }
00187 
00188         HRESULT locHR = CBaseFilter::Pause();
00189         return locHR;
00190         
00191 }
00192 STDMETHODIMP NativeFLACSourceFilter::Stop(void) {
00193         CAutoLock locLock(m_pLock);
00194         CallWorker(THREAD_EXIT);
00195         Close();
00196         mJustSeeked = true;
00197         mSeekRequest = 0;
00198         mUpto = 0;
00199         mFLACSourcePin->DeliverBeginFlush();
00200         mFLACSourcePin->DeliverEndFlush();
00201         return CBaseFilter::Stop();
00202 }
00203 
00204 HRESULT NativeFLACSourceFilter::DataProcessLoop() {
00205         DWORD locCommand = 0;
00206         bool res = false;
00207         while (true) {
00208                 if(CheckRequest(&locCommand) == TRUE) {
00209                         return S_OK;
00210                 }
00211                 {
00212                         CAutoLock locLock(mCodecLock);
00213                         if (mJustSeeked) {
00214                                 mJustSeeked = false;
00215                                 bool res2 = false;
00216                                 res2 = seek_absolute(mSeekRequest);
00217                         }
00218                         
00219                         res = process_single();
00220 
00221                         if (mWasEOF) {
00222                                 break;
00223                         }
00224                         
00225                 }
00226         }
00227 
00228         mInputFile.clear();
00229         mInputFile.seekg(0);
00230         mWasEOF = false;
00231         mFLACSourcePin->DeliverEndOfStream();
00232         return S_OK;
00233 }
00234 
00235 //CAMThread Stuff
00236 DWORD NativeFLACSourceFilter::ThreadProc(void) {
00237         while(true) {
00238                 DWORD locThreadCommand = GetRequest();
00239                 switch(locThreadCommand) {
00240                         case THREAD_EXIT:
00241                                 Reply(S_OK);
00242                                 return S_OK;
00243 
00244                         case THREAD_RUN:
00245                                 Reply(S_OK);
00246                                 DataProcessLoop();
00247                                 break;
00248                 }
00249         }
00250         return S_OK;
00251 }
00252 
00253 
00254 ::FLAC__SeekableStreamDecoderReadStatus NativeFLACSourceFilter::read_callback(FLAC__byte outBuffer[], unsigned int* outNumBytes) {
00255         const unsigned long BUFF_SIZE = 8192;
00256         mInputFile.read((char*)outBuffer, BUFF_SIZE);
00257         *outNumBytes = mInputFile.gcount();
00258         mWasEOF = mInputFile.eof();
00259         return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
00260 }
00261 ::FLAC__SeekableStreamDecoderSeekStatus NativeFLACSourceFilter::seek_callback(FLAC__uint64 inSeekPos) {
00262         mInputFile.seekg(inSeekPos);
00263         return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
00264 }
00265 ::FLAC__SeekableStreamDecoderTellStatus NativeFLACSourceFilter::tell_callback(FLAC__uint64* outTellPos) {
00266         *outTellPos = mInputFile.tellg();
00267         return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
00268 }
00269 ::FLAC__SeekableStreamDecoderLengthStatus NativeFLACSourceFilter::length_callback(FLAC__uint64* outLength) {
00270         *outLength = mFileSize;
00271         return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
00272 }
00273 ::FLAC__StreamDecoderWriteStatus NativeFLACSourceFilter::write_callback(const FLAC__Frame* inFrame,const FLAC__int32 *const inBuffer[]) {
00274         
00275 
00276         if (! mBegun) {
00277                 mBegun = true;
00278                 
00279                 const int SIZE_16_BITS = 2;
00280                 
00281                 mNumChannels = inFrame->header.channels;
00282                 mFrameSize = mNumChannels * SIZE_16_BITS;
00283                 mSampleRate = inFrame->header.sample_rate;
00284         }
00285 
00286         unsigned long locNumFrames = inFrame->header.blocksize;
00287         unsigned long locBufferSize = locNumFrames * mFrameSize;
00288         unsigned long locTotalFrameCount = locNumFrames * mNumChannels;
00289 
00290         //BUG::: There's a bug here. Implicitly assumes 2 channels. I think.
00291         unsigned char* locBuff = new unsigned char[locBufferSize];                      //Gives to the deliverdata method
00292         //It could actually be a single buffer for the class.
00293 
00294         signed short* locShortBuffer = (signed short*)locBuff;          //Don't delete this.
00295         
00296         signed short tempInt = 0;
00297         int tempLong = 0;
00298         float tempFloat = 0;
00299         for(unsigned long i = 0; i < locNumFrames; i++) {
00300                 for (unsigned long j = 0; j < mNumChannels; j++) {
00301                         tempLong = inBuffer[j][i];
00302 
00303                         //FIX::: Why on earth are you dividing by 2 ? It does not make sense !
00304                         //tempInt = (signed short)(tempLong/2);
00305                         tempInt = (signed short)(tempLong);
00306                 
00307                         *locShortBuffer = tempInt;
00308                         locShortBuffer++;
00309                 }
00310         }
00311         
00312         mFLACSourcePin->deliverData(locBuff, locBufferSize, (mUpto*UNITS) / mSampleRate, ((mUpto+locNumFrames)*UNITS) / mSampleRate);
00313         mUpto += locNumFrames;
00314         return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
00315 }
00316 void NativeFLACSourceFilter::metadata_callback(const FLAC__StreamMetadata* inMetaData) {
00317 
00318 }
00319 void NativeFLACSourceFilter::error_callback(FLAC__StreamDecoderErrorStatus inStatus) {
00320 
00321 }
00322 
00323 bool NativeFLACSourceFilter::eof_callback(void) {
00324         return mInputFile.eof();
00325 }
00326 
00327 
00328 
00329 STDMETHODIMP NativeFLACSourceFilter::GetCapabilities(DWORD* inCapabilities) {
00330         *inCapabilities = AM_SEEKING_CanSeekAbsolute |
00331                                                 AM_SEEKING_CanSeekForwards |
00332                                                 AM_SEEKING_CanSeekBackwards |
00333                                                 AM_SEEKING_CanGetCurrentPos |
00334                                                 AM_SEEKING_CanGetStopPos |
00335                                                 AM_SEEKING_CanGetDuration;
00336         return S_OK;
00337 }
00338 STDMETHODIMP NativeFLACSourceFilter::CheckCapabilities(DWORD *pCapabilities) {
00339         return E_NOTIMPL;
00340 }
00341 STDMETHODIMP NativeFLACSourceFilter::IsFormatSupported(const GUID *pFormat) {
00342         if (*pFormat == TIME_FORMAT_MEDIA_TIME) {
00343                 return S_OK;
00344         } else {
00345                 return S_FALSE;
00346         }
00347 }
00348 STDMETHODIMP NativeFLACSourceFilter::QueryPreferredFormat(GUID *pFormat) {
00349         *pFormat = TIME_FORMAT_MEDIA_TIME;
00350         return S_OK;
00351 }
00352 STDMETHODIMP NativeFLACSourceFilter::SetTimeFormat(const GUID *pFormat) {
00353         return E_NOTIMPL;
00354 }
00355 STDMETHODIMP NativeFLACSourceFilter::GetTimeFormat( GUID *pFormat) {
00356         *pFormat = TIME_FORMAT_MEDIA_TIME;
00357         return S_OK;
00358 }
00359 STDMETHODIMP NativeFLACSourceFilter::GetDuration(LONGLONG *pDuration) {
00360         *pDuration = (mTotalNumSamples * UNITS) / mSampleRate;
00361         return S_OK;
00362 }
00363 STDMETHODIMP NativeFLACSourceFilter::GetStopPosition(LONGLONG *pStop) {
00364         *pStop = (mTotalNumSamples * UNITS) / mSampleRate;
00365         return S_OK;
00366 }
00367 STDMETHODIMP NativeFLACSourceFilter::GetCurrentPosition(LONGLONG *pCurrent){
00368         return E_NOTIMPL;
00369 }
00370 STDMETHODIMP NativeFLACSourceFilter::ConvertTimeFormat(LONGLONG *pTarget, const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat){
00371         return E_NOTIMPL;
00372 }
00373 STDMETHODIMP NativeFLACSourceFilter::SetPositions(LONGLONG *pCurrent,DWORD dwCurrentFlags,LONGLONG *pStop,DWORD dwStopFlags){
00374         unsigned __int64 locSampleToSeek = (*pCurrent) * mSampleRate/ UNITS;
00375         mFLACSourcePin->DeliverBeginFlush();
00376         mFLACSourcePin->DeliverEndFlush();
00377 
00378         bool locRes = false;
00379         {
00380                 CAutoLock locLock(mCodecLock);
00381                 mUpto = 0;
00382                 mJustSeeked = true;
00383                 mSeekRequest = locSampleToSeek;
00384         }
00385         
00386         return S_OK;
00387 }
00388 STDMETHODIMP NativeFLACSourceFilter::GetPositions(LONGLONG *pCurrent, LONGLONG *pStop){
00389         return E_NOTIMPL;
00390 }
00391 STDMETHODIMP NativeFLACSourceFilter::GetAvailable(LONGLONG *pEarliest, LONGLONG *pLatest){
00392         *pEarliest = 0;
00393         *pLatest = (mTotalNumSamples * UNITS) / mSampleRate;
00394         return S_OK;
00395 }
00396 STDMETHODIMP NativeFLACSourceFilter::SetRate(double dRate){
00397         return E_NOTIMPL;
00398 }
00399 STDMETHODIMP NativeFLACSourceFilter::GetRate(double *dRate){
00400         *dRate = 1.0;
00401         return S_OK;
00402 }
00403 STDMETHODIMP NativeFLACSourceFilter::GetPreroll(LONGLONG *pllPreroll){
00404         *pllPreroll = 0;
00405         return S_OK;
00406 }
00407 STDMETHODIMP NativeFLACSourceFilter::IsUsingTimeFormat(const GUID *pFormat){
00408         if (*pFormat == TIME_FORMAT_MEDIA_TIME) {
00409                 return S_OK;
00410         } else {
00411                 return S_FALSE;
00412         }
00413 }

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