TuttleOFX  1
AVWriterPluginFactory.cpp
Go to the documentation of this file.
00001 #include "AVWriterPluginFactory.hpp"
00002 #include "AVWriterPlugin.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/LibAVOptionsFactory.hpp>
00011 
00012 
00013 #include <tuttle/plugin/context/WriterPluginFactory.hpp>
00014 
00015 #include <boost/algorithm/string/join.hpp>
00016 #include <boost/algorithm/string/split.hpp>
00017 #include <boost/algorithm/string/classification.hpp>
00018 
00019 #include <string>
00020 #include <vector>
00021 
00022 namespace tuttle {
00023 namespace plugin {
00024 namespace av {
00025 namespace writer {
00026 
00027 /**
00028  * @brief Function called to describe the plugin main features.
00029  * @param[in, out]   desc     Effect descriptor
00030  */
00031 void AVWriterPluginFactory::describe( OFX::ImageEffectDescriptor& desc )
00032 {
00033         desc.setLabels(
00034                 "TuttleAVWriter",
00035                 "AVWriter",
00036                 "Audio Video writer" );
00037         desc.setPluginGrouping( "tuttle/image/io" );
00038 
00039         std::vector<std::string> supportedExtensions;
00040         {
00041                 AVOutputFormat* oFormat = av_oformat_next( NULL );
00042                 while( oFormat != NULL )
00043                 {
00044                         if( oFormat->extensions != NULL )
00045                         {
00046                                 using namespace boost::algorithm;
00047                                 const std::string extStr( oFormat->extensions );
00048                                 std::vector<std::string> exts;
00049                                 split( exts, extStr, is_any_of(",") );
00050                                 
00051                                 // remove empty extensions...
00052                                 for( std::vector<std::string>::iterator it = exts.begin(); it != exts.end(); )
00053                                 {
00054                                         if( it->size() == 0 )
00055                                                 it = exts.erase( it );
00056                                         else
00057                                                 ++it;
00058                                 }
00059                                 supportedExtensions.insert( supportedExtensions.end(), exts.begin(), exts.end() );
00060                         }
00061                         oFormat = av_oformat_next( oFormat );
00062                 }
00063         }
00064         
00065         desc.setDescription( "Video writer based on LibAV library\n\n"
00066                         "Supported extensions: \n" +
00067                         boost::algorithm::join( supportedExtensions, ", " )
00068                 );
00069         
00070         // add the supported contexts
00071         desc.addSupportedContext( OFX::eContextWriter );
00072         desc.addSupportedContext( OFX::eContextGeneral );
00073 
00074         // add supported pixel depths
00075         desc.addSupportedBitDepth( OFX::eBitDepthUByte );
00076         desc.addSupportedBitDepth( OFX::eBitDepthUShort );
00077         desc.addSupportedBitDepth( OFX::eBitDepthFloat );
00078 
00079         // add supported extensions
00080         desc.addSupportedExtensions( supportedExtensions );
00081         
00082         // plugin flags
00083         desc.setRenderThreadSafety( OFX::eRenderInstanceSafe );
00084         desc.setHostFrameThreading( false );
00085         desc.setSupportsMultiResolution( false );
00086         desc.setSupportsMultipleClipDepths( true );
00087         desc.setSupportsTiles( kSupportTiles );
00088 }
00089 
00090 /**
00091  * @brief Function called to describe the plugin controls and features.
00092  * @param[in, out]   desc       Effect descriptor
00093  * @param[in]        context    Application context
00094  */
00095 void AVWriterPluginFactory::describeInContext( OFX::ImageEffectDescriptor& desc,
00096                                                    OFX::EContext               context )
00097 {
00098         LibAVVideoWriter writer;
00099 
00100         OFX::ClipDescriptor* srcClip = desc.defineClip( kOfxImageEffectSimpleSourceClipName );
00101 
00102         srcClip->addSupportedComponent( OFX::ePixelComponentRGBA );
00103         srcClip->addSupportedComponent( OFX::ePixelComponentRGB );
00104         srcClip->addSupportedComponent( OFX::ePixelComponentAlpha );
00105         srcClip->setSupportsTiles( kSupportTiles );
00106 
00107         // Create the mandated output clip
00108         OFX::ClipDescriptor* dstClip = desc.defineClip( kOfxImageEffectOutputClipName );
00109         dstClip->addSupportedComponent( OFX::ePixelComponentRGBA );
00110         dstClip->addSupportedComponent( OFX::ePixelComponentRGB );
00111         dstClip->addSupportedComponent( OFX::ePixelComponentAlpha );
00112         dstClip->setSupportsTiles( kSupportTiles );
00113         
00114         // Controls
00115         describeWriterParamsInContext( desc, context );
00116         OFX::ChoiceParamDescriptor* bitDepth = static_cast<OFX::ChoiceParamDescriptor*>( desc.getParamDescriptor( kTuttlePluginBitDepth ) );
00117         bitDepth->appendOption( kTuttlePluginBitDepth8 );
00118         /// @todo: 16 bits
00119         bitDepth->setDefault( eTuttlePluginBitDepth8 );
00120         bitDepth->setEnabled( false );
00121 
00122         OFX::BooleanParamDescriptor* premult = static_cast<OFX::BooleanParamDescriptor*>( desc.getParamDescriptor( kParamPremultiplied ) );
00123         premult->setDefault( true );
00124         
00125         /// MAIN PRESET SELECTOR
00126         OFX::ChoiceParamDescriptor* mainPreset = desc.defineChoiceParam( kParamMainPreset );
00127         mainPreset->setLabel( "Main Preset" );
00128         mainPreset->appendOption( "custom", "Customized configuration" );
00129         
00130         std::vector<std::string> idList;
00131         std::vector<std::string> idLabelList;
00132         LibAVPreset::getPresetList( idList, idLabelList );
00133         for( unsigned int it = 0; it < idList.size(); ++it )
00134         {
00135                 mainPreset->appendOption( idList.at( it ), idLabelList.at( it ) );
00136         }
00137         
00138         // Groups
00139         OFX::GroupParamDescriptor* formatGroup = desc.defineGroupParam( kParamFormatGroup );
00140         OFX::GroupParamDescriptor* videoGroup  = desc.defineGroupParam( kParamVideoGroup );
00141         OFX::GroupParamDescriptor* audioGroup  = desc.defineGroupParam( kParamAudioGroup );
00142         OFX::GroupParamDescriptor* metaGroup   = desc.defineGroupParam( kParamMetaGroup );
00143         
00144         formatGroup->setLabel( "Format" );
00145         videoGroup->setLabel( "Video" );
00146         audioGroup->setLabel( "Audio" );
00147         metaGroup->setLabel( "Metadata" );
00148         
00149         formatGroup->setAsTab( );
00150         videoGroup->setAsTab( );
00151         audioGroup->setAsTab( );
00152         metaGroup->setAsTab( );
00153         
00154         /// FORMAT PARAMETERS
00155         /// format preset
00156         OFX::ChoiceParamDescriptor* formatPreset = desc.defineChoiceParam( kParamFormatPreset );
00157         formatPreset->setLabel( "Format Preset" );
00158         formatPreset->appendOption( "custom", "Customized configuration" );
00159         std::vector<std::string> idFormatList;
00160         std::vector<std::string> idFormatLabelList;
00161         LibAVFormatPreset::getPresetList( idFormatList, idFormatLabelList );
00162         for( unsigned int it = 0; it < idFormatList.size(); ++it )
00163         {
00164                 formatPreset->appendOption( idFormatList.at( it ), idFormatLabelList.at( it ) );
00165         }
00166         formatPreset->setParent( formatGroup );
00167         
00168         /// format list
00169         int default_format = 0;
00170         OFX::ChoiceParamDescriptor* format = desc.defineChoiceParam( kParamFormat );
00171         for( std::vector<std::string>::const_iterator itShort = writer.getFormatsShort().begin(),
00172                 itLong = writer.getFormatsLong().begin(),
00173                 itEnd = writer.getFormatsShort().end();
00174                 itShort != itEnd;
00175                 ++itShort,
00176                 ++itLong )
00177         {
00178                 format->appendOption( *itShort, *itLong );
00179                 if( (*itShort) == "mp4" )
00180                         default_format = format->getNOptions() - 1;
00181         }
00182         format->setCacheInvalidation( OFX::eCacheInvalidateValueAll );
00183         format->setDefault( default_format );
00184         format->setParent( formatGroup );
00185         
00186         AVFormatContext* avFormatContext;
00187         avFormatContext = avformat_alloc_context();
00188         addOptionsFromAVOption( desc, formatGroup, (void*)avFormatContext, AV_OPT_FLAG_ENCODING_PARAM, 0 );
00189         avformat_free_context( avFormatContext );
00190         
00191         /// format parameters
00192         OFX::GroupParamDescriptor* formatDetailledGroup = desc.defineGroupParam( kParamFormatDetailledGroup );
00193         formatDetailledGroup->setLabel( "Detailled" );
00194         formatDetailledGroup->setAsTab( );
00195         formatDetailledGroup->setParent( formatGroup );
00196         
00197         addOptionsFromAVOption( desc, formatDetailledGroup, writer.getFormatPrivOpts() );
00198         
00199         // fps parameters
00200         OFX::BooleanParamDescriptor* useCustomFps = desc.defineBooleanParam( kParamUseCustomFps );
00201         useCustomFps->setLabel( "Override Fps" );
00202         useCustomFps->setDefault( false );
00203         useCustomFps->setHint( "Override the input Fps (Frames Per Second) with a custom Fps value." );
00204 
00205         OFX::DoubleParamDescriptor* customFps = desc.defineDoubleParam( kParamCustomFps );
00206         customFps->setLabel( "Custom Fps" );
00207         customFps->setDefault( 1.0 );
00208         customFps->setHint( "Choose a custom value to override the Fps (Frames Per Second)." );
00209         
00210         /// VIDEO PARAMETERS
00211         /// video codec preset
00212         OFX::ChoiceParamDescriptor* videoPreset = desc.defineChoiceParam( kParamVideoPreset );
00213         videoPreset->setLabel( "Video Preset" );
00214         videoPreset->appendOption( "custom", "Customized configuration" );
00215         
00216         std::vector<std::string> idVideoList;
00217         std::vector<std::string> idVideoLabelList;
00218         LibAVVideoPreset::getPresetList( idVideoList, idVideoLabelList );
00219         for( unsigned int it = 0; it < idVideoList.size(); ++it )
00220         {
00221                 videoPreset->appendOption( idVideoList.at( it ), idVideoLabelList.at( it ) );
00222         }
00223         videoPreset->setParent( videoGroup );
00224         
00225         /// video codec list
00226         int default_codec = 0;
00227         OFX::ChoiceParamDescriptor* videoCodec = desc.defineChoiceParam( kParamVideoCodec );
00228         for( std::vector<std::string>::const_iterator itShort = writer.getVideoCodecsShort().begin(),
00229                 itLong  = writer.getVideoCodecsLong().begin(),
00230                 itEnd = writer.getVideoCodecsShort().end();
00231                 itShort != itEnd;
00232                 ++itShort,
00233                 ++itLong )
00234         {
00235                 videoCodec->appendOption( *itShort, *itLong );
00236                 if( (*itShort) == "mpeg4" )
00237                         default_codec = videoCodec->getNOptions() - 1;
00238         }
00239         videoCodec->setCacheInvalidation( OFX::eCacheInvalidateValueAll );
00240         videoCodec->setDefault( default_codec );
00241         videoCodec->setParent( videoGroup );
00242         
00243         /// video codec parameters
00244         OFX::ChoiceParamDescriptor* videoCodecPixelFmt = desc.defineChoiceParam( kParamVideoCodecPixelFmt );
00245         videoCodecPixelFmt->setLabel( kParamVideoCodecPixelFmt );
00246         videoCodecPixelFmt->setLabel( "Select the output video pixel type." );
00247         
00248         for( int pix_fmt = 0; pix_fmt < PIX_FMT_NB; pix_fmt++ )
00249         {
00250                 const AVPixFmtDescriptor *pix_desc = &av_pix_fmt_descriptors[pix_fmt];
00251                 if(!pix_desc->name)
00252                         continue;
00253                 videoCodecPixelFmt->appendOption( pix_desc->name );
00254         }
00255         videoCodecPixelFmt->setParent( videoGroup );
00256         
00257         AVCodecContext* avCodecContext;
00258 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT( 53, 8, 0 )
00259         avCodecContext = avcodec_alloc_context();
00260         // deprecated in the same version
00261         //avCodecContext = avcodec_alloc_context2( AVMEDIA_TYPE_UNKNOWN );
00262 #else
00263         AVCodec* avCodec = NULL;
00264         avCodecContext = avcodec_alloc_context3( avCodec );
00265 #endif
00266         
00267         addOptionsFromAVOption( desc, videoGroup, (void*)avCodecContext, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM, 0 );
00268         
00269         OFX::GroupParamDescriptor* videoDetailledGroup  = desc.defineGroupParam( kParamVideoDetailledGroup );
00270         videoDetailledGroup->setLabel( "Detailled" );
00271         videoDetailledGroup->setAsTab( );
00272         videoDetailledGroup->setParent( videoGroup );
00273         
00274         addOptionsFromAVOption( desc, videoDetailledGroup, writer.getVideoCodecPrivOpts() );
00275         
00276         /// AUDIO PARAMETERS
00277         /// audio codec preset
00278         OFX::ChoiceParamDescriptor* audioPreset = desc.defineChoiceParam( kParamAudioPreset );
00279         audioPreset->setLabel( "Audio Preset" );
00280         audioPreset->appendOption( "custom", "Customized configuration" );
00281         
00282         std::vector<std::string> idAudioList;
00283         std::vector<std::string> idAudioLabelList;
00284         LibAVAudioPreset::getPresetList( idAudioList, idAudioLabelList );
00285         for( unsigned int it = 0; it < idAudioList.size(); ++it )
00286         {
00287                 audioPreset->appendOption( idAudioList.at( it ), idAudioLabelList.at( it ) );
00288         }
00289         audioPreset->setParent( audioGroup );
00290         
00291         /// audio codec list
00292         int default_audio_codec = 0;
00293         OFX::ChoiceParamDescriptor* audioCodec = desc.defineChoiceParam( kParamAudioCodec );
00294         for( std::vector<std::string>::const_iterator itShort = writer.getAudioCodecsShort().begin(),
00295                 itLong  = writer.getAudioCodecsLong().begin(),
00296                 itEnd = writer.getAudioCodecsShort().end();
00297                 itShort != itEnd;
00298                 ++itShort,
00299                 ++itLong )
00300         {
00301                 audioCodec->appendOption( *itShort, *itLong );
00302                 if( (*itShort) == "pcm_s24be" )
00303                         default_audio_codec = audioCodec->getNOptions() - 1;
00304         }
00305         audioCodec->setCacheInvalidation( OFX::eCacheInvalidateValueAll );
00306         audioCodec->setDefault( default_audio_codec );
00307         audioCodec->setParent( audioGroup );
00308         
00309         /// audio codec parameters
00310         addOptionsFromAVOption( desc, audioGroup, (void*)avCodecContext, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM, AV_OPT_FLAG_VIDEO_PARAM );
00311         
00312         OFX::GroupParamDescriptor* audioDetailledGroup  = desc.defineGroupParam( kParamAudioDetailledGroup );
00313         audioDetailledGroup->setLabel( "Detailled" );
00314         audioDetailledGroup->setAsTab( );
00315         audioDetailledGroup->setParent( audioGroup );
00316         
00317         addOptionsFromAVOption( desc, audioDetailledGroup, writer.getAudioCodecPrivOpts() );
00318         
00319         av_free( avCodecContext );
00320         
00321         /// METADATA PARAMETERS
00322         OFX::GroupParamDescriptor* metaDetailledGroup   = desc.defineGroupParam( kParamMetaDetailledGroup );
00323         metaDetailledGroup->setLabel( "Detailled" );
00324         metaDetailledGroup->setAsTab( );
00325         metaDetailledGroup->setParent( metaGroup );
00326 }
00327 
00328 /**
00329  * @brief Function called to create a plugin effect instance
00330  * @param[in] handle  effect handle
00331  * @param[in] context    Application context
00332  * @return  plugin instance
00333  */
00334 OFX::ImageEffect* AVWriterPluginFactory::createInstance( OfxImageEffectHandle handle,
00335                                                              OFX::EContext        context )
00336 {
00337         return new AVWriterPlugin( handle );
00338 }
00339 
00340 }
00341 }
00342 }
00343 }