00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "stdafx.h"
00032 #include ".\NativeFLACSourceFilter.h"
00033
00034 CFactoryTemplate g_Templates[] =
00035 {
00036 {
00037 L"Native FLAC SourceFilter",
00038 &CLSID_NativeFLACSourceFilter,
00039 NativeFLACSourceFilter::CreateInstance,
00040 NULL,
00041 NULL
00042 }
00043
00044 };
00045
00046
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
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
00096 ULONG NativeFLACSourceFilter::GetMiscFlags(void) {
00097 return AM_FILTER_MISC_FLAGS_IS_SOURCE;
00098 }
00099
00100
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
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
00117
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;
00144 const unsigned char FLAC_BPS_START_MASK = 1;
00145 const unsigned char FLAC_BPS_END_MASK = 240;
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
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
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
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
00291 unsigned char* locBuff = new unsigned char[locBufferSize];
00292
00293
00294 signed short* locShortBuffer = (signed short*)locBuff;
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
00304
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 }