00001
00031 #include "linden_common.h"
00032
00033 #include "llaudiodecodemgr.h"
00034
00035 #include "vorbisdecode.h"
00036 #include "audioengine.h"
00037 #include "lllfsthread.h"
00038 #include "llvfile.h"
00039 #include "llstring.h"
00040 #include "lldir.h"
00041 #include "llendianswizzle.h"
00042 #include "audioengine.h"
00043 #include "llassetstorage.h"
00044
00045 #include "vorbis/codec.h"
00046 #include "vorbis/vorbisfile.h"
00047
00048 extern LLAudioEngine *gAudiop;
00049
00050 LLAudioDecodeMgr *gAudioDecodeMgrp = NULL;
00051
00052 static const S32 WAV_HEADER_SIZE = 44;
00053
00054
00056
00057
00058 class LLVorbisDecodeState : public LLRefCount
00059 {
00060 public:
00061 class WriteResponder : public LLLFSThread::Responder
00062 {
00063 public:
00064 WriteResponder(LLVorbisDecodeState* decoder) : mDecoder(decoder) {}
00065 ~WriteResponder() {}
00066 void completed(S32 bytes)
00067 {
00068 mDecoder->ioComplete(bytes);
00069 }
00070 LLPointer<LLVorbisDecodeState> mDecoder;
00071 };
00072
00073 LLVorbisDecodeState(const LLUUID &uuid, const LLString &out_filename);
00074
00075 BOOL initDecode();
00076 BOOL decodeSection();
00077 BOOL finishDecode();
00078
00079 void flushBadFile();
00080
00081 void ioComplete(S32 bytes) { mBytesRead = bytes; }
00082 BOOL isValid() const { return mValid; }
00083 BOOL isDone() const { return mDone; }
00084 const LLUUID &getUUID() const { return mUUID; }
00085
00086 protected:
00087 virtual ~LLVorbisDecodeState();
00088
00089 BOOL mValid;
00090 BOOL mDone;
00091 LLAtomicS32 mBytesRead;
00092 LLUUID mUUID;
00093
00094 std::vector<U8> mWAVBuffer;
00095 #if !defined(USE_WAV_VFILE)
00096 LLString mOutFilename;
00097 LLLFSThread::handle_t mFileHandle;
00098 #endif
00099
00100 LLVFile *mInFilep;
00101 OggVorbis_File mVF;
00102 S32 mCurrentSection;
00103 };
00104
00105 size_t vfs_read(void *ptr, size_t size, size_t nmemb, void *datasource)
00106 {
00107 LLVFile *file = (LLVFile *)datasource;
00108
00109 if (file->read((U8*)ptr, (S32)(size * nmemb)))
00110 {
00111 S32 read = file->getLastBytesRead();
00112 return read / size;
00113 }
00114 else
00115 {
00116 return 0;
00117 }
00118 }
00119
00120 int vfs_seek(void *datasource, ogg_int64_t offset, int whence)
00121 {
00122 LLVFile *file = (LLVFile *)datasource;
00123
00124
00125 if (offset > S32_MAX)
00126 {
00127 return -1;
00128 }
00129
00130 S32 origin;
00131 switch (whence) {
00132 case SEEK_SET:
00133 origin = 0;
00134 break;
00135 case SEEK_END:
00136 origin = file->getSize();
00137 break;
00138 case SEEK_CUR:
00139 origin = -1;
00140 break;
00141 default:
00142 llerrs << "Invalid whence argument to vfs_seek" << llendl;
00143 return -1;
00144 }
00145
00146 if (file->seek((S32)offset, origin))
00147 {
00148 return 0;
00149 }
00150 else
00151 {
00152 return -1;
00153 }
00154 }
00155
00156 int vfs_close (void *datasource)
00157 {
00158 LLVFile *file = (LLVFile *)datasource;
00159 delete file;
00160 return 0;
00161 }
00162
00163 long vfs_tell (void *datasource)
00164 {
00165 LLVFile *file = (LLVFile *)datasource;
00166 return file->tell();
00167 }
00168
00169 LLVorbisDecodeState::LLVorbisDecodeState(const LLUUID &uuid, const LLString &out_filename)
00170 {
00171 mDone = FALSE;
00172 mValid = FALSE;
00173 mBytesRead = -1;
00174 mUUID = uuid;
00175 mInFilep = NULL;
00176 mCurrentSection = 0;
00177 #if !defined(USE_WAV_VFILE)
00178 mOutFilename = out_filename;
00179 mFileHandle = LLLFSThread::nullHandle();
00180 #endif
00181
00182 }
00183
00184 LLVorbisDecodeState::~LLVorbisDecodeState()
00185 {
00186 if (!mDone)
00187 {
00188 delete mInFilep;
00189 mInFilep = NULL;
00190 }
00191 }
00192
00193
00194 BOOL LLVorbisDecodeState::initDecode()
00195 {
00196 ov_callbacks vfs_callbacks;
00197 vfs_callbacks.read_func = vfs_read;
00198 vfs_callbacks.seek_func = vfs_seek;
00199 vfs_callbacks.close_func = vfs_close;
00200 vfs_callbacks.tell_func = vfs_tell;
00201
00202
00203
00204 mInFilep = new LLVFile(gVFS, mUUID, LLAssetType::AT_SOUND);
00205 if (!mInFilep || !mInFilep->getSize())
00206 {
00207 llwarns << "unable to open vorbis source vfile for reading" << llendl;
00208 delete mInFilep;
00209 mInFilep = NULL;
00210 return FALSE;
00211 }
00212
00213 int r = ov_open_callbacks(mInFilep, &mVF, NULL, 0, vfs_callbacks);
00214 if(r < 0)
00215 {
00216 llwarns << r << " Input to vorbis decode does not appear to be an Ogg bitstream: " << mUUID << llendl;
00217 return(FALSE);
00218 }
00219
00220 size_t size_guess = (size_t)ov_pcm_total(&mVF, -1);
00221 vorbis_info* vi = ov_info(&mVF, -1);
00222 size_guess *= vi->channels;
00223 size_guess *= 2;
00224 size_guess += 2048;
00225 mWAVBuffer.reserve(size_guess);
00226 mWAVBuffer.resize(WAV_HEADER_SIZE);
00227
00228 {
00229
00230
00231 mWAVBuffer[0] = 0x52;
00232 mWAVBuffer[1] = 0x49;
00233 mWAVBuffer[2] = 0x46;
00234 mWAVBuffer[3] = 0x46;
00235
00236
00237 mWAVBuffer[4] = 0x00;
00238 mWAVBuffer[5] = 0x00;
00239 mWAVBuffer[6] = 0x00;
00240 mWAVBuffer[7] = 0x00;
00241
00242
00243 mWAVBuffer[8] = 0x57;
00244 mWAVBuffer[9] = 0x41;
00245 mWAVBuffer[10] = 0x56;
00246 mWAVBuffer[11] = 0x45;
00247
00248
00249 mWAVBuffer[12] = 0x66;
00250 mWAVBuffer[13] = 0x6D;
00251 mWAVBuffer[14] = 0x74;
00252 mWAVBuffer[15] = 0x20;
00253
00254
00255 mWAVBuffer[16] = 0x10;
00256 mWAVBuffer[17] = 0x00;
00257 mWAVBuffer[18] = 0x00;
00258 mWAVBuffer[19] = 0x00;
00259
00260
00261 mWAVBuffer[20] = 0x01;
00262 mWAVBuffer[21] = 0x00;
00263
00264
00265 mWAVBuffer[22] = 0x01;
00266 mWAVBuffer[23] = 0x00;
00267
00268
00269 mWAVBuffer[24] = 0x44;
00270 mWAVBuffer[25] = 0xAC;
00271 mWAVBuffer[26] = 0x00;
00272 mWAVBuffer[27] = 0x00;
00273
00274
00275 mWAVBuffer[28] = 0x88;
00276 mWAVBuffer[29] = 0x58;
00277 mWAVBuffer[30] = 0x01;
00278 mWAVBuffer[31] = 0x00;
00279
00280
00281 mWAVBuffer[32] = 0x02;
00282 mWAVBuffer[33] = 0x00;
00283
00284
00285 mWAVBuffer[34] = 0x10;
00286 mWAVBuffer[35] = 0x00;
00287
00288
00289 mWAVBuffer[36] = 0x64;
00290 mWAVBuffer[37] = 0x61;
00291 mWAVBuffer[38] = 0x74;
00292 mWAVBuffer[39] = 0x61;
00293
00294
00295 mWAVBuffer[40] = 0x00;
00296 mWAVBuffer[41] = 0x00;
00297 mWAVBuffer[42] = 0x00;
00298 mWAVBuffer[43] = 0x00;
00299 }
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 return TRUE;
00313 }
00314
00315 BOOL LLVorbisDecodeState::decodeSection()
00316 {
00317 if (!mInFilep)
00318 {
00319 llwarns << "No VFS file to decode in vorbis!" << llendl;
00320 return TRUE;
00321 }
00322 if (mDone)
00323 {
00324
00325 return TRUE;
00326 }
00327 char pcmout[4096];
00328
00329 BOOL eof = FALSE;
00330 long ret=ov_read(&mVF, pcmout, sizeof(pcmout), 0, 2, 1, &mCurrentSection);
00331 if (ret == 0)
00332 {
00333
00334 eof = TRUE;
00335 mDone = TRUE;
00336 mValid = TRUE;
00337
00338 }
00339 else if (ret < 0)
00340 {
00341
00342
00343
00344 llwarns << "BAD vorbis decode in decodeSection." << llendl;
00345
00346 mValid = FALSE;
00347 mDone = TRUE;
00348
00349 return TRUE;
00350 }
00351 else
00352 {
00353
00354
00355
00356 std::copy(pcmout, pcmout+ret, std::back_inserter(mWAVBuffer));
00357 }
00358 return eof;
00359 }
00360
00361 BOOL LLVorbisDecodeState::finishDecode()
00362 {
00363 if (!isValid())
00364 {
00365 llwarns << "Bogus vorbis decode state for " << getUUID() << ", aborting!" << llendl;
00366 return TRUE;
00367 }
00368
00369 #if !defined(USE_WAV_VFILE)
00370 if (mFileHandle == LLLFSThread::nullHandle())
00371 #endif
00372 {
00373 ov_clear(&mVF);
00374
00375
00376 S32 data_length = mWAVBuffer.size() - WAV_HEADER_SIZE;
00377 mWAVBuffer[40] = (data_length) & 0x000000FF;
00378 mWAVBuffer[41] = (data_length >> 8) & 0x000000FF;
00379 mWAVBuffer[42] = (data_length >> 16) & 0x000000FF;
00380 mWAVBuffer[43] = (data_length >> 24) & 0x000000FF;
00381
00382 data_length += 36;
00383 mWAVBuffer[4] = (data_length) & 0x000000FF;
00384 mWAVBuffer[5] = (data_length >> 8) & 0x000000FF;
00385 mWAVBuffer[6] = (data_length >> 16) & 0x000000FF;
00386 mWAVBuffer[7] = (data_length >> 24) & 0x000000FF;
00387
00388
00389
00390
00391
00392 {
00393 S16 *samplep;
00394 S32 i;
00395 S32 fade_length;
00396 char pcmout[4096];
00397
00398 fade_length = llmin((S32)128,(S32)(data_length-36)/8);
00399 if((S32)mWAVBuffer.size() >= (WAV_HEADER_SIZE + 2* fade_length))
00400 {
00401 memcpy(pcmout, &mWAVBuffer[WAV_HEADER_SIZE], (2 * fade_length));
00402 }
00403 llendianswizzle(&pcmout, 2, fade_length);
00404
00405 samplep = (S16 *)pcmout;
00406 for (i = 0 ;i < fade_length; i++)
00407 {
00408 *samplep = llfloor((F32)*samplep * ((F32)i/(F32)fade_length));
00409 samplep++;
00410 }
00411
00412 llendianswizzle(&pcmout, 2, fade_length);
00413 if((WAV_HEADER_SIZE+(2 * fade_length)) < (S32)mWAVBuffer.size())
00414 {
00415 memcpy(&mWAVBuffer[WAV_HEADER_SIZE], pcmout, (2 * fade_length));
00416 }
00417 S32 near_end = mWAVBuffer.size() - (2 * fade_length);
00418 if ((S32)mWAVBuffer.size() >= ( near_end + 2* fade_length))
00419 {
00420 memcpy(pcmout, &mWAVBuffer[near_end], (2 * fade_length));
00421 }
00422 llendianswizzle(&pcmout, 2, fade_length);
00423
00424 samplep = (S16 *)pcmout;
00425 for (i = fade_length-1 ; i >= 0; i--)
00426 {
00427 *samplep = llfloor((F32)*samplep * ((F32)i/(F32)fade_length));
00428 samplep++;
00429 }
00430
00431 llendianswizzle(&pcmout, 2, fade_length);
00432 if (near_end + (2 * fade_length) < (S32)mWAVBuffer.size())
00433 {
00434 memcpy(&mWAVBuffer[near_end], pcmout, (2 * fade_length));
00435 }
00436 }
00437
00438 if (36 == data_length)
00439 {
00440 llwarns << "BAD Vorbis decode in finishDecode!" << llendl;
00441 mValid = FALSE;
00442 return TRUE;
00443 }
00444 #if !defined(USE_WAV_VFILE)
00445 mBytesRead = -1;
00446 mFileHandle = LLLFSThread::sLocal->write(mOutFilename, &mWAVBuffer[0], 0, data_length,
00447 new WriteResponder(this));
00448 #endif
00449 }
00450
00451 if (mFileHandle != LLLFSThread::nullHandle())
00452 {
00453 if (mBytesRead >= 0)
00454 {
00455 if (mBytesRead == 0)
00456 {
00457 llwarns << "Unable to write file in LLVorbisDecodeState::finishDecode" << llendl;
00458 mValid = FALSE;
00459 return TRUE;
00460 }
00461 }
00462 else
00463 {
00464 return FALSE;
00465 }
00466 }
00467
00468 mDone = TRUE;
00469
00470 #if defined(USE_WAV_VFILE)
00471
00472 LLVFile output(gVFS, mUUID, LLAssetType::AT_SOUND_WAV);
00473 output.write(&mWAVBuffer[0], mWAVBuffer.size());
00474 #endif
00475
00476
00477 return TRUE;
00478 }
00479
00480 void LLVorbisDecodeState::flushBadFile()
00481 {
00482 if (mInFilep)
00483 {
00484 llwarns << "Flushing bad vorbis file from VFS for " << mUUID << llendl;
00485 mInFilep->remove();
00486 }
00487 }
00488
00490
00491 class LLAudioDecodeMgr::Impl
00492 {
00493 friend class LLAudioDecodeMgr;
00494 public:
00495 Impl() {};
00496 ~Impl() {};
00497
00498 void processQueue(const F32 num_secs = 0.005);
00499
00500 protected:
00501 LLLinkedQueue<LLUUID> mDecodeQueue;
00502 LLPointer<LLVorbisDecodeState> mCurrentDecodep;
00503 };
00504
00505
00506 void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs)
00507 {
00508 LLUUID uuid;
00509
00510 LLTimer decode_timer;
00511
00512 BOOL done = FALSE;
00513 while (!done)
00514 {
00515 if (mCurrentDecodep)
00516 {
00517 BOOL res;
00518
00519
00520 while(!(res = mCurrentDecodep->decodeSection()) && (decode_timer.getElapsedTimeF32() < num_secs))
00521 {
00522
00523 }
00524
00525 if (mCurrentDecodep->isDone() && !mCurrentDecodep->isValid())
00526 {
00527
00528 llwarns << mCurrentDecodep->getUUID() << " has invalid vorbis data, aborting decode" << llendl;
00529 mCurrentDecodep->flushBadFile();
00530 LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID());
00531 adp->setHasValidData(FALSE);
00532 mCurrentDecodep = NULL;
00533 done = TRUE;
00534 }
00535
00536 if (!res)
00537 {
00538
00539 done = TRUE;
00540 }
00541 else if (mCurrentDecodep)
00542 {
00543 if (mCurrentDecodep->finishDecode())
00544 {
00545
00546 if (mCurrentDecodep->isValid() && mCurrentDecodep->isDone())
00547 {
00548 LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID());
00549 adp->setHasDecodedData(TRUE);
00550 adp->setHasValidData(TRUE);
00551
00552
00553
00554
00555
00556 }
00557 else
00558 {
00559 llinfos << "Vorbis decode failed!!!" << llendl;
00560 }
00561 mCurrentDecodep = NULL;
00562 }
00563 done = TRUE;
00564 }
00565 }
00566
00567 if (!done)
00568 {
00569 if (!mDecodeQueue.getLength())
00570 {
00571
00572 done = TRUE;
00573 }
00574 else
00575 {
00576 LLUUID uuid;
00577 mDecodeQueue.pop(uuid);
00578 if (gAudiop->hasDecodedFile(uuid))
00579 {
00580
00581 continue;
00582 }
00583
00584 lldebugs << "Decoding " << uuid << " from audio queue!" << llendl;
00585
00586 char uuid_str[64];
00587 char d_path[LL_MAX_PATH];
00588
00589 LLTimer timer;
00590 timer.reset();
00591
00592 uuid.toString(uuid_str);
00593 snprintf(d_path, LL_MAX_PATH, "%s.dsf", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str).c_str());
00594
00595 mCurrentDecodep = new LLVorbisDecodeState(uuid, d_path);
00596 if (!mCurrentDecodep->initDecode())
00597 {
00598 mCurrentDecodep = NULL;
00599 }
00600 }
00601 }
00602 }
00603 }
00604
00606
00607 LLAudioDecodeMgr::LLAudioDecodeMgr()
00608 {
00609 mImpl = new Impl;
00610 }
00611
00612 LLAudioDecodeMgr::~LLAudioDecodeMgr()
00613 {
00614 delete mImpl;
00615 }
00616
00617 void LLAudioDecodeMgr::processQueue(const F32 num_secs)
00618 {
00619 mImpl->processQueue(num_secs);
00620 }
00621
00622 BOOL LLAudioDecodeMgr::addDecodeRequest(const LLUUID &uuid)
00623 {
00624 if (gAudiop->hasDecodedFile(uuid))
00625 {
00626
00627 return TRUE;
00628 }
00629
00630 if (gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND))
00631 {
00632
00633 mImpl->mDecodeQueue.push(uuid);
00634 return TRUE;
00635 }
00636
00637 return FALSE;
00638 }
00639
00640