QuickTime.h
Go to the documentation of this file.
1 /*
2  Copyright (c) 2010, The Barbarian Group
3  All rights reserved.
4 
5  Redistribution and use in source and binary forms, with or without modification, are permitted provided that
6  the following conditions are met:
7 
8  * Redistributions of source code must retain the above copyright notice, this list of conditions and
9  the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
11  the following disclaimer in the documentation and/or other materials provided with the distribution.
12 
13  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
14  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
15  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
16  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
17  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
18  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
19  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
20  POSSIBILITY OF SUCH DAMAGE.
21 */
22 
23 #pragma once
24 
25 // None of this works in 64 bit on the mac or Windows. We'll need to move to QTKit on the mac.
26 #if ! defined( __LP64__ )
27 
28 #include "cinder/Cinder.h"
29 #include "cinder/gl/gl.h"
30 #include "cinder/Surface.h"
31 #include "cinder/gl/Texture.h"
32 #include "cinder/Display.h"
33 #include "cinder/Url.h"
34 #include "cinder/DataSource.h"
35 #include "cinder/Thread.h"
36 
37 #include <string>
38 
39 #if defined( CINDER_MAC )
40  #include <QuickTime/QuickTime.h>
41  #if defined( __OBJC__ )
42  @class QTMovie;
43  #else
44  class QTMovie;
45  #endif
46 #endif
47 
48 
49 // these are forward-declared to avoid bringing all of QuickTime into the global namespace on Windows
50 #if defined( CINDER_MSW )
51  typedef struct MovieType** Movie;
52  typedef struct OpaqueQTVisualContext* QTVisualContextRef;
53  typedef long TimeValue;
55  typedef unsigned long FourCharCode;
56  typedef struct __CVBuffer* CVBufferRef;
58 #endif
59 
60 namespace cinder { namespace qtime {
61 
62 class MovieLoader;
63 typedef std::shared_ptr<MovieLoader> MovieLoaderRef;
64 
65 class MovieBase {
66  public:
67  virtual ~MovieBase() {}
68 
70  bool checkPlayable();
71 
73  int32_t getWidth() const { return getObj()->mWidth; }
75  int32_t getHeight() const { return getObj()->mHeight; }
77  Vec2i getSize() const { return Vec2i( getWidth(), getHeight() ); }
79  float getAspectRatio() const { return getObj()->mWidth / (float)getObj()->mHeight; }
81  Area getBounds() const { return Area( 0, 0, getWidth(), getHeight() ); }
83  float getPixelAspectRatio() const;
85  float getDuration() const { return getObj()->mDuration; }
87  float getFramerate() const;
89  int32_t getNumFrames() const;
91  bool hasAlpha() const;
92 
94  bool hasVisuals() const;
96  bool hasAudio() const;
97 
99  bool checkNewFrame();
100 
102  float getCurrentTime() const;
104  void seekToTime( float seconds );
106  void seekToFrame( int frame );
108  void seekToStart();
110  void seekToEnd();
112  void setActiveSegment( float startTime, float duration );
114  void resetActiveSegment();
115 
117  void setLoop( bool loop = true, bool palindrome = false );
119  void stepForward();
121  void stepBackward();
123  void setRate( float rate );
124 
126  void setVolume( float volume );
128  float getVolume() const;
129 
131  void setupMonoFft( uint32_t numBands );
133  void setupStereoFft( uint32_t numBands );
135  void setupMultiChannelFft( uint32_t numBands );
136 
137  float* getFftData() const;
138  uint32_t getNumFftBands() const;
139  uint32_t getNumFftChannels() const;
140 
142  bool isPlaying() const;
144  bool isDone() const;
146  void play();
148  void stop();
149 
151  void setNewFrameCallback( void(*aNewFrameCallback)( long, void * ), void *aNewFrameCallbackRefcon );
152 
154  ::Movie getMovieHandle() const { return getObj()->mMovie; }
155 
156  protected:
158  void init();
159  void updateFrame();
160  void updateLoadState();
161 
162  void setupFft( FourCharCode code, uint32_t bandNum, uint8_t channelNum );
163 
164  static int32_t countFrames( ::Movie theMovie );
166 
167  protected:
168  void initFromPath( const fs::path &filePath );
169  void initFromLoader( const class MovieLoader &loader );
170  void initFromMemory( const void *data, size_t dataSize, const std::string &fileNameHint, const std::string &mimeTypeHint );
171  void initFromDataSource( DataSourceRef dataSource, const std::string &mimeTypeHint );
172 
173  struct Obj {
174  Obj();
175  virtual ~Obj();
176 
177  void prepareForDestruction();
178 
179  void lock() { mMutex.lock(); }
180  void unlock() { mMutex.unlock(); }
181 
182  // because the MovieBase* might change over time, but the MovieBase::Obj* will not, we need our callbacks to take an Obj* as a refcon
183  // which in turn means this functionality must be in the Obj, not the MovieBase
184  virtual void releaseFrame() = 0;
185  virtual void newFrame( CVImageBufferRef cvImage ) = 0;
186 
187  int32_t mWidth, mHeight;
188  int32_t mFrameCount;
189  float mDuration;
192 
196  uint32_t mFFTNumChannels;
199 
200  void (*mNewFrameCallback)(long timeValue, void *refcon);
202 
203  std::mutex mMutex;
204  DataSourceRef mDataSource; // sometimes used to retain a reference to a data source so that it doesn't go away before we do
205  };
206 
207  virtual Obj* getObj() const = 0;
208 };
209 
210 class MovieSurface;
211 typedef std::shared_ptr<MovieSurface> MovieSurfaceRef;
212 
213 class MovieSurface : public MovieBase {
214  public:
215  MovieSurface() : MovieBase() {}
216  MovieSurface( const fs::path &path );
217  MovieSurface( const class MovieLoader &loader );
219 
220  MovieSurface( const void *data, size_t dataSize, const std::string &fileNameHint, const std::string &mimeTypeHint = "" );
221  MovieSurface( DataSourceRef dataSource, const std::string mimeTypeHint = "" );
222 
223  static MovieSurfaceRef create( const fs::path &path ) { return std::shared_ptr<MovieSurface>( new MovieSurface( path ) ); }
224  static MovieSurfaceRef create( const MovieLoaderRef &loader );
225  static MovieSurfaceRef create( const void *data, size_t dataSize, const std::string &fileNameHint, const std::string &mimeTypeHint = "" )
226  { return std::shared_ptr<MovieSurface>( new MovieSurface( data, dataSize, fileNameHint, mimeTypeHint ) ); }
227  static MovieSurfaceRef create( DataSourceRef dataSource, const std::string mimeTypeHint = "" )
228  { return std::shared_ptr<MovieSurface>( new MovieSurface( dataSource, mimeTypeHint ) ); }
229 
231  Surface getSurface();
232 
233  protected:
234  void allocateVisualContext();
235 
236  struct Obj : public MovieBase::Obj {
237  virtual ~Obj();
238 
239  virtual void releaseFrame();
240  virtual void newFrame( CVImageBufferRef cvImage );
241 
242  Surface mSurface;
243  };
244 
245  std::shared_ptr<Obj> mObj;
246  virtual MovieBase::Obj* getObj() const { return mObj.get(); }
247 
248  public:
250 
251  typedef std::shared_ptr<Obj> MovieSurface::*unspecified_bool_type;
252  operator unspecified_bool_type() const { return ( mObj.get() == 0 ) ? 0 : &MovieSurface::mObj; }
253  void reset() { mObj.reset(); }
255 };
256 
257 class MovieGl;
258 typedef std::shared_ptr<MovieGl> MovieGlRef;
263 class MovieGl : public MovieBase {
264  public:
265  MovieGl() : MovieBase() {}
266  MovieGl( const fs::path &path );
267  MovieGl( const class MovieLoader &loader );
269 
270  MovieGl( const void *data, size_t dataSize, const std::string &fileNameHint, const std::string &mimeTypeHint = "" );
271  MovieGl( DataSourceRef dataSource, const std::string mimeTypeHint = "" );
272 
273  static MovieGlRef create( const fs::path &path ) { return std::shared_ptr<MovieGl>( new MovieGl( path ) ); }
274  static MovieGlRef create( const MovieLoaderRef &loader );
275  static MovieGlRef create( const void *data, size_t dataSize, const std::string &fileNameHint, const std::string &mimeTypeHint = "" )
276  { return std::shared_ptr<MovieGl>( new MovieGl( data, dataSize, fileNameHint, mimeTypeHint ) ); }
277  static MovieGlRef create( DataSourceRef dataSource, const std::string mimeTypeHint = "" )
278  { return std::shared_ptr<MovieGl>( new MovieGl( dataSource, mimeTypeHint ) ); }
279 
281  const gl::Texture getTexture();
282 
283  protected:
284  void allocateVisualContext();
285 
286  struct Obj : public MovieBase::Obj {
287  Obj();
288  ~Obj();
289 
290  virtual void releaseFrame();
291  virtual void newFrame( CVImageBufferRef cvImage );
292 
293  gl::Texture mTexture;
294 #if defined( CINDER_MSW )
295  gl::TextureCache mTextureCache;
296 #endif
297  };
298 
299  std::shared_ptr<Obj> mObj;
300  virtual MovieBase::Obj* getObj() const { return mObj.get(); }
301 
302  public:
304 
305  typedef std::shared_ptr<Obj> MovieGl::*unspecified_bool_type;
306  operator unspecified_bool_type() const { return ( mObj.get() == 0 ) ? 0 : &MovieGl::mObj; }
307  void reset() { mObj.reset(); }
309 };
310 
311 class MovieLoader {
312  public:
313  MovieLoader() {}
314  MovieLoader( const Url &url );
315 
316  static MovieLoaderRef create( const Url &url ) { return std::shared_ptr<MovieLoader>( new MovieLoader( url ) ); }
317 
319  bool checkLoaded() const;
321  bool checkPlayable() const;
323  bool checkPlaythroughOk() const;
324 
326  void waitForLoaded() const;
328  void waitForPlayable() const;
330  void waitForPlaythroughOk() const;
331 
333  const Url& getUrl() const { return mObj->mUrl; }
334 
336  ::Movie getMovieHandle() const { return mObj->mMovie; }
337 
339  ::Movie transferMovieHandle() const { mObj->mOwnsMovie = false; return mObj->mMovie; }
340 
341  protected:
342  void updateLoadState() const;
343 
344  struct Obj {
345  Obj( const Url &url );
346  ~Obj();
347 
348  mutable bool mOwnsMovie;
349  ::Movie mMovie;
350  Url mUrl;
351  mutable bool mLoaded, mPlayable, mPlaythroughOK;
352  };
353 
354  std::shared_ptr<Obj> mObj;
355 
356  public:
358 
359  typedef std::shared_ptr<Obj> MovieLoader::*unspecified_bool_type;
360  operator unspecified_bool_type() const { return ( mObj.get() == 0 ) ? 0 : &MovieLoader::mObj; }
361  void reset() { mObj.reset(); }
363 };
364 
365 inline int32_t floatToFixed( float fl ) { return ((int32_t)((float)(fl) * ((int32_t) 0x00010000L))); }
366 
368 void startQuickTime();
370 extern int32_t getQuickTimeVersion();
372 extern std::string getQuickTimeVersionString();
373 
375 extern void quickTimeTask();
376 
377 class QuickTimeExc : public std::exception {
378 };
379 
380 class QuickTimePathInvalidExc : public QuickTimeExc {
381 };
382 
383 class QuickTimeFileInvalidExc : public QuickTimeExc {
384 };
385 
386 class QuickTimeExcUrlInvalid : public QuickTimeExc {
387 };
388 
389 class QuickTimeErrorLoadingExc : public QuickTimeExc {
390 };
391 
392 class QuickTimeExcFft : public QuickTimeExc {
393 };
394 
395 } /* namespace qtime */ } /* namespace cinder */
396 #endif // ! defined( __LP64__ )