include/cinder/qtime/MovieWriter.h
Go to the documentation of this file.
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 #include "cinder/Cinder.h"
00026 #include "cinder/ImageIo.h"
00027 #include "cinder/Stream.h"
00028 #include "cinder/qtime/QuickTime.h"
00029 
00030 #include <string>
00031 
00032 // These forward declarations prevent us from having to bring all of QuickTime into the global namespace in MSW
00034 #if defined( CINDER_MSW )
00035     typedef struct ComponentInstanceRecord      ComponentInstanceRecord;
00036     typedef ComponentInstanceRecord *           ComponentInstance;
00037     typedef ComponentInstance                   DataHandler;
00038     typedef struct TrackType**                  Track;
00039     typedef struct MediaType**                  Media;
00040     typedef struct OpaqueICMCompressionSession*         ICMCompressionSessionRef;
00041     typedef struct OpaqueICMCompressionSessionOptions*  ICMCompressionSessionOptionsRef;
00042     typedef const struct OpaqueICMEncodedFrame* ICMEncodedFrameRef;
00043     typedef signed long                         OSStatus;
00044     typedef unsigned long                       CodecType;
00045     typedef unsigned long                       ICMCompressionPassModeFlags;
00046 #else
00047     #include <QuickTime/QuickTime.h>
00048     #include <QuickTime/ImageCompression.h>
00049 #endif // defined( CINDER_MSW )
00050 
00051 
00052 namespace cinder { namespace qtime {
00053 
00054 class MovieWriter;
00055 typedef std::shared_ptr<MovieWriter>    MovieWriterRef;
00056 
00057 class MovieWriter {
00058     struct Obj;
00059 
00060   public:
00062     class Format {
00063       public:
00064         Format();
00065         Format( uint32_t codec, float quality );
00066         Format( const ICMCompressionSessionOptionsRef settings, uint32_t codec, float quality, float frameRate, bool enableMultiPass );
00067         Format( const Format &format );
00068         ~Format();
00069 
00070         const Format& operator=( const Format &format );
00071 
00073         uint32_t    getCodec() const { return mCodec; }
00075         Format&     setCodec( uint32_t codec ) { mCodec = codec; return *this; }
00077         float       getQuality() const { return mQualityFloat; }
00079         Format&     setQuality( float quality );
00081         float       getDefaultDuration() const { return mDefaultTime; }
00083         Format&     setDefaultDuration( float defaultDuration ) { mDefaultTime = defaultDuration; return *this; }
00085         long        getTimeScale() const { return mTimeBase; }
00087         Format&     setTimeScale( long timeScale ) { mTimeBase = timeScale; return *this; }
00089         float       getGamma() const { return mGamma; }
00091         Format&     setGamma( float gamma ) { mGamma = gamma; return *this; }
00093         bool        isTemporal() const;
00095         Format&     enableTemporal( bool enable = true );
00097         bool        isReordering() const;
00099         Format&     enableReordering( bool enable = true );
00101         int32_t     getMaxKeyFrameRate() const;
00103         Format&     setMaxKeyFrameRate( int32_t rate );
00105         bool        isFrameTimeChanges() const;
00107         Format&     enableFrameTimeChanges( bool enable = true );
00109         bool        isMultiPass() const { return mEnableMultiPass; }
00111         Format&     enableMultiPass( bool enable = true ) { mEnableMultiPass = enable; return *this; }
00112 
00113       private:
00114         void        initDefaults();
00115 
00116         uint32_t    mCodec;
00117         long        mTimeBase;
00118         float       mDefaultTime;
00119         float       mQualityFloat;
00120         float       mGamma;
00121         bool        mEnableMultiPass;
00122 
00123         ICMCompressionSessionOptionsRef     mOptions;
00124 
00125         friend class MovieWriter;
00126         friend struct Obj;
00127     };
00128 
00129 
00130     MovieWriter() {}
00131     MovieWriter( const fs::path &path, int32_t width, int32_t height, const Format &format = Format::Format() );
00132 
00133     static MovieWriterRef   create( const fs::path &path, int32_t width, int32_t height, const Format &format = Format::Format() )
00134         { return std::shared_ptr<MovieWriter>( new MovieWriter( path, width, height, format ) ); }
00135 
00137     float   getDefaultDuration() const { return mObj->mFormat.mDefaultTime; }
00139     int32_t getWidth() const { return mObj->mWidth; }
00141     int32_t getHeight() const { return mObj->mHeight; }
00143     Vec2i   getSize() const { return Vec2i( getWidth(), getHeight() ); }
00145     float   getAspectRatio() const { return getWidth() / (float)getHeight(); }
00147     Area    getBounds() const { return Area( 0, 0, getWidth(), getHeight() ); }
00148 
00150     const Format&   getFormat() const { return mObj->mFormat; }
00151 
00154     static bool     getUserCompressionSettings( Format *result, ImageSourceRef previewImage = ImageSourceRef() );
00155 
00158     void addFrame( const ImageSourceRef &imageSource, float duration = -1.0f ) { mObj->addFrame( imageSource, duration ); }
00159     
00161     uint32_t    getNumFrames() const { return mObj->mNumFrames; }
00162 
00164     void finish() { mObj->finish(); }
00165     
00166     enum { CODEC_H264 = 'avc1', CODEC_JPEG = 'jpeg', CODEC_MP4 = 'mp4v', CODEC_PNG = 'png ', CODEC_RAW = 'raw ', CODEC_ANIMATION = 'rle ' };
00167 
00168   private:
00170     struct Obj {
00171         Obj( const fs::path &path, int32_t width, int32_t height, const Format &format );
00172         ~Obj();
00173         
00174         void    addFrame( const ImageSourceRef &imageSource, float duration );
00175         void    createCompressionSession();
00176         void    finish();
00177         
00178         static OSStatus encodedFrameOutputCallback( void *refCon, ::ICMCompressionSessionRef session, OSStatus err, ICMEncodedFrameRef encodedFrame, void *reserved );
00179 
00180         ::Movie                         mMovie;
00181         ::DataHandler                   mDataHandler;
00182         ::Track                         mTrack;
00183         ::Media                         mMedia;
00184         ::ICMCompressionSessionRef      mCompressionSession;
00185         ::ICMCompressionPassModeFlags   mMultiPassModeFlags;        
00186         fs::path        mPath;
00187         uint32_t        mNumFrames;
00188         int64_t         mCurrentTimeValue;
00189         
00190         int32_t     mWidth, mHeight;
00191         Format      mFormat;
00192         bool        mRequestedMultiPass, mDoingMultiPass, mFinished;        
00193 
00194         IoStreamRef     mMultiPassFrameCache;
00195 
00196         std::vector<std::pair<int64_t,int64_t> >    mFrameTimes;
00197     };
00199     
00200     std::shared_ptr<Obj>        mObj;  
00201 
00202   public:
00204 
00205     typedef std::shared_ptr<Obj> MovieWriter::*unspecified_bool_type;
00206     operator unspecified_bool_type() const { return ( mObj.get() == 0 ) ? 0 : &MovieWriter::mObj; }
00207     void reset() { mObj.reset(); }
00209 };
00210 
00211 class MovieWriterExc : public Exception {
00212 };
00213 class MovieWriterExcInvalidPath : public MovieWriterExc {
00214 };
00215 class MovieWriterExcFrameEncode : public MovieWriterExc {
00216 };
00217 class MovieWriterExcAlreadyFinished : public MovieWriterExc {
00218 };
00219 
00220 } } // namespace cinder::qtime