TuttleOFX  1
ClipImage.cpp
Go to the documentation of this file.
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