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         //Initialise the file here and setup the stream
00110         CAutoLock locLock(m_pLock);
00111         mFileName = inFileName;
00112 
00113         mInputFile.open(StringHelper::toNarrowStr(mFileName).c_str(), ios_base::in | ios_base::binary);
00114 
00115         mInputFile.seekg(0, ios_base::end);
00116         mFileSize = mInputFile.tellg();
00117         mInputFile.seekg(0, ios_base::beg);
00118 
00119         unsigned char locBuff[64];
00120         mInputFile.read((char*)&locBuff, 64);
00121         const unsigned char FLAC_CHANNEL_MASK = 14;  //00001110
00122         const unsigned char FLAC_BPS_START_MASK = 1; //00000001
00123         const unsigned char FLAC_BPS_END_MASK = 240;  //11110000
00124 
00125         mNumChannels = (((locBuff[20]) & FLAC_CHANNEL_MASK) >> 1) + 1;
00126         mSampleRate = (iBE_Math::charArrToULong(&locBuff[18])) >> 12;
00127         mBitsPerSample =        (((locBuff[20] & FLAC_BPS_START_MASK) << 4)     | ((locBuff[21] & FLAC_BPS_END_MASK) >> 4)) + 1;        
00128         mTotalNumSamples = (((__int64)(locBuff[21] % 16)) << 32) + ((__int64)(iBE_Math::charArrToULong(&locBuff[22])));
00129 
00130         //TODO::: NEed to handle the case where the number of samples is zero by making it non-seekable.
00131         mInputFile.seekg(0, ios_base::beg);
00132 
00133         init();
00134         bool locResult = process_until_end_of_metadata();
00135 
00136         return S_OK;
00137 }
00138 
00139 STDMETHODIMP NativeFLACSourceFilter::NonDelegatingQueryInterface(REFIID riid, void **ppv)
00140 {
00141         if (riid == IID_IFileSourceFilter) {
00142                 *ppv = (IFileSourceFilter*)this;
00143                 ((IUnknown*)*ppv)->AddRef();
00144                 return NOERROR;
00145         }
00146 
00147         return CBaseFilter::NonDelegatingQueryInterface(riid, ppv); 
00148 }
00149 
00150 
00151 //IMEdiaStreaming
00152 STDMETHODIMP NativeFLACSourceFilter::Run(REFERENCE_TIME tStart) {
00153         CAutoLock locLock(m_pLock);
00154         return CBaseFilter::Run(tStart);
00155 }
00156 STDMETHODIMP NativeFLACSourceFilter::Pause(void) {
00157         CAutoLock locLock(m_pLock);
00158         if (m_State == State_Stopped) {
00159                 if (ThreadExists() == FALSE) {
00160                         Create();
00161                 }
00162                 CallWorker(THREAD_RUN);
00163         }
00164 
00165         HRESULT locHR = CBaseFilter::Pause();
00166         return locHR;
00167         
00168 }
00169 STDMETHODIMP NativeFLACSourceFilter::Stop(void) {
00170         CAutoLock locLock(m_pLock);
00171         CallWorker(THREAD_EXIT);
00172         Close();
00173         mJustSeeked = true;
00174         mSeekRequest = 0;
00175         mUpto = 0;
00176         mFLACSourcePin->DeliverBeginFlush();
00177         mFLACSourcePin->DeliverEndFlush();
00178         return CBaseFilter::Stop();
00179 }
00180 
00181 HRESULT NativeFLACSourceFilter::DataProcessLoop() {
00182         DWORD locCommand = 0;
00183         bool res = false;
00184         while (true) {
00185                 if(CheckRequest(&locCommand) == TRUE) {
00186                         return S_OK;
00187                 }
00188                 {
00189                         CAutoLock locLock(mCodecLock);
00190                         if (mJustSeeked) {
00191                                 mJustSeeked = false;
00192                                 bool res2 = false;
00193                                 res2 = seek_absolute(mSeekRequest);
00194                         }
00195                         
00196                         res = process_single();
00197 
00198                         if (mWasEOF) {
00199                                 break;
00200                         }
00201                         
00202                 }
00203         }
00204 
00205         mInputFile.clear();
00206         mInputFile.seekg(0);
00207         mWasEOF = false;
00208         mFLACSourcePin->DeliverEndOfStream();
00209         return S_OK;
00210 }
00211 
00212 //CAMThread Stuff
00213 DWORD NativeFLACSourceFilter::ThreadProc(void) {
00214         while(true) {
00215                 DWORD locThreadCommand = GetRequest();
00216                 switch(locThreadCommand) {
00217                         case THREAD_EXIT:
00218                                 Reply(S_OK);
00219                                 return S_OK;
00220 
00221                         case THREAD_RUN:
00222                                 Reply(S_OK);
00223                                 DataProcessLoop();
00224                                 break;
00225                 }
00226         }
00227         return S_OK;
00228 }
00229 
00230 
00231 ::FLAC__SeekableStreamDecoderReadStatus NativeFLACSourceFilter::read_callback(FLAC__byte outBuffer[], unsigned int* outNumBytes) {
00232         const unsigned long BUFF_SIZE = 8192;
00233         mInputFile.read((char*)outBuffer, BUFF_SIZE);
00234         *outNumBytes = mInputFile.gcount();
00235         mWasEOF = mInputFile.eof();
00236         return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
00237 }
00238 ::FLAC__SeekableStreamDecoderSeekStatus NativeFLACSourceFilter::seek_callback(FLAC__uint64 inSeekPos) {
00239         mInputFile.seekg(inSeekPos);
00240         return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
00241 }
00242 ::FLAC__SeekableStreamDecoderTellStatus NativeFLACSourceFilter::tell_callback(FLAC__uint64* outTellPos) {
00243         *outTellPos = mInputFile.tellg();
00244         return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
00245 }
00246 ::FLAC__SeekableStreamDecoderLengthStatus NativeFLACSourceFilter::length_callback(FLAC__uint64* outLength) {
00247         *outLength = mFileSize;
00248         return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
00249 }
00250 ::FLAC__StreamDecoderWriteStatus NativeFLACSourceFilter::write_callback(const FLAC__Frame* inFrame,const FLAC__int32 *const inBuffer[]) {
00251         //Do the magic !
00252         if (! mBegun) {
00253                 //This may not even be needed any more. 
00254                 mBegun = true;
00255                 const int SIZE_16_BITS = 2;
00256                 mNumChannels = inFrame->header.channels;
00257                 mFrameSize = mNumChannels * SIZE_16_BITS;
00258                 mSampleRate = inFrame->header.sample_rate;
00259         }
00260 
00261         unsigned long locNumFrames = inFrame->header.blocksize;
00262         unsigned long locActualSize = locNumFrames * mFrameSize;
00263         unsigned long locTotalFrameCount = locNumFrames * mNumChannels;
00264 
00265         //BUG::: There's a bug here. Implicitly assumes 2 channels. I think.
00266         unsigned char* locBuff = new unsigned char[locActualSize];                      //Gives to the deliverdata method
00267         //It could actually be a single buffer for the class.
00268 
00269         signed short* locShortBuffer = (signed short*)locBuff;          //Don't delete this.
00270         
00271         signed short tempInt = 0;
00272         int tempLong = 0;
00273         float tempFloat = 0;
00274         for(unsigned long i = 0; i < locNumFrames; i++) {
00275                 for (unsigned long j = 0; j < mNumChannels; j++) {
00276                         tempLong = inBuffer[j][i];
00277 
00278                         //FIX::: Why on earth are you dividing by 2 ? It does not make sense !
00279                         tempInt = (signed short)(tempLong/2);
00280                 
00281                         *locShortBuffer = tempInt;
00282                         locShortBuffer++;
00283                 }
00284         }
00285         
00286         mFLACSourcePin->deliverData(locBuff, locActualSize, (mUpto*UNITS) / mSampleRate, ((mUpto+locNumFrames)*UNITS) / mSampleRate);
00287         mUpto += locNumFrames;
00288         return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
00289 }
00290 void NativeFLACSourceFilter::metadata_callback(const FLAC__StreamMetadata* inMetaData) {
00291 
00292 }
00293 void NativeFLACSourceFilter::error_callback(FLAC__StreamDecoderErrorStatus inStatus) {
00294 
00295 }
00296 
00297 bool NativeFLACSourceFilter::eof_callback(void) {
00298         return mInputFile.eof();
00299 }
00300 
00301 
00302 
00303 STDMETHODIMP NativeFLACSourceFilter::GetCapabilities(DWORD* inCapabilities) {
00304         *inCapabilities = AM_SEEKING_CanSeekAbsolute |
00305                                                 AM_SEEKING_CanSeekForwards |
00306                                                 AM_SEEKING_CanSeekBackwards |
00307                                                 AM_SEEKING_CanGetCurrentPos |
00308                                                 AM_SEEKING_CanGetStopPos |
00309                                                 AM_SEEKING_CanGetDuration;
00310         return S_OK;
00311 }
00312 STDMETHODIMP NativeFLACSourceFilter::CheckCapabilities(DWORD *pCapabilities) {
00313         return E_NOTIMPL;
00314 }
00315 STDMETHODIMP NativeFLACSourceFilter::IsFormatSupported(const GUID *pFormat) {
00316         if (*pFormat == TIME_FORMAT_MEDIA_TIME) {
00317                 return S_OK;
00318         } else {
00319                 return S_FALSE;
00320         }
00321 }
00322 STDMETHODIMP NativeFLACSourceFilter::QueryPreferredFormat(GUID *pFormat) {
00323         *pFormat = TIME_FORMAT_MEDIA_TIME;
00324         return S_OK;
00325 }
00326 STDMETHODIMP NativeFLACSourceFilter::SetTimeFormat(const GUID *pFormat) {
00327         return E_NOTIMPL;
00328 }
00329 STDMETHODIMP NativeFLACSourceFilter::GetTimeFormat( GUID *pFormat) {
00330         *pFormat = TIME_FORMAT_MEDIA_TIME;
00331         return S_OK;
00332 }
00333 STDMETHODIMP NativeFLACSourceFilter::GetDuration(LONGLONG *pDuration) {
00334         *pDuration = (mTotalNumSamples * UNITS) / mSampleRate;
00335         return S_OK;
00336 }
00337 STDMETHODIMP NativeFLACSourceFilter::GetStopPosition(LONGLONG *pStop) {
00338         *pStop = (mTotalNumSamples * UNITS) / mSampleRate;
00339         return S_OK;
00340 }
00341 STDMETHODIMP NativeFLACSourceFilter::GetCurrentPosition(LONGLONG *pCurrent){
00342         return E_NOTIMPL;
00343 }
00344 STDMETHODIMP NativeFLACSourceFilter::ConvertTimeFormat(LONGLONG *pTarget, const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat){
00345         return E_NOTIMPL;
00346 }
00347 STDMETHODIMP NativeFLACSourceFilter::SetPositions(LONGLONG *pCurrent,DWORD dwCurrentFlags,LONGLONG *pStop,DWORD dwStopFlags){
00348         unsigned __int64 locSampleToSeek = (*pCurrent) * mSampleRate/ UNITS;
00349         mFLACSourcePin->DeliverBeginFlush();
00350         mFLACSourcePin->DeliverEndFlush();
00351 
00352         bool locRes = false;
00353         {
00354                 CAutoLock locLock(mCodecLock);
00355                 mUpto = 0;
00356                 mJustSeeked = true;
00357                 mSeekRequest = locSampleToSeek;
00358         }
00359         
00360         return S_OK;
00361 }
00362 STDMETHODIMP NativeFLACSourceFilter::GetPositions(LONGLONG *pCurrent, LONGLONG *pStop){
00363         return E_NOTIMPL;
00364 }
00365 STDMETHODIMP NativeFLACSourceFilter::GetAvailable(LONGLONG *pEarliest, LONGLONG *pLatest){
00366         *pEarliest = 0;
00367         *pLatest = (mTotalNumSamples * UNITS) / mSampleRate;
00368         return S_OK;
00369 }
00370 STDMETHODIMP NativeFLACSourceFilter::SetRate(double dRate){
00371         return E_NOTIMPL;
00372 }
00373 STDMETHODIMP NativeFLACSourceFilter::GetRate(double *dRate){
00374         *dRate = 1.0;
00375         return S_OK;
00376 }
00377 STDMETHODIMP NativeFLACSourceFilter::GetPreroll(LONGLONG *pllPreroll){
00378         *pllPreroll = 0;
00379         return S_OK;
00380 }
00381 STDMETHODIMP NativeFLACSourceFilter::IsUsingTimeFormat(const GUID *pFormat){
00382         if (*pFormat == TIME_FORMAT_MEDIA_TIME) {
00383                 return S_OK;
00384         } else {
00385                 return S_FALSE;
00386         }
00387 }

Generated on Tue Feb 15 14:54:15 2005 for oggdsf by  doxygen 1.3.9