TuttleOFX
1
|
00001 #include "OutputBufferPlugin.hpp" 00002 #include "OutputBufferDefinitions.hpp" 00003 00004 #include <pointerParam.hpp> 00005 00006 #include <tuttle/plugin/memory/OfxAllocator.hpp> 00007 #include <ofxImageEffect.h> 00008 00009 #include <boost/assert.hpp> 00010 #include <boost/scoped_ptr.hpp> 00011 #include <boost/cstdint.hpp> 00012 00013 namespace tuttle { 00014 namespace plugin { 00015 namespace outputBuffer { 00016 00017 using namespace memoryBuffer; 00018 00019 OutputBufferPlugin::OutputBufferPlugin( OfxImageEffectHandle handle ) 00020 : OFX::ImageEffect( handle ) 00021 , _tempStoreCustomDataPtr(NULL) 00022 { 00023 _clipSrc = fetchClip( kOfxImageEffectSimpleSourceClipName ); 00024 _clipDst = fetchClip( kOfxImageEffectOutputClipName ); 00025 00026 _paramCallbackOutputPointer = fetchStringParam( kParamOutputCallbackPointer ); 00027 _paramCustomData = fetchStringParam( kParamOutputCustomData ); 00028 _paramCallbackDestroyCustomData = fetchStringParam( kParamOutputCallbackDestroyCustomData ); 00029 } 00030 00031 OutputBufferPlugin::~OutputBufferPlugin() 00032 { 00033 OutputBufferProcessParams params = getProcessParams(); 00034 if( params._callbackDestroyPtr != NULL ) 00035 params._callbackDestroyPtr( params._customDataPtr ); 00036 } 00037 00038 void OutputBufferPlugin::changedParam( const OFX::InstanceChangedArgs& args, const std::string& paramName ) 00039 { 00040 if( paramName == kParamOutputCustomData ) 00041 { 00042 OutputBufferProcessParams params = getProcessParams(); 00043 if( params._callbackDestroyPtr != NULL && _tempStoreCustomDataPtr != NULL ) 00044 params._callbackDestroyPtr( _tempStoreCustomDataPtr ); 00045 _tempStoreCustomDataPtr = static_cast<CustomDataPtr>( stringToPointer( _paramCustomData->getValue() ) ); 00046 } 00047 } 00048 00049 OutputBufferProcessParams OutputBufferPlugin::getProcessParams() const 00050 { 00051 OutputBufferProcessParams params; 00052 params._callbackPtr = reinterpret_cast<CallbackOutputImagePtr>( stringToPointer( _paramCallbackOutputPointer->getValue() ) ); 00053 params._customDataPtr = static_cast<CustomDataPtr>( stringToPointer( _paramCustomData->getValue() ) ); 00054 params._callbackDestroyPtr = reinterpret_cast<CallbackDestroyCustomDataPtr>( stringToPointer( _paramCallbackDestroyCustomData->getValue() ) ); 00055 return params; 00056 } 00057 00058 void OutputBufferPlugin::render( const OFX::RenderArguments& args ) 00059 { 00060 TUTTLE_TLOG( TUTTLE_INFO, " --> Output Buffer "); 00061 typedef std::vector<char, OfxAllocator<char> > DataVector; 00062 DataVector rawImage; 00063 char* rawImagePtrLink; 00064 00065 boost::scoped_ptr<OFX::Image> src( _clipSrc->fetchImage( args.time ) ); 00066 boost::scoped_ptr<OFX::Image> dst( _clipDst->fetchImage( args.time ) ); 00067 00068 // Get Image info 00069 const OfxRectI bounds = dst->getBounds(); 00070 const OFX::EBitDepth depth = dst->getPixelDepth(); 00071 const OFX::EPixelComponent components = dst->getPixelComponents(); 00072 const OFX::EField field = dst->getField(); 00073 00074 // User parameters 00075 OutputBufferProcessParams params = getProcessParams(); 00076 00077 const std::size_t imageDataBytes = dst->getBoundsImageDataBytes(); 00078 const std::size_t rowBytesToCopy = dst->getBoundsRowDataBytes(); 00079 00080 if( src->isLinearBuffer() && dst->isLinearBuffer() ) 00081 { 00082 // Two linear buffers. No copy needed. 00083 if( imageDataBytes ) 00084 { 00085 void* dataSrcPtr = src->getPixelAddress( bounds.x1, bounds.y1 ); 00086 void* dataDstPtr = dst->getPixelAddress( bounds.x1, bounds.y1 ); 00087 memcpy( dataDstPtr, dataSrcPtr, imageDataBytes ); 00088 00089 // No image copy 00090 rawImagePtrLink = (char *)dataDstPtr; 00091 } 00092 } 00093 else 00094 { 00095 // Non-linear buffer. Line by line copy. 00096 for( int y = bounds.y1; y < bounds.y2; ++y ) 00097 { 00098 void* dataSrcPtr = src->getPixelAddress( bounds.x1, y ); 00099 void* dataDstPtr = dst->getPixelAddress( bounds.x1, y ); 00100 memcpy( dataDstPtr, dataSrcPtr, rowBytesToCopy ); 00101 } 00102 if( params._callbackPtr != NULL ) 00103 { 00104 // need a temporary buffer copy to give a linear buffer to the callback 00105 rawImage.resize( imageDataBytes ); 00106 rawImagePtrLink = &rawImage.front(); 00107 for( int y = bounds.y1; y < bounds.y2; ++y ) 00108 { 00109 void* dataSrcPtr = src->getPixelAddress( bounds.x1, y ); 00110 void* dataDstPtr = rawImagePtrLink + rowBytesToCopy*(y-bounds.y1); 00111 memcpy( dataDstPtr, dataSrcPtr, rowBytesToCopy ); 00112 } 00113 } 00114 } 00115 00116 if( params._callbackPtr != NULL ) 00117 { 00118 params._callbackPtr( 00119 args.time, params._customDataPtr, rawImagePtrLink, 00120 bounds.x2-bounds.x1, bounds.y2-bounds.y1, rowBytesToCopy, 00121 depth, components, field ); 00122 } 00123 } 00124 00125 00126 } 00127 } 00128 }