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 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;
00122 const unsigned char FLAC_BPS_START_MASK = 1;
00123 const unsigned char FLAC_BPS_END_MASK = 240;
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
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
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
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
00252 if (! mBegun) {
00253
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
00266 unsigned char* locBuff = new unsigned char[locActualSize];
00267
00268
00269 signed short* locShortBuffer = (signed short*)locBuff;
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
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 }