TuttleOFX
1
|
00001 #include "ClipImage.hpp" 00002 00003 #include <tuttle/host/HostDescriptor.hpp> 00004 #include <tuttle/host/Core.hpp> 00005 #include <tuttle/host/ImageEffectNode.hpp> 00006 #include <tuttle/host/InputBufferWrapper.hpp> 00007 #include <tuttle/host/graph/ProcessEdgeAtTime.hpp> 00008 00009 #include <tuttle/host/ofx/OfxhCore.hpp> 00010 #include <tuttle/host/ofx/OfxhBinary.hpp> 00011 #include <tuttle/host/ofx/OfxhMemory.hpp> 00012 #include <tuttle/host/ofx/OfxhPluginAPICache.hpp> 00013 #include <tuttle/host/ofx/OfxhPluginCache.hpp> 00014 #include <tuttle/host/ofx/OfxhHost.hpp> 00015 #include <tuttle/host/ofx/OfxhImageEffectNode.hpp> 00016 #include <tuttle/host/ofx/OfxhImageEffectPlugin.hpp> 00017 #include <tuttle/host/ofx/property/OfxhSet.hpp> 00018 #include <tuttle/host/ofx/attribute/OfxhClip.hpp> 00019 #include <tuttle/host/ofx/attribute/OfxhParam.hpp> 00020 00021 #include <tuttle/common/utils/global.hpp> 00022 #include <boost/scoped_ptr.hpp> 00023 00024 #include <iostream> 00025 #include <fstream> 00026 #include <cmath> 00027 #include <ctime> 00028 #include <cstring> 00029 00030 namespace tuttle { 00031 namespace host { 00032 namespace attribute { 00033 00034 ClipImage::ClipImage( INode& effect, const ofx::attribute::OfxhClipImageDescriptor& desc ) 00035 : Attribute( effect ) 00036 , tuttle::host::ofx::attribute::OfxhClipImage( desc ) 00037 , _isConnected( false ) 00038 , _continuousSamples( false ) 00039 , _memoryCache( core().getMemoryCache() ) 00040 { 00041 getEditableProperties().addProperty( new ofx::property::String( "TuttleFullName", 1, 1, getFullName().c_str() ) ); 00042 getEditableProperties().addProperty( new ofx::property::String( "TuttleIdentifier", 1, 1, "" ) ); 00043 } 00044 00045 ClipImage::ClipImage( const ClipImage& other ) 00046 : Attribute( other ) 00047 , ofx::attribute::OfxhClipImage( other ) 00048 , _memoryCache( core().getMemoryCache() ) 00049 { 00050 _name = other._name; 00051 _isConnected = other._isConnected; 00052 _continuousSamples = other._continuousSamples; 00053 _connectedClip = other._connectedClip; 00054 } 00055 00056 ClipImage::~ClipImage() 00057 {} 00058 00059 std::string ClipImage::getFullName() const 00060 { 00061 return getNode().getName() + "." + getName(); 00062 } 00063 00064 OfxTime ClipImage::getRemappedTime( const OfxTime time ) const 00065 { 00066 //return time; // to disable time propagation support 00067 00068 if( isOutput() ) 00069 return time; 00070 00071 /// Maybe we are not inside a compute (eg. overlay)... so datas are not initialized, etc. 00072 if( ! getNode().hasData(time) ) 00073 return time; // throw an error? 00074 00075 const OfxTime remappedTime = getNode().getData(time).getInputEdgeByClipName(getName()).getOutTime(); 00076 return remappedTime; 00077 } 00078 00079 /// Return the rod on the clip cannoical coords! 00080 OfxRectD ClipImage::fetchRegionOfDefinition( const OfxTime time ) const 00081 { 00082 if( !isOutput() ) 00083 { 00084 if( !isConnected() ) 00085 { 00086 BOOST_THROW_EXCEPTION( exception::Bug() 00087 << exception::dev( "fetchRegionOfDefinition on an unconnected input clip ! (clip: " + getFullName() + ")." ) ); 00088 } 00089 return _connectedClip->fetchRegionOfDefinition( getRemappedTime(time) ); 00090 } 00091 00092 /// @todo tuttle: renderscale, time, ? 00093 00094 switch( getNode().getNodeType() ) 00095 { 00096 case INode::eNodeTypeImageEffect: 00097 return getNode().asImageEffectNode().getRegionOfDefinition( time ); 00098 default: 00099 BOOST_THROW_EXCEPTION( exception::Bug() 00100 << exception::dev( "fetchRegionOfDefinition unsupported on " + mapNodeTypeEnumToString(getNode().getNodeType()) + " node." ) ); 00101 } 00102 } 00103 00104 /// Get the Raw Unmapped Pixel Depth 00105 const std::string& ClipImage::getUnmappedBitDepth() const 00106 { 00107 return getProperties().getStringProperty( kOfxImageClipPropUnmappedPixelDepth ); 00108 } 00109 00110 /// Get the Raw Unmapped Components from the host. 00111 00112 const std::string& ClipImage::getUnmappedComponents() const 00113 { 00114 return getProperties().getStringProperty( kOfxImageClipPropUnmappedComponents ); 00115 } 00116 00117 /** 00118 * @brief Frame Rate 00119 * The frame rate of a clip or instance's project. 00120 */ 00121 double ClipImage::getFrameRate() const 00122 { 00123 return getProperties().getDoubleProperty( kOfxImageEffectPropFrameRate ); 00124 } 00125 00126 void ClipImage::setFrameRate( const double fps ) 00127 { 00128 getEditableProperties().setDoubleProperty( kOfxImageEffectPropFrameRate, fps ); 00129 } 00130 00131 // Frame Range (startFrame, endFrame) - 00132 // 00133 // The frame range over which a clip has images. 00134 void ClipImage::setFrameRange( const double startFrame, const double endFrame ) 00135 { 00136 getEditableProperties().setDoubleProperty( kOfxImageEffectPropFrameRange, startFrame, 0 ); 00137 getEditableProperties().setDoubleProperty( kOfxImageEffectPropFrameRange, endFrame, 1 ); 00138 } 00139 00140 /** 00141 * @brief Unmapped Frame Rate 00142 * The unmaped frame range over which an output clip has images. 00143 */ 00144 const double ClipImage::getUnmappedFrameRate() const 00145 { 00146 return getNode().asImageEffectNode().getOutputFrameRate(); 00147 } 00148 00149 // Unmapped Frame Range - 00150 // 00151 // The unmaped frame range over which an output clip has images. 00152 // this is applicable only to hosts and plugins that allow a plugin to change frame rates 00153 void ClipImage::setUnmappedFrameRange( const double unmappedStartFrame, const double unmappedEndFrame ) 00154 { 00155 getEditableProperties().setDoubleProperty( kOfxImageEffectPropUnmappedFrameRange, unmappedStartFrame, 0 ); 00156 getEditableProperties().setDoubleProperty( kOfxImageEffectPropUnmappedFrameRange, unmappedEndFrame, 1 ); 00157 } 00158 00159 /// override this to fill in the image at the given time. 00160 /// The bounds of the image on the image plane should be 00161 /// 'appropriate', typically the value returned in getRegionsOfInterest 00162 /// on the effect instance. Outside a render call, the optionalBounds should 00163 /// be 'appropriate' for the. 00164 /// If bounds is not null, fetch the indicated section of the canonical image plane. 00165 tuttle::host::ofx::imageEffect::OfxhImage* ClipImage::getImage( const OfxTime time, const OfxRectD* optionalBounds ) 00166 { 00167 OfxRectD bounds; 00168 00169 if( optionalBounds ) 00170 { 00171 bounds.x1 = optionalBounds->x1; 00172 bounds.y1 = optionalBounds->y1; 00173 bounds.x2 = optionalBounds->x2; 00174 bounds.y2 = optionalBounds->y2; 00175 //BOOST_THROW_EXCEPTION( exception::MissingHostFeature() 00176 // << exception::dev("Uses optionalBounds not supported yet.") ); ///< @todo tuttle: needs to be supported ! 00177 //TUTTLE_TLOG( TUTTLE_TRACE, "on clip: " << getFullName() << " optionalBounds="<< bounds); 00178 } 00179 else 00180 { 00181 bounds = fetchRegionOfDefinition( time ); 00182 } 00183 00184 const OfxTime realTime = getRemappedTime(time); 00185 //TUTTLE_TLOG( TUTTLE_TRACE, "--> getImage <" << getFullName() << "> connected on <" << getConnectedClipFullName() << "> with connection <" << isConnected() << "> isOutput <" << isOutput() << ">" << " bounds: " << bounds ); 00186 boost::shared_ptr<Image> image = _memoryCache.get( getClipIdentifier(), realTime ); 00187 // std::cout << "got image : " << image.get() << std::endl; 00188 /// @todo tuttle do something with bounds... 00189 /// if bounds != cache buffer bounds: 00190 /// * bounds < cache buffer: use rowSize to adjust, and modify pointer 00191 /// * bounds > cache buffer: recompute / exception ? 00192 00193 return image.get(); 00194 } 00195 00196 } 00197 } 00198 } 00199