1 /* ***** BEGIN LICENSE BLOCK *****
2  * This file is part of openfx-io <https://github.com/MrKepzie/openfx-io>,
3  * Copyright (C) 2013-2018 INRIA
4  *
5  * openfx-io is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * openfx-io is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with openfx-io.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>
17  * ***** END LICENSE BLOCK ***** */
18 
19 /*
20  * OFX ffmpegReader plugin.
21  * Reads a video input file using the libav library.
22  *
23  * Synced with mov64Reader 11.1v3
24  *
25  * BUGS:
26  * - The last frames from long-GOP mp4 don't read, see:
27  *   - https://github.com/NatronGitHub/Natron/issues/241
28  *   - https://github.com/NatronGitHub/Natron/issues/231
29  * - MPEG1 files cannot be read, for example
30  *   - https://github.com/NatronGitHub/Natron-Tests/raw/master/TestReadMPEG1/input.mpg
31  *   - http://devernay.free.fr/vision/diffprop/herve3d.mpg
32  *   This was already true before the 11.1v3 sync (e.g. at commit 4d0d3a5).
33  */
34 
35 #if (defined(_STDINT_H) || defined(_STDINT_H_) || defined(_MSC_STDINT_H_ ) ) && !defined(UINT64_C)
36 #warning "__STDC_CONSTANT_MACROS has to be defined before including <stdint.h>, this file will probably not compile."
37 #endif
38 #ifndef __STDC_CONSTANT_MACROS
39 #define __STDC_CONSTANT_MACROS // ...or stdint.h wont' define UINT64_C, needed by libavutil
40 #endif
41 
42 #include <cmath>
43 #include <sstream>
44 #include <algorithm>
45 #ifdef DEBUG
46 #include <cstdio>
47 #define DBG(x) x
48 #else
49 #define DBG(x) (void)0
50 #endif
51 
52 #include "IOUtility.h"
53 
54 #include "GenericOCIO.h"
55 #include "GenericReader.h"
56 #include "FFmpegFile.h"
57 #include "ofxsCopier.h"
58 
59 using namespace OFX;
60 using namespace OFX::IO;
61 
62 using std::string;
63 using std::stringstream;
64 using std::vector;
65 
66 OFXS_NAMESPACE_ANONYMOUS_ENTER
67 
68 #define kPluginName "ReadFFmpeg"
69 #define kPluginGrouping "Image/Readers"
70 #define kPluginDescription "Read video using FFmpeg.\n" \
71 "All formats supported by FFmpeg should be supported, but there may be issues with some non-conform files. In this case, it is recommended to transcode the video to a digital intermediate format, which is more suitable for grading, compositing and video editing.\n" \
72 "This can be done using the ffmpeg command-line tool, by following the instructions at https://trac.ffmpeg.org/wiki/Encode/VFX"
73 
74 #define kPluginIdentifier "fr.inria.openfx.ReadFFmpeg"
75 #define kPluginVersionMajor 1 // Incrementing this number means that you have broken backwards compatibility of the plug-in.
76 #define kPluginVersionMinor 0 // Increment this when you have fixed a bug or made it faster.
77 #define kPluginEvaluation 0
78 
79 #define kParamMaxRetries "maxRetries"
80 #define kParamMaxRetriesLabel "Max retries per frame"
81 #define kParamMaxRetriesHint "Some video files are sometimes tricky to read and needs several retries before successfully decoding a frame. This" \
82     " parameter controls how many times we should attempt to decode the same frame before failing. "
83 
84 #define kParamFirstTrackOnly "firstTrackOnly"
85 #define kParamFirstTrackOnlyLabelAndHint "First Track Only", "Causes the reader to ignore all but the first video track it finds in the file. This should be selected in a multiview project if the file happens to contain multiple video tracks that don't correspond to different views."
86 
87 #define kParamLibraryInfo "libraryInfo"
88 #define kParamLibraryInfoLabel "FFmpeg Info...", "Display information about the underlying library."
89 
90 
91 #define kSupportsRGBA true
92 #define kSupportsRGB true
93 #define kSupportsXY false
94 #define kSupportsAlpha false
95 #define kSupportsTiles false
96 
97 
98 class ReadFFmpegPlugin
99     : public GenericReaderPlugin
100 {
101     FFmpegFileManager& _manager;
102     IntParam *_maxRetries;
103     BooleanParam *_firstTrackOnly;
104 
105 public:
106 
107     ReadFFmpegPlugin(FFmpegFileManager& manager, OfxImageEffectHandle handle, const vector<string>& extensions);
108 
109     virtual ~ReadFFmpegPlugin();
110 
111     virtual void changedParam(const InstanceChangedArgs &args, const string &paramName) OVERRIDE FINAL;
112 
113     bool loadNearestFrame() const;
114 
115     /**
116      * @brief Restore any state from the parameters set
117      * Called from createInstance() and changedParam() (via changedFilename()), must restore the
118      * state of the Reader, such as Choice param options, data members and non-persistent param values.
119      * We don't do this in the ctor of the plug-in since we can't call virtuals yet.
120      * Any derived implementation must call GenericReaderPlugin::restoreStateFromParams() first
121      **/
122     virtual void restoreStateFromParams() OVERRIDE FINAL;
123 
124 private:
125 
126     virtual bool isVideoStream(const string& filename) OVERRIDE FINAL;
127 
128     /**
129      * @brief Called when the input image/video file changed.
130      *
131      * returns true if file exists and parameters successfully guessed, false in case of error.
132      *
133      * This function is only called once: when the filename is first set.
134      *
135      * Besides returning colorspace, premult, components, and componentcount, if it returns true
136      * this function may also set extra format-specific parameters using Param::setValue.
137      * The parameters must not be animated, since their value must remain the same for a whole sequence.
138      *
139      * You shouldn't do any strong processing as this is called on the main thread and
140      * the getRegionOfDefinition() and  decode() should open the file in a separate thread.
141      *
142      * The colorspace may be set if available, else a default colorspace is used.
143      *
144      * You must also return the premultiplication state and pixel components of the image.
145      * When reading an image sequence, this is called only for the first image when the user actually selects the new sequence.
146      **/
147     virtual bool guessParamsFromFilename(const string& filename, string *colorspace, PreMultiplicationEnum *filePremult, PixelComponentEnum *components, int *componentCount) OVERRIDE FINAL;
148     virtual void decode(const string& filename, OfxTime time, int view, bool isPlayback, const OfxRectI& renderWindow, float *pixelData, const OfxRectI& bounds, PixelComponentEnum pixelComponents, int pixelComponentCount, int rowBytes) OVERRIDE FINAL;
149     virtual bool getSequenceTimeDomain(const string& filename, OfxRangeI &range) OVERRIDE FINAL;
150     virtual bool getFrameBounds(const string& filename, OfxTime time, int view, OfxRectI *bounds, OfxRectI *format, double *par, string *error, int* tile_width, int* tile_height) OVERRIDE FINAL;
151     virtual bool getFrameRate(const string& filename, double* fps) const OVERRIDE FINAL;
152 };
153 
ReadFFmpegPlugin(FFmpegFileManager & manager,OfxImageEffectHandle handle,const vector<string> & extensions)154 ReadFFmpegPlugin::ReadFFmpegPlugin(FFmpegFileManager& manager,
155                                    OfxImageEffectHandle handle,
156                                    const vector<string>& extensions)
157     : GenericReaderPlugin(handle, extensions, kSupportsRGBA, kSupportsRGB, kSupportsXY, kSupportsAlpha, kSupportsTiles, false)
158     , _manager(manager)
159     , _maxRetries(NULL)
160     , _firstTrackOnly(NULL)
161 {
162     _maxRetries = fetchIntParam(kParamMaxRetries);
163     _firstTrackOnly = fetchBooleanParam(kParamFirstTrackOnly);
164     assert(_maxRetries && _firstTrackOnly);
165     int originalFrameRangeMin, originalFrameRangeMax;
166     _originalFrameRange->getValue(originalFrameRangeMin, originalFrameRangeMax);
167     if (originalFrameRangeMin == 0) {
168         // probably a buggy instance from before Jan 19 2015, where 0 is the first frame
169         _originalFrameRange->setValue(originalFrameRangeMin + 1, originalFrameRangeMax + 1);
170         int timeOffset;
171         _timeOffset->getValue(timeOffset);
172         _timeOffset->setValue(timeOffset - 1);
173     }
174 }
175 
~ReadFFmpegPlugin()176 ReadFFmpegPlugin::~ReadFFmpegPlugin()
177 {
178 }
179 
180 /**
181  * @brief Restore any state from the parameters set
182  * Called from createInstance() and changedParam() (via changedFilename()), must restore the
183  * state of the Reader, such as Choice param options, data members and non-persistent param values.
184  * We don't do this in the ctor of the plug-in since we can't call virtuals yet.
185  * Any derived implementation must call GenericReaderPlugin::restoreStateFromParams() first
186  **/
187 void
restoreStateFromParams()188 ReadFFmpegPlugin::restoreStateFromParams()
189 {
190     GenericReaderPlugin::restoreStateFromParams();
191     //_manager.getOrCreate(this, filename);
192 }
193 
194 bool
loadNearestFrame() const195 ReadFFmpegPlugin::loadNearestFrame() const
196 {
197     int v;
198 
199     _missingFrameParam->getValue(v);
200 
201     return v == 0;
202 }
203 
204 
205 static string
ffmpeg_versions()206 ffmpeg_versions()
207 {
208     std::ostringstream oss;
209 #ifdef FFMS_USE_FFMPEG_COMPAT
210     oss << "FFmpeg ";
211 #else
212     oss << "libav";
213 #endif
214     oss << " versions (compiled with / running with):" << std::endl;
215     oss << "libavformat ";
216     oss << LIBAVFORMAT_VERSION_MAJOR << '.' << LIBAVFORMAT_VERSION_MINOR << '.' << LIBAVFORMAT_VERSION_MICRO << " / ";
217     oss << (avformat_version() >> 16) << '.' << (avformat_version() >> 8 & 0xff) << '.' << (avformat_version() & 0xff) << std::endl;
218     //oss << "libavdevice ";
219     //oss << LIBAVDEVICE_VERSION_MAJOR << '.' << LIBAVDEVICE_VERSION_MINOR << '.' << LIBAVDEVICE_VERSION_MICRO << " / ";
220     //oss << avdevice_version() >> 16 << '.' << avdevice_version() >> 8 & 0xff << '.' << avdevice_version() & 0xff << std::endl;
221     oss << "libavcodec ";
222     oss << LIBAVCODEC_VERSION_MAJOR << '.' << LIBAVCODEC_VERSION_MINOR << '.' << LIBAVCODEC_VERSION_MICRO << " / ";
223     oss << (avcodec_version() >> 16) << '.' << (avcodec_version() >> 8 & 0xff) << '.' << (avcodec_version() & 0xff) << std::endl;
224     oss << "libavutil ";
225     oss << LIBAVUTIL_VERSION_MAJOR << '.' << LIBAVUTIL_VERSION_MINOR << '.' << LIBAVUTIL_VERSION_MICRO << " / ";
226     oss << (avutil_version() >> 16) << '.' << (avutil_version() >> 8 & 0xff) << '.' << (avutil_version() & 0xff) << std::endl;
227     oss << "libswscale ";
228     oss << LIBSWSCALE_VERSION_MAJOR << '.' << LIBSWSCALE_VERSION_MINOR << '.' << LIBSWSCALE_VERSION_MICRO << " / ";
229     oss << (swscale_version() >> 16) << '.' << (swscale_version() >> 8 & 0xff) << '.' << (swscale_version() & 0xff) << std::endl;
230 
231     return oss.str();
232 }
233 
234 
235 void
changedParam(const InstanceChangedArgs & args,const string & paramName)236 ReadFFmpegPlugin::changedParam(const InstanceChangedArgs &args,
237                                const string &paramName)
238 {
239     if (paramName == kParamLibraryInfo) {
240         sendMessage(Message::eMessageMessage, "", ffmpeg_versions());
241     } else {
242         GenericReaderPlugin::changedParam(args, paramName);
243     }
244 }
245 
246 /**
247  * @brief Called when the input image/video file changed.
248  *
249  * returns true if file exists and parameters successfully guessed, false in case of error.
250  *
251  * This function is only called once: when the filename is first set.
252  *
253  * Besides returning colorspace, premult, components, and componentcount, if it returns true
254  * this function may also set extra format-specific parameters using Param::setValue.
255  * The parameters must not be animated, since their value must remain the same for a whole sequence.
256  *
257  * You shouldn't do any strong processing as this is called on the main thread and
258  * the getRegionOfDefinition() and  decode() should open the file in a separate thread.
259  *
260  * The colorspace may be set if available, else a default colorspace is used.
261  *
262  * You must also return the premultiplication state and pixel components of the image.
263  * When reading an image sequence, this is called only for the first image when the user actually selects the new sequence.
264  **/
265 bool
guessParamsFromFilename(const string & filename,string * colorspace,PreMultiplicationEnum * filePremult,PixelComponentEnum * components,int * componentCount)266 ReadFFmpegPlugin::guessParamsFromFilename(const string& filename,
267                                           string *colorspace,
268                                           PreMultiplicationEnum *filePremult,
269                                           PixelComponentEnum *components,
270                                           int *componentCount)
271 {
272     assert(colorspace && filePremult && components && componentCount);
273     FFmpegFile* file = _manager.get(this, filename);
274     if (!file) {
275         //Clear all opened files by this plug-in since the user changed the selected file/sequence
276         _manager.clear(this);
277         file = _manager.getOrCreate(this, filename);
278     }
279 
280     if ( !file || file->isInvalid() ) {
281         if (file) {
282             //setPersistentMessage(Message::eMessageError, "", file->getError());
283         } else {
284             //setPersistentMessage(Message::eMessageError, "", "Cannot open file.");
285         }
286 
287         return false;
288     }
289 
290 #   ifdef OFX_IO_USING_OCIO
291     // Unless otherwise specified, video files are assumed to be rec709.
292     if ( _ocio->hasColorspace("Rec709") ) {
293         // nuke-default
294         *colorspace = "Rec709";
295     } else if ( _ocio->hasColorspace("nuke_rec709") ) {
296         // blender
297         *colorspace = "nuke_rec709";
298     } else if ( _ocio->hasColorspace("Rec.709 - Full") ) {
299         // out_rec709full or "Rec.709 - Full" in aces 1.0.0
300         *colorspace = "Rec.709 - Full";
301     } else if ( _ocio->hasColorspace("out_rec709full") ) {
302         // out_rec709full or "Rec.709 - Full" in aces 1.0.0
303         *colorspace = "out_rec709full";
304     } else if ( _ocio->hasColorspace("rrt_rec709_full_100nits") ) {
305         // rrt_rec709_full_100nits in aces 0.7.1
306         *colorspace = "rrt_rec709_full_100nits";
307     } else if ( _ocio->hasColorspace("rrt_rec709") ) {
308         // rrt_rec709 in aces 0.1.1
309         *colorspace = "rrt_rec709";
310     } else if ( _ocio->hasColorspace("hd10") ) {
311         // hd10 in spi-anim and spi-vfx
312         *colorspace = "hd10";
313     }
314 #   endif
315 
316     *componentCount = file->getNumberOfComponents();
317     *components = (*componentCount > 3) ? ePixelComponentRGBA : ePixelComponentRGB;
318     ///Ffmpeg is RGB opaque.
319     *filePremult = (*componentCount > 3) ? eImageUnPreMultiplied : eImageOpaque;
320 
321     return true;
322 } // ReadFFmpegPlugin::guessParamsFromFilename
323 
324 bool
isVideoStream(const string & filename)325 ReadFFmpegPlugin::isVideoStream(const string& filename)
326 {
327     return !FFmpegFile::isImageFile(filename);
328 }
329 
330 void
decode(const string & filename,OfxTime time,int view,bool,const OfxRectI & renderWindow,float * pixelData,const OfxRectI & imgBounds,PixelComponentEnum pixelComponents,int pixelComponentCount,int rowBytes)331 ReadFFmpegPlugin::decode(const string& filename,
332                          OfxTime time,
333                          int view,
334                          bool /*isPlayback*/,
335                          const OfxRectI& renderWindow,
336                          float *pixelData,
337                          const OfxRectI& imgBounds,
338                          PixelComponentEnum pixelComponents,
339                          int pixelComponentCount,
340                          int rowBytes)
341 {
342     FFmpegFile* file = _manager.getOrCreate(this, filename);
343 
344     if ( file && file->isInvalid() ) {
345         setPersistentMessage( Message::eMessageError, "", file->getError() );
346 
347         return;
348     }
349     clearPersistentMessage();
350 
351     /// we only support RGB or RGBA output clip
352     if ( (pixelComponents != ePixelComponentRGB) &&
353          (pixelComponents != ePixelComponentRGBA) &&
354          (pixelComponents != ePixelComponentAlpha) ) {
355         throwSuiteStatusException(kOfxStatErrFormat);
356 
357         return;
358     }
359     assert( (pixelComponents == ePixelComponentRGB && pixelComponentCount == 3) || (pixelComponents == ePixelComponentRGBA && pixelComponentCount == 4) || (pixelComponents == ePixelComponentAlpha && pixelComponentCount == 1) );
360 
361     ///blindly ignore the filename, we suppose that the file is the same than the file loaded in the changedParam
362     if (!file) {
363         setPersistentMessage(Message::eMessageError, "", filename +  ": Missing frame");
364         throwSuiteStatusException(kOfxStatFailed);
365 
366         return;
367     }
368 
369     bool firstTrackOnly = _firstTrackOnly->getValueAtTime(time);
370     if (firstTrackOnly) {
371         view = 0;
372     }
373     file->setSelectedStream(view);
374 
375     int width, height, frames;
376     double ap;
377     file->getInfo(width, height, ap, frames);
378 
379     // wrong assert:
380     // http://openfx.sourceforge.net/Documentation/1.3/ofxProgrammingReference.html#kOfxImageEffectPropSupportsTiles
381     //  "If a clip or plugin does not support tiled images, then the host should supply full RoD images to the effect whenever it fetches one."
382     //  The renderWindow itself may or may not be the full image...
383     //assert(kSupportsTiles || (renderWindow.x1 == 0 && renderWindow.x2 == width && renderWindow.y1 == 0 && renderWindow.y2 == height));
384 
385     if ( ( (imgBounds.x2 - imgBounds.x1) < width ) ||
386          ( (imgBounds.y2 - imgBounds.y1) < height ) ) {
387         setPersistentMessage(Message::eMessageError, "", "The host provided an image of wrong size, can't decode.");
388         throwSuiteStatusException(kOfxStatFailed);
389 
390         return;
391     }
392 
393     int maxRetries;
394     _maxRetries->getValue(maxRetries);
395 
396     // not in FFmpeg Reader: initialize the output buffer
397     // TODO: use avpicture_get_size? see WriteFFmpeg
398     unsigned int numComponents = file->getNumberOfComponents();
399     assert(numComponents == 3 || numComponents == 4);
400 
401     std::size_t sizeOfData = file->getSizeOfData();
402     assert( sizeOfData == sizeof(unsigned char) || sizeOfData == sizeof(unsigned short) );
403 
404     int srcRowBytes = width * numComponents * sizeOfData;
405     std::size_t bufferSize =  height * srcRowBytes;
406 
407     RamBuffer bufferRaii(bufferSize);
408     unsigned char* buffer = bufferRaii.getData();
409     if (!buffer) {
410         throwSuiteStatusException(kOfxStatErrMemory);
411 
412         return;
413     }
414     // this is the first stream (in fact the only one we consider for now), allocate the output buffer according to the bitdepth
415 
416     try {
417         if ( !file->decode(this, (int)time, loadNearestFrame(), maxRetries, buffer) ) {
418             if ( abort() ) {
419                 // decode() probably existed because plugin was aborted
420                 return;
421             }
422             setPersistentMessage( Message::eMessageError, "", file->getError() );
423             throwSuiteStatusException(kOfxStatFailed);
424 
425             return;
426         }
427     } catch (const std::exception& e) {
428         int choice;
429         _missingFrameParam->getValue(choice);
430         if (choice == 1) { //error
431             setPersistentMessage( Message::eMessageError, "", e.what() );
432             throwSuiteStatusException(kOfxStatFailed);
433 
434             return;
435         }
436 
437         return;
438     }
439 
440 
441     convertDepthAndComponents(buffer, renderWindow, imgBounds, numComponents == 3 ? ePixelComponentRGB : ePixelComponentRGBA, sizeOfData == sizeof(unsigned char) ? eBitDepthUByte : eBitDepthUShort, srcRowBytes, pixelData, imgBounds, pixelComponents, rowBytes);
442 } // ReadFFmpegPlugin::decode
443 
444 bool
getSequenceTimeDomain(const string & filename,OfxRangeI & range)445 ReadFFmpegPlugin::getSequenceTimeDomain(const string& filename,
446                                         OfxRangeI &range)
447 {
448     if ( FFmpegFile::isImageFile(filename) ) {
449         range.min = range.max = 0.;
450 
451         return false;
452     }
453 
454     int width, height, frames;
455     double ap;
456     FFmpegFile* file = _manager.getOrCreate(this, filename);
457     if ( !file || file->isInvalid() ) {
458         range.min = range.max = 0.;
459 
460         return false;
461     }
462     file->getInfo(width, height, ap, frames);
463 
464     range.min = 1;
465     range.max = frames;
466 
467     return true;
468 }
469 
470 bool
getFrameRate(const string & filename,double * fps) const471 ReadFFmpegPlugin::getFrameRate(const string& filename,
472                                double* fps) const
473 {
474     assert(fps);
475 
476     FFmpegFile* file = _manager.getOrCreate(this, filename);
477     if ( !file || file->isInvalid() ) {
478         return false;
479     }
480 
481     bool gotFps = file->getFPS(*fps);
482 
483     return gotFps;
484 }
485 
486 bool
getFrameBounds(const string & filename,OfxTime time,int view,OfxRectI * bounds,OfxRectI * format,double * par,string * error,int * tile_width,int * tile_height)487 ReadFFmpegPlugin::getFrameBounds(const string& filename,
488                                  OfxTime time,
489                                  int view,
490                                  OfxRectI *bounds,
491                                  OfxRectI *format,
492                                  double *par,
493                                  string *error,
494                                  int* tile_width,
495                                  int* tile_height)
496 {
497     assert(bounds && par);
498     FFmpegFile* file = _manager.getOrCreate(this, filename);
499     if ( !file || file->isInvalid() ) {
500         if (error && file) {
501             *error = file->getError();
502         }
503 
504         return false;
505     }
506 
507     bool firstTrackOnly = _firstTrackOnly->getValueAtTime(time);
508     if (firstTrackOnly) {
509         view = 0;
510     }
511     file->setSelectedStream(view);
512     int width, height, frames;
513     double ap;
514     if ( !file->getInfo(width, height, ap, frames) ) {
515         width = 0;
516         height = 0;
517         ap = 1.;
518     }
519     bounds->x1 = 0;
520     bounds->x2 = width;
521     bounds->y1 = 0;
522     bounds->y2 = height;
523     *format = *bounds;
524     *par = ap;
525     *tile_width = *tile_height = 0;
526 
527     return true;
528 }
529 
530 class ReadFFmpegPluginFactory
531     : public PluginFactoryHelper<ReadFFmpegPluginFactory>
532 {
533     auto_ptr<FFmpegFileManager> _manager;
534 
535 public:
ReadFFmpegPluginFactory(const string & id,unsigned int verMaj,unsigned int verMin)536     ReadFFmpegPluginFactory(const string& id,
537                             unsigned int verMaj,
538                             unsigned int verMin)
539         : PluginFactoryHelper<ReadFFmpegPluginFactory>(id, verMaj, verMin)
540         , _manager()
541     {}
542 
543     virtual void load() OVERRIDE FINAL;
unload()544     virtual void unload() OVERRIDE FINAL
545     {
546         _manager.reset(NULL);
547         _extensions.clear();
548     }
549 
550     virtual ImageEffect* createInstance(OfxImageEffectHandle handle, ContextEnum context) OVERRIDE FINAL;
551 
isVideoStreamPlugin() const552     bool isVideoStreamPlugin() const { return true; }
553 
554     virtual void describe(ImageEffectDescriptor &desc) OVERRIDE FINAL;
555     virtual void describeInContext(ImageEffectDescriptor &desc, ContextEnum context) OVERRIDE FINAL;
556 
557     vector<string> _extensions;
558 };
559 
560 #if 0
561 static
562 vector<string> &
563 split(const string &s,
564       char delim,
565       vector<string> &elems)
566 {
567     stringstream ss(s);
568     string item;
569 
570     while ( std::getline(ss, item, delim) ) {
571         elems.push_back(item);
572     }
573 
574     return elems;
575 }
576 
577 #endif
578 
579 static
580 std::list<string> &
split(const string & s,char delim,std::list<string> & elems)581 split(const string &s,
582       char delim,
583       std::list<string> &elems)
584 {
585     stringstream ss(s);
586     string item;
587 
588     while ( std::getline(ss, item, delim) ) {
589         elems.push_back(item);
590     }
591 
592     return elems;
593 }
594 
595 #ifdef OFX_IO_MT_FFMPEG
596 static int
FFmpegLockManager(void ** mutex,enum AVLockOp op)597 FFmpegLockManager(void** mutex,
598                   enum AVLockOp op)
599 {
600     switch (op) {
601     case AV_LOCK_CREATE:     // Create a mutex.
602         try {
603             *mutex = static_cast< void* >(new FFmpegFile::Mutex);
604 
605             return 0;
606         }catch (...) {
607             // Return error if mutex creation failed.
608             return 1;
609         }
610 
611     case AV_LOCK_OBTAIN:     // Lock the specified mutex.
612         try {
613             static_cast< FFmpegFile::Mutex* >(*mutex)->lock();
614 
615             return 0;
616         }catch (...) {
617             // Return error if mutex lock failed.
618             return 1;
619         }
620 
621     case AV_LOCK_RELEASE:     // Unlock the specified mutex.
622         // Mutex unlock can't fail.
623         static_cast< FFmpegFile::Mutex* >(*mutex)->unlock();
624 
625         return 0;
626 
627     case AV_LOCK_DESTROY:     // Destroy the specified mutex.
628         // Mutex destruction can't fail.
629         delete static_cast< FFmpegFile::Mutex* >(*mutex);
630         *mutex = 0;
631 
632         return 0;
633 
634     default:     // Unknown operation.
635         assert(false);
636 
637         return 1;
638     }
639 }
640 
641 #endif
642 
643 void
load()644 ReadFFmpegPluginFactory::load()
645 {
646     _extensions.clear();
647 #if 0
648     // hard-coded extensions list
649     const char* extensionsl[] = { "avi", "flv", "mkv", "webm", "mov", "mp4", "mpg", "m2ts", "mts", "ts", "mxf", "ogv", "r3d", "bmp", "pix", "dpx", "exr", "jpeg", "jpg", "png", "pgm", "ppm", "ptx", "rgba", "rgb", "tiff", "tga", "gif", NULL };
650     for (const char** ext = extensionsl; *ext != NULL; ++ext) {
651         _extensions.push_back(*ext);
652     }
653 #else
654     std::list<string> extensionsl;
655     AVInputFormat* iFormat = av_iformat_next(NULL);
656     while (iFormat != NULL) {
657         //DBG(std::printf("ReadFFmpeg: \"%s\", // %s (%s)\n", iFormat->extensions ? iFormat->extensions : iFormat->name, iFormat->name, iFormat->long_name));
658         if (iFormat->extensions != NULL) {
659             string extStr( iFormat->extensions );
660             split(extStr, ',', extensionsl);
661         }
662         {
663             // name's format defines (in general) extensions
664             // require to fix extension in LibAV/FFMpeg to don't use it.
665             string extStr( iFormat->name);
666             split(extStr, ',', extensionsl);
667         }
668         iFormat = av_iformat_next( iFormat );
669     }
670 
671     // Hack: Add basic video container extensions
672     // as some versions of LibAV doesn't declare properly all extensions...
673     // or there may be other well-known extensions (such as mts or m2ts)
674     //extensionsl.push_back("pix"); // alias_pix (Alias/Wavefront PIX image)
675     extensionsl.push_back("avi"); // AVI (Audio Video Interleaved)
676     //extensionsl.push_back("bsa"); // bethsoftvid (Bethesda Softworks VID)
677     //extensionsl.push_back("bik"); // bink (Bink)
678     //extensionsl.push_back("cpk"); // film_cpk (Sega FILM / CPK)
679     //extensionsl.push_back("cak"); // film_cpk (Sega FILM / CPK)
680     //extensionsl.push_back("film"); // film_cpk (Sega FILM / CPK)
681     //extensionsl.push_back("fli"); // flic (FLI/FLC/FLX animation)
682     //extensionsl.push_back("flc"); // flic (FLI/FLC/FLX animation)
683     //extensionsl.push_back("flx"); // flic (FLI/FLC/FLX animation)
684     extensionsl.push_back("flv"); // flv (FLV (Flash Video))
685     //extensionsl.push_back("ilbm"); // iff (IFF (Interchange File Format))
686     //extensionsl.push_back("anim"); // iff (IFF (Interchange File Format))
687     //extensionsl.push_back("mve"); // ipmovie (Interplay MVE)
688     //extensionsl.push_back("lml"); // lmlm4 (raw lmlm4)
689     extensionsl.push_back("mkv"); // matroska,webm (Matroska / WebM)
690     extensionsl.push_back("mk3d"); // matroska,webm (Matroska / WebM)
691     extensionsl.push_back("webm"); // matroska,webm (Matroska / WebM)
692     extensionsl.push_back("mov"); // QuickTime / MOV
693     extensionsl.push_back("mp4"); // MP4 (MPEG-4 Part 14)
694     extensionsl.push_back("mpg"); // MPEG-1 Systems / MPEG program stream
695     extensionsl.push_back("m2ts"); // mpegts (MPEG-TS (MPEG-2 Transport Stream))
696     extensionsl.push_back("mts"); // mpegts (MPEG-TS (MPEG-2 Transport Stream))
697     extensionsl.push_back("ts"); // mpegts (MPEG-TS (MPEG-2 Transport Stream))
698     extensionsl.push_back("mxf"); // mxf (MXF (Material eXchange Format))
699     extensionsl.push_back("ogv"); // ogv (Ogg Video)
700 
701     // remove audio and subtitle-only formats
702     const char* extensions_blacklist[] = {
703         "aa", // aa (Audible AA format files)
704         "aac", // aac (raw ADTS AAC (Advanced Audio Coding))
705         "ac3", // ac3 (raw AC-3)
706         "act", // act (ACT Voice file format)
707         // "adf", // adf (Artworx Data Format)
708         "adp", "dtk", // adp (ADP) Audio format used on the Nintendo Gamecube.
709         "adx", // adx (CRI ADX) Audio-only format used in console video games.
710         "aea", // aea (MD STUDIO audio)
711         "afc", // afc (AFC) Audio format used on the Nintendo Gamecube.
712         "aiff", // aiff (Audio IFF)
713         "amr", // amr (3GPP AMR)
714         // "anm", // anm (Deluxe Paint Animation)
715         "apc", // apc (CRYO APC)
716         "ape", "apl", "mac", // ape (Monkey's Audio)
717         // "apng", // apng (Animated Portable Network Graphics)
718         "aqt", "aqtitle", // aqtitle (AQTitle subtitles)
719         // "asf", // asf (ASF (Advanced / Active Streaming Format))
720         // "asf_o", // asf_o (ASF (Advanced / Active Streaming Format))
721         "ass", // ass (SSA (SubStation Alpha) subtitle)
722         "ast", // ast (AST (Audio Stream))
723         "au", // au (Sun AU)
724         // "avi", // avi (AVI (Audio Video Interleaved))
725         "avr", // avr (AVR (Audio Visual Research)) Audio format used on Mac.
726         // "avs", // avs (AVS)
727         // "bethsoftvid", // bethsoftvid (Bethesda Softworks VID)
728         // "bfi", // bfi (Brute Force & Ignorance)
729         "bin", // bin (Binary text)
730         // "bink", // bink (Bink)
731         "bit", // bit (G.729 BIT file format)
732         // "bmv", // bmv (Discworld II BMV)
733         "bfstm", "bcstm", // bfstm (BFSTM (Binary Cafe Stream)) Audio format used on the Nintendo WiiU (based on BRSTM).
734         "brstm", // brstm (BRSTM (Binary Revolution Stream)) Audio format used on the Nintendo Wii.
735         "boa", // boa (Black Ops Audio)
736         // "c93", // c93 (Interplay C93)
737         "caf", // caf (Apple CAF (Core Audio Format))
738         // "cavsvideo", // cavsvideo (raw Chinese AVS (Audio Video Standard))
739         // "cdg", // cdg (CD Graphics)
740         // "cdxl,xl", // cdxl (Commodore CDXL video)
741         // "cine", // cine (Phantom Cine)
742         // "concat", // concat (Virtual concatenation script)
743         // "data", // data (raw data)
744         "302", "daud", // daud (D-Cinema audio)
745         // "dfa", // dfa (Chronomaster DFA)
746         // "dirac", // dirac (raw Dirac)
747         // "dnxhd", // dnxhd (raw DNxHD (SMPTE VC-3))
748         "dsf", // dsf (DSD Stream File (DSF))
749         // "dsicin", // dsicin (Delphine Software International CIN)
750         "dss", // dss (Digital Speech Standard (DSS))
751         "dts", // dts (raw DTS)
752         "dtshd", // dtshd (raw DTS-HD)
753         // "dv,dif", // dv (DV (Digital Video))
754         "dvbsub", // dvbsub (raw dvbsub)
755         // "dxa", // dxa (DXA)
756         // "ea", // ea (Electronic Arts Multimedia)
757         // "cdata", // ea_cdata (Electronic Arts cdata)
758         "eac3", // eac3 (raw E-AC-3)
759         "paf", "fap", "epaf", // epaf (Ensoniq Paris Audio File)
760         "ffm", // ffm (FFM (FFserver live feed))
761         "ffmetadata", // ffmetadata (FFmpeg metadata in text)
762         // "flm", // filmstrip (Adobe Filmstrip)
763         "flac", // flac (raw FLAC)
764         // "flic", // flic (FLI/FLC/FLX animation)
765         // "flv", // flv (FLV (Flash Video))
766         // "flv", // live_flv (live RTMP FLV (Flash Video))
767         // "4xm", // 4xm (4X Technologies)
768         // "frm", // frm (Megalux Frame)
769         "g722", "722", // g722 (raw G.722)
770         "tco", "rco", "g723_1", // g723_1 (G.723.1)
771         "g729", // g729 (G.729 raw format demuxer)
772         // "gif", // gif (CompuServe Graphics Interchange Format (GIF))
773         "gsm", // gsm (raw GSM)
774         // "gxf", // gxf (GXF (General eXchange Format))
775         // "h261", // h261 (raw H.261)
776         // "h263", // h263 (raw H.263)
777         // "h26l,h264,264,avc", // h264 (raw H.264 video)
778         // "hevc,h265,265", // hevc (raw HEVC video)
779         // "hls,applehttp", // hls,applehttp (Apple HTTP Live Streaming)
780         // "hnm", // hnm (Cryo HNM v4)
781         // "ico", // ico (Microsoft Windows ICO)
782         // "idcin", // idcin (id Cinematic)
783         // "idf", // idf (iCE Draw File)
784         // "iff", // iff (IFF (Interchange File Format))
785         "ilbc", // ilbc (iLBC storage)
786         // "image2", // image2 (image2 sequence)
787         "image2pipe", // image2pipe (piped image2 sequence)
788         "alias_pix", // alias_pix (Alias/Wavefront PIX image)
789         "brender_pix", // brender_pix (BRender PIX image)
790         // "cgi", // ingenient (raw Ingenient MJPEG)
791         "ipmovie", // ipmovie (Interplay MVE)
792         "sf", "ircam", // ircam (Berkeley/IRCAM/CARL Sound Format)
793         "iss", // iss (Funcom ISS)
794         // "iv8", // iv8 (IndigoVision 8000 video)
795         // "ivf", // ivf (On2 IVF)
796         "jacosub", // jacosub (JACOsub subtitle format)
797         "jv", // jv (Bitmap Brothers JV)
798         "latm", // latm (raw LOAS/LATM)
799         "lmlm4", // lmlm4 (raw lmlm4)
800         "loas", // loas (LOAS AudioSyncStream)
801         "lrc", // lrc (LRC lyrics)
802         // "lvf", // lvf (LVF)
803         // "lxf", // lxf (VR native stream (LXF))
804         // "m4v", // m4v (raw MPEG-4 video)
805         "mka", "mks", // "mkv,mk3d,mka,mks", // matroska,webm (Matroska / WebM)
806         "mgsts", // mgsts (Metal Gear Solid: The Twin Snakes)
807         "microdvd", // microdvd (MicroDVD subtitle format)
808         // "mjpg,mjpeg,mpo", // mjpeg (raw MJPEG video)
809         "mlp", // mlp (raw MLP)
810         // "mlv", // mlv (Magic Lantern Video (MLV))
811         "mm", // mm (American Laser Games MM)
812         "mmf", // mmf (Yamaha SMAF)
813         "m4a", // "mov,mp4,m4a,3gp,3g2,mj2", // mov,mp4,m4a,3gp,3g2,mj2 (QuickTime / MOV)
814         "mp2", "mp3", "m2a", "mpa", // mp3 (MP2/3 (MPEG audio layer 2/3))
815         "mpc", // mpc (Musepack)
816         "mpc8", // mpc8 (Musepack SV8)
817         // "mpeg", // mpeg (MPEG-PS (MPEG-2 Program Stream))
818         "mpegts", // mpegts (MPEG-TS (MPEG-2 Transport Stream))
819         "mpegtsraw", // mpegtsraw (raw MPEG-TS (MPEG-2 Transport Stream))
820         "mpegvideo", // mpegvideo (raw MPEG video)
821         // "mjpg", // mpjpeg (MIME multipart JPEG)
822         "txt", "mpl2", // mpl2 (MPL2 subtitles)
823         "sub", "mpsub", // mpsub (MPlayer subtitles)
824         "msnwctcp", // msnwctcp (MSN TCP Webcam stream)
825         // "mtv", // mtv (MTV)
826         // "mv", // mv (Silicon Graphics Movie)
827         // "mvi", // mvi (Motion Pixels MVI)
828         // "mxf", // mxf (MXF (Material eXchange Format))
829         // "mxg", // mxg (MxPEG clip)
830         // "v", // nc (NC camera feed)
831         "nist", "sph", "nistsphere", // nistsphere (NIST SPeech HEader REsources)
832         // "nsv", // nsv (Nullsoft Streaming Video)
833         // "nut", // nut (NUT)
834         // "nuv", // nuv (NuppelVideo)
835         // "ogg", // ogg (Ogg)
836         "oma", "omg", "aa3", // oma (Sony OpenMG audio)
837         // "paf", // paf (Amazing Studio Packed Animation File)
838         "al", "alaw", // alaw (PCM A-law)
839         "ul", "mulaw", // mulaw (PCM mu-law)
840         "f64be", // f64be (PCM 64-bit floating-point big-endian)
841         "f64le", // f64le (PCM 64-bit floating-point little-endian)
842         "f32be", // f32be (PCM 32-bit floating-point big-endian)
843         "f32le", // f32le (PCM 32-bit floating-point little-endian)
844         "s32be", // s32be (PCM signed 32-bit big-endian)
845         "s32le", // s32le (PCM signed 32-bit little-endian)
846         "s24be", // s24be (PCM signed 24-bit big-endian)
847         "s24le", // s24le (PCM signed 24-bit little-endian)
848         "s16be", // s16be (PCM signed 16-bit big-endian)
849         "sw", "s16le", // s16le (PCM signed 16-bit little-endian)
850         "sb", "s8", // s8 (PCM signed 8-bit)
851         "u32be", // u32be (PCM unsigned 32-bit big-endian)
852         "u32le", // u32le (PCM unsigned 32-bit little-endian)
853         "u24be", // u24be (PCM unsigned 24-bit big-endian)
854         "u24le", // u24le (PCM unsigned 24-bit little-endian)
855         "u16be", // u16be (PCM unsigned 16-bit big-endian)
856         "uw", "u16le", // u16le (PCM unsigned 16-bit little-endian)
857         "ub", "u8", // u8 (PCM unsigned 8-bit)
858         "pjs", // pjs (PJS (Phoenix Japanimation Society) subtitles)
859         "pmp", // pmp (Playstation Portable PMP)
860         "pva", // pva (TechnoTrend PVA)
861         "pvf", // pvf (PVF (Portable Voice Format))
862         "qcp", // qcp (QCP)
863         // "r3d", // r3d (REDCODE R3D)
864         // "yuv,cif,qcif,rgb", // rawvideo (raw video)
865         "rt", "realtext", // realtext (RealText subtitle format)
866         "rsd", "redspark", // redspark (RedSpark)
867         // "rl2", // rl2 (RL2)
868         // "rm", // rm (RealMedia)
869         // "roq", // roq (id RoQ)
870         // "rpl", // rpl (RPL / ARMovie)
871         "rsd", // rsd (GameCube RSD)
872         "rso", // rso (Lego Mindstorms RSO)
873         "rtp", // rtp (RTP input)
874         "rtsp", // rtsp (RTSP input)
875         "smi", "sami", // sami (SAMI subtitle format)
876         "sap", // sap (SAP input)
877         "sbg", // sbg (SBaGen binaural beats script)
878         "sdp", // sdp (SDP)
879         // "sdr2", // sdr2 (SDR2)
880         "film_cpk", // film_cpk (Sega FILM / CPK)
881         "shn", // shn (raw Shorten)
882         // "vb,son", // siff (Beam Software SIFF)
883         // "sln", // sln (Asterisk raw pcm)
884         "smk", // smk (Smacker)
885         // "mjpg", // smjpeg (Loki SDL MJPEG)
886         "smush", // smush (LucasArts Smush)
887         "sol", // sol (Sierra SOL)
888         "sox", // sox (SoX native)
889         "spdif", // spdif (IEC 61937 (compressed data in S/PDIF))
890         "srt", // srt (SubRip subtitle)
891         "psxstr", // psxstr (Sony Playstation STR)
892         "stl", // stl (Spruce subtitle format)
893         "sub", "subviewer1", // subviewer1 (SubViewer v1 subtitle format)
894         "sub", "subviewer", // subviewer (SubViewer subtitle format)
895         "sup", // sup (raw HDMV Presentation Graphic Stream subtitles)
896         // "swf", // swf (SWF (ShockWave Flash))
897         "tak", // tak (raw TAK)
898         "tedcaptions", // tedcaptions (TED Talks captions)
899         "thp", // thp (THP)
900         "tiertexseq", // tiertexseq (Tiertex Limited SEQ)
901         "tmv", // tmv (8088flex TMV)
902         "thd", "truehd", // truehd (raw TrueHD)
903         "tta", // tta (TTA (True Audio))
904         // "txd", // txd (Renderware TeXture Dictionary)
905         "ans", "art", "asc", "diz", "ice", "nfo", "txt", "vt", // tty (Tele-typewriter)
906         // "vc1", // vc1 (raw VC-1)
907         "vc1test", // vc1test (VC-1 test bitstream)
908         // "viv", // vivo (Vivo)
909         "vmd", // vmd (Sierra VMD)
910         "idx", "vobsub", // vobsub (VobSub subtitle format)
911         "voc", // voc (Creative Voice)
912         "txt", "vplayer", // vplayer (VPlayer subtitles)
913         "vqf", "vql", "vqe", // vqf (Nippon Telegraph and Telephone Corporation (NTT) TwinVQ)
914         "w64", // w64 (Sony Wave64)
915         "wav", // wav (WAV / WAVE (Waveform Audio))
916         "wc3movie", // wc3movie (Wing Commander III movie)
917         "webm_dash_manifest", // webm_dash_manifest (WebM DASH Manifest)
918         "vtt", "webvtt", // webvtt (WebVTT subtitle)
919         "wsaud", // wsaud (Westwood Studios audio)
920         "wsvqa", // wsvqa (Westwood Studios VQA)
921         "wtv", // wtv (Windows Television (WTV))
922         "wv", // wv (WavPack)
923         "xa", // xa (Maxis XA)
924         "xbin", // xbin (eXtended BINary text (XBIN))
925         "xmv", // xmv (Microsoft XMV)
926         "xwma", // xwma (Microsoft xWMA)
927         // "yop", // yop (Psygnosis YOP)
928         // "y4m", // yuv4mpegpipe (YUV4MPEG pipe)
929         "bmp_pipe", // bmp_pipe (piped bmp sequence)
930         "dds_pipe", // dds_pipe (piped dds sequence)
931         "dpx_pipe", // dpx_pipe (piped dpx sequence)
932         "exr_pipe", // exr_pipe (piped exr sequence)
933         "j2k_pipe", // j2k_pipe (piped j2k sequence)
934         "jpeg_pipe", // jpeg_pipe (piped jpeg sequence)
935         "jpegls_pipe", // jpegls_pipe (piped jpegls sequence)
936         "pictor_pipe", // pictor_pipe (piped pictor sequence)
937         "png_pipe", // png_pipe (piped png sequence)
938         "qdraw_pipe", // qdraw_pipe (piped qdraw sequence)
939         "sgi_pipe", // sgi_pipe (piped sgi sequence)
940         "sunrast_pipe", // sunrast_pipe (piped sunrast sequence)
941         "tiff_pipe", // tiff_pipe (piped tiff sequence)
942         "webp_pipe", // webp_pipe (piped webp sequence)
943 
944         // OIIO and PFM extensions:
945         "bmp", "cin", "dds", "dpx", "f3d", "fits", "hdr", "ico",
946         "iff", "jpg", "jpe", "jpeg", "jif", "jfif", "jfi", "jp2", "j2k", "exr", "png",
947         "pbm", "pgm", "ppm",
948         "pfm",
949         "psd", "pdd", "psb", "ptex", "rla", "sgi", "rgb", "rgba", "bw", "int", "inta", "pic", "tga", "tpic", "tif", "tiff", "tx", "env", "sm", "vsm", "zfile",
950 
951         NULL
952     };
953     for (const char*const* e = extensions_blacklist; *e != NULL; ++e) {
954         extensionsl.remove(*e);
955     }
956 
957     _extensions.assign( extensionsl.begin(), extensionsl.end() );
958     // sort / unique
959     std::sort( _extensions.begin(), _extensions.end() );
960     _extensions.erase( std::unique( _extensions.begin(), _extensions.end() ), _extensions.end() );
961 #endif // if 0
962 } // ReadFFmpegPluginFactory::load
963 
964 /** @brief The basic describe function, passed a plugin descriptor */
965 void
describe(ImageEffectDescriptor & desc)966 ReadFFmpegPluginFactory::describe(ImageEffectDescriptor &desc)
967 {
968     GenericReaderDescribe(desc, _extensions, kPluginEvaluation, kSupportsTiles, false);
969     // basic labels
970     desc.setLabel(kPluginName);
971     desc.setPluginDescription(kPluginDescription);
972 #ifdef OFX_IO_MT_FFMPEG
973     // Register a lock manager callback with FFmpeg, providing it the ability to use mutex locking around
974     // otherwise non-thread-safe calls.
975     av_lockmgr_register(FFmpegLockManager);
976     desc.setRenderThreadSafety(eRenderFullySafe);
977 #else
978     desc.setRenderThreadSafety(eRenderInstanceSafe);
979 #endif
980 
981     av_log_set_level(AV_LOG_WARNING);
982     avcodec_register_all();
983     av_register_all();
984 
985     _manager.reset(new FFmpegFileManager);
986     _manager->init();
987 
988     // Thus effect prefers sequential render, but will still give correct results otherwise
989     desc.getPropertySet().propSetInt(kOfxImageEffectInstancePropSequentialRender, 2, false);
990 }
991 
992 /** @brief The describe in context function, passed a plugin descriptor and a context */
993 void
describeInContext(ImageEffectDescriptor & desc,ContextEnum context)994 ReadFFmpegPluginFactory::describeInContext(ImageEffectDescriptor &desc,
995                                            ContextEnum context)
996 {
997     // make some pages and to things in
998     PageParamDescriptor *page = GenericReaderDescribeInContextBegin(desc, context, isVideoStreamPlugin(),
999                                                                     kSupportsRGBA, kSupportsRGB, kSupportsXY, kSupportsAlpha, kSupportsTiles, false);
1000 
1001     {
1002         IntParamDescriptor *param = desc.defineIntParam(kParamMaxRetries);
1003         param->setLabel(kParamMaxRetriesLabel);
1004         param->setHint(kParamMaxRetriesHint);
1005         param->setAnimates(false);
1006         param->setDefault(10);
1007         param->setRange(0, 100);
1008         param->setDisplayRange(0, 20);
1009         if (page) {
1010             page->addChild(*param);
1011         }
1012     }
1013     {
1014         BooleanParamDescriptor *param = desc.defineBooleanParam(kParamFirstTrackOnly);
1015         param->setLabelAndHint(kParamFirstTrackOnlyLabelAndHint);
1016         param->setAnimates(false);
1017         param->setDefault(false);
1018         param->setLayoutHint(eLayoutHintDivider);
1019         if (page) {
1020             page->addChild(*param);
1021         }
1022     }
1023     {
1024         PushButtonParamDescriptor* param = desc.definePushButtonParam(kParamLibraryInfo);
1025         param->setLabelAndHint(kParamLibraryInfoLabel);
1026         if (page) {
1027             page->addChild(*param);
1028         }
1029     }
1030 
1031     GenericReaderDescribeInContextEnd(desc, context, page, "rec709", "scene_linear");
1032 }
1033 
1034 /** @brief The create instance function, the plugin must return an object derived from the \ref ImageEffect class */
1035 ImageEffect*
createInstance(OfxImageEffectHandle handle,ContextEnum)1036 ReadFFmpegPluginFactory::createInstance(OfxImageEffectHandle handle,
1037                                         ContextEnum /*context*/)
1038 {
1039     ReadFFmpegPlugin* ret =  new ReadFFmpegPlugin(*_manager, handle, _extensions);
1040 
1041     ret->restoreStateFromParams();
1042 
1043     return ret;
1044 }
1045 
1046 static ReadFFmpegPluginFactory p(kPluginIdentifier, kPluginVersionMajor, kPluginVersionMinor);
1047 mRegisterPluginFactoryInstance(p)
1048 
1049 OFXS_NAMESPACE_ANONYMOUS_EXIT
1050