//----------------------------------------------------------------------------- // Torque Game Engine // Copyright (C) GarageGames.com, Inc. //----------------------------------------------------------------------------- #ifndef _THEORATEXTURE_H_ #define _THEORATEXTURE_H_ #ifndef _CONSOLE_H_ #include "console/console.h" #endif #ifndef _GTEXMANAGER_H_ #include "dgl/gTexManager.h" #endif #ifndef _GBITMAP_H_ #include "dgl/gBitmap.h" #endif #ifndef _O_THEORA_H_ #include "theora/theora.h" #endif #ifndef _vorbis_codec_h_ #include "vorbis/codec.h" #endif #ifndef _PLATFORMTHREAD_H_ #include "platform/platformThread.h" #endif #ifndef _OGGMIXEDSTREAMSOURCE_H_ #include "audio/oggMixedStreamSource.h" #endif #ifndef _VORBISSTREAMSOURCE_H_ #include "audio/vorbisStreamSource.h" #endif /// TheoraTexture decodes Ogg Theora files, and their audio. /// /// TheoraTexture objects can be used similarly to TextureObjects. Just /// set the video, call play(), and then refresh every frame to get the /// latest video. Audio happens automagically. /// /// @note Uses Theora and ogg libraries which are Copyright (C) Xiph.org Foundation class TheoraTexture { private: Thread* mPlayThread; /// Ogg and codec state for demux/decode. ogg_sync_state mOggSyncState; ogg_page mOggPage; ogg_stream_state mOggTheoraStream; ogg_stream_state mOggVorbisStream; theora_info mTheoraInfo; theora_comment mTheoraComment; theora_state mTheoraState; vorbis_info mVorbisInfo; vorbis_comment mVorbisComment; vorbis_dsp_state mVorbisDspState; vorbis_block mVorbisBlock; /// File handle for the theora file. Stream* mTheoraFile; volatile bool mReady; volatile bool mPlaying; volatile bool mHasVorbis; OggMixedStreamSource* mVorbisBuffer; AUDIOHANDLE mVorbisHandle; volatile F32 mCurrentTime; volatile U32 mStartTick; void init(); bool parseHeaders(); bool createVideoBuffers(); bool createAudioBuffers(Audio::Description* desc); /// We precalculate adjusted YUV values for faster RGB conversion. This /// function is responsible for making sure they're present and valid. void generateLookupTables(); void destroyTexture(bool restartOgg = false); void drawFrame(); bool readyVideo(const F64 lastFrame, F64 &vBuffTime); bool readyAudio(); bool demandOggPage(); S32 bufferOggPage(); S32 queueOggPage(ogg_page *page); F64 getTheoraTime(); /// Background playback thread. static void playThread( void *udata ); bool playLoop(); /// Magical Trevor is responsible for tracking elapsed time based on /// the currently playing buffer. /// /// @note He's ever so clear. /// /// Basically it takes periodic updates of the currently playing buffer /// and figures the time between that buffer and the last tracked /// buffer, and tells you how much time passed between those two events. /// (time == duration of audio) struct MagicalTrevor { struct BufInf { BufInf(); ALuint id; F64 time; BufInf *next; }; FreeListChunker mBuffPool; BufInf *mBufListHead; ALint mLastBufferID; void *mMutex; MagicalTrevor(); ~MagicalTrevor(); /// Given current buffer, infer elapsed time since last call. const F64 advanceTime(const ALuint buffId); /// Note a buffer, and how much time it contains. void postBuffer(const ALuint buffId, const F64 duration); /// How many items in our list? Used for debugging. const U32 getListSize() const; /// Clear everything out in preparation for the next playback. void reset(); }; MagicalTrevor mMagicalTrevor; public: TheoraTexture(); TheoraTexture(const char *filename, bool play = false, Audio::Description* desc = NULL); ~TheoraTexture(); operator TextureObject*() { return (TextureObject*)*mTextureHandle; } bool setFile(const char*, bool play = false, bool restart = false, Audio::Description* desc = NULL); const bool isPlaying() const { return mPlaying; } const bool isReady() const { return mReady; } bool play(); void stop(); bool pause(); /// Update the GL texture from the bitmap the background thread writes to. void refresh(); U32 getGLName(); const F64 getCurrentTime() { return getTheoraTime(); } TextureHandle* mTextureHandle; }; #endif