TuttleOFX
1
|
00001 #include "AVWriterPlugin.hpp" 00002 #include "AVWriterProcess.hpp" 00003 #include "AVWriterDefinitions.hpp" 00004 00005 #include <libav/LibAVPreset.hpp> 00006 #include <libav/LibAVFormatPreset.hpp> 00007 #include <libav/LibAVVideoPreset.hpp> 00008 #include <libav/LibAVAudioPreset.hpp> 00009 #include <libav/LibAVVideoWriter.hpp> 00010 #include <libav/LibAVOptions.hpp> 00011 00012 #include <boost/gil/gil_all.hpp> 00013 #include <boost/foreach.hpp> 00014 00015 #include <cctype> 00016 00017 namespace tuttle { 00018 namespace plugin { 00019 namespace av { 00020 namespace writer { 00021 00022 void AVWriterPlugin::disableAVOptionsForCodecOrFormat( const std::vector<AVPrivOption>& avPrivOpts, const std::string& codec ) 00023 { 00024 std::vector<OFX::GroupParam*> groups; 00025 00026 BOOST_FOREACH( AVPrivOption opt, avPrivOpts ) 00027 { 00028 if( opt.o.unit && opt.o.type == AV_OPT_TYPE_FLAGS ) 00029 { 00030 std::string name = "g_"; 00031 name += opt.class_name; 00032 name += "_"; 00033 name += opt.o.unit; 00034 00035 OFX::GroupParam* curOpt = fetchGroupParam( name ); 00036 curOpt->setIsSecretAndDisabled( !( opt.class_name == codec ) ); 00037 00038 groups.push_back( curOpt ); 00039 continue; 00040 } 00041 if( opt.o.unit && opt.o.type == AV_OPT_TYPE_INT ) 00042 { 00043 std::string name = opt.class_name; 00044 name += "_"; 00045 name += opt.o.name; 00046 00047 OFX::ChoiceParam* curOpt = fetchChoiceParam( name ); 00048 curOpt->setIsSecretAndDisabled( !( opt.class_name == codec ) ); 00049 continue; 00050 } 00051 00052 std::string name = opt.class_name; 00053 name += "_"; 00054 name += opt.o.name; 00055 00056 switch( opt.o.type ) 00057 { 00058 case AV_OPT_TYPE_FLAGS: 00059 { 00060 OFX::BooleanParam* curOpt = fetchBooleanParam( name ); 00061 curOpt->setIsSecretAndDisabled( !( opt.class_name == codec ) ); 00062 break; 00063 } 00064 case AV_OPT_TYPE_INT: 00065 case AV_OPT_TYPE_INT64: 00066 { 00067 OFX::IntParam* curOpt = fetchIntParam( name ); 00068 curOpt->setIsSecretAndDisabled( !( opt.class_name == codec ) ); 00069 break; 00070 } 00071 case AV_OPT_TYPE_DOUBLE: 00072 case AV_OPT_TYPE_FLOAT: 00073 { 00074 OFX::DoubleParam* curOpt = fetchDoubleParam( name ); 00075 curOpt->setIsSecretAndDisabled( !( opt.class_name == codec ) ); 00076 break; 00077 } 00078 case AV_OPT_TYPE_STRING: 00079 { 00080 OFX::StringParam* curOpt = fetchStringParam( name ); 00081 curOpt->setIsSecretAndDisabled( !( opt.class_name == codec ) ); 00082 break; 00083 } 00084 case AV_OPT_TYPE_RATIONAL: 00085 { 00086 OFX::Int2DParam* curOpt = fetchInt2DParam( name ); 00087 curOpt->setIsSecretAndDisabled( !( opt.class_name == codec ) ); 00088 break; 00089 } 00090 case AV_OPT_TYPE_BINARY: 00091 { 00092 OFX::StringParam* curOpt = fetchStringParam( name ); 00093 curOpt->setIsSecretAndDisabled( !( opt.class_name == codec ) ); 00094 break; 00095 } 00096 case AV_OPT_TYPE_CONST: 00097 { 00098 break; 00099 } 00100 default: 00101 { 00102 TUTTLE_LOG_WARNING( "AudioVideo: undefined type for " << opt.o.name ); 00103 } 00104 } 00105 } 00106 00107 BOOST_FOREACH( AVPrivOption opt, avPrivOpts ) 00108 { 00109 switch( opt.o.type ) 00110 { 00111 case AV_OPT_TYPE_CONST: 00112 { 00113 BOOST_FOREACH( OFX::GroupParam* g, groups ) 00114 { 00115 std::string name = "g_"; 00116 name += opt.class_name; 00117 name += "_"; 00118 name += opt.o.unit; 00119 if( name == g->getName() ) 00120 { 00121 std::string name = "flags_"; 00122 name += opt.class_name; 00123 name += "_"; 00124 name += opt.o.name; 00125 00126 OFX::BooleanParam* curOpt = fetchBooleanParam( name ); 00127 curOpt->setIsSecretAndDisabled( !( opt.class_name == codec ) ); 00128 break; 00129 } 00130 } 00131 break; 00132 } 00133 default: 00134 { 00135 break; 00136 } 00137 } 00138 } 00139 } 00140 00141 void AVWriterPlugin::updatePixelFormat( const std::string& videoCodecName ) 00142 { 00143 AVCodec* _videoCodec = avcodec_find_encoder_by_name( videoCodecName.c_str() ); 00144 00145 _paramVideoPixelFormat->resetOptions(); 00146 if( _videoCodec->pix_fmts == 0 ) 00147 { 00148 for( int pix_fmt = 0; pix_fmt < PIX_FMT_NB; pix_fmt++ ) 00149 { 00150 const AVPixFmtDescriptor *pix_desc = &av_pix_fmt_descriptors[pix_fmt]; 00151 if(!pix_desc->name) 00152 continue; 00153 _paramVideoPixelFormat->appendOption( pix_desc->name ); 00154 } 00155 return; 00156 } 00157 00158 int i = 0; 00159 while( _videoCodec->pix_fmts[i] != -1 ) 00160 { 00161 const AVPixFmtDescriptor *pix_desc = &av_pix_fmt_descriptors[ _videoCodec->pix_fmts[i] ]; 00162 _paramVideoPixelFormat->appendOption( pix_desc->name ); 00163 i++; 00164 } 00165 } 00166 00167 AVWriterPlugin::AVWriterPlugin( OfxImageEffectHandle handle ) 00168 : AVOptionPlugin( handle ) 00169 , _initWriter ( false ) 00170 { 00171 // We want to render a sequence 00172 setSequentialRender( true ); 00173 00174 _paramFormat = AVOptionPlugin::fetchChoiceParam( kParamFormat ); 00175 _paramVideoCodec = fetchChoiceParam( kParamVideoCodec ); 00176 _paramAudioCodec = fetchChoiceParam( kParamAudioCodec ); 00177 00178 _paramMainPreset = fetchChoiceParam( kParamMainPreset ); 00179 _paramFormatPreset = fetchChoiceParam( kParamFormatPreset ); 00180 _paramVideoCodecPreset = fetchChoiceParam( kParamVideoPreset ); 00181 _paramAudioCodecPreset = fetchChoiceParam( kParamAudioPreset ); 00182 00183 _paramUseCustomFps = fetchBooleanParam( kParamUseCustomFps ); 00184 _paramCustomFps = fetchDoubleParam( kParamCustomFps ); 00185 00186 _paramVideoPixelFormat = fetchChoiceParam( kParamVideoCodecPixelFmt ); 00187 00188 std::string formatName = _writer.getFormatsShort( ).at(_paramFormat->getValue() ); 00189 disableAVOptionsForCodecOrFormat( _writer.getFormatPrivOpts(), formatName ); 00190 00191 std::string videoCodecName = _writer.getVideoCodecsShort( ).at(_paramVideoCodec->getValue() ); 00192 disableAVOptionsForCodecOrFormat( _writer.getVideoCodecPrivOpts(), videoCodecName ); 00193 00194 updatePixelFormat( videoCodecName ); 00195 00196 std::string audioCodecName = _writer.getAudioCodecsShort( ).at(_paramAudioCodec->getValue() ); 00197 disableAVOptionsForCodecOrFormat( _writer.getAudioCodecPrivOpts(), audioCodecName ); 00198 } 00199 00200 AVProcessParams AVWriterPlugin::getProcessParams() 00201 { 00202 AVProcessParams params; 00203 00204 params._filepath = _paramFilepath->getValue(); 00205 params._format = _paramFormat->getValue(); 00206 params._videoCodec = _paramVideoCodec ->getValue(); 00207 params._audioCodec = _paramAudioCodec ->getValue(); 00208 params._videoPixelFormat = static_cast<PixelFormat>( _paramVideoPixelFormat->getValue() ); 00209 00210 _writer.setVideoCodec( params._videoCodec ); 00211 00212 return params; 00213 } 00214 00215 void AVWriterPlugin::changedParam( const OFX::InstanceChangedArgs& args, const std::string& paramName ) 00216 { 00217 WriterPlugin::changedParam( args, paramName ); 00218 00219 if( paramName == kParamFormat ) 00220 { 00221 std::string formatName = _writer.getFormatsShort( ).at(_paramFormat->getValue() ); 00222 disableAVOptionsForCodecOrFormat( _writer.getFormatPrivOpts(), formatName ); 00223 } 00224 if( paramName == kParamVideoCodec ) 00225 { 00226 std::string videoCodecName = _writer.getVideoCodecsShort( ).at(_paramVideoCodec->getValue() ); 00227 disableAVOptionsForCodecOrFormat( _writer.getVideoCodecPrivOpts(), videoCodecName ); 00228 updatePixelFormat( videoCodecName ); 00229 } 00230 if( paramName == kParamAudioCodec ) 00231 { 00232 std::string codecName = _writer.getAudioCodecsShort( ).at(_paramAudioCodec->getValue() ); 00233 disableAVOptionsForCodecOrFormat( _writer.getAudioCodecPrivOpts(), codecName ); 00234 } 00235 00236 if( paramName == kParamMainPreset ) 00237 { 00238 //TUTTLE_LOG_TRACE( "preset change " << _paramMainPreset->getValue() ); 00239 if( _paramMainPreset->getValue() == 0 ) 00240 return; 00241 00242 std::vector<std::string> idList; 00243 std::vector<std::string> idLabelList; 00244 LibAVPreset::getPresetList( idList, idLabelList ); 00245 00246 LibAVPreset p( idList.at( _paramMainPreset->getValue() - 1 ) ); 00247 00248 std::vector<std::string> idFormatList; 00249 LibAVFormatPreset::getPresetList( idFormatList ); 00250 00251 std::vector<std::string> idVideoList; 00252 LibAVVideoPreset::getPresetList( idVideoList ); 00253 00254 std::vector<std::string> idAudioList; 00255 LibAVAudioPreset::getPresetList( idAudioList); 00256 00257 int formatIndex = 0; 00258 int videoIndex = 0; 00259 int audioIndex = 0; 00260 for( unsigned int id = 0; id < idFormatList.size(); id++ ) 00261 { 00262 if( idFormatList.at( id ) == p.getFormatID() ) 00263 { 00264 formatIndex = id + 1; 00265 break; 00266 } 00267 } 00268 00269 for( unsigned int id = 0; id < idVideoList.size(); id++ ) 00270 { 00271 if( idVideoList.at( id ) == p.getVideoID() ) 00272 { 00273 videoIndex = id + 1; 00274 break; 00275 } 00276 } 00277 00278 00279 for( unsigned int id = 0; id < idAudioList.size(); id++ ) 00280 { 00281 if( idAudioList.at( id ) == p.getAudioID() ) 00282 { 00283 audioIndex = id + 1; 00284 break; 00285 } 00286 } 00287 /* 00288 TUTTLE_LOG_INFO( "set format at " << formatIndex ); 00289 TUTTLE_LOG_INFO( "set video at " << formatIndex ); 00290 TUTTLE_LOG_INFO( "set audio at " << formatIndex );*/ 00291 00292 _paramFormatPreset->setValue( formatIndex ); 00293 _paramVideoCodecPreset->setValue( videoIndex ); 00294 _paramAudioCodecPreset->setValue( audioIndex ); 00295 } 00296 00297 if( paramName == kParamFormatPreset ) 00298 { 00299 //TUTTLE_LOG_INFO( "preset change " << _paramFormatPreset->getValue() ); 00300 if( _paramFormatPreset->getValue() == 0 ) 00301 return; 00302 std::vector<std::string> idFormatList; 00303 LibAVFormatPreset::getPresetList( idFormatList ); 00304 00305 LibAVFormatPreset p( idFormatList.at( _paramFormatPreset->getValue() - 1 ) ); 00306 setParameters( p.getParameters() ); 00307 } 00308 00309 if( paramName == kParamVideoPreset ) 00310 { 00311 if( _paramVideoCodecPreset->getValue() == 0 ) 00312 return; 00313 std::vector<std::string> idVideoList; 00314 LibAVVideoPreset::getPresetList( idVideoList ); 00315 00316 LibAVVideoPreset p( idVideoList.at( _paramVideoCodecPreset->getValue() - 1 ) ); 00317 setParameters( p.getParameters() ); 00318 } 00319 00320 if( paramName == kParamAudioPreset ) 00321 { 00322 if( _paramAudioCodecPreset->getValue() == 0 ) 00323 return; 00324 std::vector<std::string> idAudioList; 00325 LibAVAudioPreset::getPresetList( idAudioList); 00326 00327 LibAVAudioPreset p( idAudioList.at( _paramAudioCodecPreset->getValue() - 1 ) ); 00328 setParameters( p.getParameters() ); 00329 } 00330 } 00331 00332 void AVWriterPlugin::getClipPreferences( OFX::ClipPreferencesSetter& clipPreferences ) 00333 { 00334 // Need to be computed at each frame 00335 clipPreferences.setOutputFrameVarying( true ); 00336 } 00337 00338 bool AVWriterPlugin::isIdentity( const OFX::RenderArguments& args, OFX::Clip*& identityClip, OfxTime& identityTime ) 00339 { 00340 return WriterPlugin::isIdentity( args, identityClip, identityTime ); 00341 } 00342 00343 void AVWriterPlugin::beginSequenceRender( const OFX::BeginSequenceRenderArguments& args ) 00344 { 00345 _initWriter = false; 00346 WriterPlugin::beginSequenceRender( args ); 00347 00348 AVProcessParams params = getProcessParams(); 00349 00350 //TUTTLE_LOG_VAR( TUTTLE_WARNING, _clipSrc->getFrameRate() ); 00351 00352 _writer.setFilename ( params._filepath ); 00353 _writer.setFormat ( params._format ); 00354 _writer.setVideoCodec ( params._videoCodec ); 00355 if( _paramUseCustomFps->getValue() ) 00356 { 00357 _writer.setFps( _paramCustomFps->getValue() ); 00358 } 00359 else 00360 { 00361 _writer.setFps( _clipSrc->getFrameRate() ); 00362 } 00363 _writer.setAspectRatio ( _clipSrc->getPixelAspectRatio() ); 00364 _writer.setPixelFormat ( params._videoPixelFormat ); 00365 } 00366 00367 /** 00368 * @brief The overridden render function 00369 * @param[in] args Rendering parameters 00370 */ 00371 void AVWriterPlugin::render( const OFX::RenderArguments& args ) 00372 { 00373 WriterPlugin::render( args ); 00374 00375 //OfxRangeD range = args.frameRange; 00376 const OfxRectI bounds = _clipSrc->getPixelRod( args.time, args.renderScale ); 00377 _writer.setWidth ( bounds.x2 - bounds.x1 ); 00378 _writer.setHeight( bounds.y2 - bounds.y1 ); 00379 00380 if( !_initWriter ) 00381 { 00382 _writer.start( ); 00383 00384 // set Format parameters 00385 AVFormatContext* avFormatContext; 00386 avFormatContext = avformat_alloc_context(); 00387 setParameters( _writer, eAVParamFormat, (void*)avFormatContext, AV_OPT_FLAG_ENCODING_PARAM, 0 ); 00388 00389 std::string formatName = _writer.getFormatsShort( ).at(_paramFormat->getValue() ); 00390 setParameters( _writer, eAVParamFormat, _writer.getFormatPrivOpts(), formatName ); 00391 00392 // set Video Codec parameters 00393 AVCodecContext* avCodecContext; 00394 00395 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT( 53, 8, 0 ) 00396 avCodecContext = avcodec_alloc_context(); 00397 // deprecated in the same version 00398 //avCodecContext = avcodec_alloc_context2( AVMEDIA_TYPE_UNKNOWN ); 00399 #else 00400 AVCodec* avCodec = NULL; 00401 avCodecContext = avcodec_alloc_context3( avCodec ); 00402 #endif 00403 setParameters( _writer, eAVParamVideo, (void*)avCodecContext, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM, 0 ); 00404 00405 std::string codecName = _writer.getVideoCodecsShort( ).at(_paramVideoCodec->getValue() ); 00406 setParameters( _writer, eAVParamVideo, _writer.getVideoCodecPrivOpts(), codecName ); 00407 00408 // set Audio Codec parameters 00409 //codecName = _writer.getAudioCodecsShort( ).at(_paramAudioCodec->getValue() ); 00410 //setParameters( _writer, eAVParamAudio, _writer.getAudioCodecPrivOpts(), codecName ); 00411 00412 _writer.finishInit(); 00413 00414 _initWriter = true; 00415 } 00416 00417 doGilRender<AVWriterProcess>( *this, args ); 00418 } 00419 00420 void AVWriterPlugin::endSequenceRender( const OFX::EndSequenceRenderArguments& args ) 00421 { 00422 _writer.finish(); 00423 _initWriter = false; 00424 } 00425 00426 } 00427 } 00428 } 00429 }