TuttleOFX  1
SwscalePlugin.cpp
Go to the documentation of this file.
00001 #include "SwscalePlugin.hpp"
00002 #include "SwscaleProcess.hpp"
00003 #include "SwscaleDefinitions.hpp"
00004 
00005 #include <libav/LibAV.hpp>
00006 
00007 #include <tuttle/plugin/ofxToGil/point.hpp>
00008 #include <terry/point/operations.hpp>
00009 #include <boost/numeric/conversion/cast.hpp>
00010 
00011 
00012 namespace tuttle {
00013 namespace plugin {
00014 namespace swscale {
00015 
00016 using boost::numeric_cast;
00017 
00018 
00019 int filterParamToSwscaleFlag( const EParamFilter paramFilter )
00020 {
00021         switch( paramFilter )
00022         {
00023                 case eParamFilterFastBilinear:
00024                         return SWS_FAST_BILINEAR;
00025                 case eParamFilterBilinear:
00026                         return SWS_BILINEAR;
00027                 case eParamFilterBicubic:
00028                         return SWS_BICUBIC;
00029                 case eParamFilterX:
00030                         return SWS_X;
00031                 case eParamFilterPoint:
00032                         return SWS_POINT;
00033                 case eParamFilterArea:
00034                         return SWS_AREA;
00035                 case eParamFilterBicublin:
00036                         return SWS_BICUBLIN;
00037                 case eParamFilterGauss:
00038                         return SWS_GAUSS;
00039                 case eParamFilterSinc:
00040                         return SWS_SINC;
00041                 case eParamFilterLanczos:
00042                         return SWS_LANCZOS;
00043                 case eParamFilterSpline:
00044                         return SWS_SPLINE;
00045         }
00046         BOOST_ASSERT( false );
00047         return SWS_FAST_BILINEAR;
00048 }
00049 
00050 
00051 
00052 SwscalePlugin::SwscalePlugin( OfxImageEffectHandle handle )
00053         : ImageEffectGilPlugin( handle )
00054 {
00055         _paramMode            = fetchChoiceParam   ( kParamMode );
00056 
00057         _paramFormat          = fetchChoiceParam   ( kParamFormat );
00058 
00059         _paramScale           = fetchDouble2DParam ( kParamModeScale );
00060         
00061         _paramSize            = fetchInt2DParam    ( kParamSize );
00062         _paramSizeWidth       = fetchIntParam      ( kParamSizeWidth );
00063         _paramSizeHeight      = fetchIntParam      ( kParamSizeHeight );
00064         _paramSizeOrientation = fetchChoiceParam   ( kParamSizeOrientation );
00065         _paramSizeKeepRatio   = fetchBooleanParam  ( kParamSizeKeepRatio );
00066 
00067         _paramFilter          = fetchChoiceParam   ( kParamFilter );
00068         
00069         updateVisibleTools();
00070 }
00071 
00072 void SwscalePlugin::updateVisibleTools()
00073 {
00074         OFX::InstanceChangedArgs args( this->timeLineGetTime() );
00075         
00076         changedParam( args, kParamMode );
00077         changedParam( args, kParamFilter );
00078         changedParam( args, kParamSizeKeepRatio );
00079         changedParam( args, kParamSizeOrientation );
00080 }
00081 
00082 SwscaleProcessParams SwscalePlugin::getProcessParams( const OfxPointD& renderScale ) const
00083 {
00084         SwscaleProcessParams params;
00085         
00086         params._filter = static_cast<EParamFilter>( _paramFilter-> getValue() );
00087         params._sws_filter = filterParamToSwscaleFlag( params._filter );
00088         
00089         return params;
00090 }
00091 
00092 void SwscalePlugin::changedParam( const OFX::InstanceChangedArgs &args, const std::string &paramName )
00093 {
00094         ImageEffectGilPlugin::changedParam( args, paramName );
00095 
00096         if( paramName == kParamMode )
00097         {
00098                 switch( _paramMode->getValue() )
00099                 {
00100                         case eParamModeFormat:
00101                         {
00102                                 _paramScale           -> setIsSecretAndDisabled( true );
00103                                 _paramSize            -> setIsSecretAndDisabled( true );
00104                                 _paramSizeWidth       -> setIsSecretAndDisabled( true );
00105                                 _paramSizeHeight      -> setIsSecretAndDisabled( true );
00106                                 _paramSizeOrientation -> setIsSecretAndDisabled( true );
00107                                 _paramSizeKeepRatio   -> setIsSecretAndDisabled( true );
00108                                 
00109                                 _paramFormat          -> setIsSecretAndDisabled( false );
00110                                 break;
00111                         }
00112                         case eParamModeSize:
00113                         {
00114                                 const bool                  keepRatio   = _paramSizeKeepRatio->getValue();
00115                                 const EParamSizeOrientation orientation = static_cast<EParamSizeOrientation>(_paramSizeOrientation->getValue());
00116 
00117                                 _paramFormat          -> setIsSecretAndDisabled( true );
00118                                 _paramScale           -> setIsSecretAndDisabled( true );
00119 
00120                                 _paramSizeKeepRatio   -> setIsSecretAndDisabled( false );
00121 
00122                                 _paramSizeWidth       -> setIsSecretAndDisabled( ! keepRatio || orientation != eParamSizeOrientationX );
00123                                 _paramSizeHeight      -> setIsSecretAndDisabled( ! keepRatio || orientation != eParamSizeOrientationY );
00124                                 _paramSizeOrientation -> setIsSecretAndDisabled( ! keepRatio );
00125                                 _paramSize            -> setIsSecretAndDisabled( keepRatio );
00126                                 break;
00127                         }
00128                         case eParamModeScale:
00129                         {
00130                                 _paramFormat          -> setIsSecretAndDisabled( true );
00131                                 _paramSize            -> setIsSecretAndDisabled( true );
00132                                 _paramSizeWidth       -> setIsSecretAndDisabled( true );
00133                                 _paramSizeHeight      -> setIsSecretAndDisabled( true );
00134                                 _paramSizeOrientation -> setIsSecretAndDisabled( true );
00135                                 _paramSizeKeepRatio   -> setIsSecretAndDisabled( true );
00136                                 
00137                                 _paramScale           -> setIsSecretAndDisabled( false );
00138                                 break;
00139                         }
00140                 }
00141         }
00142         else if( paramName == kParamFormat && args.reason == OFX::eChangeUserEdit )
00143         {
00144                 std::size_t width  = 0;
00145                 std::size_t height = 0;
00146                 getFormatResolution( static_cast<EParamFormat>(_paramFormat->getValue()), width, height );
00147 
00148                 _paramMode            -> setValue( eParamModeFormat );
00149                 _paramSize            -> setValue( numeric_cast<int>(width), numeric_cast<int>(height) );
00150                 _paramSizeWidth       -> setValue( numeric_cast<int>(width) );
00151                 _paramSizeHeight      -> setValue( numeric_cast<int>(height) );
00152         }
00153         else if( paramName == kParamSize && args.reason == OFX::eChangeUserEdit )
00154         {
00155                 const OfxPointI s = _paramSize->getValue();
00156 
00157                 _paramMode->setValue( eParamModeSize );
00158                 _paramSizeWidth       -> setValue( s.x );
00159                 _paramSizeHeight      -> setValue( s.y );
00160         }
00161         else if( paramName == kParamSizeKeepRatio && args.reason == OFX::eChangeUserEdit )
00162         {
00163                 const bool                  keepRatio   = _paramSizeKeepRatio->getValue();
00164                 const EParamSizeOrientation orientation = static_cast<EParamSizeOrientation>(_paramSizeOrientation->getValue());
00165 
00166                 _paramSizeWidth       -> setIsSecretAndDisabled( ! keepRatio || orientation != eParamSizeOrientationX );
00167                 _paramSizeHeight      -> setIsSecretAndDisabled( ! keepRatio || orientation != eParamSizeOrientationY );
00168                 _paramSizeOrientation -> setIsSecretAndDisabled( ! keepRatio );
00169                 _paramSize            -> setIsSecretAndDisabled( keepRatio );
00170         }
00171         else if( paramName == kParamSizeOrientation && args.reason == OFX::eChangeUserEdit )
00172         {
00173                 const bool                  keepRatio   = _paramSizeKeepRatio->getValue();
00174                 const EParamSizeOrientation orientation = static_cast<EParamSizeOrientation>(_paramSizeOrientation->getValue());
00175 
00176                 _paramSizeWidth       -> setIsSecretAndDisabled( ! keepRatio || orientation != eParamSizeOrientationX );
00177                 _paramSizeHeight      -> setIsSecretAndDisabled( ! keepRatio || orientation != eParamSizeOrientationY );
00178         }
00179         else if( paramName == kParamSizeWidth && args.reason == OFX::eChangeUserEdit )
00180         {
00181                 _paramMode            -> setValue( eParamModeSize );
00182                 _paramSizeKeepRatio   -> setValue( true );
00183                 _paramSizeOrientation -> setValue( eParamSizeOrientationX );
00184                 
00185                 _paramSize            -> setValue( _paramSizeWidth->getValue(), _paramSize->getValue().y );
00186         }
00187         else if( paramName == kParamSizeHeight && args.reason == OFX::eChangeUserEdit )
00188         {
00189                 _paramMode            -> setValue( eParamModeSize );
00190                 _paramSizeKeepRatio   -> setValue( true );
00191                 _paramSizeOrientation -> setValue( eParamSizeOrientationY );
00192                 
00193                 _paramSize            -> setValue( _paramSize->getValue().x, _paramSizeHeight->getValue() );
00194         }
00195         else if( paramName == kParamScale && args.reason == OFX::eChangeUserEdit )
00196         {
00197                 _paramMode->setValue( eParamModeScale );
00198         }
00199 }
00200 
00201 bool SwscalePlugin::getRegionOfDefinition( const OFX::RegionOfDefinitionArguments& args, OfxRectD& rod )
00202 {
00203         using namespace boost::gil;
00204 
00205         const OfxRectD srcRod = _clipSrc->getCanonicalRod( args.time );
00206         const Point2   srcRodSize( srcRod.x2 - srcRod.x1, srcRod.y2 - srcRod.y1 );
00207         
00208         switch( _paramMode->getValue() )
00209         {
00210                 case eParamModeFormat :
00211                 {
00212                         std::size_t width = 0;
00213                         std::size_t height = 0;
00214                         getFormatResolution( static_cast<EParamFormat>(_paramFormat->getValue()), width, height );
00215                         rod.x1 = 0;
00216                         rod.y1 = 0;
00217                         rod.x2 = width;
00218                         rod.y2 = height;
00219 
00220                         return true;
00221                 }
00222                 case eParamModeSize :
00223                 {
00224                         std::size_t sizex = 0;
00225                         std::size_t sizey = 0;
00226                         if( _paramSizeKeepRatio->getValue() )
00227                         {
00228                                 if( _paramSizeOrientation->getValue() == eParamSizeOrientationX )
00229                                 {
00230                                         sizex   = _paramSizeWidth->getValue();
00231                                         sizey   = srcRodSize.y / numeric_cast<double>(srcRodSize.x) * sizex;
00232                                 }
00233                                 else // direction == eParamSizeY
00234                                 {
00235                                         sizey   = _paramSizeHeight->getValue();
00236                                         sizex   = srcRodSize.x / numeric_cast<double>(srcRodSize.y) * sizey;
00237                                 }
00238                         }
00239                         else
00240                         {
00241                                 const OfxPointI s = _paramSize->getValue();
00242                                 sizex = s.x;
00243                                 sizey = s.y;
00244                         }
00245 
00246                         rod.x1 = 0;
00247                         rod.y1 = 0;
00248                         rod.x2 = sizex;
00249                         rod.y2 = sizey;
00250 
00251                         return true;
00252                 }
00253                 case eParamModeScale :
00254                 {
00255                         const Point2 scale = ofxToGil( _paramScale->getValue() );
00256                         if( scale.x == 0.0 || scale.y == 0.0 )
00257                                 return false;
00258 
00259                         const Point2 dstSize( srcRodSize * scale );
00260                         rod.x1 = 0;
00261                         rod.y1 = 0;
00262                         rod.x2 = dstSize.x;
00263                         rod.y2 = dstSize.y;
00264                         return true;
00265                 }
00266         }
00267 
00268         return false;
00269 }
00270 
00271 //void SwscalePlugin::getRegionsOfInterest( const OFX::RegionsOfInterestArguments& args, OFX::RegionOfInterestSetter& rois )
00272 //{
00273 //      // TODO: to enable tiles...
00274 //}
00275 
00276 bool SwscalePlugin::isIdentity() const
00277 {
00278         switch( _paramMode->getValue() )
00279         {
00280                 case eParamModeFormat :
00281                 {
00282                         ///@todo could we read the input rod at this step?
00283                         return false;
00284                 }
00285                 case eParamModeSize :
00286                 {
00287                         ///@todo could we read the input rod at this step?
00288                         return false;
00289                 }
00290                 case eParamModeScale :
00291                 {
00292                         const Point2 scale = ofxToGil( _paramScale->getValue() );
00293                         if( scale.x == 1.0 && scale.y == 1.0 )
00294                                 return true;
00295                         return false;
00296                 }
00297         }
00298         return false;
00299 }
00300 
00301 bool SwscalePlugin::isIdentity( const OFX::RenderArguments& args, OFX::Clip*& identityClip, double& identityTime )
00302 {
00303         if( isIdentity() )
00304         {
00305                 identityClip = _clipSrc;
00306                 identityTime = args.time;
00307                 return true;
00308         }
00309         return false;
00310 }
00311 
00312 /**
00313  * @brief The overridden render function
00314  * @param[in]   args     Rendering parameters
00315  */
00316 void SwscalePlugin::render( const OFX::RenderArguments &args )
00317 {
00318         OFX::ImageEffectHostDescription* desc = OFX::getImageEffectHostDescription();
00319         
00320         if( desc->_supportedPixelDepths.size() == 1 && OFX::eBitDepthFloat == desc->_supportedPixelDepths.at(0) )
00321         {
00322                 BOOST_THROW_EXCEPTION( exception::BitDepthMismatch()
00323                         << exception::user( "SwScale: unsupported plugin on this host." ) );
00324         }
00325         
00326         SwscaleProcess procObj( *this );
00327         procObj.setupAndProcess( args );
00328 }
00329 
00330 
00331 }
00332 }
00333 }