TuttleOFX
1
|
00001 #include "AVReaderPlugin.hpp" 00002 #include "AVReaderProcess.hpp" 00003 #include "AVReaderDefinitions.hpp" 00004 00005 #include <libav/LibAVVideoReader.hpp> 00006 00007 #include <boost/gil/gil_all.hpp> 00008 #include <boost/filesystem.hpp> 00009 00010 namespace tuttle { 00011 namespace plugin { 00012 namespace av { 00013 namespace reader { 00014 00015 using namespace boost::gil; 00016 namespace fs = boost::filesystem; 00017 00018 AVReaderPlugin::AVReaderPlugin( OfxImageEffectHandle handle ) 00019 : AVOptionPlugin( handle ) 00020 , _errorInFile( false ) 00021 , _initReader( false ) 00022 { 00023 // We want to render a sequence 00024 setSequentialRender( true ); 00025 00026 _clipDst = fetchClip( kOfxImageEffectOutputClipName ); 00027 _paramFilepath = fetchStringParam( kTuttlePluginFilename ); 00028 _paramBitDepth = fetchChoiceParam( kTuttlePluginBitDepth ); 00029 _paramUseCustomSAR = fetchBooleanParam( kParamUseCustomSAR ); 00030 _paramCustomSAR = fetchDoubleParam( kParamCustomSAR ); 00031 00032 updateVisibleTools(); 00033 } 00034 00035 void AVReaderPlugin::updateVisibleTools() 00036 { 00037 OFX::InstanceChangedArgs args( this->timeLineGetTime() ); 00038 changedParam( args, kParamUseCustomSAR ); 00039 } 00040 00041 AVReaderParams AVReaderPlugin::getProcessParams() const 00042 { 00043 AVReaderParams params; 00044 00045 _paramFilepath->getValue( params._filepath ); 00046 return params; 00047 } 00048 00049 /** 00050 * @brief Open the video if not already opened. 00051 * @return If the video file is now open, 00052 * else the file doesn't exist, is unrecognized or is corrupted. 00053 */ 00054 bool AVReaderPlugin::ensureVideoIsOpen() 00055 { 00056 if( _reader.isOpen() ) 00057 return true; 00058 00059 // if we have not already tried 00060 if( !_errorInFile ) 00061 { 00062 _errorInFile = !_reader.open( _paramFilepath->getValue() ); 00063 } 00064 return !_errorInFile; 00065 } 00066 00067 void AVReaderPlugin::changedParam( const OFX::InstanceChangedArgs& args, const std::string& paramName ) 00068 { 00069 ReaderPlugin::changedParam( args, paramName ); 00070 if( paramName == kTuttlePluginFilename ) 00071 { 00072 _errorInFile = false; 00073 } 00074 else if( paramName == kParamUseCustomSAR ) 00075 { 00076 const bool useCustomSAR = _paramUseCustomSAR->getValue(); 00077 _paramCustomSAR->setIsSecretAndDisabled( !useCustomSAR ); 00078 } 00079 else if( paramName == kParamCustomSAR ) 00080 { 00081 const bool useCustomSAR = _paramUseCustomSAR->getValue(); 00082 if( ! useCustomSAR ) 00083 { 00084 // If we set a customSAR and the useCustomSAR param is not enabled, 00085 // use it directly! 00086 // This could not happen in a UI application, but only from command line or from API. 00087 _paramUseCustomSAR->setValue( true ); 00088 } 00089 } 00090 } 00091 00092 void AVReaderPlugin::getClipPreferences( OFX::ClipPreferencesSetter& clipPreferences ) 00093 { 00094 ReaderPlugin::getClipPreferences( clipPreferences ); 00095 clipPreferences.setOutputFrameVarying( true ); 00096 clipPreferences.setClipComponents( *_clipDst, OFX::ePixelComponentRGBA ); 00097 if( getExplicitBitDepthConversion() == eParamReaderBitDepthAuto ) 00098 { 00099 clipPreferences.setClipBitDepth( *_clipDst, OFX::eBitDepthUByte ); /// @todo tuttle: some video format may need other bit depth (how we can detect this ?) 00100 } 00101 00102 if( !ensureVideoIsOpen() ) 00103 return; 00104 00105 // options depending on input file 00106 const bool useCustomSAR = _paramUseCustomSAR->getValue(); 00107 const double customSAR = _paramCustomSAR->getValue(); 00108 clipPreferences.setPixelAspectRatio( *_clipDst, useCustomSAR ? customSAR : _reader.aspectRatio() ); 00109 clipPreferences.setOutputFrameRate( _reader.fps() ); 00110 00111 // Setup fielding 00112 switch( _reader.interlacment() ) 00113 { 00114 case eInterlacmentNone: 00115 { 00116 clipPreferences.setOutputFielding( OFX::eFieldNone ); 00117 break; 00118 } 00119 case eInterlacmentUpper: 00120 { 00121 clipPreferences.setOutputFielding( OFX::eFieldUpper ); 00122 break; 00123 } 00124 case eInterlacmentLower: 00125 { 00126 clipPreferences.setOutputFielding( OFX::eFieldLower ); 00127 break; 00128 } 00129 } 00130 } 00131 00132 bool AVReaderPlugin::getTimeDomain( OfxRangeD& range ) 00133 { 00134 if( !ensureVideoIsOpen() ) 00135 return false; 00136 00137 range.min = 0.0; 00138 range.max = (double)(_reader.nbFrames()-1); 00139 00140 //TUTTLE_LOG_VAR2( TUTTLE_INFO, range.min, range.max ); 00141 00142 return true; 00143 } 00144 00145 bool AVReaderPlugin::getRegionOfDefinition( const OFX::RegionOfDefinitionArguments& args, OfxRectD& rod ) 00146 { 00147 if( !ensureVideoIsOpen() ) 00148 return false; 00149 00150 const bool useCustomSAR = _paramUseCustomSAR->getValue(); 00151 const double customSAR = _paramCustomSAR->getValue(); 00152 00153 rod.x1 = 0; 00154 rod.x2 = _reader.width() * ( useCustomSAR ? customSAR : _reader.aspectRatio() ); 00155 rod.y1 = 0; 00156 rod.y2 = _reader.height(); 00157 return true; 00158 } 00159 00160 void AVReaderPlugin::beginSequenceRender( const OFX::BeginSequenceRenderArguments& args ) 00161 { 00162 ensureVideoIsOpen(); 00163 } 00164 00165 /** 00166 * @brief The overridden render function 00167 * @param[in] args Rendering parameters 00168 */ 00169 void AVReaderPlugin::render( const OFX::RenderArguments& args ) 00170 { 00171 if( !ensureVideoIsOpen() ) 00172 { 00173 BOOST_THROW_EXCEPTION( exception::Unknown() ); 00174 } 00175 00176 if( !_initReader ) 00177 { 00178 // set Format parameters 00179 AVFormatContext* avFormatContext; 00180 avFormatContext = avformat_alloc_context(); 00181 setParameters( _reader, eAVParamFormat, (void*)avFormatContext, AV_OPT_FLAG_DECODING_PARAM, 0 ); 00182 avformat_free_context( avFormatContext ); 00183 00184 // set Video Codec parameters 00185 AVCodecContext* avCodecContext; 00186 00187 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT( 53, 8, 0 ) 00188 avCodecContext = avcodec_alloc_context(); 00189 // deprecated in the same version 00190 //avCodecContext = avcodec_alloc_context2( AVMEDIA_TYPE_UNKNOWN ); 00191 #else 00192 AVCodec* avCodec = NULL; 00193 avCodecContext = avcodec_alloc_context3( avCodec ); 00194 #endif 00195 setParameters( _reader, eAVParamVideo, (void*)avCodecContext, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM, 0 ); 00196 } 00197 00198 doGilRender<AVReaderProcess>( *this, args ); 00199 } 00200 00201 void AVReaderPlugin::endSequenceRender( const OFX::EndSequenceRenderArguments& args ) 00202 { 00203 _reader.close(); 00204 } 00205 00206 } 00207 } 00208 } 00209 }