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
00032 #include "stdafx.h"
00033 #include "SpeexDecodeInputPin.h"
00034
00035
00036 SpeexDecodeInputPin::SpeexDecodeInputPin(AbstractTransformFilter* inFilter, CCritSec* inFilterLock, AbstractTransformOutputPin* inOutputPin, vector<CMediaType*> inAcceptableMediaTypes)
00037 : AbstractTransformInputPin(inFilter, inFilterLock, inOutputPin, NAME("SpeexDecodeInputPin"), L"Speex In", inAcceptableMediaTypes)
00038 , mFishSound(NULL)
00039
00040 , mNumChannels(0)
00041 , mFrameSize(0)
00042 , mSampleRate(0)
00043 , mUptoFrame(0)
00044
00045 , mDecodedByteCount(0)
00046 , mDecodedBuffer(NULL)
00047 , mRateNumerator(RATE_DENOMINATOR)
00048
00049 , mSetupState(VSS_SEEN_NOTHING)
00050
00051 , mBegun(false)
00052 {
00053 ConstructCodec();
00054
00055 mDecodedBuffer = new unsigned char[DECODED_BUFFER_SIZE];
00056 }
00057
00058 bool SpeexDecodeInputPin::ConstructCodec() {
00059 mFishSound = fish_sound_new (FISH_SOUND_DECODE, &mFishInfo);
00060
00061 int i = 1;
00062
00063 fish_sound_command(mFishSound, FISH_SOUND_SET_INTERLEAVE, &i, sizeof(int));
00064
00065 fish_sound_set_decoded_callback (mFishSound, SpeexDecodeInputPin::SpeexDecoded, this);
00066
00067 return true;
00068 }
00069 void SpeexDecodeInputPin::DestroyCodec() {
00070 fish_sound_delete(mFishSound);
00071 mFishSound = NULL;
00072 }
00073 SpeexDecodeInputPin::~SpeexDecodeInputPin(void)
00074 {
00075 DestroyCodec();
00076
00077 delete mDecodedBuffer;
00078 }
00079
00080 STDMETHODIMP SpeexDecodeInputPin::NonDelegatingQueryInterface(REFIID riid, void **ppv)
00081 {
00082 if (riid == IID_IMediaSeeking) {
00083 *ppv = (IMediaSeeking*)this;
00084 ((IUnknown*)*ppv)->AddRef();
00085 return NOERROR;
00086 } else if (riid == IID_IOggDecoder) {
00087 *ppv = (IOggDecoder*)this;
00088
00089 return NOERROR;
00090
00091 }
00092
00093 return CBaseInputPin::NonDelegatingQueryInterface(riid, ppv);
00094 }
00095 STDMETHODIMP SpeexDecodeInputPin::NewSegment(REFERENCE_TIME inStartTime, REFERENCE_TIME inStopTime, double inRate)
00096 {
00097 CAutoLock locLock(mStreamLock);
00098
00099 mUptoFrame = 0;
00100
00101 mRateNumerator = RATE_DENOMINATOR * inRate;
00102 if (mRateNumerator > RATE_DENOMINATOR) {
00103 mRateNumerator = RATE_DENOMINATOR;
00104 }
00105 return AbstractTransformInputPin::NewSegment(inStartTime, inStopTime, inRate);
00106 }
00107
00108 STDMETHODIMP SpeexDecodeInputPin::EndFlush()
00109 {
00110 CAutoLock locLock(m_pLock);
00111
00112 HRESULT locHR = AbstractTransformInputPin::EndFlush();
00113 mDecodedByteCount = 0;
00114 return locHR;
00115 }
00116 HRESULT SpeexDecodeInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *outRequestedProps)
00117 {
00118 outRequestedProps->cbBuffer = SPEEX_BUFFER_SIZE;
00119 outRequestedProps->cBuffers = SPEEX_NUM_BUFFERS;
00120 outRequestedProps->cbAlign = 1;
00121 outRequestedProps->cbPrefix = 0;
00122
00123 return S_OK;
00124 }
00125 int SpeexDecodeInputPin::SpeexDecoded (FishSound* inFishSound, float** inPCM, long inFrames, void* inThisPointer)
00126 {
00127
00128 SpeexDecodeInputPin* locThis = reinterpret_cast<SpeexDecodeInputPin*> (inThisPointer);
00129 SpeexDecodeFilter* locFilter = reinterpret_cast<SpeexDecodeFilter*>(locThis->m_pFilter);
00130
00131 if (locThis->CheckStreaming() == S_OK) {
00132
00133 unsigned long locActualSize = inFrames * locThis->mFrameSize;
00134 unsigned long locTotalFrameCount = inFrames * locThis->mNumChannels;
00135 unsigned long locBufferRemaining = DECODED_BUFFER_SIZE - locThis->mDecodedByteCount;
00136
00137
00138
00139
00140 signed short* locShortBuffer = (signed short*)&locThis->mDecodedBuffer[locThis->mDecodedByteCount];
00141
00142
00143 signed short tempInt = 0;
00144 float tempFloat = 0;
00145
00146
00147
00148 if (locBufferRemaining >= locActualSize) {
00149
00150 const float SINT_MAX_AS_FLOAT = 32767.0f;
00151 for (unsigned long i = 0; i < locTotalFrameCount; i++) {
00152
00153 if (((float*)inPCM)[i] <= -1.0f) {
00154 tempInt = SINT_MIN;
00155 } else if (((float*)inPCM)[i] >= 1.0f) {
00156 tempInt = SINT_MAX;
00157 } else {
00158
00159 tempFloat = ((( (float*) inPCM )[i]) * SINT_MAX_AS_FLOAT);
00160
00161 tempInt = (signed short)(tempFloat);
00162
00163 }
00164
00165 *locShortBuffer = tempInt;
00166 locShortBuffer++;
00167 }
00168
00169 locThis->mDecodedByteCount += locActualSize;
00170
00171 return 0;
00172 } else {
00173 throw 0;
00174 }
00175 } else {
00176 DbgLog((LOG_TRACE,1,TEXT("Fishsound sending stuff we aren't ready for...")));
00177 return -1;
00178 }
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00194
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00212
00213
00214
00215
00217
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00232
00233
00234
00236
00237
00238
00239
00240
00241
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 }
00283
00284 STDMETHODIMP SpeexDecodeInputPin::Receive(IMediaSample* inSample)
00285 {
00286 CAutoLock locLock(mStreamLock);
00287
00288 HRESULT locHR = CheckStreaming();
00289
00290 if (locHR == S_OK) {
00291
00292
00293 BYTE* locBuff = NULL;
00294 locHR = inSample->GetPointer(&locBuff);
00295
00296 if (locHR != S_OK) {
00297
00298 return locHR;
00299 } else {
00300 REFERENCE_TIME locStart = -1;
00301 REFERENCE_TIME locEnd = -1;
00302 __int64 locSampleDuration = 0;
00303 inSample->GetTime(&locStart, &locEnd);
00304
00305 HRESULT locResult = TransformData(locBuff, inSample->GetActualDataLength());
00306 if (locResult != S_OK) {
00307 return S_FALSE;
00308 }
00309 if (locEnd > 0) {
00310
00311 IMediaSample* locSample;
00312 unsigned long locBytesCopied = 0;
00313 unsigned long locBytesToCopy = 0;
00314
00315 locStart = convertGranuleToTime(locEnd) - (((mDecodedByteCount / mFrameSize) * UNITS) / mSampleRate);
00316 do {
00317 HRESULT locHR = mOutputPin->GetDeliveryBuffer(&locSample, NULL, NULL, NULL);
00318 if (locHR != S_OK) {
00319 return locHR;
00320 }
00321
00322 BYTE* locBuffer = NULL;
00323 locHR = locSample->GetPointer(&locBuffer);
00324
00325 if (locHR != S_OK) {
00326 return locHR;
00327 }
00328
00329 locBytesToCopy = ((mDecodedByteCount - locBytesCopied) <= locSample->GetSize()) ? (mDecodedByteCount - locBytesCopied) : locSample->GetSize();
00330
00331
00332 locSampleDuration = (((locBytesToCopy/mFrameSize) * UNITS) / mSampleRate);
00333 locEnd = locStart + locSampleDuration;
00334
00335
00336 REFERENCE_TIME locAdjustedStart = (locStart * RATE_DENOMINATOR) / mRateNumerator;
00337 REFERENCE_TIME locAdjustedEnd = (locEnd * RATE_DENOMINATOR) / mRateNumerator;
00338 locAdjustedStart -= m_tStart;
00339 locAdjustedEnd -= m_tStart;
00340
00341 __int64 locSeekStripOffset = 0;
00342 if (locAdjustedEnd < 0) {
00343 locSample->Release();
00344 } else {
00345 if (locAdjustedStart < 0) {
00346 locSeekStripOffset = (-locAdjustedStart) * mSampleRate;
00347 locSeekStripOffset *= mFrameSize;
00348 locSeekStripOffset /= UNITS;
00349 locSeekStripOffset += (mFrameSize - (locSeekStripOffset % mFrameSize));
00350 __int64 locStrippedDuration = (((locSeekStripOffset/mFrameSize) * UNITS) / mSampleRate);
00351 locAdjustedStart += locStrippedDuration;
00352 }
00353
00354
00355
00356
00357 memcpy((void*)locBuffer, (const void*)&mDecodedBuffer[locBytesCopied + locSeekStripOffset], locBytesToCopy - locSeekStripOffset);
00358
00359 locSample->SetTime(&locAdjustedStart, &locAdjustedEnd);
00360 locSample->SetMediaTime(&locStart, &locEnd);
00361 locSample->SetSyncPoint(TRUE);
00362 locSample->SetActualDataLength(locBytesToCopy - locSeekStripOffset);
00363 locHR = ((SpeexDecodeOutputPin*)(mOutputPin))->mDataQueue->Receive(locSample);
00364 if (locHR != S_OK) {
00365 return locHR;
00366 }
00367 locStart += locSampleDuration;
00368
00369 }
00370 locBytesCopied += locBytesToCopy;
00371
00372
00373 } while(locBytesCopied < mDecodedByteCount);
00374
00375 mDecodedByteCount = 0;
00376
00377 }
00378 return S_OK;
00379
00380 }
00381 } else {
00382
00383 return S_FALSE;
00384 }
00385 }
00386
00387
00388 HRESULT SpeexDecodeInputPin::TransformData(BYTE* inBuf, long inNumBytes)
00389 {
00390 long locErr = fish_sound_decode(mFishSound, inBuf, inNumBytes);
00391 if (locErr == 0) {
00392 return S_OK;
00393 } else {
00394 return S_FALSE;
00395 }
00396 }
00397
00398
00399
00400 HRESULT SpeexDecodeInputPin::SetMediaType(const CMediaType* inMediaType)
00401 {
00402
00403
00404 if (CheckMediaType(inMediaType) == S_OK) {
00405 ((SpeexDecodeFilter*)mParentFilter)->setSpeexFormat(inMediaType->pbFormat);
00406
00407 } else {
00408 throw 0;
00409 }
00410 return CBaseInputPin::SetMediaType(inMediaType);
00411
00412
00413
00414
00415
00416
00417
00418
00419 }
00420
00421 HRESULT SpeexDecodeInputPin::CheckMediaType(const CMediaType *inMediaType)
00422 {
00423 if (AbstractTransformInputPin::CheckMediaType(inMediaType) == S_OK) {
00424 if (inMediaType->cbFormat == SPEEX_IDENT_HEADER_SIZE) {
00425 if (strncmp((char*)inMediaType->pbFormat, "Speex ", 8) == 0) {
00426
00427 return S_OK;
00428 }
00429 }
00430 }
00431 return S_FALSE;
00432
00433 }
00434
00435 LOOG_INT64 SpeexDecodeInputPin::convertGranuleToTime(LOOG_INT64 inGranule)
00436 {
00437 if (mBegun) {
00438 return (inGranule * UNITS) / mSampleRate;
00439 } else {
00440 return -1;
00441 }
00442 }
00443
00444 LOOG_INT64 SpeexDecodeInputPin::mustSeekBefore(LOOG_INT64 inGranule)
00445 {
00446
00447 return inGranule;
00448 }
00449 IOggDecoder::eAcceptHeaderResult SpeexDecodeInputPin::showHeaderPacket(OggPacket* inCodecHeaderPacket)
00450 {
00451 switch (mSetupState) {
00452 case VSS_SEEN_NOTHING:
00453 if (strncmp((char*)inCodecHeaderPacket->packetData(), "Speex ", 8) == 0) {
00454
00455 if (fish_sound_decode(mFishSound, inCodecHeaderPacket->packetData(), inCodecHeaderPacket->packetSize()) >= 0) {
00456 mSetupState = VSS_SEEN_BOS;
00457 return IOggDecoder::AHR_MORE_HEADERS_TO_COME;
00458 }
00459 }
00460 return IOggDecoder::AHR_INVALID_HEADER;
00461
00462
00463 case VSS_SEEN_BOS:
00464
00465
00466
00467
00468 if (fish_sound_decode(mFishSound, inCodecHeaderPacket->packetData(), inCodecHeaderPacket->packetSize()) >= 0) {
00469 mSetupState = VSS_ALL_HEADERS_SEEN;
00470
00471 fish_sound_command (mFishSound, FISH_SOUND_GET_INFO, &(mFishInfo), sizeof (FishSoundInfo));
00472 mBegun = true;
00473
00474 mNumChannels = mFishInfo.channels;
00475 mFrameSize = mNumChannels * SIZE_16_BITS;
00476 mSampleRate = mFishInfo.samplerate;
00477
00478 return IOggDecoder::AHR_ALL_HEADERS_RECEIVED;
00479 }
00480
00481
00482
00483 return IOggDecoder::AHR_INVALID_HEADER;
00484
00485
00486
00487 case VSS_ALL_HEADERS_SEEN:
00488 case VSS_ERROR:
00489 default:
00490 return IOggDecoder::AHR_UNEXPECTED;
00491 }
00492 }
00493 string SpeexDecodeInputPin::getCodecShortName()
00494 {
00495 return "speex";
00496 }
00497 string SpeexDecodeInputPin::getCodecIdentString()
00498 {
00499
00500 return "speex";
00501 }
00502