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