Patch #33837: ffmpeg1.1 and libav9.1 compatibility update
authorSergey Sharybin <sergey.vfx@gmail.com>
Sat, 12 Jan 2013 12:51:10 +0000 (12:51 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Sat, 12 Jan 2013 12:51:10 +0000 (12:51 +0000)
Patch makes it possible to compile blender with recent ffmpeg
and libav libraries, mainly by getting rid of deprecated API.

Original patch by Campbell Barton with own modifications to
support compilation with older ffmpeg versions.

This patch could break compatibility of FFV1 videos playing
back in older players, mainly because of alpha support changes.
Preserving compatibility with such players became a headache
and think it's high time to get rid of workarounds here.

intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp
intern/ffmpeg/ffmpeg_compat.h
source/blender/blenkernel/intern/writeffmpeg.c
source/blender/imbuf/intern/anim_movie.c
source/blender/imbuf/intern/indexer.c
source/blender/imbuf/intern/util.c
source/gameengine/VideoTexture/VideoFFmpeg.cpp

index 0a3d0f8e85ad8528bc4cf705b7d41131f4655f8e..831e19981829751efafdfc9fe6ffdeef1074e9aa 100644 (file)
@@ -107,7 +107,7 @@ void AUD_FFMPEGReader::init()
        m_position = 0;
        m_pkgbuf_left = 0;
 
-       if(av_find_stream_info(m_formatCtx)<0)
+       if(avformat_find_stream_info(m_formatCtx, NULL) < 0)
                AUD_THROW(AUD_ERROR_FFMPEG, streaminfo_error);
 
        // find audio stream and codec
@@ -133,7 +133,7 @@ void AUD_FFMPEGReader::init()
        if(!aCodec)
                AUD_THROW(AUD_ERROR_FFMPEG, nodecoder_error);
 
-       if(avcodec_open(m_codecCtx, aCodec)<0)
+       if(avcodec_open2(m_codecCtx, aCodec, NULL) < 0)
                AUD_THROW(AUD_ERROR_FFMPEG, codecopen_error);
 
        // XXX this prints file information to stdout:
@@ -236,14 +236,7 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(boost::shared_ptr<AUD_Buffer> buffer) :
 AUD_FFMPEGReader::~AUD_FFMPEGReader()
 {
        avcodec_close(m_codecCtx);
-
-       if(m_aviocontext)
-       {
-               avformat_close_input(&m_formatCtx);
-               av_free(m_aviocontext);
-       }
-       else
-               av_close_input_file(m_formatCtx);
+       avformat_close_input(&m_formatCtx);
 }
 
 int AUD_FFMPEGReader::read_packet(void* opaque, uint8_t* buf, int buf_size)
index 2b34348da8111197bcddf9a197a7bd7d9fed4621..55040e4db8e3b47c62b8ee3459b04896e892de74 100644 (file)
@@ -55,10 +55,15 @@ AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs,
 {
        static const char* formats[] = { NULL, "ac3", "flac", "matroska", "mp2", "mp3", "ogg", "wav" };
 
-       if(avformat_alloc_output_context2(&m_formatCtx, NULL, formats[format], filename.c_str()))
-               AUD_THROW(AUD_ERROR_FFMPEG, context_error);
+       m_formatCtx = avformat_alloc_context();
+       if (!m_formatCtx) AUD_THROW(AUD_ERROR_FFMPEG, context_error);
 
-       m_outputFmt = m_formatCtx->oformat;
+       strcpy(m_formatCtx->filename, filename.c_str());
+       m_outputFmt = m_formatCtx->oformat = av_guess_format(formats[format], filename.c_str(), NULL);
+       if (!m_outputFmt) {
+               avformat_free_context(m_formatCtx);
+               AUD_THROW(AUD_ERROR_FFMPEG, context_error);
+       }
 
        switch(codec)
        {
@@ -116,7 +121,7 @@ AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs,
                if(m_outputFmt->audio_codec == CODEC_ID_NONE)
                        AUD_THROW(AUD_ERROR_SPECS, codec_error);
 
-               m_stream = av_new_stream(m_formatCtx, 0);
+               m_stream = avformat_new_stream(m_formatCtx, NULL);
                if(!m_stream)
                        AUD_THROW(AUD_ERROR_FFMPEG, stream_error);
 
@@ -164,7 +169,7 @@ AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs,
                        if(!codec)
                                AUD_THROW(AUD_ERROR_FFMPEG, codec_error);
 
-                       if(avcodec_open(m_codecCtx, codec))
+                       if(avcodec_open2(m_codecCtx, codec, NULL))
                                AUD_THROW(AUD_ERROR_FFMPEG, codec_error);
 
                        m_output_buffer.resize(FF_MIN_BUFFER_SIZE);
index 37cde2c2837774b3cb89916a9bfff53e7c6ba924..5492a7ba88a8cfa297b9743355dfd38de8347c36 100644 (file)
@@ -33,6 +33,7 @@
 #include <libavcodec/avcodec.h>
 #include <libavutil/rational.h>
 #include <libavutil/opt.h>
+#include <libavutil/mathematics.h>
 
 #if (LIBAVFORMAT_VERSION_MAJOR > 52) || ((LIBAVFORMAT_VERSION_MAJOR >= 52) && (LIBAVFORMAT_VERSION_MINOR >= 101))
 #define FFMPEG_HAVE_PARSE_UTILS 1
 
 #if ((LIBAVUTIL_VERSION_MAJOR > 51) || (LIBAVUTIL_VERSION_MAJOR == 51) && (LIBAVUTIL_VERSION_MINOR >= 32))
 #define FFMPEG_FFV1_ALPHA_SUPPORTED
+#else
+static inline
+int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
+{
+       const AVOption *rv = NULL;
+       av_set_string3(obj, name, val, 1, &rv);
+       return rv != NULL;
+}
+
+static inline
+int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
+{
+       const AVOption *rv = NULL;
+       rv = av_set_int(obj, name, val);
+       return rv != NULL;
+}
+
+static inline
+int av_opt_set_double(void *obj, const char *name, double val, int search_flags)
+{
+       const AVOption *rv = NULL;
+       rv = av_set_double(obj, name, val);
+       return rv != NULL;
+}
+
+#define AV_OPT_TYPE_INT     FF_OPT_TYPE_INT
+#define AV_OPT_TYPE_INT64   FF_OPT_TYPE_INT64
+#define AV_OPT_TYPE_STRING  FF_OPT_TYPE_STRING
+#define AV_OPT_TYPE_CONST   FF_OPT_TYPE_CONST
+#define AV_OPT_TYPE_DOUBLE  FF_OPT_TYPE_DOUBLE
+#define AV_OPT_TYPE_FLOAT   FF_OPT_TYPE_FLOAT
 #endif
 
 #if ((LIBAVFORMAT_VERSION_MAJOR < 53) || ((LIBAVFORMAT_VERSION_MAJOR == 53) && (LIBAVFORMAT_VERSION_MINOR < 24)) || ((LIBAVFORMAT_VERSION_MAJOR == 53) && (LIBAVFORMAT_VERSION_MINOR < 24) && (LIBAVFORMAT_VERSION_MICRO < 2)))
 #define avformat_close_input(x) av_close_input_file(*(x))
 #endif
 
+#if ((LIBAVCODEC_VERSION_MAJOR < 53) || (LIBAVCODEC_VERSION_MAJOR == 53 && LIBAVCODEC_VERSION_MINOR < 42))
+static inline
+int avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options)
+{
+       /* TODO: no options are taking into account */
+       return avcodec_open(avctx, codec);
+}
+#endif
+
+#if ((LIBAVFORMAT_VERSION_MAJOR < 53) || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR < 24))
+static inline
+AVStream *avformat_new_stream(AVFormatContext *s, AVCodec *c)
+{
+       /* TODO: no codec is taking into account */
+       return av_new_stream(s, 0);
+}
+
+static inline
+int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
+{
+       /* TODO: no options are taking into account */
+       return av_find_stream_info(ic);
+}
+#endif
+
 #if ((LIBAVFORMAT_VERSION_MAJOR > 53) || ((LIBAVFORMAT_VERSION_MAJOR == 53) && (LIBAVFORMAT_VERSION_MINOR > 32)) || ((LIBAVFORMAT_VERSION_MAJOR == 53) && (LIBAVFORMAT_VERSION_MINOR == 24) && (LIBAVFORMAT_VERSION_MICRO >= 100)))
 static inline
 void my_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
index cf2a165c2b277dc12dcc56c3d53bca9baff36a87..7e51025883dd8ef1b956c867dddd704582900b1c 100644 (file)
@@ -373,7 +373,7 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop)
 {
        char name[128];
        char *param;
-       const AVOption *rv = NULL;
+       int fail = TRUE;
 
        PRINT("FFMPEG expert option: %s: ", prop->name);
 
@@ -388,30 +388,30 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop)
        switch (prop->type) {
                case IDP_STRING:
                        PRINT("%s.\n", IDP_String(prop));
-                       av_set_string3(c, prop->name, IDP_String(prop), 1, &rv);
+                       fail = av_opt_set(c, prop->name, IDP_String(prop), 0);
                        break;
                case IDP_FLOAT:
                        PRINT("%g.\n", IDP_Float(prop));
-                       rv = av_set_double(c, prop->name, IDP_Float(prop));
+                       fail = av_opt_set_double(c, prop->name, IDP_Float(prop), 0);
                        break;
                case IDP_INT:
                        PRINT("%d.\n", IDP_Int(prop));
 
                        if (param) {
                                if (IDP_Int(prop)) {
-                                       av_set_string3(c, name, param, 1, &rv);
+                                       fail = av_opt_set(c, name, param, 0);
                                }
                                else {
                                        return;
                                }
                        }
                        else {
-                               rv = av_set_int(c, prop->name, IDP_Int(prop));
+                               fail = av_opt_set_int(c, prop->name, IDP_Int(prop), 0);
                        }
                        break;
        }
 
-       if (!rv) {
+       if (fail) {
                PRINT("ffmpeg-option not supported: %s! Skipping.\n", prop->name);
        }
 }
@@ -464,8 +464,9 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
 
        error[0] = '\0';
 
-       st = av_new_stream(of, 0);
+       st = avformat_new_stream(of, NULL);
        if (!st) return NULL;
+       st->id = 0;
 
        /* Set up the codec context */
        
@@ -541,16 +542,7 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
        }
 
        if (codec_id == CODEC_ID_FFV1) {
-#ifdef FFMPEG_FFV1_ALPHA_SUPPORTED
-               if (rd->im_format.planes == R_IMF_PLANES_RGBA) {
-                       c->pix_fmt = PIX_FMT_RGB32;
-               }
-               else {
-                       c->pix_fmt = PIX_FMT_BGR0;
-               }
-#else
                c->pix_fmt = PIX_FMT_RGB32;
-#endif
        }
 
        if (codec_id == CODEC_ID_QTRLE) {
@@ -582,7 +574,7 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
 
        set_ffmpeg_properties(rd, c, "video");
        
-       if (avcodec_open(c, codec) < 0) {
+       if (avcodec_open2(c, codec, NULL) < 0) {
                BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
                return NULL;
        }
@@ -619,8 +611,9 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
 
        error[0] = '\0';
 
-       st = av_new_stream(of, 1);
+       st = avformat_new_stream(of, NULL);
        if (!st) return NULL;
+       st->id = 1;
 
        c = st->codec;
        c->codec_id = codec_id;
@@ -642,7 +635,7 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
 
        set_ffmpeg_properties(rd, c, "audio");
 
-       if (avcodec_open(c, codec) < 0) {
+       if (avcodec_open2(c, codec, NULL) < 0) {
                //XXX error("Couldn't initialize audio codec");
                BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
                return NULL;
@@ -1151,7 +1144,7 @@ IDProperty *BKE_ffmpeg_property_add(RenderData *rd, const char *type, int opt_in
        
        val.i = 0;
 
-       avcodec_get_context_defaults(&c);
+       avcodec_get_context_defaults3(&c, NULL);
 
        o = c.av_class->option + opt_index;
        parent = c.av_class->option + parent_index;
@@ -1182,23 +1175,23 @@ IDProperty *BKE_ffmpeg_property_add(RenderData *rd, const char *type, int opt_in
        }
 
        switch (o->type) {
-               case FF_OPT_TYPE_INT:
-               case FF_OPT_TYPE_INT64:
+               case AV_OPT_TYPE_INT:
+               case AV_OPT_TYPE_INT64:
                        val.i = FFMPEG_DEF_OPT_VAL_INT(o);
                        idp_type = IDP_INT;
                        break;
-               case FF_OPT_TYPE_DOUBLE:
-               case FF_OPT_TYPE_FLOAT:
+               case AV_OPT_TYPE_DOUBLE:
+               case AV_OPT_TYPE_FLOAT:
                        val.f = FFMPEG_DEF_OPT_VAL_DOUBLE(o);
                        idp_type = IDP_FLOAT;
                        break;
-               case FF_OPT_TYPE_STRING:
+               case AV_OPT_TYPE_STRING:
                        val.string.str = (char *)"                                                                               ";
                        val.string.len = 80;
 /*             val.str = (char *)"                                                                               ";*/
                        idp_type = IDP_STRING;
                        break;
-               case FF_OPT_TYPE_CONST:
+               case AV_OPT_TYPE_CONST:
                        val.i = 1;
                        idp_type = IDP_INT;
                        break;
@@ -1238,7 +1231,7 @@ int BKE_ffmpeg_property_add_string(RenderData *rd, const char *type, const char
        char *param;
        IDProperty *prop = NULL;
        
-       avcodec_get_context_defaults(&c);
+       avcodec_get_context_defaults3(&c, NULL);
 
        strncpy(name_, str, sizeof(name_));
 
@@ -1259,10 +1252,10 @@ int BKE_ffmpeg_property_add_string(RenderData *rd, const char *type, const char
        if (!o) {
                return 0;
        }
-       if (param && o->type == FF_OPT_TYPE_CONST) {
+       if (param && o->type == AV_OPT_TYPE_CONST) {
                return 0;
        }
-       if (param && o->type != FF_OPT_TYPE_CONST && o->unit) {
+       if (param && o->type != AV_OPT_TYPE_CONST && o->unit) {
                p = my_av_find_opt(&c, param, o->unit, 0, 0);
                if (p) {
                        prop = BKE_ffmpeg_property_add(rd, (char *) type, p - c.av_class->option, o - c.av_class->option);
index 8dfdbd4fddcfe077e672b58b0b3a01484b445f46..8d79482ed18060f6d46a9528aea3cc44a8410e1d 100644 (file)
@@ -486,7 +486,7 @@ static int startffmpeg(struct anim *anim)
                return -1;
        }
 
-       if (av_find_stream_info(pFormatCtx) < 0) {
+       if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
                av_close_input_file(pFormatCtx);
                return -1;
        }
@@ -523,7 +523,7 @@ static int startffmpeg(struct anim *anim)
 
        pCodecCtx->workaround_bugs = 1;
 
-       if (avcodec_open(pCodecCtx, pCodec) < 0) {
+       if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
                av_close_input_file(pFormatCtx);
                return -1;
        }
index 277f50bcdbccd5dac2cb0c1ce1ecd122dfdef607..86e451e746794305c64728ab83c2f2f3c2d267ea 100644 (file)
@@ -496,7 +496,9 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
 
        fprintf(stderr, "Starting work on proxy: %s\n", rv->of->filename);
 
-       rv->st = av_new_stream(rv->of, 0);
+       rv->st = avformat_new_stream(rv->of, NULL);
+       rv->st->id = 0;
+
        rv->c = rv->st->codec;
        rv->c->codec_type = AVMEDIA_TYPE_VIDEO;
        rv->c->codec_id = CODEC_ID_MJPEG;
@@ -531,8 +533,8 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
        /* there's no  way to set JPEG quality in the same way as in AVI JPEG and image sequence,
         * but this seems to be giving expected quality result */
        ffmpeg_quality = (int)(1.0f + 30.0f * (1.0f - (float)quality / 100.0f) + 0.5f);
-       av_set_int(rv->c, "qmin", ffmpeg_quality);
-       av_set_int(rv->c, "qmax", ffmpeg_quality);
+       av_opt_set_int(rv->c, "qmin", ffmpeg_quality, 0);
+       av_opt_set_int(rv->c, "qmax", ffmpeg_quality, 0);
 
        if (rv->of->flags & AVFMT_GLOBALHEADER) {
                rv->c->flags |= CODEC_FLAG_GLOBAL_HEADER;
@@ -545,7 +547,7 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
                return 0;
        }
 
-       avcodec_open(rv->c, rv->codec);
+       avcodec_open2(rv->c, rv->codec, NULL);
 
        rv->video_buffersize = 2000000;
        rv->video_buffer = (uint8_t *)MEM_mallocN(
@@ -758,7 +760,7 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, IMB_Tim
                return NULL;
        }
 
-       if (av_find_stream_info(context->iFormatCtx) < 0) {
+       if (avformat_find_stream_info(context->iFormatCtx, NULL) < 0) {
                av_close_input_file(context->iFormatCtx);
                MEM_freeN(context);
                return NULL;
@@ -797,7 +799,7 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, IMB_Tim
 
        context->iCodecCtx->workaround_bugs = 1;
 
-       if (avcodec_open(context->iCodecCtx, context->iCodec) < 0) {
+       if (avcodec_open2(context->iCodecCtx, context->iCodec, NULL) < 0) {
                av_close_input_file(context->iFormatCtx);
                MEM_freeN(context);
                return NULL;
index 42fb0c79b62234ee123872f13e3262e27d5b2698..549a95e383dfd2771904d69b7901a5118c11dd5c 100644 (file)
@@ -306,8 +306,8 @@ static int isffmpeg(const char *filename)
                return 0;
        }
 
-       if (av_find_stream_info(pFormatCtx) < 0) {
-               if (UTIL_DEBUG) fprintf(stderr, "isffmpeg: av_find_stream_info failed\n");
+       if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
+               if (UTIL_DEBUG) fprintf(stderr, "isffmpeg: avformat_find_stream_info failed\n");
                av_close_input_file(pFormatCtx);
                return 0;
        }
@@ -340,7 +340,7 @@ static int isffmpeg(const char *filename)
                return 0;
        }
 
-       if (avcodec_open(pCodecCtx, pCodec) < 0) {
+       if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
                av_close_input_file(pFormatCtx);
                return 0;
        }
index 8976a21376a0f734f4b03d8638396899632e06ff..10eef9e0cf2754838fc12646b4bd99e4c02be1a6 100644 (file)
@@ -174,7 +174,7 @@ int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AV
        if (avformat_open_input(&formatCtx, filename, inputFormat, formatParams)!=0)
                return -1;
 
-       if (av_find_stream_info(formatCtx)<0) 
+       if (avformat_find_stream_info(formatCtx, NULL) < 0)
        {
                av_close_input_file(formatCtx);
                return -1;
@@ -209,7 +209,7 @@ int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AV
                return -1;
        }
        codecCtx->workaround_bugs = 1;
-       if (avcodec_open(codecCtx, codec)<0) 
+       if (avcodec_open2(codecCtx, codec, NULL) < 0)
        {
                av_close_input_file(formatCtx);
                return -1;