TuttleOFX  1
TuttleOFX/libraries/tuttle/src/tuttle/host/attribute/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         , _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