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 , _connectedClip( NULL ) 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 { 00049 _name = other._name; 00050 _isConnected = other._isConnected; 00051 _continuousSamples = other._continuousSamples; 00052 _connectedClip = other._connectedClip; 00053 } 00054 00055 ClipImage::~ClipImage() 00056 {} 00057 00058 std::string ClipImage::getFullName() const 00059 { 00060 return getNode().getName() + "." + getName(); 00061 } 00062 00063 OfxTime ClipImage::getRemappedTime( const OfxTime time ) const 00064 { 00065 //return time; // to disable time propagation support 00066 00067 if( isOutput() ) 00068 return time; 00069 00070 /// Maybe we are not inside a compute (eg. overlay)... so datas are not initialized, etc. 00071 if( ! getNode().hasData(time) ) 00072 return time; // throw an error? 00073 00074 const OfxTime remappedTime = getNode().getData(time).getInputEdgeByClipName(getName(), time).getOutTime(); 00075 return remappedTime; 00076 } 00077 00078 /// Return the rod on the clip canonical coords! 00079 OfxRectD ClipImage::fetchRegionOfDefinition( const OfxTime time ) const 00080 { 00081 if( !isOutput() ) 00082 { 00083 if( !isConnected() ) 00084 { 00085 BOOST_THROW_EXCEPTION( exception::Bug() 00086 << exception::dev( "fetchRegionOfDefinition on an unconnected input clip ! (clip: " + getFullName() + ")." ) ); 00087 } 00088 return _connectedClip->fetchRegionOfDefinition( getRemappedTime(time) ); 00089 } 00090 00091 /// @todo tuttle: renderscale, time, ? 00092 00093 switch( getNode().getNodeType() ) 00094 { 00095 case INode::eNodeTypeImageEffect: 00096 return getNode().asImageEffectNode().getRegionOfDefinition( time ); 00097 default: 00098 BOOST_THROW_EXCEPTION( exception::Bug() 00099 << exception::dev( "fetchRegionOfDefinition unsupported on " + mapNodeTypeEnumToString(getNode().getNodeType()) + " node." ) ); 00100 } 00101 } 00102 00103 /// Get the Raw Unmapped Pixel Depth 00104 const std::string& ClipImage::getUnmappedBitDepth() const 00105 { 00106 return getProperties().getStringProperty( kOfxImageClipPropUnmappedPixelDepth ); 00107 } 00108 00109 /// Get the Raw Unmapped Components from the host. 00110 00111 const std::string& ClipImage::getUnmappedComponents() const 00112 { 00113 return getProperties().getStringProperty( kOfxImageClipPropUnmappedComponents ); 00114 } 00115 00116 /** 00117 * @brief Frame Rate 00118 * The frame rate of a clip or instance's project. 00119 */ 00120 double ClipImage::getFrameRate() const 00121 { 00122 return getProperties().getDoubleProperty( kOfxImageEffectPropFrameRate ); 00123 } 00124 00125 void ClipImage::setFrameRate( const double fps ) 00126 { 00127 getEditableProperties().setDoubleProperty( kOfxImageEffectPropFrameRate, fps ); 00128 } 00129 00130 // Frame Range (startFrame, endFrame) - 00131 // 00132 // The frame range over which a clip has images. 00133 void ClipImage::setFrameRange( const double startFrame, const double endFrame ) 00134 { 00135 getEditableProperties().setDoubleProperty( kOfxImageEffectPropFrameRange, startFrame, 0 ); 00136 getEditableProperties().setDoubleProperty( kOfxImageEffectPropFrameRange, endFrame, 1 ); 00137 } 00138 00139 /** 00140 * @brief Unmapped Frame Rate 00141 * The unmaped frame range over which an output clip has images. 00142 */ 00143 const double ClipImage::getUnmappedFrameRate() const 00144 { 00145 return getNode().asImageEffectNode().getOutputFrameRate(); 00146 } 00147 00148 // Unmapped Frame Range - 00149 // 00150 // The unmaped frame range over which an output clip has images. 00151 // this is applicable only to hosts and plugins that allow a plugin to change frame rates 00152 void ClipImage::setUnmappedFrameRange( const double unmappedStartFrame, const double unmappedEndFrame ) 00153 { 00154 getEditableProperties().setDoubleProperty( kOfxImageEffectPropUnmappedFrameRange, unmappedStartFrame, 0 ); 00155 getEditableProperties().setDoubleProperty( kOfxImageEffectPropUnmappedFrameRange, unmappedEndFrame, 1 ); 00156 } 00157 00158 /// override this to fill in the image at the given time. 00159 /// The bounds of the image on the image plane should be 00160 /// 'appropriate', typically the value returned in getRegionsOfInterest 00161 /// on the effect instance. Outside a render call, the optionalBounds should 00162 /// be 'appropriate' for the. 00163 /// If bounds is not null, fetch the indicated section of the canonical image plane. 00164 tuttle::host::ofx::imageEffect::OfxhImage* ClipImage::getImage( const OfxTime time, const OfxRectD* optionalBounds ) 00165 { 00166 OfxRectD bounds; 00167 00168 if( optionalBounds ) 00169 { 00170 bounds.x1 = optionalBounds->x1; 00171 bounds.y1 = optionalBounds->y1; 00172 bounds.x2 = optionalBounds->x2; 00173 bounds.y2 = optionalBounds->y2; 00174 //BOOST_THROW_EXCEPTION( exception::MissingHostFeature() 00175 // << exception::dev("Uses optionalBounds not supported yet.") ); ///< @todo tuttle: needs to be supported ! 00176 //TUTTLE_TLOG( TUTTLE_TRACE, "on clip: " << getFullName() << " optionalBounds="<< bounds); 00177 } 00178 else 00179 { 00180 bounds = fetchRegionOfDefinition( time ); 00181 } 00182 00183 const OfxTime realTime = getRemappedTime(time); 00184 //TUTTLE_TLOG( TUTTLE_TRACE, "--> getImage <" << getFullName() << "> connected on <" << getConnectedClipFullName() << "> with connection <" << isConnected() << "> isOutput <" << isOutput() << ">" << " bounds: " << bounds ); 00185 boost::shared_ptr<Image> image = getNode().getData().getInternMemoryCache().get( getClipIdentifier(), realTime ); 00186 // std::cout << "got image : " << image.get() << std::endl; 00187 /// @todo tuttle do something with bounds... 00188 /// if bounds != cache buffer bounds: 00189 /// * bounds < cache buffer: use rowSize to adjust, and modify pointer 00190 /// * bounds > cache buffer: recompute / exception ? 00191 00192 return image.get(); 00193 } 00194 00195 } 00196 } 00197 } 00198