Some FFmpeg changes
authorSergey Sharybin <sergey.vfx@gmail.com>
Sun, 26 Aug 2012 11:01:14 +0000 (11:01 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Sun, 26 Aug 2012 11:01:14 +0000 (11:01 +0000)
- Make FFmpeg initialization called from creator, not from functions
  which requires FFmpeg. Makes it easier to follow when initialization
  should happen.

- Enable DNxHD codec. It was commented a while ago due to some strange
  behavior on some platforms. Re-tested it on Linux and Windows and
  it seemd to be working quite nice. Would let it be tested further,
  if it wouldn't be stable enough, easy to comment it again.

- Make non-error messages from writeffmpeg.c printed only if ffmpeg
  debug argument was passed to blender. Reduces console pollution
  with messages which are not useful for general troubleshooting.
  Error messages would still be printed to the console.

- Show FFmpeg error message when video stream failed to allocate.
  makes it easier to understand what exactly is wrong from Blender
  interface, no need to restart blender with FFmpeg debug flag and
  check for console messages.

  Used custom log callback for this which stores last error message
  in static variable. This is not thread safe, but with current
  design FFmpeg routines could not be called form several threads
  anyway, so think it's fine solution/

source/blender/blenkernel/intern/writeffmpeg.c
source/blender/blenlib/BLI_string.h
source/blender/blenlib/intern/string.c
source/blender/imbuf/IMB_imbuf.h
source/blender/imbuf/intern/anim_movie.c
source/blender/imbuf/intern/util.c
source/blender/makesrna/intern/rna_scene.c
source/creator/creator.c
source/gameengine/VideoTexture/VideoFFmpeg.cpp

index f22fd74..2e07b41 100644 (file)
@@ -69,8 +69,6 @@
 
 #include "ffmpeg_compat.h"
 
 
 #include "ffmpeg_compat.h"
 
-extern void do_init_ffmpeg(void);
-
 static int ffmpeg_type = 0;
 static int ffmpeg_codec = CODEC_ID_MPEG4;
 static int ffmpeg_audio_codec = CODEC_ID_NONE;
 static int ffmpeg_type = 0;
 static int ffmpeg_codec = CODEC_ID_MPEG4;
 static int ffmpeg_audio_codec = CODEC_ID_NONE;
@@ -101,6 +99,8 @@ static AUD_Device *audio_mixdown_device = 0;
 
 #define FFMPEG_AUTOSPLIT_SIZE 2000000000
 
 
 #define FFMPEG_AUTOSPLIT_SIZE 2000000000
 
+#define PRINT if (G.debug & G_DEBUG_FFMPEG) printf
+
 /* Delete a picture buffer */
 
 static void delete_picture(AVFrame *f)
 /* Delete a picture buffer */
 
 static void delete_picture(AVFrame *f)
@@ -139,7 +139,7 @@ static int write_audio_frame(void)
        if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE) {
                pkt.pts = av_rescale_q(c->coded_frame->pts,
                                       c->time_base, audio_stream->time_base);
        if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE) {
                pkt.pts = av_rescale_q(c->coded_frame->pts,
                                       c->time_base, audio_stream->time_base);
-               fprintf(stderr, "Audio Frame PTS: %d\n", (int)pkt.pts);
+               PRINT("Audio Frame PTS: %d\n", (int) pkt.pts);
        }
 
        pkt.stream_index = audio_stream->index;
        }
 
        pkt.stream_index = audio_stream->index;
@@ -265,10 +265,10 @@ static int write_video_frame(RenderData *rd, int cfra, AVFrame *frame, ReportLis
                        packet.pts = av_rescale_q(c->coded_frame->pts,
                                                  c->time_base,
                                                  video_stream->time_base);
                        packet.pts = av_rescale_q(c->coded_frame->pts,
                                                  c->time_base,
                                                  video_stream->time_base);
-                       fprintf(stderr, "Video Frame PTS: %d\n", (int)packet.pts);
+                       PRINT("Video Frame PTS: %d\n", (int)packet.pts);
                }
                else {
                }
                else {
-                       fprintf(stderr, "Video Frame PTS: not set\n");
+                       PRINT("Video Frame PTS: not set\n");
                }
                if (c->coded_frame->key_frame)
                        packet.flags |= AV_PKT_FLAG_KEY;
                }
                if (c->coded_frame->key_frame)
                        packet.flags |= AV_PKT_FLAG_KEY;
@@ -364,7 +364,7 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop)
        char *param;
        const AVOption *rv = NULL;
 
        char *param;
        const AVOption *rv = NULL;
 
-       fprintf(stderr, "FFMPEG expert option: %s: ", prop->name);
+       PRINT("FFMPEG expert option: %s: ", prop->name);
 
        BLI_strncpy(name, prop->name, sizeof(name));
 
 
        BLI_strncpy(name, prop->name, sizeof(name));
 
@@ -376,15 +376,15 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop)
 
        switch (prop->type) {
                case IDP_STRING:
 
        switch (prop->type) {
                case IDP_STRING:
-                       fprintf(stderr, "%s.\n", IDP_String(prop));
+                       PRINT("%s.\n", IDP_String(prop));
                        av_set_string3(c, prop->name, IDP_String(prop), 1, &rv);
                        break;
                case IDP_FLOAT:
                        av_set_string3(c, prop->name, IDP_String(prop), 1, &rv);
                        break;
                case IDP_FLOAT:
-                       fprintf(stderr, "%g.\n", IDP_Float(prop));
+                       PRINT("%g.\n", IDP_Float(prop));
                        rv = av_set_double(c, prop->name, IDP_Float(prop));
                        break;
                case IDP_INT:
                        rv = av_set_double(c, prop->name, IDP_Float(prop));
                        break;
                case IDP_INT:
-                       fprintf(stderr, "%d.\n", IDP_Int(prop));
+                       PRINT("%d.\n", IDP_Int(prop));
 
                        if (param) {
                                if (IDP_Int(prop)) {
 
                        if (param) {
                                if (IDP_Int(prop)) {
@@ -401,7 +401,7 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop)
        }
 
        if (!rv) {
        }
 
        if (!rv) {
-               fprintf(stderr, "ffmpeg-option not supported: %s! Skipping.\n",
+               PRINT("ffmpeg-option not supported: %s! Skipping.\n",
                        prop->name);
        }
 }
                        prop->name);
        }
 }
@@ -446,11 +446,14 @@ static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char
 /* prepare a video stream for the output file */
 
 static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContext *of,
 /* prepare a video stream for the output file */
 
 static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContext *of,
-                                    int rectx, int recty)
+                                    int rectx, int recty, char *error, int error_size)
 {
        AVStream *st;
        AVCodecContext *c;
        AVCodec *codec;
 {
        AVStream *st;
        AVCodecContext *c;
        AVCodec *codec;
+
+       error[0] = '\0';
+
        st = av_new_stream(of, 0);
        if (!st) return NULL;
 
        st = av_new_stream(of, 0);
        if (!st) return NULL;
 
@@ -547,13 +550,13 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
 //         || !strcmp(of->oformat->name, "3gp")
            )
        {
 //         || !strcmp(of->oformat->name, "3gp")
            )
        {
-               fprintf(stderr, "Using global header\n");
+               PRINT("Using global header\n");
                c->flags |= CODEC_FLAG_GLOBAL_HEADER;
        }
        
        /* Determine whether we are encoding interlaced material or not */
        if (rd->mode & R_FIELDS) {
                c->flags |= CODEC_FLAG_GLOBAL_HEADER;
        }
        
        /* Determine whether we are encoding interlaced material or not */
        if (rd->mode & R_FIELDS) {
-               fprintf(stderr, "Encoding interlaced video\n");
+               PRINT("Encoding interlaced video\n");
                c->flags |= CODEC_FLAG_INTERLACED_DCT;
                c->flags |= CODEC_FLAG_INTERLACED_ME;
        }
                c->flags |= CODEC_FLAG_INTERLACED_DCT;
                c->flags |= CODEC_FLAG_INTERLACED_ME;
        }
@@ -566,8 +569,7 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
        set_ffmpeg_properties(rd, c, "video");
        
        if (avcodec_open(c, codec) < 0) {
        set_ffmpeg_properties(rd, c, "video");
        
        if (avcodec_open(c, codec) < 0) {
-               //
-               //XXX error("Couldn't initialize codec");
+               BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
                return NULL;
        }
 
                return NULL;
        }
 
@@ -672,7 +674,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
        AVFormatContext *of;
        AVOutputFormat *fmt;
        AVDictionary *opts = NULL;
        AVFormatContext *of;
        AVOutputFormat *fmt;
        AVDictionary *opts = NULL;
-       char name[256];
+       char name[256], error[1024];
        const char **exts;
 
        ffmpeg_type = rd->ffcodecdata.type;
        const char **exts;
 
        ffmpeg_type = rd->ffcodecdata.type;
@@ -684,11 +686,9 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
        ffmpeg_autosplit = rd->ffcodecdata.flags
                           & FFMPEG_AUTOSPLIT_OUTPUT;
        
        ffmpeg_autosplit = rd->ffcodecdata.flags
                           & FFMPEG_AUTOSPLIT_OUTPUT;
        
-       do_init_ffmpeg();
-
        /* Determine the correct filename */
        BKE_ffmpeg_filepath_get(name, rd);
        /* Determine the correct filename */
        BKE_ffmpeg_filepath_get(name, rd);
-       fprintf(stderr, "Starting output to %s(ffmpeg)...\n"
+       PRINT("Starting output to %s(ffmpeg)...\n"
                "  Using type=%d, codec=%d, audio_codec=%d,\n"
                "  video_bitrate=%d, audio_bitrate=%d,\n"
                "  gop_size=%d, autosplit=%d\n"
                "  Using type=%d, codec=%d, audio_codec=%d,\n"
                "  video_bitrate=%d, audio_bitrate=%d,\n"
                "  gop_size=%d, autosplit=%d\n"
@@ -793,10 +793,14 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
        }
        
        if (fmt->video_codec != CODEC_ID_NONE) {
        }
        
        if (fmt->video_codec != CODEC_ID_NONE) {
-               video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty);
-               printf("alloc video stream %p\n", video_stream);
+               video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty, error, sizeof(error));
+               PRINT("alloc video stream %p\n", video_stream);
                if (!video_stream) {
                if (!video_stream) {
-                       BKE_report(reports, RPT_ERROR, "Error initializing video stream.");
+                       if (error[0])
+                               BKE_report(reports, RPT_ERROR, error);
+                       else
+                               BKE_report(reports, RPT_ERROR, "Error initializing video stream.");
+
                        av_dict_free(&opts);
                        return 0;
                }
                        av_dict_free(&opts);
                        return 0;
                }
@@ -870,10 +874,10 @@ void flush_ffmpeg(void)
                        packet.pts = av_rescale_q(c->coded_frame->pts,
                                                  c->time_base,
                                                  video_stream->time_base);
                        packet.pts = av_rescale_q(c->coded_frame->pts,
                                                  c->time_base,
                                                  video_stream->time_base);
-                       fprintf(stderr, "Video Frame PTS: %d\n", (int)packet.pts);
+                       PRINT("Video Frame PTS: %d\n", (int)packet.pts);
                }
                else {
                }
                else {
-                       fprintf(stderr, "Video Frame PTS: not set\n");
+                       PRINT("Video Frame PTS: not set\n");
                }
                if (c->coded_frame->key_frame) {
                        packet.flags |= AV_PKT_FLAG_KEY;
                }
                if (c->coded_frame->key_frame) {
                        packet.flags |= AV_PKT_FLAG_KEY;
@@ -983,9 +987,9 @@ int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, i
        AVFrame *avframe;
        int success = 1;
 
        AVFrame *avframe;
        int success = 1;
 
-       fprintf(stderr, "Writing frame %i, "
-               "render width=%d, render height=%d\n", frame,
-               rectx, recty);
+       PRINT("Writing frame %i, "
+             "render width=%d, render height=%d\n", frame,
+             rectx, recty);
 
 // why is this done before writing the video frame and again at end_ffmpeg?
 //     write_audio_frames(frame / (((double)rd->frs_sec) / rd->frs_sec_base));
 
 // why is this done before writing the video frame and again at end_ffmpeg?
 //     write_audio_frames(frame / (((double)rd->frs_sec) / rd->frs_sec_base));
@@ -1013,7 +1017,7 @@ void BKE_ffmpeg_end(void)
 {
        unsigned int i;
        
 {
        unsigned int i;
        
-       fprintf(stderr, "Closing ffmpeg...\n");
+       PRINT("Closing ffmpeg...\n");
 
 #if 0
        if (audio_stream) { /* SEE UPPER */
 
 #if 0
        if (audio_stream) { /* SEE UPPER */
@@ -1029,7 +1033,7 @@ void BKE_ffmpeg_end(void)
 #endif
 
        if (video_stream && video_stream->codec) {
 #endif
 
        if (video_stream && video_stream->codec) {
-               fprintf(stderr, "Flushing delayed frames...\n");
+               PRINT("Flushing delayed frames...\n");
                flush_ffmpeg();
        }
        
                flush_ffmpeg();
        }
        
@@ -1041,7 +1045,7 @@ void BKE_ffmpeg_end(void)
 
        if (video_stream && video_stream->codec) {
                avcodec_close(video_stream->codec);
 
        if (video_stream && video_stream->codec) {
                avcodec_close(video_stream->codec);
-               printf("zero video stream %p\n", video_stream);
+               PRINT("zero video stream %p\n", video_stream);
                video_stream = 0;
        }
 
                video_stream = 0;
        }
 
@@ -1142,8 +1146,8 @@ IDProperty *BKE_ffmpeg_property_add(RenderData *rd, const char *type, int opt_in
                BLI_strncpy(name, o->name, sizeof(name));
        }
 
                BLI_strncpy(name, o->name, sizeof(name));
        }
 
-       fprintf(stderr, "ffmpeg_property_add: %s %d %d %s\n",
-               type, parent_index, opt_index, name);
+       PRINT("ffmpeg_property_add: %s %d %d %s\n",
+             type, parent_index, opt_index, name);
 
        prop = IDP_GetPropertyFromGroup(group, name);
        if (prop) {
 
        prop = IDP_GetPropertyFromGroup(group, name);
        if (prop) {
@@ -1316,12 +1320,10 @@ static void ffmpeg_set_expert_options(RenderData *rd)
                if (rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT)
                        BKE_ffmpeg_property_add_string(rd, "video", "cqp:0");
        }
                if (rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT)
                        BKE_ffmpeg_property_add_string(rd, "video", "cqp:0");
        }
-#if 0   /* disabled for after release */
        else if (codec_id == CODEC_ID_DNXHD) {
                if (rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT)
        else if (codec_id == CODEC_ID_DNXHD) {
                if (rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT)
-                       ffmpeg_property_add_string(rd, "video", "mbd:rd");
+                       BKE_ffmpeg_property_add_string(rd, "video", "mbd:rd");
        }
        }
-#endif
 }
 
 void BKE_ffmpeg_preset_set(RenderData *rd, int preset)
 }
 
 void BKE_ffmpeg_preset_set(RenderData *rd, int preset)
index a74629e..b3d0df0 100644 (file)
@@ -32,6 +32,8 @@
  *  \ingroup bli
  */
 
  *  \ingroup bli
  */
 
+#include <stdarg.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -139,6 +141,11 @@ __attribute__((nonnull))
 #endif
 ;
 
 #endif
 ;
 
+/*
+ * Replacement for vsnprintf
+ */
+size_t BLI_vsnprintf(char *buffer, size_t count, const char *format, va_list arg);
+
 /*
  * Print formatted string into a newly mallocN'd string
  * and return it.
 /*
  * Print formatted string into a newly mallocN'd string
  * and return it.
index 7a750a7..8501db7 100644 (file)
@@ -78,22 +78,31 @@ char *BLI_strncpy(char *dst, const char *src, const size_t maxncpy)
        return dst;
 }
 
        return dst;
 }
 
-size_t BLI_snprintf(char *buffer, size_t count, const char *format, ...)
+size_t BLI_vsnprintf(char *buffer, size_t count, const char *format, va_list arg)
 {
        size_t n;
 {
        size_t n;
-       va_list arg;
 
 
-       va_start(arg, format);
        n = vsnprintf(buffer, count, format, arg);
        n = vsnprintf(buffer, count, format, arg);
-       
+
        if (n != -1 && n < count) {
                buffer[n] = '\0';
        }
        else {
                buffer[count - 1] = '\0';
        }
        if (n != -1 && n < count) {
                buffer[n] = '\0';
        }
        else {
                buffer[count - 1] = '\0';
        }
-       
+
+       return n;
+}
+
+size_t BLI_snprintf(char *buffer, size_t count, const char *format, ...)
+{
+       size_t n;
+       va_list arg;
+
+       va_start(arg, format);
+       n = BLI_vsnprintf(buffer, count, format, arg);
        va_end(arg);
        va_end(arg);
+
        return n;
 }
 
        return n;
 }
 
index 738e61d..a04affd 100644 (file)
@@ -506,5 +506,9 @@ void IMB_processor_apply_threaded(int buffer_lines, int handle_size, void *init_
                                                       void *customdata),
                                   void *(do_thread) (void *));
 
                                                       void *customdata),
                                   void *(do_thread) (void *));
 
+/* ffmpeg */
+void IMB_ffmpeg_init(void);
+const char *IMB_ffmpeg_last_error(void);
+
 #endif
 
 #endif
 
index f07a18c..9092d59 100644 (file)
@@ -439,8 +439,6 @@ static ImBuf *avi_fetchibuf(struct anim *anim, int position)
 
 #ifdef WITH_FFMPEG
 
 
 #ifdef WITH_FFMPEG
 
-extern void do_init_ffmpeg(void);
-
 static int startffmpeg(struct anim *anim)
 {
        int i, videoStream;
 static int startffmpeg(struct anim *anim)
 {
        int i, videoStream;
@@ -463,8 +461,6 @@ static int startffmpeg(struct anim *anim)
 
        streamcount = anim->streamindex;
 
 
        streamcount = anim->streamindex;
 
-       do_init_ffmpeg();
-
        if (avformat_open_input(&pFormatCtx, anim->name, NULL, NULL) != 0) {
                return -1;
        }
        if (avformat_open_input(&pFormatCtx, anim->name, NULL, NULL) != 0) {
                return -1;
        }
index 2b0597d..9ec22f0 100644 (file)
@@ -43,6 +43,8 @@
 
 #include "BLI_path_util.h"
 #include "BLI_fileops.h"
 
 #include "BLI_path_util.h"
 #include "BLI_fileops.h"
+#include "BLI_utildefines.h"
+#include "BLI_string.h"
 
 #include "DNA_userdef_types.h"
 #include "BKE_global.h"
 
 #include "DNA_userdef_types.h"
 #include "BKE_global.h"
@@ -220,6 +222,8 @@ static int isqtime(const char *name)
 
 #ifdef WITH_FFMPEG
 
 
 #ifdef WITH_FFMPEG
 
+static char ffmpeg_last_error[1024];
+
 void silence_log_ffmpeg(int quiet)
 {
        if (quiet) {
 void silence_log_ffmpeg(int quiet)
 {
        if (quiet) {
@@ -230,21 +234,40 @@ void silence_log_ffmpeg(int quiet)
        }
 }
 
        }
 }
 
-extern void do_init_ffmpeg(void);
-void do_init_ffmpeg(void)
+void ffmpeg_log_callback(void *ptr, int level, const char *format, va_list arg)
 {
 {
-       static int ffmpeg_init = 0;
-       if (!ffmpeg_init) {
-               ffmpeg_init = 1;
-               av_register_all();
-               avdevice_register_all();
-               if ((G.debug & G_DEBUG_FFMPEG) == 0) {
-                       silence_log_ffmpeg(1);
-               }
-               else {
-                       silence_log_ffmpeg(0);
-               }
+       if (ELEM(level, AV_LOG_FATAL, AV_LOG_ERROR)) {
+               size_t n = BLI_vsnprintf(ffmpeg_last_error, sizeof(ffmpeg_last_error), format, arg);
+
+               /* strip trailing \n */
+               ffmpeg_last_error[n - 1] = '\0';
        }
        }
+
+       /* call default logger to print all message to console */
+       av_log_default_callback(ptr, level, format, arg);
+}
+
+void IMB_ffmpeg_init(void)
+{
+       av_register_all();
+       avdevice_register_all();
+
+       if ((G.debug & G_DEBUG_FFMPEG) == 0) {
+               silence_log_ffmpeg(1);
+       }
+       else {
+               silence_log_ffmpeg(0);
+       }
+
+       ffmpeg_last_error[0] = '\0';
+
+       /* set own callback which could store last error to report to UI */
+       av_log_set_callback(ffmpeg_log_callback);
+}
+
+const char *IMB_ffmpeg_last_error(void)
+{
+       return ffmpeg_last_error;
 }
 
 static int isffmpeg(const char *filename)
 }
 
 static int isffmpeg(const char *filename)
@@ -255,8 +278,6 @@ static int isffmpeg(const char *filename)
        AVCodec *pCodec;
        AVCodecContext *pCodecCtx;
 
        AVCodec *pCodec;
        AVCodecContext *pCodecCtx;
 
-       do_init_ffmpeg();
-
        if (BLI_testextensie(filename, ".swf") ||
            BLI_testextensie(filename, ".jpg") ||
            BLI_testextensie(filename, ".png") ||
        if (BLI_testextensie(filename, ".swf") ||
            BLI_testextensie(filename, ".jpg") ||
            BLI_testextensie(filename, ".png") ||
index a6f3c00..597c229 100644 (file)
@@ -2995,7 +2995,7 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna)
                {CODEC_ID_FLV1, "FLASH", 0, "Flash Video", ""},
                {CODEC_ID_FFV1, "FFV1", 0, "FFmpeg video codec #1", ""},
                {CODEC_ID_QTRLE, "QTRLE", 0, "QTRLE", ""},
                {CODEC_ID_FLV1, "FLASH", 0, "Flash Video", ""},
                {CODEC_ID_FFV1, "FFV1", 0, "FFmpeg video codec #1", ""},
                {CODEC_ID_QTRLE, "QTRLE", 0, "QTRLE", ""},
-               /* {CODEC_ID_DNXHD, "DNXHD", 0, "DNxHD", ""}, */ /* disabled for after release */
+               {CODEC_ID_DNXHD, "DNXHD", 0, "DNxHD", ""},
                {0, NULL, 0, NULL, NULL}
        };
 
                {0, NULL, 0, NULL, NULL}
        };
 
index 3e884d1..58e1066 100644 (file)
@@ -1273,6 +1273,7 @@ int main(int argc, const char **argv)
        initglobals();  /* blender.c */
 
        IMB_init();
        initglobals();  /* blender.c */
 
        IMB_init();
+       IMB_ffmpeg_init();
 
        BLI_callback_global_init();
 
 
        BLI_callback_global_init();
 
index 4586a50..1ba944a 100644 (file)
@@ -52,8 +52,6 @@ const long timeScale = 1000;
 #define CATCH_EXCP catch (Exception & exp) \
 { exp.report(); m_status = SourceError; }
 
 #define CATCH_EXCP catch (Exception & exp) \
 { exp.report(); m_status = SourceError; }
 
-extern "C" void do_init_ffmpeg();
-
 // class RenderVideo
 
 // constructor
 // class RenderVideo
 
 // constructor
@@ -521,8 +519,6 @@ void VideoFFmpeg::releaseFrame(AVFrame* frame)
 // open video file
 void VideoFFmpeg::openFile (char * filename)
 {
 // open video file
 void VideoFFmpeg::openFile (char * filename)
 {
-       do_init_ffmpeg();
-
        if (openStream(filename, NULL, NULL) != 0)
                return;
 
        if (openStream(filename, NULL, NULL) != 0)
                return;
 
@@ -586,8 +582,6 @@ void VideoFFmpeg::openCam (char * file, short camIdx)
        char                            filename[28], rateStr[20];
        char                *p;
 
        char                            filename[28], rateStr[20];
        char                *p;
 
-       do_init_ffmpeg();
-
 #ifdef WIN32
        // video capture on windows only through Video For Windows driver
        inputFormat = av_find_input_format("vfwcap");
 #ifdef WIN32
        // video capture on windows only through Video For Windows driver
        inputFormat = av_find_input_format("vfwcap");