PageRenderTime 92ms CodeModel.GetById 18ms app.highlight 69ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llaudio/llaudiodecodemgr.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 689 lines | 501 code | 101 blank | 87 comment | 58 complexity | b657995c3a11760cddbeee33ed28d94e MD5 | raw file
  1/** 
  2 * @file llaudiodecodemgr.cpp
  3 *
  4 * $LicenseInfo:firstyear=2003&license=viewerlgpl$
  5 * Second Life Viewer Source Code
  6 * Copyright (C) 2010, Linden Research, Inc.
  7 * 
  8 * This library is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU Lesser General Public
 10 * License as published by the Free Software Foundation;
 11 * version 2.1 of the License only.
 12 * 
 13 * This library is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16 * Lesser General Public License for more details.
 17 * 
 18 * You should have received a copy of the GNU Lesser General Public
 19 * License along with this library; if not, write to the Free Software
 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 21 * 
 22 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 23 * $/LicenseInfo$
 24 */
 25
 26#include "linden_common.h"
 27
 28#include "llaudiodecodemgr.h"
 29
 30#include "llaudioengine.h"
 31#include "lllfsthread.h"
 32#include "llvfile.h"
 33#include "llstring.h"
 34#include "lldir.h"
 35#include "llendianswizzle.h"
 36#include "llassetstorage.h"
 37#include "llrefcount.h"
 38
 39#include "llvorbisencode.h"
 40
 41#include "vorbis/codec.h"
 42#include "vorbis/vorbisfile.h"
 43
 44extern LLAudioEngine *gAudiop;
 45
 46LLAudioDecodeMgr *gAudioDecodeMgrp = NULL;
 47
 48static const S32 WAV_HEADER_SIZE = 44;
 49
 50
 51//////////////////////////////////////////////////////////////////////////////
 52
 53
 54class LLVorbisDecodeState : public LLRefCount
 55{
 56public:
 57	class WriteResponder : public LLLFSThread::Responder
 58	{
 59	public:
 60		WriteResponder(LLVorbisDecodeState* decoder) : mDecoder(decoder) {}
 61		~WriteResponder() {}
 62		void completed(S32 bytes)
 63		{
 64			mDecoder->ioComplete(bytes);
 65		}
 66		LLPointer<LLVorbisDecodeState> mDecoder;
 67	};
 68	
 69	LLVorbisDecodeState(const LLUUID &uuid, const std::string &out_filename);
 70
 71	BOOL initDecode();
 72	BOOL decodeSection(); // Return TRUE if done.
 73	BOOL finishDecode();
 74
 75	void flushBadFile();
 76
 77	void ioComplete(S32 bytes)			{ mBytesRead = bytes; }
 78	BOOL isValid() const				{ return mValid; }
 79	BOOL isDone() const					{ return mDone; }
 80	const LLUUID &getUUID() const		{ return mUUID; }
 81
 82protected:
 83	virtual ~LLVorbisDecodeState();
 84
 85	BOOL mValid;
 86	BOOL mDone;
 87	LLAtomicS32 mBytesRead;
 88	LLUUID mUUID;
 89
 90	std::vector<U8> mWAVBuffer;
 91#if !defined(USE_WAV_VFILE)
 92	std::string mOutFilename;
 93	LLLFSThread::handle_t mFileHandle;
 94#endif
 95	
 96	LLVFile *mInFilep;
 97	OggVorbis_File mVF;
 98	S32 mCurrentSection;
 99};
100
101size_t vfs_read(void *ptr, size_t size, size_t nmemb, void *datasource)
102{
103	LLVFile *file = (LLVFile *)datasource;
104
105	if (file->read((U8*)ptr, (S32)(size * nmemb)))	/*Flawfinder: ignore*/
106	{
107		S32 read = file->getLastBytesRead();
108		return  read / size;	/*Flawfinder: ignore*/
109	}
110	else
111	{
112		return 0;
113	}
114}
115
116int vfs_seek(void *datasource, ogg_int64_t offset, int whence)
117{
118	LLVFile *file = (LLVFile *)datasource;
119
120	// vfs has 31-bit files
121	if (offset > S32_MAX)
122	{
123		return -1;
124	}
125
126	S32 origin;
127	switch (whence) {
128	case SEEK_SET:
129		origin = 0;
130		break;
131	case SEEK_END:
132		origin = file->getSize();
133		break;
134	case SEEK_CUR:
135		origin = -1;
136		break;
137	default:
138		llerrs << "Invalid whence argument to vfs_seek" << llendl;
139		return -1;
140	}
141
142	if (file->seek((S32)offset, origin))
143	{
144		return 0;
145	}
146	else
147	{
148		return -1;
149	}
150}
151
152int vfs_close (void *datasource)
153{
154	LLVFile *file = (LLVFile *)datasource;
155	delete file;
156	return 0;
157}
158
159long vfs_tell (void *datasource)
160{
161	LLVFile *file = (LLVFile *)datasource;
162	return file->tell();
163}
164
165LLVorbisDecodeState::LLVorbisDecodeState(const LLUUID &uuid, const std::string &out_filename)
166{
167	mDone = FALSE;
168	mValid = FALSE;
169	mBytesRead = -1;
170	mUUID = uuid;
171	mInFilep = NULL;
172	mCurrentSection = 0;
173#if !defined(USE_WAV_VFILE)
174	mOutFilename = out_filename;
175	mFileHandle = LLLFSThread::nullHandle();
176#endif
177	// No default value for mVF, it's an ogg structure?
178	// Hey, let's zero it anyway, for predictability.
179	memset(&mVF, 0, sizeof(mVF));
180}
181
182LLVorbisDecodeState::~LLVorbisDecodeState()
183{
184	if (!mDone)
185	{
186		delete mInFilep;
187		mInFilep = NULL;
188	}
189}
190
191
192BOOL LLVorbisDecodeState::initDecode()
193{
194	ov_callbacks vfs_callbacks;
195	vfs_callbacks.read_func = vfs_read;
196	vfs_callbacks.seek_func = vfs_seek;
197	vfs_callbacks.close_func = vfs_close;
198	vfs_callbacks.tell_func = vfs_tell;
199
200	//llinfos << "Initing decode from vfile: " << mUUID << llendl;
201
202	mInFilep = new LLVFile(gVFS, mUUID, LLAssetType::AT_SOUND);
203	if (!mInFilep || !mInFilep->getSize())
204	{
205		llwarns << "unable to open vorbis source vfile for reading" << llendl;
206		delete mInFilep;
207		mInFilep = NULL;
208		return FALSE;
209	}
210
211	int r = ov_open_callbacks(mInFilep, &mVF, NULL, 0, vfs_callbacks);
212	if(r < 0) 
213	{
214		llwarns << r << " Input to vorbis decode does not appear to be an Ogg bitstream: " << mUUID << llendl;
215		return(FALSE);
216	}
217	
218	S32 sample_count = ov_pcm_total(&mVF, -1);
219	size_t size_guess = (size_t)sample_count;
220	vorbis_info* vi = ov_info(&mVF, -1);
221	size_guess *= (vi? vi->channels : 1);
222	size_guess *= 2;
223	size_guess += 2048;
224	
225	bool abort_decode = false;
226	
227	if (vi)
228	{
229		if( vi->channels < 1 || vi->channels > LLVORBIS_CLIP_MAX_CHANNELS )
230		{
231			abort_decode = true;
232			llwarns << "Bad channel count: " << vi->channels << llendl;
233		}
234	}
235	else // !vi
236	{
237		abort_decode = true;
238		llwarns << "No default bitstream found" << llendl;	
239	}
240	
241	if( (size_t)sample_count > LLVORBIS_CLIP_REJECT_SAMPLES ||
242	    (size_t)sample_count <= 0)
243	{
244		abort_decode = true;
245		llwarns << "Illegal sample count: " << sample_count << llendl;
246	}
247	
248	if( size_guess > LLVORBIS_CLIP_REJECT_SIZE ||
249	    size_guess < 0)
250	{
251		abort_decode = true;
252		llwarns << "Illegal sample size: " << size_guess << llendl;
253	}
254	
255	if( abort_decode )
256	{
257		llwarns << "Canceling initDecode. Bad asset: " << mUUID << llendl;
258		vorbis_comment* comment = ov_comment(&mVF,-1);
259		if (comment && comment->vendor)
260		{
261			llwarns << "Bad asset encoded by: " << comment->vendor << llendl;
262		}
263		delete mInFilep;
264		mInFilep = NULL;
265		return FALSE;
266	}
267	
268	mWAVBuffer.reserve(size_guess);
269	mWAVBuffer.resize(WAV_HEADER_SIZE);
270
271	{
272		// write the .wav format header
273		//"RIFF"
274		mWAVBuffer[0] = 0x52;
275		mWAVBuffer[1] = 0x49;
276		mWAVBuffer[2] = 0x46;
277		mWAVBuffer[3] = 0x46;
278
279		// length = datalen + 36 (to be filled in later)
280		mWAVBuffer[4] = 0x00;
281		mWAVBuffer[5] = 0x00;
282		mWAVBuffer[6] = 0x00;
283		mWAVBuffer[7] = 0x00;
284
285		//"WAVE"
286		mWAVBuffer[8] = 0x57;
287		mWAVBuffer[9] = 0x41;
288		mWAVBuffer[10] = 0x56;
289		mWAVBuffer[11] = 0x45;
290
291		// "fmt "
292		mWAVBuffer[12] = 0x66;
293		mWAVBuffer[13] = 0x6D;
294		mWAVBuffer[14] = 0x74;
295		mWAVBuffer[15] = 0x20;
296
297		// chunk size = 16
298		mWAVBuffer[16] = 0x10;
299		mWAVBuffer[17] = 0x00;
300		mWAVBuffer[18] = 0x00;
301		mWAVBuffer[19] = 0x00;
302
303		// format (1 = PCM)
304		mWAVBuffer[20] = 0x01;
305		mWAVBuffer[21] = 0x00;
306
307		// number of channels
308		mWAVBuffer[22] = 0x01;
309		mWAVBuffer[23] = 0x00;
310
311		// samples per second
312		mWAVBuffer[24] = 0x44;
313		mWAVBuffer[25] = 0xAC;
314		mWAVBuffer[26] = 0x00;
315		mWAVBuffer[27] = 0x00;
316
317		// average bytes per second
318		mWAVBuffer[28] = 0x88;
319		mWAVBuffer[29] = 0x58;
320		mWAVBuffer[30] = 0x01;
321		mWAVBuffer[31] = 0x00;
322
323		// bytes to output at a single time
324		mWAVBuffer[32] = 0x02;
325		mWAVBuffer[33] = 0x00;
326		 
327		// 16 bits per sample
328		mWAVBuffer[34] = 0x10;
329		mWAVBuffer[35] = 0x00;
330
331		// "data"
332		mWAVBuffer[36] = 0x64;
333		mWAVBuffer[37] = 0x61;
334		mWAVBuffer[38] = 0x74;
335		mWAVBuffer[39] = 0x61;
336
337		// these are the length of the data chunk, to be filled in later
338		mWAVBuffer[40] = 0x00;
339		mWAVBuffer[41] = 0x00;
340		mWAVBuffer[42] = 0x00;
341		mWAVBuffer[43] = 0x00;
342	}
343	
344	//{
345		//char **ptr=ov_comment(&mVF,-1)->user_comments;
346//		vorbis_info *vi=ov_info(&vf,-1);
347		//while(*ptr){
348		//	fprintf(stderr,"%s\n",*ptr);
349		//	++ptr;
350		//}
351//    fprintf(stderr,"\nBitstream is %d channel, %ldHz\n",vi->channels,vi->rate);
352//    fprintf(stderr,"\nDecoded length: %ld samples\n", (long)ov_pcm_total(&vf,-1));
353//    fprintf(stderr,"Encoded by: %s\n\n",ov_comment(&vf,-1)->vendor);
354	//}
355	return TRUE;
356}
357
358BOOL LLVorbisDecodeState::decodeSection()
359{
360	if (!mInFilep)
361	{
362		llwarns << "No VFS file to decode in vorbis!" << llendl;
363		return TRUE;
364	}
365	if (mDone)
366	{
367// 		llwarns << "Already done with decode, aborting!" << llendl;
368		return TRUE;
369	}
370	char pcmout[4096];	/*Flawfinder: ignore*/
371
372	BOOL eof = FALSE;
373	long ret=ov_read(&mVF, pcmout, sizeof(pcmout), 0, 2, 1, &mCurrentSection);
374	if (ret == 0)
375	{
376		/* EOF */
377		eof = TRUE;
378		mDone = TRUE;
379		mValid = TRUE;
380//			llinfos << "Vorbis EOF" << llendl;
381	}
382	else if (ret < 0)
383	{
384		/* error in the stream.  Not a problem, just reporting it in
385		   case we (the app) cares.  In this case, we don't. */
386
387		llwarns << "BAD vorbis decode in decodeSection." << llendl;
388
389		mValid = FALSE;
390		mDone = TRUE;
391		// We're done, return TRUE.
392		return TRUE;
393	}
394	else
395	{
396//			llinfos << "Vorbis read " << ret << "bytes" << llendl;
397		/* we don't bother dealing with sample rate changes, etc, but.
398		   you'll have to*/
399		std::copy(pcmout, pcmout+ret, std::back_inserter(mWAVBuffer));
400	}
401	return eof;
402}
403
404BOOL LLVorbisDecodeState::finishDecode()
405{
406	if (!isValid())
407	{
408		llwarns << "Bogus vorbis decode state for " << getUUID() << ", aborting!" << llendl;
409		return TRUE; // We've finished
410	}
411
412#if !defined(USE_WAV_VFILE)	
413	if (mFileHandle == LLLFSThread::nullHandle())
414#endif
415	{
416		ov_clear(&mVF);
417  
418		// write "data" chunk length, in little-endian format
419		S32 data_length = mWAVBuffer.size() - WAV_HEADER_SIZE;
420		mWAVBuffer[40] = (data_length) & 0x000000FF;
421		mWAVBuffer[41] = (data_length >> 8) & 0x000000FF;
422		mWAVBuffer[42] = (data_length >> 16) & 0x000000FF;
423		mWAVBuffer[43] = (data_length >> 24) & 0x000000FF;
424		// write overall "RIFF" length, in little-endian format
425		data_length += 36;
426		mWAVBuffer[4] = (data_length) & 0x000000FF;
427		mWAVBuffer[5] = (data_length >> 8) & 0x000000FF;
428		mWAVBuffer[6] = (data_length >> 16) & 0x000000FF;
429		mWAVBuffer[7] = (data_length >> 24) & 0x000000FF;
430
431		//
432		// FUDGECAKES!!! Vorbis encode/decode messes up loop point transitions (pop)
433		// do a cheap-and-cheesy crossfade 
434		//
435		{
436			S16 *samplep;
437			S32 i;
438			S32 fade_length;
439			char pcmout[4096];		/*Flawfinder: ignore*/ 	
440
441			fade_length = llmin((S32)128,(S32)(data_length-36)/8);			
442			if((S32)mWAVBuffer.size() >= (WAV_HEADER_SIZE + 2* fade_length))
443			{
444				memcpy(pcmout, &mWAVBuffer[WAV_HEADER_SIZE], (2 * fade_length));	/*Flawfinder: ignore*/
445			}
446			llendianswizzle(&pcmout, 2, fade_length);
447	
448			samplep = (S16 *)pcmout;
449			for (i = 0 ;i < fade_length; i++)
450			{
451				*samplep = llfloor((F32)*samplep * ((F32)i/(F32)fade_length));
452				samplep++;
453			}
454
455			llendianswizzle(&pcmout, 2, fade_length);			
456			if((WAV_HEADER_SIZE+(2 * fade_length)) < (S32)mWAVBuffer.size())
457			{
458				memcpy(&mWAVBuffer[WAV_HEADER_SIZE], pcmout, (2 * fade_length));	/*Flawfinder: ignore*/
459			}
460			S32 near_end = mWAVBuffer.size() - (2 * fade_length);
461			if ((S32)mWAVBuffer.size() >= ( near_end + 2* fade_length))
462			{
463				memcpy(pcmout, &mWAVBuffer[near_end], (2 * fade_length));	/*Flawfinder: ignore*/
464			}
465			llendianswizzle(&pcmout, 2, fade_length);
466
467			samplep = (S16 *)pcmout;
468			for (i = fade_length-1 ; i >=  0; i--)
469			{
470				*samplep = llfloor((F32)*samplep * ((F32)i/(F32)fade_length));
471				samplep++;
472			}
473	
474			llendianswizzle(&pcmout, 2, fade_length);			
475			if (near_end + (2 * fade_length) < (S32)mWAVBuffer.size())
476			{
477				memcpy(&mWAVBuffer[near_end], pcmout, (2 * fade_length));/*Flawfinder: ignore*/
478			}
479		}
480
481		if (36 == data_length)
482		{
483			llwarns << "BAD Vorbis decode in finishDecode!" << llendl;
484			mValid = FALSE;
485			return TRUE; // we've finished
486		}
487#if !defined(USE_WAV_VFILE)
488		mBytesRead = -1;
489		mFileHandle = LLLFSThread::sLocal->write(mOutFilename, &mWAVBuffer[0], 0, mWAVBuffer.size(),
490							 new WriteResponder(this));
491#endif
492	}
493
494	if (mFileHandle != LLLFSThread::nullHandle())
495	{
496		if (mBytesRead >= 0)
497		{
498			if (mBytesRead == 0)
499			{
500				llwarns << "Unable to write file in LLVorbisDecodeState::finishDecode" << llendl;
501				mValid = FALSE;
502				return TRUE; // we've finished
503			}
504		}
505		else
506		{
507			return FALSE; // not done
508		}
509	}
510	
511	mDone = TRUE;
512
513#if defined(USE_WAV_VFILE)
514	// write the data.
515	LLVFile output(gVFS, mUUID, LLAssetType::AT_SOUND_WAV);
516	output.write(&mWAVBuffer[0], mWAVBuffer.size());
517#endif
518	//llinfos << "Finished decode for " << getUUID() << llendl;
519
520	return TRUE;
521}
522
523void LLVorbisDecodeState::flushBadFile()
524{
525	if (mInFilep)
526	{
527		llwarns << "Flushing bad vorbis file from VFS for " << mUUID << llendl;
528		mInFilep->remove();
529	}
530}
531
532//////////////////////////////////////////////////////////////////////////////
533
534class LLAudioDecodeMgr::Impl
535{
536	friend class LLAudioDecodeMgr;
537public:
538	Impl() {};
539	~Impl() {};
540
541	void processQueue(const F32 num_secs = 0.005);
542
543protected:
544	LLLinkedQueue<LLUUID> mDecodeQueue;
545	LLPointer<LLVorbisDecodeState> mCurrentDecodep;
546};
547
548
549void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs)
550{
551	LLUUID uuid;
552
553	LLTimer decode_timer;
554
555	BOOL done = FALSE;
556	while (!done)
557	{
558		if (mCurrentDecodep)
559		{
560			BOOL res;
561
562			// Decode in a loop until we're done or have run out of time.
563			while(!(res = mCurrentDecodep->decodeSection()) && (decode_timer.getElapsedTimeF32() < num_secs))
564			{
565				// decodeSection does all of the work above
566			}
567
568			if (mCurrentDecodep->isDone() && !mCurrentDecodep->isValid())
569			{
570				// We had an error when decoding, abort.
571				llwarns << mCurrentDecodep->getUUID() << " has invalid vorbis data, aborting decode" << llendl;
572				mCurrentDecodep->flushBadFile();
573				LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID());
574				adp->setHasValidData(FALSE);
575				mCurrentDecodep = NULL;
576				done = TRUE;
577			}
578
579			if (!res)
580			{
581				// We've used up out time slice, bail...
582				done = TRUE;
583			}
584			else if (mCurrentDecodep)
585			{
586				if (mCurrentDecodep->finishDecode())
587				{
588					// We finished!
589					if (mCurrentDecodep->isValid() && mCurrentDecodep->isDone())
590					{
591						LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID());
592						adp->setHasDecodedData(TRUE);
593						adp->setHasValidData(TRUE);
594
595						// At this point, we could see if anyone needs this sound immediately, but
596						// I'm not sure that there's a reason to - we need to poll all of the playing
597						// sounds anyway.
598						//llinfos << "Finished the vorbis decode, now what?" << llendl;
599					}
600					else
601					{
602						llinfos << "Vorbis decode failed!!!" << llendl;
603					}
604					mCurrentDecodep = NULL;
605				}
606				done = TRUE; // done for now
607			}
608		}
609
610		if (!done)
611		{
612			if (!mDecodeQueue.getLength())
613			{
614				// Nothing else on the queue.
615				done = TRUE;
616			}
617			else
618			{
619				LLUUID uuid;
620				mDecodeQueue.pop(uuid);
621				if (gAudiop->hasDecodedFile(uuid))
622				{
623					// This file has already been decoded, don't decode it again.
624					continue;
625				}
626
627				lldebugs << "Decoding " << uuid << " from audio queue!" << llendl;
628
629				std::string uuid_str;
630				std::string d_path;
631
632				LLTimer timer;
633				timer.reset();
634
635				uuid.toString(uuid_str);
636				d_path = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str) + ".dsf";
637
638				mCurrentDecodep = new LLVorbisDecodeState(uuid, d_path);
639				if (!mCurrentDecodep->initDecode())
640				{
641					mCurrentDecodep = NULL;
642				}
643			}
644		}
645	}
646}
647
648//////////////////////////////////////////////////////////////////////////////
649
650LLAudioDecodeMgr::LLAudioDecodeMgr()
651{
652	mImpl = new Impl;
653}
654
655LLAudioDecodeMgr::~LLAudioDecodeMgr()
656{
657	delete mImpl;
658}
659
660void LLAudioDecodeMgr::processQueue(const F32 num_secs)
661{
662	mImpl->processQueue(num_secs);
663}
664
665BOOL LLAudioDecodeMgr::addDecodeRequest(const LLUUID &uuid)
666{
667	if (gAudiop->hasDecodedFile(uuid))
668	{
669		// Already have a decoded version, don't need to decode it.
670		return TRUE;
671	}
672
673	if (gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND))
674	{
675		// Just put it on the decode queue.
676		mImpl->mDecodeQueue.push(uuid);
677		return TRUE;
678	}
679
680	return FALSE;
681}
682
683#if LL_DARWIN || LL_LINUX
684// HACK: to fool the compiler into not emitting unused warnings.
685namespace {
686	const ov_callbacks callback_array[4] = {OV_CALLBACKS_DEFAULT, OV_CALLBACKS_NOCLOSE, OV_CALLBACKS_STREAMONLY, 
687		OV_CALLBACKS_STREAMONLY_NOCLOSE};
688}
689#endif