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