TuttleOFX  1
TuttleOFX/libraries/tuttle/src/tuttle/host/ofx/OfxhImageEffectNode.hpp
Go to the documentation of this file.
00001 /*
00002  * Software License :
00003  *
00004  * Copyright (c) 2007-2009, The Open Effects Association Ltd.  All Rights Reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  *
00009  * Redistributions of source code must retain the above copyright notice,
00010  *    this list of conditions and the following disclaimer.
00011  * Redistributions in binary form must reproduce the above copyright notice,
00012  *    this list of conditions and the following disclaimer in the documentation
00013  *    and/or other materials provided with the distribution.
00014  * Neither the name The Open Effects Association Ltd, nor the names of its
00015  *    contributors may be used to endorse or promote products derived from this
00016  *    software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00019  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00020  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00021  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
00022  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00023  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00024  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00025  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00026  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00027  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #ifndef _TUTTLE_HOST_OFX_IMAGEEFFECTNODE_HPP_
00031 #define _TUTTLE_HOST_OFX_IMAGEEFFECTNODE_HPP_
00032 
00033 #include <tuttle/host/exceptions.hpp>
00034 
00035 #include "OfxhImageEffectNodeBase.hpp"
00036 #include "OfxhImageEffectNodeDescriptor.hpp"
00037 #include "OfxhImageEffectPlugin.hpp"
00038 #include "OfxhHost.hpp"
00039 #include "OfxhMessage.hpp"
00040 #include "OfxhProgress.hpp"
00041 #include "OfxhTimeline.hpp"
00042 #include "OfxhMemory.hpp"
00043 #include "OfxhInteract.hpp"
00044 #include "OfxhException.hpp"
00045 #include "property/OfxhSet.hpp"
00046 #include "attribute/OfxhParamSet.hpp"
00047 #include "attribute/OfxhClipImageSet.hpp"
00048 
00049 #include <ofxCore.h>
00050 #include <ofxImageEffect.h>
00051 
00052 namespace tuttle {
00053 namespace host {
00054 namespace ofx {
00055 namespace imageEffect {
00056 
00057 /**
00058  *  an image effect plugin instance.
00059  *
00060  *  Client code needs to filling the pure virtuals in this.
00061  */
00062 class OfxhImageEffectNode : public OfxhImageEffectNodeBase
00063         , public attribute::OfxhParamSet
00064         , public attribute::OfxhClipImageSet
00065         , public OfxhIProgress
00066         , public OfxhIMessage
00067         , public OfxhITimeline
00068         , private property::OfxhNotifyHook
00069         , private property::OfxhGetHook
00070 {
00071 public:
00072         typedef OfxhImageEffectNode This;
00073         /// a map used to specify needed frame ranges on set of clips
00074         typedef std::map<attribute::OfxhClipImage*, std::vector<OfxRangeD> > ClipRangeMap;
00075         typedef std::set<OfxTime> TimesSet;
00076         typedef std::map<std::string, TimesSet > ClipTimesSetMap;
00077 
00078 protected:
00079         const OfxhImageEffectPlugin& _plugin;
00080         std::string _context;
00081         const OfxhImageEffectNodeDescriptor& _descriptor;
00082         bool _interactive;
00083         bool _created;
00084         bool _continuousSamples; ///< set by clip prefs
00085         bool _frameVarying; ///< set by clip prefs
00086         std::string _outputPreMultiplication;  ///< set by clip prefs
00087         std::string _outputFielding;  ///< set by clip prefs
00088         double _outputFrameRate; ///< set by clip prefs
00089         
00090 public:
00091         /// constructor based on clip descriptor
00092         OfxhImageEffectNode( const OfxhImageEffectPlugin&         plugin,
00093                              const OfxhImageEffectNodeDescriptor& other,
00094                              const std::string&                   context,
00095                              bool                                 interactive );
00096 
00097         OfxhImageEffectNode( const OfxhImageEffectNode& other );
00098 
00099         virtual ~OfxhImageEffectNode() = 0;
00100 
00101 protected:
00102         void initHook();
00103 
00104         /**
00105          *  called after construction to populate the various members
00106          *  ideally should be called in the ctor, but it relies on
00107          *  virtuals so has to be delayed until after the effect is
00108          *  constructed
00109          */
00110         void populate();
00111         void populateParams( const imageEffect::OfxhImageEffectNodeDescriptor& descriptor );
00112 
00113 private:
00114         attribute::OfxhClipImage&       getOutputOfxhClip()       { return getClip( kOfxImageEffectOutputClipName ); }
00115         const attribute::OfxhClipImage& getOutputOfxhClip() const { return getClip( kOfxImageEffectOutputClipName ); }
00116 
00117 public:
00118         void copyAttributesValues( const OfxhImageEffectNode& other )
00119         {
00120                 copyParamsValues( other );
00121                 copyClipsValues( other );
00122         }
00123 
00124         bool operator==( const This& ) const;
00125         bool operator!=( const This& other ) const { return !This::operator==( other ); }
00126 
00127         /// implemented for Param::SetInstance
00128         virtual property::OfxhSet& getParamSetProps();
00129 
00130         /// implemented for Param::SetInstance
00131         virtual void paramChanged( const attribute::OfxhParam& param, const attribute::EChange change );
00132 
00133         /// get the descriptor for this instance
00134         const OfxhImageEffectNodeDescriptor& getDescriptor() const { return _descriptor; }
00135 
00136         /// return the plugin this instance was created with
00137         const tuttle::host::ofx::imageEffect::OfxhImageEffectPlugin& getPlugin() const { return _plugin; }
00138 
00139         /// return the context this instance was created with
00140         const std::string& getContext() const { return _context; }
00141 
00142         // get the descriptor for this instance
00143         //Descriptor& getDescriptor() { return *_descriptor; }
00144 
00145         /**
00146          *  get default output fielding. This is passed into the clip prefs action
00147          *  and  might be mapped (if the host allows such a thing)
00148          */
00149         virtual const std::string& getDefaultOutputFielding() const = 0;
00150 
00151         /// get output fielding as set in the clip preferences action.
00152         const std::string& getOutputFielding() const { return _outputFielding; }
00153 
00154         /// get output fielding as set in the clip preferences action.
00155         const std::string& getOutputPreMultiplication() const { return _outputPreMultiplication; }
00156 
00157         /// get the output frame rate, as set in the clip prefences action.
00158         double getOutputFrameRate() const { return _outputFrameRate; }
00159         
00160         double getOutputPixelAspectRatio() const { return getOutputOfxhClip().getPixelAspectRatio(); }
00161 
00162         /// are all the non optional clips connected
00163         bool checkClipConnectionStatus() const;
00164 
00165         /// can this this instance render images at arbitrary times, not just frame boundaries
00166         /// set by getClipPreferenceAction()
00167         bool continuousSamples() const { return _continuousSamples; }
00168 
00169         /// does this instance generate a different picture on a frame change, even if the
00170         /// params and input images are exactly the same. eg: random noise generator
00171         bool isFrameVarying() const { return _frameVarying; }
00172 
00173         /// override this to make processing abort, return 1 to abort processing
00174         virtual int abort() = 0;
00175 
00176 #ifndef SWIG
00177         /// override this to use your own memory instance - must inherrit from OfxhMemory
00178         virtual OfxhMemory* newMemoryInstance( size_t nBytes ) = 0;
00179 
00180         // return an memory::instance calls makeMemoryInstance that can be overriden
00181         OfxhMemory* imageMemoryAlloc( size_t nBytes );
00182 #endif
00183 
00184         /// make a clip
00185         //        virtual tuttle::host::ofx::attribute::ClipImageInstance* newClipImage( tuttle::host::ofx::attribute::ClipImageDescriptor* descriptor) = 0;
00186 
00187 protected:
00188         #ifndef SWIG
00189         virtual void vmessage( const char* type,
00190                                const char* id,
00191                                const char* format,
00192                                va_list     args ) const OFX_EXCEPTION_SPEC = 0;
00193 
00194         /// call the effect entry point
00195         virtual OfxStatus mainEntry( const char*        action,
00196                                      const void*        handle,
00197                                      property::OfxhSet* inArgs,
00198                                      property::OfxhSet* outArgs ) const;
00199         #endif
00200 
00201 public:
00202         size_t upperGetDimension( const std::string& name );
00203 
00204         /// overridden from Property::Notify
00205         virtual void notify( const std::string& name, bool singleValue, int indexOrN ) OFX_EXCEPTION_SPEC;
00206 
00207         /// overridden from gethook,  get the virtuals for viewport size, pixel scale, background colour
00208         virtual double getDoubleProperty( const std::string& name, int index ) const OFX_EXCEPTION_SPEC;
00209 
00210         /// overridden from gethook,  get the virtuals for viewport size, pixel scale, background colour
00211         virtual void getDoublePropertyN( const std::string& name, double* values, int count ) const OFX_EXCEPTION_SPEC;
00212 
00213         /// overridden from gethook, don't know what to do
00214         virtual void reset( const std::string& name ) OFX_EXCEPTION_SPEC;
00215 
00216         //// overridden from gethook
00217         virtual size_t getDimension( const std::string& name )  const OFX_EXCEPTION_SPEC;
00218 
00219         //
00220         // live parameters
00221         //
00222 
00223         // The size of the current project in canonical coordinates.
00224         // The size of a project is a sub set of the kOfxImageEffectPropProjectExtent. For example a
00225         // project may be a PAL SD project, but only be a letter-box within that. The project size is
00226         // the size of this sub window.
00227         virtual void getProjectSize( double& xSize, double& ySize ) const = 0;
00228 
00229         // The offset of the current project in canonical coordinates.
00230         // The offset is related to the kOfxImageEffectPropProjectSize and is the offset from the origin
00231         // of the project 'subwindow'. For example for a PAL SD project that is in letterbox form, the
00232         // project offset is the offset to the bottom left hand corner of the letter box. The project
00233         // offset is in canonical coordinates.
00234         virtual void getProjectOffset( double& xOffset, double& yOffset ) const = 0;
00235 
00236         // The extent of the current project in canonical coordinates.
00237         // The extent is the size of the 'output' for the current project. See ProjectCoordinateSystems
00238         // for more infomation on the project extent. The extent is in canonical coordinates and only
00239         // returns the top right position, as the extent is always rooted at 0,0. For example a PAL SD
00240         // project would have an extent of 768, 576.
00241         virtual void getProjectExtent( double& xSize, double& ySize ) const = 0;
00242 
00243         // The pixel aspect ratio of the current project
00244         virtual double getProjectPixelAspectRatio() const = 0;
00245 
00246         // The duration of the effect
00247         // This contains the duration of the plug-in effect, in frames.
00248         virtual double getEffectDuration() const = 0;
00249 
00250         /// This is called whenever a param is changed by the plugin so that
00251         /// the recursive instanceChangedAction will be fed the correct frame
00252         virtual double getFrameRecursive() const = 0;
00253 
00254         /// This is called whenever a param is changed by the plugin so that
00255         /// the recursive instanceChangedAction will be fed the correct
00256         /// renderScale
00257         virtual void getRenderScaleRecursive( double& x, double& y ) const = 0;
00258 
00259         /// Get whether the component is a supported 'chromatic' component (RGBA or alpha) in
00260         /// the base API.
00261         /// Override this if you have extended your chromatic colour types (eg RGB) and want
00262         /// the clip preferences logic to still work
00263         virtual bool isChromaticComponent( const std::string& str ) const;
00264 
00265 protected:
00266         /// function to check for multiple bit depth support
00267         /// The answer will depend on host, plugin and context
00268         virtual bool canCurrentlyHandleMultipleClipDepths() const;
00269 
00270         OfxRectD computeClipRodUnionAtTimes( const attribute::OfxhClipImage& clip, const TimesSet& timesSet ) const;
00271         
00272         /// calculate the default rod for this effect instance
00273         virtual OfxRectD calcDefaultRegionOfDefinition( OfxTime   time,
00274                                                         OfxPointD renderScale ) const;
00275 
00276         //
00277         // actions
00278         //
00279 
00280         /// this is used to populate with any extra action in arguments that may be needed
00281         virtual void setCustomInArgs( const std::string& action, property::OfxhSet& inArgs ) const;
00282 
00283         /// this is used to populate with any extra action out arguments that may be needed
00284         virtual void setCustomOutArgs( const std::string& action, property::OfxhSet& outArgs ) const;
00285 
00286         /// this is used retrieve any out args after the action was called in mainEntry
00287         virtual void examineOutArgs( const std::string& action, OfxStatus stat, const property::OfxhSet& outArgs ) const;
00288 
00289 public:
00290         /// create an instance. This needs to be called _after_ construction and
00291         /// _after_ the host populates it's params and clips with the 'correct'
00292         /// values (either persisted ones or the defaults)
00293         virtual void createInstanceAction() OFX_EXCEPTION_SPEC;
00294 
00295         // begin/change/end instance changed
00296         //
00297         // why -
00298         //
00299         // kOfxChangeUserEdited   - the user or host changed the instance somehow and
00300         //                          caused a change to something, this includes undo/redos,
00301         //                          resets and loading values from files or presets,
00302         // kOfxChangePluginEdited - the plugin itself has changed the value of the instance
00303         //                          in some action
00304         // kOfxChangeTime         - the time has changed and this has affected the value
00305         //                          of the object because it varies over time
00306         //
00307         virtual void beginInstanceChangedAction( const std::string& why ) OFX_EXCEPTION_SPEC;
00308 
00309         virtual void paramInstanceChangedAction( const std::string& paramName,
00310                                                  const std::string& why,
00311                                                  OfxTime            time,
00312                                                  OfxPointD          renderScale ) OFX_EXCEPTION_SPEC;
00313 
00314         virtual void clipInstanceChangedAction( const std::string& clipName,
00315                                                 const std::string& why,
00316                                                 OfxTime            time,
00317                                                 OfxPointD          renderScale ) OFX_EXCEPTION_SPEC;
00318 
00319         virtual void endInstanceChangedAction( const std::string& why ) OFX_EXCEPTION_SPEC;
00320 
00321         // purge your caches
00322         virtual void purgeCachesAction() OFX_EXCEPTION_SPEC;
00323 
00324         // sync your private data
00325         virtual void syncPrivateDataAction() OFX_EXCEPTION_SPEC;
00326 
00327         // begin/end edit instance
00328         virtual void beginInstanceEditAction() OFX_EXCEPTION_SPEC;
00329         virtual void endInstanceEditAction() OFX_EXCEPTION_SPEC;
00330 
00331         // render action
00332         virtual void beginSequenceRenderAction( OfxTime   startFrame,
00333                                         OfxTime   endFrame,
00334                                         double    step,
00335                                         bool      interactive,
00336                                         OfxPointD renderScale ) OFX_EXCEPTION_SPEC;
00337 
00338         virtual void renderAction( OfxTime            time,
00339                                    const std::string& field,
00340                                    const OfxRectI&    renderWindow,
00341                                    OfxPointD          renderScale ) OFX_EXCEPTION_SPEC;
00342 
00343         virtual void endSequenceRenderAction( OfxTime   startFrame,
00344                                       OfxTime   endFrame,
00345                                       double    step,
00346                                       bool      interactive,
00347                                       OfxPointD renderScale ) OFX_EXCEPTION_SPEC;
00348 
00349         /**
00350          *  Call the region of definition action the plugin at the given time
00351          *  and with the given render scales. The value is returned in rod.
00352          *  Note that if the plugin does not trap the action the default
00353          *  RoD is calculated and returned.
00354          */
00355         virtual void getRegionOfDefinitionAction( OfxTime   time,
00356                                                   OfxPointD renderScale,
00357                                                   OfxRectD& rod ) const OFX_EXCEPTION_SPEC;
00358 
00359         /**
00360          *  call the get region of interest action on the plugin for the
00361          *  given frame and renderscale. The render RoI is passed in in
00362          *  roi, the std::map will contain the requested rois. Note
00363          *  That this call will check for tiling support and for
00364          *  default replies and set up the correct rois in these cases
00365          *  as well
00366          */
00367         virtual void getRegionOfInterestAction( OfxTime time,
00368                                                 OfxPointD renderScale,
00369                                                 const OfxRectD& roi,
00370                                                 std::map<attribute::OfxhClipImage*, OfxRectD>& rois ) const OFX_EXCEPTION_SPEC;
00371 
00372         // get frames needed to render the given frame
00373         virtual void getFramesNeededAction( OfxTime   time,
00374                                            ClipRangeMap& rangeMap ) const OFX_EXCEPTION_SPEC;
00375 
00376         ClipTimesSetMap getFramesNeeded( const OfxTime time ) const;
00377         
00378         // is identity
00379         virtual bool isIdentityAction( OfxTime&           time,
00380                                        const std::string& field,
00381                                        const OfxRectI&    renderWindow,
00382                                        OfxPointD          renderScale,
00383                                        std::string&       clip ) const OFX_EXCEPTION_SPEC;
00384 
00385         // time domain
00386         virtual bool getTimeDomainAction( OfxRangeD& range ) const OFX_EXCEPTION_SPEC;
00387 
00388         /**
00389          * Get the interact description, this will also call describe on the interact
00390          * This will return NULL if there is not main entry point or if the description failed
00391          * otherwise it will return the described overlay
00392          * This is called by the CTOR of OverlayInteract to get the descriptor to do things with
00393          */
00394         void initOverlayDescriptor( int bitDepthPerComponent = 8, bool hasAlpha = false )
00395         {
00396                 /// @todo tuttle initOverlayDescriptor... !!! Correct the constness
00397                 const_cast<OfxhImageEffectNodeDescriptor&>(_descriptor).initOverlayDescriptor( bitDepthPerComponent, hasAlpha );
00398         }
00399 
00400         const interact::OfxhInteractDescriptor& getOverlayDescriptor() const
00401         {
00402                 return _descriptor.getOverlayDescriptor();
00403         }
00404 
00405 private:
00406         /// Setup the default clip preferences on the clips
00407         virtual void setDefaultClipPreferences();
00408 
00409         /// Setup the default host clip instance members data retrieved from the plugin instance
00410         virtual void setupClipInstancePreferences( property::OfxhSet& outArgs );
00411 
00412         /// Initialise the clip preferences arguments, override this to do
00413         /// stuff with wierd components etc... Calls setDefaultClipPreferences
00414         virtual void setupClipPreferencesArgs( property::OfxhSet& outArgs, std::list<std::string>& outKeepPropNamesOwnership );
00415 
00416         /**
00417          * @brief Check if the node is a leaf in the graph.
00418          * If there is no input clip connected.
00419          */
00420         bool isLeafNode() const;
00421         
00422 public:
00423         /**
00424          * Run the clip preferences action from the effect.
00425          *
00426          * This will look into the input clips and output clip
00427          * and set the following properties that the effect should
00428          * fetch the image at.
00429          *     - pixel depth
00430          *     - components
00431          *     - pixel aspect ratio
00432          * It will also set on the effect itself
00433          *     - whether it is continuously samplable
00434          *     - the premult state of the output
00435          *     - whether the effect is frame varying
00436          *     - the fielding of the output clip
00437          *
00438          * This will be run automatically by the effect in the following situations...
00439          *     - an input clip is changed
00440          *     - a clip preferences slave param is changed
00441          *
00442          * The host still needs to call this explicitly just after the effect is wired
00443          * up.
00444          */
00445         virtual void getClipPreferencesAction() OFX_EXCEPTION_SPEC;
00446 
00447         /**
00448          *  calls getClipPreferences only if the prefs are dirty
00449          *
00450          *  returns whether the clips prefs were dirty or not
00451          */
00452         bool runGetClipPrefsConditionally()
00453         {
00454                 if( areClipPrefsDirty() )
00455                 {
00456                         getClipPreferencesAction();
00457                         return true;
00458                 }
00459                 return false;
00460         }
00461 
00462 protected:
00463         
00464         virtual ofx::attribute::OfxhParam* newParam( const ofx::attribute::OfxhParamDescriptor& Descriptor ) = 0;
00465         
00466         /// find the best supported bit depth for the given one. Override this if you define
00467         /// more depths
00468         virtual const std::string& bestSupportedBitDepth( const std::string& depth ) const;
00469 
00470         /// find the most chromatic components out of the two. Override this if you define
00471         /// more chromatic components
00472         virtual const std::string& findMostChromaticComponents( const std::string& a, const std::string& b ) const;
00473 
00474         /** is the given bit depth supported
00475          */
00476         bool isSupportedBitDepth( const std::string& depth ) const
00477         {
00478                 return getProperties().findStringPropValueIndex( kOfxImageEffectPropSupportedPixelDepths, depth ) != -1;
00479         }
00480 
00481 private:
00482         friend class boost::serialization::access;
00483         template<class Archive>
00484         void serialize( Archive& ar, const unsigned int version )
00485         {
00486                 ar& BOOST_SERIALIZATION_BASE_OBJECT_NVP( OfxhImageEffectNodeBase );
00487 
00488                 ar& BOOST_SERIALIZATION_BASE_OBJECT_NVP( attribute::OfxhParamSet );
00489                 ar& BOOST_SERIALIZATION_BASE_OBJECT_NVP( attribute::OfxhClipImageSet );
00490         }
00491 };
00492 
00493 }
00494 }
00495 }
00496 }
00497 
00498 #endif