Camera tracking: fixed issue when track used for rotation stabilization points to...
[blender.git] / source / blender / blenkernel / intern / writeffmpeg.c
index 4db5399..e9f7823 100644 (file)
@@ -1,8 +1,4 @@
-/** \file blender/blenkernel/intern/writeffmpeg.c
- *  \ingroup bke
- */
 /*
- * $Id$
  *
  * ffmpeg-write support
  *
  *
  */
 
+/** \file blender/blenkernel/intern/writeffmpeg.c
+ *  \ingroup bke
+ */
+
 #ifdef WITH_FFMPEG
 #include <string.h>
 #include <stdio.h>
 #include <libswscale/swscale.h>
 #include <libavcodec/opt.h>
 
-#if defined(WIN32) && (!(defined snprintf))
-#define snprintf _snprintf
-#endif
-
 #include "MEM_guardedalloc.h"
 
 #include "DNA_scene_types.h"
@@ -53,6 +49,8 @@
 #  include "AUD_C-API.h"
 #endif
 
+#include "BLI_utildefines.h"
+
 #include "BKE_global.h"
 #include "BKE_idprop.h"
 #include "BKE_main.h"
@@ -240,13 +238,13 @@ static const char** get_file_extensions(int format)
 }
 
 /* Write a frame to the output file */
-static int write_video_frame(RenderData *rd, AVFrame* frame, ReportList *reports)
+static int write_video_frame(RenderData *rd, int cfra, AVFrame* frame, ReportList *reports)
 {
        int outsize = 0;
        int ret, success= 1;
        AVCodecContext* c = video_stream->codec;
 
-       frame->pts = rd->cfra - rd->sfra;
+       frame->pts = cfra;
 
        if (rd->mode & R_FIELDS) {
                frame->top_field_first = ((rd->mode & R_ODDFIELD) != 0);
@@ -254,7 +252,8 @@ static int write_video_frame(RenderData *rd, AVFrame* frame, ReportList *reports
 
        outsize = avcodec_encode_video(c, video_buffer, video_buffersize, 
                                           frame);
-       if (outsize != 0) {
+
+       if (outsize > 0) {
                AVPacket packet;
                av_init_packet(&packet);
 
@@ -272,14 +271,13 @@ static int write_video_frame(RenderData *rd, AVFrame* frame, ReportList *reports
                packet.data = video_buffer;
                packet.size = outsize;
                ret = av_interleaved_write_frame(outfile, &packet);
-       } else {
-               ret = 0;
+               success = (ret == 0);
+       } else if (outsize < 0) {
+               success = 0;
        }
 
-       if (ret != 0) {
-               success= 0;
+       if (!success)
                BKE_report(reports, RPT_ERROR, "Error writing frame.");
-       }
 
        return success;
 }
@@ -347,8 +345,8 @@ static AVFrame* generate_video_frame(uint8_t* pixels, ReportList *reports)
 
        if (c->pix_fmt != PIX_FMT_BGR32) {
                sws_scale(img_convert_ctx, (const uint8_t * const*) rgb_frame->data,
-                         rgb_frame->linesize, 0, c->height, 
-                         current_frame->data, current_frame->linesize);
+                         rgb_frame->linesize, 0, c->height,
+                         current_frame->data, current_frame->linesize);
                delete_picture(rgb_frame);
        }
        return current_frame;
@@ -400,6 +398,20 @@ static void set_ffmpeg_property_option(AVCodecContext* c, IDProperty * prop)
        }
 }
 
+static int ffmpeg_proprty_valid(AVCodecContext *c, const char *prop_name, IDProperty *curr)
+{
+       int valid= 1;
+
+       if(strcmp(prop_name, "video")==0) {
+               if(strcmp(curr->name, "bf")==0) {
+                       /* flash codec doesn't support b frames */
+                       valid&= c->codec_id!=CODEC_ID_FLV1;
+               }
+       }
+
+       return valid;
+}
+
 static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char * prop_name)
 {
        IDProperty * prop;
@@ -410,8 +422,7 @@ static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char
                return;
        }
        
-       prop = IDP_GetPropertyFromGroup(
-               rd->ffcodecdata.properties, (char*) prop_name);
+       prop = IDP_GetPropertyFromGroup(rd->ffcodecdata.properties, prop_name);
        if (!prop) {
                return;
        }
@@ -419,7 +430,8 @@ static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char
        iter = IDP_GetGroupIterator(prop);
 
        while ((curr = IDP_GroupIterNext(iter)) != NULL) {
-               set_ffmpeg_property_option(c, curr);
+               if(ffmpeg_proprty_valid(c, prop_name, curr))
+                       set_ffmpeg_property_option(c, curr);
        }
 }
 
@@ -473,7 +485,7 @@ static AVStream* alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
        if (!codec) return NULL;
        
        /* Be sure to use the correct pixel format(e.g. RGB, YUV) */
-       
+
        if (codec->pix_fmts) {
                c->pix_fmt = codec->pix_fmts[0];
        } else {
@@ -493,6 +505,18 @@ static AVStream* alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
                c->qmax=51;
        }
        
+       // Keep lossless encodes in the RGB domain.
+       if (codec_id == CODEC_ID_HUFFYUV || codec_id == CODEC_ID_FFV1) {
+               /* HUFFYUV was PIX_FMT_YUV422P before */
+               c->pix_fmt = PIX_FMT_RGB32;
+       }
+
+       if ( codec_id == CODEC_ID_QTRLE ) {
+               if (rd->im_format.planes ==  R_IMF_PLANES_RGBA) {
+                       c->pix_fmt = PIX_FMT_ARGB;
+               }
+       }
+
        if ((of->oformat->flags & AVFMT_GLOBALHEADER)
 //             || !strcmp(of->oformat->name, "mp4")
 //         || !strcmp(of->oformat->name, "mov")
@@ -522,8 +546,20 @@ static AVStream* alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
                return NULL;
        }
 
-       video_buffersize = 2000000;
-       video_buffer = (uint8_t*)MEM_mallocN(video_buffersize, 
+       if ( codec_id == CODEC_ID_QTRLE ) {
+               // normally it should be enough to have buffer with actual image size,
+               // but some codecs like QTRLE might store extra information in this buffer,
+               // so it should be a way larger
+
+               // maximum video buffer size is 6-bytes per pixel, plus DPX header size (1664)
+               // (from FFmpeg sources)
+               int size = c->width * c->height;
+               video_buffersize = 7*size + 10000;
+       }
+       else
+               video_buffersize = avpicture_get_size(c->pix_fmt, c->width, c->height);
+
+       video_buffer = (uint8_t*)MEM_mallocN(video_buffersize*sizeof(uint8_t),
                                                 "FFMPEG video buffer");
        
        current_frame = alloc_picture(c->pix_fmt, c->width, c->height);
@@ -555,7 +591,7 @@ static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
        c->sample_rate = rd->ffcodecdata.audio_mixrate;
        c->bit_rate = ffmpeg_audio_bitrate*1000;
        c->sample_fmt = SAMPLE_FMT_S16;
-       c->channels = 2;
+       c->channels = rd->ffcodecdata.audio_channels;
        codec = avcodec_find_encoder(c->codec_id);
        if (!codec) {
                //XXX error("Couldn't find a valid audio codec");
@@ -569,6 +605,11 @@ static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
                return NULL;
        }
 
+       /* need to prevent floating point exception when using vorbis audio codec,
+          initialize this value in the same way as it's done in FFmpeg iteslf (sergey) */
+       st->codec->time_base.num= 1;
+       st->codec->time_base.den= st->codec->sample_rate;
+
        audio_outbuf_size = FF_MIN_BUFFER_SIZE;
 
        if((c->codec_id >= CODEC_ID_PCM_S16LE) && (c->codec_id <= CODEC_ID_PCM_DVD))
@@ -580,12 +621,11 @@ static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
                        audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4;
        }
 
-       audio_output_buffer = (uint8_t*)MEM_mallocN(
-               audio_outbuf_size, "FFMPEG audio encoder input buffer");
+       audio_output_buffer = (uint8_t*)av_malloc(
+               audio_outbuf_size);
 
-       audio_input_buffer = (uint8_t*)MEM_mallocN(
-               audio_input_samples * c->channels * sizeof(int16_t),
-               "FFMPEG audio encoder output buffer");
+       audio_input_buffer = (uint8_t*)av_malloc(
+               audio_input_samples * c->channels * sizeof(int16_t));
 
        audio_time = 0.0f;
 
@@ -653,15 +693,17 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
 
        fmt->audio_codec = ffmpeg_audio_codec;
 
-       snprintf(of->filename, sizeof(of->filename), "%s", name);
+       BLI_snprintf(of->filename, sizeof(of->filename), "%s", name);
        /* set the codec to the user's selection */
        switch(ffmpeg_type) {
        case FFMPEG_AVI:
        case FFMPEG_MOV:
-       case FFMPEG_OGG:
        case FFMPEG_MKV:
                fmt->video_codec = ffmpeg_codec;
                break;
+       case FFMPEG_OGG:
+               fmt->video_codec = CODEC_ID_THEORA;
+               break;
        case FFMPEG_DV:
                fmt->video_codec = CODEC_ID_DVVIDEO;
                break;
@@ -707,7 +749,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
        
        if (ffmpeg_type == FFMPEG_DV) {
                fmt->audio_codec = CODEC_ID_PCM_S16LE;
-               if (ffmpeg_audio_codec != CODEC_ID_NONE && rd->ffcodecdata.audio_mixrate != 48000) {
+               if (ffmpeg_audio_codec != CODEC_ID_NONE && rd->ffcodecdata.audio_mixrate != 48000 && rd->ffcodecdata.audio_channels != 2) {
                        BKE_report(reports, RPT_ERROR, "FFMPEG only supports 48khz / stereo audio for DV!");
                        return 0;
                }
@@ -740,7 +782,11 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
                }
        }
 
-       av_write_header(of);
+       if (av_write_header(of) < 0) {
+               BKE_report(reports, RPT_ERROR, "Could not initialize streams. Probably unsupported codec combination.");
+               return 0;
+       }
+
        outfile = of;
        av_dump_format(of, 0, name, 1);
 
@@ -811,7 +857,8 @@ void flush_ffmpeg(void)
    ********************************************************************** */
 
 /* Get the output filename-- similar to the other output formats */
-void filepath_ffmpeg(char* string, RenderData* rd) {
+void filepath_ffmpeg(char* string, RenderData* rd)
+{
        char autosplit[20];
 
        const char ** exts = get_file_extensions(rd->ffcodecdata.type);
@@ -866,6 +913,10 @@ int start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty, Repo
                specs.format = AUD_FORMAT_S16;
                specs.rate = rd->ffcodecdata.audio_mixrate;
                audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->ffcodecdata.audio_volume);
+#ifdef FFMPEG_CODEC_TIME_BASE
+               c->time_base.den = specs.rate;
+               c->time_base.num = 1;
+#endif
        }
 #endif
        return success;
@@ -887,7 +938,7 @@ static void write_audio_frames(double to_pts)
 }
 #endif
 
-int append_ffmpeg(RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports) 
+int append_ffmpeg(RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, ReportList *reports)
 {
        AVFrame* avframe;
        int success = 1;
@@ -902,7 +953,7 @@ int append_ffmpeg(RenderData *rd, int frame, int *pixels, int rectx, int recty,
        if(video_stream)
        {
                avframe= generate_video_frame((unsigned char*) pixels, reports);
-               success= (avframe && write_video_frame(rd, avframe, reports));
+               success= (avframe && write_video_frame(rd, frame - start_frame, avframe, reports));
 
                if (ffmpeg_autosplit) {
                        if (avio_tell(outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) {
@@ -982,11 +1033,11 @@ void end_ffmpeg(void)
                video_buffer = 0;
        }
        if (audio_output_buffer) {
-               MEM_freeN(audio_output_buffer);
+               av_free(audio_output_buffer);
                audio_output_buffer = 0;
        }
        if (audio_input_buffer) {
-               MEM_freeN(audio_input_buffer);
+               av_free(audio_input_buffer);
                audio_input_buffer = 0;
        }
 
@@ -1007,8 +1058,7 @@ void ffmpeg_property_del(RenderData *rd, void *type, void *prop_)
                return;
        }
 
-       group = IDP_GetPropertyFromGroup(
-               rd->ffcodecdata.properties, (char*) type);
+       group = IDP_GetPropertyFromGroup(rd->ffcodecdata.properties, type);
        if (group && prop) {
                IDP_RemFromGroup(group, prop);
                IDP_FreeProperty(prop);
@@ -1016,7 +1066,7 @@ void ffmpeg_property_del(RenderData *rd, void *type, void *prop_)
        }
 }
 
-IDProperty *ffmpeg_property_add(RenderData *rd, char * type, int opt_index, int parent_index)
+IDProperty *ffmpeg_property_add(RenderData *rd, const char *type, int opt_index, int parent_index)
 {
        AVCodecContext c;
        const AVOption * o;
@@ -1036,21 +1086,20 @@ IDProperty *ffmpeg_property_add(RenderData *rd, char * type, int opt_index, int
 
        if (!rd->ffcodecdata.properties) {
                rd->ffcodecdata.properties 
-                       = IDP_New(IDP_GROUP, val, "ffmpeg"); 
+                       = IDP_New(IDP_GROUP, &val, "ffmpeg"); 
        }
 
-       group = IDP_GetPropertyFromGroup(
-               rd->ffcodecdata.properties, (char*) type);
+       group = IDP_GetPropertyFromGroup(rd->ffcodecdata.properties, type);
        
        if (!group) {
-               group = IDP_New(IDP_GROUP, val, (char*) type); 
+               group = IDP_New(IDP_GROUP, &val, type);
                IDP_AddToGroup(rd->ffcodecdata.properties, group);
        }
 
        if (parent_index) {
-               sprintf(name, "%s:%s", parent->name, o->name);
+               BLI_snprintf(name, sizeof(name), "%s:%s", parent->name, o->name);
        } else {
-               strcpy(name, o->name);
+               BLI_strncpy(name, o->name, sizeof(name));
        }
 
        fprintf(stderr, "ffmpeg_property_add: %s %d %d %s\n",
@@ -1073,7 +1122,9 @@ IDProperty *ffmpeg_property_add(RenderData *rd, char * type, int opt_index, int
                idp_type = IDP_FLOAT;
                break;
        case FF_OPT_TYPE_STRING:
-               val.str = "                                                                               ";
+               val.string.str = (char *)"                                                                               ";
+               val.string.len = 80;
+/*             val.str = (char *)"                                                                               ";*/
                idp_type = IDP_STRING;
                break;
        case FF_OPT_TYPE_CONST:
@@ -1083,7 +1134,7 @@ IDProperty *ffmpeg_property_add(RenderData *rd, char * type, int opt_index, int
        default:
                return NULL;
        }
-       prop = IDP_New(idp_type, val, name);
+       prop = IDP_New(idp_type, &val, name);
        IDP_AddToGroup(group, prop);
        return prop;
 }
@@ -1169,10 +1220,71 @@ int ffmpeg_property_add_string(RenderData *rd, const char * type, const char * s
        return 1;
 }
 
+static void ffmpeg_set_expert_options(RenderData *rd)
+{
+       int codec_id = rd->ffcodecdata.codec;
+
+       if(rd->ffcodecdata.properties)
+               IDP_FreeProperty(rd->ffcodecdata.properties);
+
+       if(codec_id == CODEC_ID_H264) {
+               /*
+                * All options here are for x264, but must be set via ffmpeg.
+                * The names are therefore different - Search for "x264 to FFmpeg option mapping"
+                * to get a list.
+                */
+
+               /*
+                * Use CABAC coder. Using "coder:1", which should be equivalent,
+                * crashes Blender for some reason. Either way - this is no big deal.
+                */
+               ffmpeg_property_add_string(rd, "video", "coder:vlc");
+
+               /*
+                * The other options were taken from the libx264-default.preset
+                * included in the ffmpeg distribution.
+                */
+//             ffmpeg_property_add_string(rd, "video", "flags:loop"); // this breaks compatibility for QT
+               ffmpeg_property_add_string(rd, "video", "cmp:chroma");
+               ffmpeg_property_add_string(rd, "video", "partitions:parti4x4");
+               ffmpeg_property_add_string(rd, "video", "partitions:partp8x8");
+               ffmpeg_property_add_string(rd, "video", "partitions:partb8x8");
+               ffmpeg_property_add_string(rd, "video", "me:hex");
+               ffmpeg_property_add_string(rd, "video", "subq:6");
+               ffmpeg_property_add_string(rd, "video", "me_range:16");
+               ffmpeg_property_add_string(rd, "video", "qdiff:4");
+               ffmpeg_property_add_string(rd, "video", "keyint_min:25");
+               ffmpeg_property_add_string(rd, "video", "sc_threshold:40");
+               ffmpeg_property_add_string(rd, "video", "i_qfactor:0.71");
+               ffmpeg_property_add_string(rd, "video", "b_strategy:1");
+               ffmpeg_property_add_string(rd, "video", "bf:3");
+               ffmpeg_property_add_string(rd, "video", "refs:2");
+               ffmpeg_property_add_string(rd, "video", "qcomp:0.6");
+               ffmpeg_property_add_string(rd, "video", "directpred:3");
+               ffmpeg_property_add_string(rd, "video", "trellis:0");
+               ffmpeg_property_add_string(rd, "video", "flags2:wpred");
+               ffmpeg_property_add_string(rd, "video", "flags2:dct8x8");
+               ffmpeg_property_add_string(rd, "video", "flags2:fastpskip");
+               ffmpeg_property_add_string(rd, "video", "wpredp:2");
+
+               if(rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT)
+                       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)
+                       ffmpeg_property_add_string(rd, "video", "mbd:rd");
+       }
+#endif
+}
+
 void ffmpeg_set_preset(RenderData *rd, int preset)
 {
        int isntsc = (rd->frs_sec != 25);
 
+       if(rd->ffcodecdata.properties)
+               IDP_FreeProperty(rd->ffcodecdata.properties);
+
        switch (preset) {
        case FFMPEG_PRESET_VCD:
                rd->ffcodecdata.type = FFMPEG_MPEG1;
@@ -1203,8 +1315,11 @@ void ffmpeg_set_preset(RenderData *rd, int preset)
        case FFMPEG_PRESET_DVD:
                rd->ffcodecdata.type = FFMPEG_MPEG2;
                rd->ffcodecdata.video_bitrate = 6000;
-               rd->xsch = 720;
-               rd->ysch = isntsc ? 480 : 576;
+
+               /* Don't set resolution, see [#21351]
+                * rd->xsch = 720;
+                * rd->ysch = isntsc ? 480 : 576; */
+
                rd->ffcodecdata.gop_size = isntsc ? 18 : 15;
                rd->ffcodecdata.rc_max_rate = 9000;
                rd->ffcodecdata.rc_min_rate = 0;
@@ -1230,47 +1345,6 @@ void ffmpeg_set_preset(RenderData *rd, int preset)
                rd->ffcodecdata.mux_packet_size = 2048;
                rd->ffcodecdata.mux_rate = 10080000;
 
-               /*
-                * All options here are for x264, but must be set via ffmpeg.
-                * The names are therefore different - Search for "x264 to FFmpeg option mapping"
-                * to get a list.
-                */
-               
-               /*
-                * Use CABAC coder. Using "coder:1", which should be equivalent,
-                * crashes Blender for some reason. Either way - this is no big deal.
-                */
-               ffmpeg_property_add_string(rd, "video", "coder:vlc");
-               
-               /* 
-                * The other options were taken from the libx264-default.preset
-                * included in the ffmpeg distribution.
-                */
-               ffmpeg_property_add_string(rd, "video", "flags:loop");
-               ffmpeg_property_add_string(rd, "video", "cmp:chroma");
-               ffmpeg_property_add_string(rd, "video", "partitions:parti4x4");
-               ffmpeg_property_add_string(rd, "video", "partitions:partp8x8");
-               ffmpeg_property_add_string(rd, "video", "partitions:partb8x8");
-               ffmpeg_property_add_string(rd, "video", "me:hex");
-               ffmpeg_property_add_string(rd, "video", "subq:6");
-               ffmpeg_property_add_string(rd, "video", "me_range:16");
-               ffmpeg_property_add_string(rd, "video", "qdiff:4");
-               ffmpeg_property_add_string(rd, "video", "keyint_min:25");
-               ffmpeg_property_add_string(rd, "video", "sc_threshold:40");
-               ffmpeg_property_add_string(rd, "video", "i_qfactor:0.71");
-               ffmpeg_property_add_string(rd, "video", "b_strategy:1");
-               ffmpeg_property_add_string(rd, "video", "bf:3");
-               ffmpeg_property_add_string(rd, "video", "refs:2");
-               ffmpeg_property_add_string(rd, "video", "qcomp:0.6");
-               ffmpeg_property_add_string(rd, "video", "directpred:3");
-               ffmpeg_property_add_string(rd, "video", "trellis:0");
-               ffmpeg_property_add_string(rd, "video", "flags2:wpred");
-               ffmpeg_property_add_string(rd, "video", "flags2:dct8x8");
-               ffmpeg_property_add_string(rd, "video", "flags2:fastpskip");
-               ffmpeg_property_add_string(rd, "video", "wpredp:2");
-               
-               // This makes x264 output lossless. Will be a separate option later.
-               //ffmpeg_property_add_string(rd, "video", "cqp:0");
                break;
 
        case FFMPEG_PRESET_THEORA:
@@ -1294,38 +1368,43 @@ void ffmpeg_set_preset(RenderData *rd, int preset)
                break;
 
        }
+
+       ffmpeg_set_expert_options(rd);
 }
 
-void ffmpeg_verify_image_type(RenderData *rd)
+void ffmpeg_verify_image_type(RenderData *rd, ImageFormatData *imf)
 {
        int audio= 0;
 
-       if(rd->imtype == R_FFMPEG) {
+       if(imf->imtype == R_IMF_IMTYPE_FFMPEG) {
                if(rd->ffcodecdata.type <= 0 ||
                   rd->ffcodecdata.codec <= 0 ||
                   rd->ffcodecdata.audio_codec <= 0 ||
                   rd->ffcodecdata.video_bitrate <= 1) {
 
                        rd->ffcodecdata.codec = CODEC_ID_MPEG2VIDEO;
-                       /* Don't set preset, disturbs render resolution.
-                        * ffmpeg_set_preset(rd, FFMPEG_PRESET_DVD); */
+
+                       ffmpeg_set_preset(rd, FFMPEG_PRESET_DVD);
+               }
+               if(rd->ffcodecdata.type == FFMPEG_OGG) {
+                       rd->ffcodecdata.type = FFMPEG_MPEG2;
                }
 
                audio= 1;
        }
-       else if(rd->imtype == R_H264) {
+       else if(imf->imtype == R_IMF_IMTYPE_H264) {
                if(rd->ffcodecdata.codec != CODEC_ID_H264) {
                        ffmpeg_set_preset(rd, FFMPEG_PRESET_H264);
                        audio= 1;
                }
        }
-       else if(rd->imtype == R_XVID) {
+       else if(imf->imtype == R_IMF_IMTYPE_XVID) {
                if(rd->ffcodecdata.codec != CODEC_ID_MPEG4) {
                        ffmpeg_set_preset(rd, FFMPEG_PRESET_XVID);
                        audio= 1;
                }
        }
-       else if(rd->imtype == R_THEORA) {
+       else if(imf->imtype == R_IMF_IMTYPE_THEORA) {
                if(rd->ffcodecdata.codec != CODEC_ID_THEORA) {
                        ffmpeg_set_preset(rd, FFMPEG_PRESET_THEORA);
                        audio= 1;
@@ -1338,5 +1417,9 @@ void ffmpeg_verify_image_type(RenderData *rd)
        }
 }
 
-#endif
+void ffmpeg_verify_codec_settings(RenderData *rd)
+{
+       ffmpeg_set_expert_options(rd);
+}
 
+#endif