00001 /* 00002 Copyright (c) 2010, The Barbarian Group 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that 00006 the following conditions are met: 00007 00008 * Redistributions of source code must retain the above copyright notice, this list of conditions and 00009 the following disclaimer. 00010 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and 00011 the following disclaimer in the documentation and/or other materials provided with the distribution. 00012 00013 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 00014 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00015 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00016 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00017 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00018 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00019 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00020 POSSIBILITY OF SUCH DAMAGE. 00021 */ 00022 00023 #pragma once 00024 00025 // None of this works in 64 bit on the mac or Windows. We'll need to move to QTKit on the mac. 00026 #if ! defined( __LP64__ ) 00027 00028 #include "cinder/Cinder.h" 00029 #include "cinder/gl/gl.h" 00030 #include "cinder/Surface.h" 00031 #include "cinder/gl/Texture.h" 00032 #include "cinder/Display.h" 00033 #include "cinder/Url.h" 00034 #include "cinder/DataSource.h" 00035 #include "cinder/Thread.h" 00036 00037 #include <string> 00038 00039 #if defined( CINDER_MAC ) 00040 #include <QuickTime/QuickTime.h> 00041 #if defined( __OBJC__ ) 00042 @class QTMovie; 00043 #else 00044 class QTMovie; 00045 #endif 00046 #endif 00047 00048 00049 // these are forward-declared to avoid bringing all of QuickTime into the global namespace on Windows 00050 #if defined( CINDER_MSW ) 00051 typedef struct MovieType** Movie; 00052 typedef struct OpaqueQTVisualContext* QTVisualContextRef; 00053 typedef long TimeValue; 00054 typedef struct QTAudioFrequencyLevels QTAudioFrequencyLevels; 00055 typedef unsigned long FourCharCode; 00056 typedef struct __CVBuffer* CVBufferRef; 00057 typedef CVBufferRef CVImageBufferRef; 00058 #endif 00059 00060 namespace cinder { namespace qtime { 00061 00062 class MovieBase { 00063 public: 00064 virtual ~MovieBase() {} 00065 00067 bool checkPlayable(); 00068 00070 int32_t getWidth() const { return getObj()->mWidth; } 00072 int32_t getHeight() const { return getObj()->mHeight; } 00074 Vec2i getSize() const { return Vec2i( getWidth(), getHeight() ); } 00076 float getAspectRatio() const { return getObj()->mWidth / (float)getObj()->mHeight; } 00078 Area getBounds() const { return Area( 0, 0, getWidth(), getHeight() ); } 00080 float getPixelAspectRatio() const; 00082 float getDuration() const { return getObj()->mDuration; } 00084 float getFramerate() const; 00086 int32_t getNumFrames() const; 00088 bool hasAlpha() const; 00089 00091 bool hasVisuals() const; 00093 bool hasAudio() const; 00094 00096 bool checkNewFrame(); 00097 00099 float getCurrentTime() const; 00101 void seekToTime( float seconds ); 00103 void seekToFrame( int frame ); 00105 void seekToStart(); 00107 void seekToEnd(); 00109 void setActiveSegment( float startTime, float duration ); 00111 void resetActiveSegment(); 00112 00114 void setLoop( bool loop = true, bool palindrome = false ); 00116 void stepForward(); 00118 void stepBackward(); 00120 void setRate( float rate ); 00121 00123 void setVolume( float volume ); 00125 float getVolume() const; 00126 00128 void setupMonoFft( uint32_t numBands ); 00130 void setupStereoFft( uint32_t numBands ); 00132 void setupMultiChannelFft( uint32_t numBands ); 00133 00134 float* getFftData() const; 00135 uint32_t getNumFftBands() const; 00136 uint32_t getNumFftChannels() const; 00137 00139 bool isPlaying() const; 00141 bool isDone() const; 00143 void play(); 00145 void stop(); 00146 00148 void setNewFrameCallback( void(*aNewFrameCallback)( long, void * ), void *aNewFrameCallbackRefcon ); 00149 00151 ::Movie getMovieHandle() const { return getObj()->mMovie; } 00152 00153 protected: 00154 MovieBase() {} 00155 void init(); 00156 void updateFrame(); 00157 void updateLoadState(); 00158 00159 void setupFft( FourCharCode code, uint32_t bandNum, uint8_t channelNum ); 00160 00161 static int32_t countFrames( ::Movie theMovie ); 00162 TimeValue getStartTimeOfFirstSample() const; 00163 00164 protected: 00165 void initFromPath( const fs::path &filePath ); 00166 void initFromLoader( const class MovieLoader &loader ); 00167 void initFromMemory( const void *data, size_t dataSize, const std::string &fileNameHint, const std::string &mimeTypeHint ); 00168 void initFromDataSource( DataSourceRef dataSource, const std::string &mimeTypeHint ); 00169 00170 struct Obj { 00171 Obj(); 00172 virtual ~Obj(); 00173 00174 void prepareForDestruction(); 00175 00176 void lock() { mMutex.lock(); } 00177 void unlock() { mMutex.unlock(); } 00178 00179 // because the MovieBase* might change over time, but the MovieBase::Obj* will not, we need our callbacks to take an Obj* as a refcon 00180 // which in turn means this functionality must be in the Obj, not the MovieBase 00181 virtual void releaseFrame() = 0; 00182 virtual void newFrame( CVImageBufferRef cvImage ) = 0; 00183 00184 int32_t mWidth, mHeight; 00185 int32_t mFrameCount; 00186 float mDuration; 00187 bool mLoaded, mPlayable; 00188 bool mPlayingForward, mLoop, mPalindrome; 00189 00190 QTAudioFrequencyLevels *mFFTData; 00191 FourCharCode mFFTFourCharCode; 00192 uint32_t mFFTNumBandLevels; 00193 uint32_t mFFTNumChannels; 00194 QTVisualContextRef mVisualContext; 00195 ::Movie mMovie; 00196 00197 void (*mNewFrameCallback)(long timeValue, void *refcon); 00198 void *mNewFrameCallbackRefcon; 00199 00200 std::mutex mMutex; 00201 DataSourceRef mDataSource; // sometimes used to retain a reference to a data source so that it doesn't go away before we do 00202 }; 00203 00204 virtual Obj* getObj() const = 0; 00205 }; 00206 00207 class MovieSurface : public MovieBase { 00208 public: 00209 MovieSurface() : MovieBase() {} 00210 MovieSurface( const fs::path &path ); 00211 MovieSurface( const class MovieLoader &loader ); 00213 00214 MovieSurface( const void *data, size_t dataSize, const std::string &fileNameHint, const std::string &mimeTypeHint = "" ); 00215 MovieSurface( DataSourceRef dataSource, const std::string mimeTypeHint = "" ); 00216 00218 Surface getSurface(); 00219 00220 protected: 00221 void allocateVisualContext(); 00222 00223 struct Obj : public MovieBase::Obj { 00224 virtual ~Obj(); 00225 00226 virtual void releaseFrame(); 00227 virtual void newFrame( CVImageBufferRef cvImage ); 00228 00229 Surface mSurface; 00230 }; 00231 00232 std::shared_ptr<Obj> mObj; 00233 virtual MovieBase::Obj* getObj() const { return mObj.get(); } 00234 00235 public: 00237 00238 typedef std::shared_ptr<Obj> MovieSurface::*unspecified_bool_type; 00239 operator unspecified_bool_type() const { return ( mObj.get() == 0 ) ? 0 : &MovieSurface::mObj; } 00240 void reset() { mObj.reset(); } 00242 }; 00243 00248 class MovieGl : public MovieBase { 00249 public: 00250 MovieGl() : MovieBase() {} 00251 MovieGl( const fs::path &path ); 00252 MovieGl( const class MovieLoader &loader ); 00254 00255 MovieGl( const void *data, size_t dataSize, const std::string &fileNameHint, const std::string &mimeTypeHint = "" ); 00256 MovieGl( DataSourceRef dataSource, const std::string mimeTypeHint = "" ); 00257 00259 const gl::Texture getTexture(); 00260 00261 protected: 00262 void allocateVisualContext(); 00263 00264 struct Obj : public MovieBase::Obj { 00265 Obj(); 00266 ~Obj(); 00267 00268 virtual void releaseFrame(); 00269 virtual void newFrame( CVImageBufferRef cvImage ); 00270 00271 gl::Texture mTexture; 00272 #if defined( CINDER_MSW ) 00273 gl::TextureCache mTextureCache; 00274 #endif 00275 }; 00276 00277 std::shared_ptr<Obj> mObj; 00278 virtual MovieBase::Obj* getObj() const { return mObj.get(); } 00279 00280 public: 00282 00283 typedef std::shared_ptr<Obj> MovieGl::*unspecified_bool_type; 00284 operator unspecified_bool_type() const { return ( mObj.get() == 0 ) ? 0 : &MovieGl::mObj; } 00285 void reset() { mObj.reset(); } 00287 }; 00288 00289 class MovieLoader { 00290 public: 00291 MovieLoader() {} 00292 MovieLoader( const Url &url ); 00293 00295 bool checkLoaded() const; 00297 bool checkPlayable() const; 00299 bool checkPlaythroughOk() const; 00300 00302 void waitForLoaded() const; 00304 void waitForPlayable() const; 00306 void waitForPlaythroughOk() const; 00307 00309 const Url& getUrl() const { return mObj->mUrl; } 00310 00312 ::Movie getMovieHandle() const { return mObj->mMovie; } 00313 00315 ::Movie transferMovieHandle() const { mObj->mOwnsMovie = false; return mObj->mMovie; } 00316 00317 protected: 00318 void updateLoadState() const; 00319 00320 struct Obj { 00321 Obj( const Url &url ); 00322 ~Obj(); 00323 00324 mutable bool mOwnsMovie; 00325 ::Movie mMovie; 00326 Url mUrl; 00327 mutable bool mLoaded, mPlayable, mPlaythroughOK; 00328 }; 00329 00330 std::shared_ptr<Obj> mObj; 00331 00332 public: 00334 00335 typedef std::shared_ptr<Obj> MovieLoader::*unspecified_bool_type; 00336 operator unspecified_bool_type() const { return ( mObj.get() == 0 ) ? 0 : &MovieLoader::mObj; } 00337 void reset() { mObj.reset(); } 00339 }; 00340 00341 inline int32_t floatToFixed( float fl ) { return ((int32_t)((float)(fl) * ((int32_t) 0x00010000L))); } 00342 00344 void startQuickTime(); 00346 extern int32_t getQuickTimeVersion(); 00348 extern std::string getQuickTimeVersionString(); 00349 00351 extern void quickTimeTask(); 00352 00353 class QuickTimeExc : public std::exception { 00354 }; 00355 00356 class QuickTimePathInvalidExc : public QuickTimeExc { 00357 }; 00358 00359 class QuickTimeFileInvalidExc : public QuickTimeExc { 00360 }; 00361 00362 class QuickTimeExcUrlInvalid : public QuickTimeExc { 00363 }; 00364 00365 class QuickTimeErrorLoadingExc : public QuickTimeExc { 00366 }; 00367 00368 class QuickTimeExcFft : public QuickTimeExc { 00369 }; 00370 00371 } /* namespace qtime */ } /* namespace cinder */ 00372 #endif // ! defined( __LP64__ )