TuttleOFX
1
|
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