Patch #34204: [Render Animation] Fails with "Error: Specified sample_fmt is not suppo...
[blender.git] / source / blender / blenkernel / intern / writeffmpeg.c
index e9f7823..082ae38 100644 (file)
@@ -1,19 +1,25 @@
 /*
 /*
+ * ***** BEGIN GPL LICENSE BLOCK *****
  *
  *
- * ffmpeg-write support
- *
- * Partial Copyright (c) 2006 Peter Schlaile
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s):
+ *
+ * Partial Copyright (c) 2006 Peter Schlaile
+ *
+ * ***** END GPL LICENSE BLOCK *****
  */
 
 /** \file blender/blenkernel/intern/writeffmpeg.c
  */
 
 /** \file blender/blenkernel/intern/writeffmpeg.c
@@ -36,8 +42,8 @@
 #include <libavformat/avformat.h>
 #include <libavcodec/avcodec.h>
 #include <libavutil/rational.h>
 #include <libavformat/avformat.h>
 #include <libavcodec/avcodec.h>
 #include <libavutil/rational.h>
+#include <libavutil/samplefmt.h>
 #include <libswscale/swscale.h>
 #include <libswscale/swscale.h>
-#include <libavcodec/opt.h>
 
 #include "MEM_guardedalloc.h"
 
 
 #include "MEM_guardedalloc.h"
 
@@ -63,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;
@@ -74,30 +78,32 @@ static int ffmpeg_gop_size = 12;
 static int ffmpeg_autosplit = 0;
 static int ffmpeg_autosplit_count = 0;
 
 static int ffmpeg_autosplit = 0;
 static int ffmpeg_autosplit_count = 0;
 
-static AVFormatContextoutfile = 0;
-static AVStreamvideo_stream = 0;
-static AVStreamaudio_stream = 0;
-static AVFramecurrent_frame = 0;
+static AVFormatContext *outfile = 0;
+static AVStream *video_stream = 0;
+static AVStream *audio_stream = 0;
+static AVFrame *current_frame = 0;
 static struct SwsContext *img_convert_ctx = 0;
 
 static struct SwsContext *img_convert_ctx = 0;
 
-static uint8_tvideo_buffer = 0;
+static uint8_t *video_buffer = 0;
 static int video_buffersize = 0;
 
 static int video_buffersize = 0;
 
-static uint8_taudio_input_buffer = 0;
+static uint8_t *audio_input_buffer = 0;
 static int audio_input_samples = 0;
 static int audio_input_samples = 0;
-static uint8_taudio_output_buffer = 0;
+static uint8_t *audio_output_buffer = 0;
 static int audio_outbuf_size = 0;
 static double audio_time = 0.0f;
 
 #ifdef WITH_AUDASPACE
 static int audio_outbuf_size = 0;
 static double audio_time = 0.0f;
 
 #ifdef WITH_AUDASPACE
-static AUD_Deviceaudio_mixdown_device = 0;
+static AUD_Device *audio_mixdown_device = 0;
 #endif
 
 #define FFMPEG_AUTOSPLIT_SIZE 2000000000
 
 #endif
 
 #define FFMPEG_AUTOSPLIT_SIZE 2000000000
 
+#define PRINT if (G.debug & G_DEBUG_FFMPEG) printf
+
 /* Delete a picture buffer */
 
 /* Delete a picture buffer */
 
-static void delete_picture(AVFramef)
+static void delete_picture(AVFrame *f)
 {
        if (f) {
                if (f->data[0]) MEM_freeN(f->data[0]);
 {
        if (f) {
                if (f->data[0]) MEM_freeN(f->data[0]);
@@ -105,10 +111,16 @@ static void delete_picture(AVFrame* f)
        }
 }
 
        }
 }
 
+static int request_float_audio_buffer(int codec_id)
+{
+       /* If any of these codecs, we prefer the float sample format (if supported) */
+       return codec_id == CODEC_ID_AAC || codec_id == CODEC_ID_AC3 || codec_id == CODEC_ID_VORBIS;
+}
+
 #ifdef WITH_AUDASPACE
 static int write_audio_frame(void) 
 {
 #ifdef WITH_AUDASPACE
 static int write_audio_frame(void) 
 {
-       AVCodecContextc = NULL;
+       AVCodecContext *c = NULL;
        AVPacket pkt;
 
        c = audio_stream->codec;
        AVPacket pkt;
 
        c = audio_stream->codec;
@@ -119,23 +131,18 @@ static int write_audio_frame(void)
        AUD_readDevice(audio_mixdown_device, audio_input_buffer, audio_input_samples);
        audio_time += (double) audio_input_samples / (double) c->sample_rate;
 
        AUD_readDevice(audio_mixdown_device, audio_input_buffer, audio_input_samples);
        audio_time += (double) audio_input_samples / (double) c->sample_rate;
 
-       pkt.size = avcodec_encode_audio(c, audio_output_buffer,
-                                       audio_outbuf_size,
-                                       (short*) audio_input_buffer);
+       pkt.size = avcodec_encode_audio(c, audio_output_buffer, audio_outbuf_size, (short *) audio_input_buffer);
 
 
-       if(pkt.size < 0)
-       {
+       if (pkt.size < 0) {
                // XXX error("Error writing audio packet");
                return -1;
        }
 
        pkt.data = audio_output_buffer;
 
                // XXX error("Error writing audio packet");
                return -1;
        }
 
        pkt.data = audio_output_buffer;
 
-       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);
+       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);
+               PRINT("Audio Frame PTS: %d\n", (int) pkt.pts);
        }
 
        pkt.stream_index = audio_stream->index;
        }
 
        pkt.stream_index = audio_stream->index;
@@ -151,10 +158,10 @@ static int write_audio_frame(void)
 #endif // #ifdef WITH_AUDASPACE
 
 /* Allocate a temporary frame */
 #endif // #ifdef WITH_AUDASPACE
 
 /* Allocate a temporary frame */
-static AVFrame* alloc_picture(int pix_fmt, int width, int height) 
+static AVFrame *alloc_picture(int pix_fmt, int width, int height)
 {
 {
-       AVFramef;
-       uint8_tbuf;
+       AVFrame *f;
+       uint8_t *buf;
        int size;
        
        /* allocate space for the struct */
        int size;
        
        /* allocate space for the struct */
@@ -167,82 +174,94 @@ static AVFrame* alloc_picture(int pix_fmt, int width, int height)
                free(f);
                return NULL;
        }
                free(f);
                return NULL;
        }
-       avpicture_fill((AVPicture*)f, buf, pix_fmt, width, height);
+       avpicture_fill((AVPicture *)f, buf, pix_fmt, width, height);
        return f;
 }
 
 /* Get the correct file extensions for the requested format,
        return f;
 }
 
 /* Get the correct file extensions for the requested format,
  first is always desired guess_format parameter */
-static const char** get_file_extensions(int format) 
* first is always desired guess_format parameter */
+static const char **get_file_extensions(int format)
 {
 {
-       switch(format) {
-       case FFMPEG_DV: {
-               static const char * rv[] = { ".dv", NULL };
-               return rv;
-       }
-       case FFMPEG_MPEG1: {
-               static const char * rv[] = { ".mpg", ".mpeg", NULL };
-               return rv;
-       }
-       case FFMPEG_MPEG2: {
-               static const char * rv[] = { ".dvd", ".vob", ".mpg", ".mpeg",
-                                                NULL };
-               return rv;
-       }
-       case FFMPEG_MPEG4: {
-               static const char * rv[] = { ".mp4", ".mpg", ".mpeg", NULL };
-               return rv;
-       }
-       case FFMPEG_AVI: {
-               static const char * rv[] = { ".avi", NULL };
-               return rv;
-       }
-       case FFMPEG_MOV: {
-               static const char * rv[] = { ".mov", NULL };
-               return rv;
-       }
-       case FFMPEG_H264: {
-               /* FIXME: avi for now... */
-               static const char * rv[] = { ".avi", NULL };
-               return rv;
-       }
+       switch (format) {
+               case FFMPEG_DV:
+               {
+                       static const char *rv[] = { ".dv", NULL };
+                       return rv;
+               }
+               case FFMPEG_MPEG1:
+               {
+                       static const char *rv[] = { ".mpg", ".mpeg", NULL };
+                       return rv;
+               }
+               case FFMPEG_MPEG2:
+               {
+                       static const char *rv[] = { ".dvd", ".vob", ".mpg", ".mpeg", NULL };
+                       return rv;
+               }
+               case FFMPEG_MPEG4:
+               {
+                       static const char *rv[] = { ".mp4", ".mpg", ".mpeg", NULL };
+                       return rv;
+               }
+               case FFMPEG_AVI:
+               {
+                       static const char *rv[] = { ".avi", NULL };
+                       return rv;
+               }
+               case FFMPEG_MOV:
+               {
+                       static const char *rv[] = { ".mov", NULL };
+                       return rv;
+               }
+               case FFMPEG_H264:
+               {
+                       /* FIXME: avi for now... */
+                       static const char *rv[] = { ".avi", NULL };
+                       return rv;
+               }
 
 
-       case FFMPEG_XVID: {
-               /* FIXME: avi for now... */
-               static const char * rv[] = { ".avi", NULL };
-               return rv;
-       }
-       case FFMPEG_FLV: {
-               static const char * rv[] = { ".flv", NULL };
-               return rv;
-       }
-       case FFMPEG_MKV: {
-               static const char * rv[] = { ".mkv", NULL };
-               return rv;
-       }
-       case FFMPEG_OGG: {
-               static const char * rv[] = { ".ogg", ".ogv", NULL };
-               return rv;
-       }
-       case FFMPEG_MP3: {
-               static const char * rv[] = { ".mp3", NULL };
-               return rv;
-       }
-       case FFMPEG_WAV: {
-               static const char * rv[] = { ".wav", NULL };
-               return rv;
-       }
-       default:
-               return NULL;
+               case FFMPEG_XVID:
+               {
+                       /* FIXME: avi for now... */
+                       static const char *rv[] = { ".avi", NULL };
+                       return rv;
+               }
+               case FFMPEG_FLV:
+               {
+                       static const char *rv[] = { ".flv", NULL };
+                       return rv;
+               }
+               case FFMPEG_MKV:
+               {
+                       static const char *rv[] = { ".mkv", NULL };
+                       return rv;
+               }
+               case FFMPEG_OGG:
+               {
+                       static const char *rv[] = { ".ogg", ".ogv", NULL };
+                       return rv;
+               }
+               case FFMPEG_MP3:
+               {
+                       static const char *rv[] = { ".mp3", NULL };
+                       return rv;
+               }
+               case FFMPEG_WAV:
+               {
+                       static const char *rv[] = { ".wav", NULL };
+                       return rv;
+               }
+               default:
+                       return NULL;
        }
 }
 
 /* Write a frame to the output file */
        }
 }
 
 /* Write a frame to the output file */
-static int write_video_frame(RenderData *rd, int cfra, AVFrameframe, ReportList *reports)
+static int write_video_frame(RenderData *rd, int cfra, AVFrame *frame, ReportList *reports)
 {
        int outsize = 0;
 {
        int outsize = 0;
-       int ret, success= 1;
-       AVCodecContextc = video_stream->codec;
+       int ret, success = 1;
+       AVCodecContext *c = video_stream->codec;
 
        frame->pts = cfra;
 
 
        frame->pts = cfra;
 
@@ -250,20 +269,18 @@ static int write_video_frame(RenderData *rd, int cfra, AVFrame* frame, ReportLis
                frame->top_field_first = ((rd->mode & R_ODDFIELD) != 0);
        }
 
                frame->top_field_first = ((rd->mode & R_ODDFIELD) != 0);
        }
 
-       outsize = avcodec_encode_video(c, video_buffer, video_buffersize, 
-                                          frame);
+       outsize = avcodec_encode_video(c, video_buffer, video_buffersize,  frame);
 
        if (outsize > 0) {
                AVPacket packet;
                av_init_packet(&packet);
 
                if (c->coded_frame->pts != AV_NOPTS_VALUE) {
 
        if (outsize > 0) {
                AVPacket packet;
                av_init_packet(&packet);
 
                if (c->coded_frame->pts != AV_NOPTS_VALUE) {
-                       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);
-               } else {
-                       fprintf(stderr, "Video Frame PTS: not set\n");
+                       packet.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_stream->time_base);
+                       PRINT("Video Frame PTS: %d\n", (int)packet.pts);
+               }
+               else {
+                       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;
@@ -272,48 +289,49 @@ static int write_video_frame(RenderData *rd, int cfra, AVFrame* frame, ReportLis
                packet.size = outsize;
                ret = av_interleaved_write_frame(outfile, &packet);
                success = (ret == 0);
                packet.size = outsize;
                ret = av_interleaved_write_frame(outfile, &packet);
                success = (ret == 0);
-       } else if (outsize < 0) {
+       }
+       else if (outsize < 0) {
                success = 0;
        }
 
        if (!success)
                success = 0;
        }
 
        if (!success)
-               BKE_report(reports, RPT_ERROR, "Error writing frame.");
+               BKE_report(reports, RPT_ERROR, "Error writing frame");
 
        return success;
 }
 
 /* read and encode a frame of audio from the buffer */
 
        return success;
 }
 
 /* read and encode a frame of audio from the buffer */
-static AVFrame* generate_video_frame(uint8_t* pixels, ReportList *reports) 
+static AVFrame *generate_video_frame(uint8_t *pixels, ReportList *reports)
 {
 {
-       uint8_trendered_frame;
+       uint8_t *rendered_frame;
 
 
-       AVCodecContextc = video_stream->codec;
+       AVCodecContext *c = video_stream->codec;
        int width = c->width;
        int height = c->height;
        int width = c->width;
        int height = c->height;
-       AVFramergb_frame;
+       AVFrame *rgb_frame;
 
        if (c->pix_fmt != PIX_FMT_BGR32) {
                rgb_frame = alloc_picture(PIX_FMT_BGR32, width, height);
                if (!rgb_frame) {
 
        if (c->pix_fmt != PIX_FMT_BGR32) {
                rgb_frame = alloc_picture(PIX_FMT_BGR32, width, height);
                if (!rgb_frame) {
-                       BKE_report(reports, RPT_ERROR, "Couldn't allocate temporary frame.");
+                       BKE_report(reports, RPT_ERROR, "Could not allocate temporary frame");
                        return NULL;
                }
                        return NULL;
                }
-       } else {
+       }
+       else {
                rgb_frame = current_frame;
        }
 
        rendered_frame = pixels;
 
        /* Do RGBA-conversion and flipping in one step depending
                rgb_frame = current_frame;
        }
 
        rendered_frame = pixels;
 
        /* Do RGBA-conversion and flipping in one step depending
-          on CPU-Endianess */
+        * on CPU-Endianess */
 
        if (ENDIAN_ORDER == L_ENDIAN) {
                int y;
                for (y = 0; y < height; y++) {
 
        if (ENDIAN_ORDER == L_ENDIAN) {
                int y;
                for (y = 0; y < height; y++) {
-                       uint8_t* target = rgb_frame->data[0]
-                               + width * 4 * (height - y - 1);
-                       uint8_t* src = rendered_frame + width * 4 * y;
-                       uint8_t* end = src + width * 4;
+                       uint8_t *target = rgb_frame->data[0] + width * 4 * (height - y - 1);
+                       uint8_t *src = rendered_frame + width * 4 * y;
+                       uint8_t *end = src + width * 4;
                        while (src != end) {
                                target[3] = src[3];
                                target[2] = src[2];
                        while (src != end) {
                                target[3] = src[3];
                                target[2] = src[2];
@@ -324,13 +342,13 @@ static AVFrame* generate_video_frame(uint8_t* pixels, ReportList *reports)
                                src += 4;
                        }
                }
                                src += 4;
                        }
                }
-       } else {
+       }
+       else {
                int y;
                for (y = 0; y < height; y++) {
                int y;
                for (y = 0; y < height; y++) {
-                       uint8_t* target = rgb_frame->data[0]
-                               + width * 4 * (height - y - 1);
-                       uint8_t* src = rendered_frame + width * 4 * y;
-                       uint8_t* end = src + width * 4;
+                       uint8_t *target = rgb_frame->data[0] + width * 4 * (height - y - 1);
+                       uint8_t *src = rendered_frame + width * 4 * y;
+                       uint8_t *end = src + width * 4;
                        while (src != end) {
                                target[3] = src[0];
                                target[2] = src[1];
                        while (src != end) {
                                target[3] = src[0];
                                target[2] = src[1];
@@ -344,7 +362,7 @@ static AVFrame* generate_video_frame(uint8_t* pixels, ReportList *reports)
        }
 
        if (c->pix_fmt != PIX_FMT_BGR32) {
        }
 
        if (c->pix_fmt != PIX_FMT_BGR32) {
-               sws_scale(img_convert_ctx, (const uint8_t * const*) rgb_frame->data,
+               sws_scale(img_convert_ctx, (const uint8_t *const *) rgb_frame->data,
                          rgb_frame->linesize, 0, c->height,
                          current_frame->data, current_frame->linesize);
                delete_picture(rgb_frame);
                          rgb_frame->linesize, 0, c->height,
                          current_frame->data, current_frame->linesize);
                delete_picture(rgb_frame);
@@ -352,13 +370,13 @@ static AVFrame* generate_video_frame(uint8_t* pixels, ReportList *reports)
        return current_frame;
 }
 
        return current_frame;
 }
 
-static void set_ffmpeg_property_option(AVCodecContext* c, IDProperty * prop)
+static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop)
 {
        char name[128];
 {
        char name[128];
-       char * param;
-       const AVOption * rv = NULL;
+       char *param;
+       int fail = TRUE;
 
 
-       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));
 
@@ -368,55 +386,56 @@ static void set_ffmpeg_property_option(AVCodecContext* c, IDProperty * prop)
                *param++ = 0;
        }
 
                *param++ = 0;
        }
 
-       switch(prop->type) {
-       case IDP_STRING:
-               fprintf(stderr, "%s.\n", IDP_String(prop));
-               av_set_string3(c, prop->name, IDP_String(prop), 1, &rv);
-               break;
-       case IDP_FLOAT:
-               fprintf(stderr, "%g.\n", IDP_Float(prop));
-               rv = av_set_double(c, prop->name, IDP_Float(prop));
-               break;
-       case IDP_INT:
-               fprintf(stderr, "%d.\n", IDP_Int(prop));
-               
-               if (param) {
-                       if (IDP_Int(prop)) {
-                               av_set_string3(c, name, param, 1, &rv);
-                       } else {
-                               return;
+       switch (prop->type) {
+               case IDP_STRING:
+                       PRINT("%s.\n", IDP_String(prop));
+                       fail = av_opt_set(c, prop->name, IDP_String(prop), 0);
+                       break;
+               case IDP_FLOAT:
+                       PRINT("%g.\n", 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)) {
+                                       fail = av_opt_set(c, name, param, 0);
+                               }
+                               else {
+                                       return;
+                               }
                        }
                        }
-               } else {
-                       rv = av_set_int(c, prop->name, IDP_Int(prop));
-               }
-               break;
+                       else {
+                               fail = av_opt_set_int(c, prop->name, IDP_Int(prop), 0);
+                       }
+                       break;
        }
 
        }
 
-       if (!rv) {
-               fprintf(stderr, "ffmpeg-option not supported: %s! Skipping.\n",
-                       prop->name);
+       if (fail) {
+               PRINT("ffmpeg-option not supported: %s! Skipping.\n", prop->name);
        }
 }
 
 static int ffmpeg_proprty_valid(AVCodecContext *c, const char *prop_name, IDProperty *curr)
 {
        }
 }
 
 static int ffmpeg_proprty_valid(AVCodecContext *c, const char *prop_name, IDProperty *curr)
 {
-       int valid= 1;
+       int valid = 1;
 
 
-       if(strcmp(prop_name, "video")==0) {
-               if(strcmp(curr->name, "bf")==0) {
+       if (strcmp(prop_name, "video") == 0) {
+               if (strcmp(curr->name, "bf") == 0) {
                        /* flash codec doesn't support b frames */
                        /* flash codec doesn't support b frames */
-                       valid&= c->codec_id!=CODEC_ID_FLV1;
+                       valid &= c->codec_id != CODEC_ID_FLV1;
                }
        }
 
        return valid;
 }
 
                }
        }
 
        return valid;
 }
 
-static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char * prop_name)
+static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char *prop_name)
 {
 {
-       IDProperty * prop;
-       void * iter;
-       IDProperty * curr;
+       IDProperty *prop;
+       void *iter;
+       IDProperty *curr;
 
        if (!rd->ffcodecdata.properties) {
                return;
 
        if (!rd->ffcodecdata.properties) {
                return;
@@ -430,21 +449,25 @@ static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char
        iter = IDP_GetGroupIterator(prop);
 
        while ((curr = IDP_GroupIterNext(iter)) != NULL) {
        iter = IDP_GetGroupIterator(prop);
 
        while ((curr = IDP_GroupIterNext(iter)) != NULL) {
-               if(ffmpeg_proprty_valid(c, prop_name, curr))
+               if (ffmpeg_proprty_valid(c, prop_name, curr))
                        set_ffmpeg_property_option(c, curr);
        }
 }
 
 /* prepare a video stream for the output file */
 
                        set_ffmpeg_property_option(c, curr);
        }
 }
 
 /* prepare a video stream for the output file */
 
-static AVStream* alloc_video_stream(RenderData *rd, int codec_id, AVFormatContext* of,
-                                       int rectx, int recty) 
+static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContext *of,
+                                    int rectx, int recty, char *error, int error_size)
 {
 {
-       AVStream* st;
-       AVCodecContext* c;
-       AVCodec* codec;
-       st = av_new_stream(of, 0);
+       AVStream *st;
+       AVCodecContext *c;
+       AVCodec *codec;
+
+       error[0] = '\0';
+
+       st = avformat_new_stream(of, NULL);
        if (!st) return NULL;
        if (!st) return NULL;
+       st->id = 0;
 
        /* Set up the codec context */
        
 
        /* Set up the codec context */
        
@@ -452,7 +475,6 @@ static AVStream* alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
        c->codec_id = codec_id;
        c->codec_type = AVMEDIA_TYPE_VIDEO;
 
        c->codec_id = codec_id;
        c->codec_type = AVMEDIA_TYPE_VIDEO;
 
-
        /* Get some values from the current render settings */
        
        c->width = rectx;
        /* Get some values from the current render settings */
        
        c->width = rectx;
@@ -462,33 +484,42 @@ static AVStream* alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
        if (ffmpeg_type == FFMPEG_DV && rd->frs_sec != 25) {
                c->time_base.den = 2997;
                c->time_base.num = 100;
        if (ffmpeg_type == FFMPEG_DV && rd->frs_sec != 25) {
                c->time_base.den = 2997;
                c->time_base.num = 100;
-       } else if ((double) ((int) rd->frs_sec_base) == 
-                  rd->frs_sec_base) {
+       }
+       else if ((float) ((int) rd->frs_sec_base) == rd->frs_sec_base) {
                c->time_base.den = rd->frs_sec;
                c->time_base.num = (int) rd->frs_sec_base;
                c->time_base.den = rd->frs_sec;
                c->time_base.num = (int) rd->frs_sec_base;
-       } else {
+       }
+       else {
                c->time_base.den = rd->frs_sec * 100000;
                c->time_base.num = ((double) rd->frs_sec_base) * 100000;
        }
        
        c->gop_size = ffmpeg_gop_size;
                c->time_base.den = rd->frs_sec * 100000;
                c->time_base.num = ((double) rd->frs_sec_base) * 100000;
        }
        
        c->gop_size = ffmpeg_gop_size;
-       c->bit_rate = ffmpeg_video_bitrate*1000;
-       c->rc_max_rate = rd->ffcodecdata.rc_max_rate*1000;
-       c->rc_min_rate = rd->ffcodecdata.rc_min_rate*1000;
+       c->bit_rate = ffmpeg_video_bitrate * 1000;
+       c->rc_max_rate = rd->ffcodecdata.rc_max_rate * 1000;
+       c->rc_min_rate = rd->ffcodecdata.rc_min_rate * 1000;
        c->rc_buffer_size = rd->ffcodecdata.rc_buffer_size * 1024;
        c->rc_buffer_size = rd->ffcodecdata.rc_buffer_size * 1024;
-       c->rc_initial_buffer_occupancy 
-               = rd->ffcodecdata.rc_buffer_size*3/4;
+
+#if 0
+       /* this options are not set in ffmpeg.c and leads to artifacts with MPEG-4
+        * see #33586: Encoding to mpeg4 makes first frame(s) blocky
+        */
+       c->rc_initial_buffer_occupancy = rd->ffcodecdata.rc_buffer_size * 3 / 4;
        c->rc_buffer_aggressivity = 1.0;
        c->rc_buffer_aggressivity = 1.0;
+#endif
+
        c->me_method = ME_EPZS;
        
        codec = avcodec_find_encoder(c->codec_id);
        c->me_method = ME_EPZS;
        
        codec = avcodec_find_encoder(c->codec_id);
-       if (!codec) return NULL;
+       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];
        
        /* Be sure to use the correct pixel format(e.g. RGB, YUV) */
 
        if (codec->pix_fmts) {
                c->pix_fmt = codec->pix_fmts[0];
-       } else {
+       }
+       else {
                /* makes HuffYUV happy ... */
                c->pix_fmt = PIX_FMT_YUV422P;
        }
                /* makes HuffYUV happy ... */
                c->pix_fmt = PIX_FMT_YUV422P;
        }
@@ -496,23 +527,33 @@ static AVStream* alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
        if (ffmpeg_type == FFMPEG_XVID) {
                /* arghhhh ... */
                c->pix_fmt = PIX_FMT_YUV420P;
        if (ffmpeg_type == FFMPEG_XVID) {
                /* arghhhh ... */
                c->pix_fmt = PIX_FMT_YUV420P;
-               c->codec_tag = (('D'<<24) + ('I'<<16) + ('V'<<8) + 'X');
+               c->codec_tag = (('D' << 24) + ('I' << 16) + ('V' << 8) + 'X');
        }
 
        if (codec_id == CODEC_ID_H264) {
                /* correct wrong default ffmpeg param which crash x264 */
        }
 
        if (codec_id == CODEC_ID_H264) {
                /* correct wrong default ffmpeg param which crash x264 */
-               c->qmin=10;
-               c->qmax=51;
+               c->qmin = 10;
+               c->qmax = 51;
        }
        
        }
        
-       // Keep lossless encodes in the RGB domain.
-       if (codec_id == CODEC_ID_HUFFYUV || codec_id == CODEC_ID_FFV1) {
+       /* Keep lossless encodes in the RGB domain. */
+       if (codec_id == CODEC_ID_HUFFYUV) {
                /* HUFFYUV was PIX_FMT_YUV422P before */
                c->pix_fmt = PIX_FMT_RGB32;
        }
 
                /* 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) {
+       if (codec_id == CODEC_ID_FFV1) {
+               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 (codec_id == CODEC_ID_PNG) {
+               if (rd->im_format.planes == R_IMF_PLANES_RGBA) {
                        c->pix_fmt = PIX_FMT_ARGB;
                }
        }
                        c->pix_fmt = PIX_FMT_ARGB;
                }
        }
@@ -521,111 +562,154 @@ static AVStream* alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
 //             || !strcmp(of->oformat->name, "mp4")
 //         || !strcmp(of->oformat->name, "mov")
 //         || !strcmp(of->oformat->name, "3gp")
 //             || !strcmp(of->oformat->name, "mp4")
 //         || !strcmp(of->oformat->name, "mov")
 //         || !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;
        }
 
        /* xasp & yasp got float lately... */
 
                c->flags |= CODEC_FLAG_INTERLACED_DCT;
                c->flags |= CODEC_FLAG_INTERLACED_ME;
        }
 
        /* xasp & yasp got float lately... */
 
-       st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q(
-               ((double) rd->xasp / (double) rd->yasp), 255);
+       st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q(((double) rd->xasp / (double) rd->yasp), 255);
 
        set_ffmpeg_properties(rd, c, "video");
        
 
        set_ffmpeg_properties(rd, c, "video");
        
-       if (avcodec_open(c, codec) < 0) {
-               //
-               //XXX error("Couldn't initialize codec");
+       if (avcodec_open2(c, codec, NULL) < 0) {
+               BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
                return NULL;
        }
 
                return NULL;
        }
 
-       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
+       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)
+               /* maximum video buffer size is 6-bytes per pixel, plus DPX header size (1664)
+                * (from FFmpeg sources) */
                int size = c->width * c->height;
                int size = c->width * c->height;
-               video_buffersize = 7*size + 10000;
+               video_buffersize = 7 * size + 10000;
        }
        else
                video_buffersize = avpicture_get_size(c->pix_fmt, c->width, c->height);
 
        }
        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");
+       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);
 
        
        current_frame = alloc_picture(c->pix_fmt, c->width, c->height);
 
-       img_convert_ctx = sws_getContext(c->width, c->height,
-                                        PIX_FMT_BGR32,
-                                        c->width, c->height,
-                                        c->pix_fmt,
-                                        SWS_BICUBIC,
-                                        NULL, NULL, NULL);
+       img_convert_ctx = sws_getContext(c->width, c->height, PIX_FMT_BGR32, c->width, c->height, c->pix_fmt, SWS_BICUBIC,
+                                        NULL, NULL, NULL);
        return st;
 }
 
 /* Prepare an audio stream for the output file */
 
        return st;
 }
 
 /* Prepare an audio stream for the output file */
 
-static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContext* of) 
+static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContext *of, char *error, int error_size)
 {
 {
-       AVStreamst;
-       AVCodecContextc;
-       AVCodeccodec;
+       AVStream *st;
+       AVCodecContext *c;
+       AVCodec *codec;
 
 
-       st = av_new_stream(of, 1);
+       error[0] = '\0';
+
+       st = avformat_new_stream(of, NULL);
        if (!st) return NULL;
        if (!st) return NULL;
+       st->id = 1;
 
        c = st->codec;
        c->codec_id = codec_id;
        c->codec_type = AVMEDIA_TYPE_AUDIO;
 
        c->sample_rate = rd->ffcodecdata.audio_mixrate;
 
        c = st->codec;
        c->codec_id = codec_id;
        c->codec_type = AVMEDIA_TYPE_AUDIO;
 
        c->sample_rate = rd->ffcodecdata.audio_mixrate;
-       c->bit_rate = ffmpeg_audio_bitrate*1000;
-       c->sample_fmt = SAMPLE_FMT_S16;
+       c->bit_rate = ffmpeg_audio_bitrate * 1000;
+       c->sample_fmt = AV_SAMPLE_FMT_S16;
        c->channels = rd->ffcodecdata.audio_channels;
        c->channels = rd->ffcodecdata.audio_channels;
+
+       if (request_float_audio_buffer(codec_id)) {
+               /* mainly for AAC codec which is experimental */
+               c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
+               c->sample_fmt = AV_SAMPLE_FMT_FLT;
+       }
+
        codec = avcodec_find_encoder(c->codec_id);
        if (!codec) {
                //XXX error("Couldn't find a valid audio codec");
                return NULL;
        }
 
        codec = avcodec_find_encoder(c->codec_id);
        if (!codec) {
                //XXX error("Couldn't find a valid audio codec");
                return NULL;
        }
 
+       if (codec->sample_fmts) {
+               /* check if the prefered sample format for this codec is supported.
+                * this is because, depending on the version of libav, and with the whole ffmpeg/libav fork situation,
+                * you have various implementations around. float samples in particular are not always supported.
+                */
+               const enum AVSampleFormat *p = codec->sample_fmts;
+               for (; *p!=-1; p++) {
+                       if (*p == st->codec->sample_fmt)
+                               break;
+               }
+               if (*p == -1) {
+                       /* sample format incompatible with codec. Defaulting to a format known to work */
+                       st->codec->sample_fmt = codec->sample_fmts[0];
+               }
+       }
+
+       if (c->sample_fmt == AV_SAMPLE_FMT_FLTP) {
+               BLI_strncpy(error, "Requested audio codec requires planar float sample format, which is not supported yet", error_size);
+               return NULL;
+       }
+
+       if (codec->supported_samplerates) {
+               const int *p = codec->supported_samplerates;
+               int best = 0;
+               int best_dist = INT_MAX;
+               for (; *p; p++){
+                       int dist = abs(st->codec->sample_rate - *p);
+                       if (dist < best_dist){
+                               best_dist = dist;
+                               best = *p;
+                       }
+               }
+               /* best is the closest supported sample rate (same as selected if best_dist == 0) */
+               st->codec->sample_rate = best;
+       }
+
        set_ffmpeg_properties(rd, c, "audio");
 
        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");
                //XXX error("Couldn't initialize audio codec");
+               BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
                return NULL;
        }
 
        /* need to prevent floating point exception when using vorbis audio codec,
                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;
+        * 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;
 
 
        audio_outbuf_size = FF_MIN_BUFFER_SIZE;
 
-       if((c->codec_id >= CODEC_ID_PCM_S16LE) && (c->codec_id <= CODEC_ID_PCM_DVD))
+       if ((c->codec_id >= CODEC_ID_PCM_S16LE) && (c->codec_id <= CODEC_ID_PCM_DVD))
                audio_input_samples = audio_outbuf_size * 8 / c->bits_per_coded_sample / c->channels;
                audio_input_samples = audio_outbuf_size * 8 / c->bits_per_coded_sample / c->channels;
-       else
-       {
+       else {
                audio_input_samples = c->frame_size;
                audio_input_samples = c->frame_size;
-               if(c->frame_size * c->channels * sizeof(int16_t) * 4 > audio_outbuf_size)
+               if (c->frame_size * c->channels * sizeof(int16_t) * 4 > audio_outbuf_size)
                        audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4;
        }
 
                        audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4;
        }
 
-       audio_output_buffer = (uint8_t*)av_malloc(
-               audio_outbuf_size);
+       audio_output_buffer = (uint8_t *) av_malloc(audio_outbuf_size);
 
 
-       audio_input_buffer = (uint8_t*)av_malloc(
-               audio_input_samples * c->channels * sizeof(int16_t));
+       if (c->sample_fmt == AV_SAMPLE_FMT_FLT) {
+               audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(float));
+       }
+       else {
+               audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(int16_t));
+       }
 
        audio_time = 0.0f;
 
 
        audio_time = 0.0f;
 
@@ -633,13 +717,23 @@ static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
 }
 /* essential functions -- start, append, end */
 
 }
 /* essential functions -- start, append, end */
 
+static void ffmpeg_dict_set_int(AVDictionary **dict, const char *key, int value)
+{
+       char buffer[32];
+
+       BLI_snprintf(buffer, sizeof(buffer), "%d", value);
+
+       av_dict_set(dict, key, buffer, 0);
+}
+
 static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, ReportList *reports)
 {
        /* Handle to the output file */
 static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, ReportList *reports)
 {
        /* Handle to the output file */
-       AVFormatContext* of;
-       AVOutputFormat* fmt;
-       char name[256];
-       const char ** exts;
+       AVFormatContext *of;
+       AVOutputFormat *fmt;
+       AVDictionary *opts = NULL;
+       char name[256], error[1024];
+       const char **exts;
 
        ffmpeg_type = rd->ffcodecdata.type;
        ffmpeg_codec = rd->ffcodecdata.codec;
 
        ffmpeg_type = rd->ffcodecdata.type;
        ffmpeg_codec = rd->ffcodecdata.codec;
@@ -647,30 +741,27 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
        ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate;
        ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate;
        ffmpeg_gop_size = rd->ffcodecdata.gop_size;
        ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate;
        ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate;
        ffmpeg_gop_size = rd->ffcodecdata.gop_size;
-       ffmpeg_autosplit = rd->ffcodecdata.flags
-               & FFMPEG_AUTOSPLIT_OUTPUT;
+       ffmpeg_autosplit = rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT;
        
        
-       do_init_ffmpeg();
-
        /* Determine the correct filename */
        /* Determine the correct filename */
-       filepath_ffmpeg(name, rd);
-       fprintf(stderr, "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"
-               "  render width=%d, render height=%d\n", 
-               name, ffmpeg_type, ffmpeg_codec, ffmpeg_audio_codec,
-               ffmpeg_video_bitrate, ffmpeg_audio_bitrate,
-               ffmpeg_gop_size, ffmpeg_autosplit, rectx, recty);
+       BKE_ffmpeg_filepath_get(name, rd);
+       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"
+               "  render width=%d, render height=%d\n",
+               name, ffmpeg_type, ffmpeg_codec, ffmpeg_audio_codec,
+               ffmpeg_video_bitrate, ffmpeg_audio_bitrate,
+               ffmpeg_gop_size, ffmpeg_autosplit, rectx, recty);
        
        exts = get_file_extensions(ffmpeg_type);
        if (!exts) {
        
        exts = get_file_extensions(ffmpeg_type);
        if (!exts) {
-               BKE_report(reports, RPT_ERROR, "No valid formats found.");
+               BKE_report(reports, RPT_ERROR, "No valid formats found");
                return 0;
        }
        fmt = av_guess_format(NULL, exts[0], NULL);
        if (!fmt) {
                return 0;
        }
        fmt = av_guess_format(NULL, exts[0], NULL);
        if (!fmt) {
-               BKE_report(reports, RPT_ERROR, "No valid formats found.");
+               BKE_report(reports, RPT_ERROR, "No valid formats found");
                return 0;
        }
 
                return 0;
        }
 
@@ -681,56 +772,58 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
        }
        
        of->oformat = fmt;
        }
        
        of->oformat = fmt;
-       of->packet_size= rd->ffcodecdata.mux_packet_size;
+       of->packet_size = rd->ffcodecdata.mux_packet_size;
        if (ffmpeg_audio_codec != CODEC_ID_NONE) {
        if (ffmpeg_audio_codec != CODEC_ID_NONE) {
-               of->mux_rate = rd->ffcodecdata.mux_rate;
-       } else {
-               of->mux_rate = 0;
+               ffmpeg_dict_set_int(&opts, "muxrate", rd->ffcodecdata.mux_rate);
        }
        }
+       else {
+               av_dict_set(&opts, "muxrate", "0", 0);
+       }
+
+       ffmpeg_dict_set_int(&opts, "preload", (int)(0.5 * AV_TIME_BASE));
 
 
-       of->preload = (int)(0.5*AV_TIME_BASE);
-       of->max_delay = (int)(0.7*AV_TIME_BASE);
+       of->max_delay = (int)(0.7 * AV_TIME_BASE);
 
        fmt->audio_codec = ffmpeg_audio_codec;
 
        BLI_snprintf(of->filename, sizeof(of->filename), "%s", name);
        /* set the codec to the user's selection */
 
        fmt->audio_codec = ffmpeg_audio_codec;
 
        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_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;
-       case FFMPEG_MPEG1:
-               fmt->video_codec = CODEC_ID_MPEG1VIDEO;
-               break;
-       case FFMPEG_MPEG2:
-               fmt->video_codec = CODEC_ID_MPEG2VIDEO;
-               break;
-       case FFMPEG_H264:
-               fmt->video_codec = CODEC_ID_H264;
-               break;
-       case FFMPEG_XVID:
-               fmt->video_codec = CODEC_ID_MPEG4;
-               break;
-       case FFMPEG_FLV:
-               fmt->video_codec = CODEC_ID_FLV1;
-               break;
-       case FFMPEG_MP3:
-               fmt->audio_codec = CODEC_ID_MP3;
-       case FFMPEG_WAV:
-               fmt->video_codec = CODEC_ID_NONE;
-               break;
-       case FFMPEG_MPEG4:
-       default:
-               fmt->video_codec = CODEC_ID_MPEG4;
-               break;
+       switch (ffmpeg_type) {
+               case FFMPEG_AVI:
+               case FFMPEG_MOV:
+               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;
+               case FFMPEG_MPEG1:
+                       fmt->video_codec = CODEC_ID_MPEG1VIDEO;
+                       break;
+               case FFMPEG_MPEG2:
+                       fmt->video_codec = CODEC_ID_MPEG2VIDEO;
+                       break;
+               case FFMPEG_H264:
+                       fmt->video_codec = CODEC_ID_H264;
+                       break;
+               case FFMPEG_XVID:
+                       fmt->video_codec = CODEC_ID_MPEG4;
+                       break;
+               case FFMPEG_FLV:
+                       fmt->video_codec = CODEC_ID_FLV1;
+                       break;
+               case FFMPEG_MP3:
+                       fmt->audio_codec = CODEC_ID_MP3;
+               case FFMPEG_WAV:
+                       fmt->video_codec = CODEC_ID_NONE;
+                       break;
+               case FFMPEG_MPEG4:
+               default:
+                       fmt->video_codec = CODEC_ID_MPEG4;
+                       break;
        }
        if (fmt->video_codec == CODEC_ID_DVVIDEO) {
                if (rectx != 720) {
        }
        if (fmt->video_codec == CODEC_ID_DVVIDEO) {
                if (rectx != 720) {
@@ -751,44 +844,53 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
                fmt->audio_codec = CODEC_ID_PCM_S16LE;
                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!");
                fmt->audio_codec = CODEC_ID_PCM_S16LE;
                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!");
+                       av_dict_free(&opts);
                        return 0;
                }
        }
        
        if (fmt->video_codec != CODEC_ID_NONE) {
                        return 0;
                }
        }
        
        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;
                }
        }
 
        if (ffmpeg_audio_codec != CODEC_ID_NONE) {
                        return 0;
                }
        }
 
        if (ffmpeg_audio_codec != CODEC_ID_NONE) {
-               audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of);
+               audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of, error, sizeof(error));
                if (!audio_stream) {
                if (!audio_stream) {
-                       BKE_report(reports, RPT_ERROR, "Error initializing audio stream.");
+                       if (error[0])
+                               BKE_report(reports, RPT_ERROR, error);
+                       else
+                               BKE_report(reports, RPT_ERROR, "Error initializing audio stream");
+                       av_dict_free(&opts);
                        return 0;
                }
        }
                        return 0;
                }
        }
-       if (av_set_parameters(of, NULL) < 0) {
-               BKE_report(reports, RPT_ERROR, "Error setting output parameters.");
-               return 0;
-       }
        if (!(fmt->flags & AVFMT_NOFILE)) {
                if (avio_open(&of->pb, name, AVIO_FLAG_WRITE) < 0) {
        if (!(fmt->flags & AVFMT_NOFILE)) {
                if (avio_open(&of->pb, name, AVIO_FLAG_WRITE) < 0) {
-                       BKE_report(reports, RPT_ERROR, "Could not open file for writing.");
+                       BKE_report(reports, RPT_ERROR, "Could not open file for writing");
+                       av_dict_free(&opts);
                        return 0;
                }
        }
                        return 0;
                }
        }
-
-       if (av_write_header(of) < 0) {
-               BKE_report(reports, RPT_ERROR, "Could not initialize streams. Probably unsupported codec combination.");
+       if (avformat_write_header(of, NULL) < 0) {
+               BKE_report(reports, RPT_ERROR, "Could not initialize streams, probably unsupported codec combination");
+               av_dict_free(&opts);
+               avio_close(of->pb);
                return 0;
        }
 
        outfile = of;
        av_dump_format(of, 0, name, 1);
                return 0;
        }
 
        outfile = of;
        av_dump_format(of, 0, name, 1);
+       av_dict_free(&opts);
 
        return 1;
 }
 
        return 1;
 }
@@ -802,7 +904,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
  * inter-frames (H.264 B-frames, for example), it can output the frames 
  * in a different order from the one it was given.
  * For example, when sending frames 1, 2, 3, 4 to the encoder, it may write
  * inter-frames (H.264 B-frames, for example), it can output the frames 
  * in a different order from the one it was given.
  * For example, when sending frames 1, 2, 3, 4 to the encoder, it may write
- * them in the order 1, 4, 2, 3 - first the two frames used for predition, 
+ * them in the order 1, 4, 2, 3 - first the two frames used for prediction,
  * and then the bidirectionally-predicted frames. What this means in practice 
  * is that the encoder may not immediately produce one output frame for each 
  * input frame. These delayed frames must be flushed before we close the 
  * and then the bidirectionally-predicted frames. What this means in practice 
  * is that the encoder may not immediately produce one output frame for each 
  * input frame. These delayed frames must be flushed before we close the 
@@ -810,12 +912,12 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
  * parameter.
  * </p>
  */
  * parameter.
  * </p>
  */
-void flush_ffmpeg(void)
+static void flush_ffmpeg(void)
 {
        int outsize = 0;
        int ret = 0;
        
 {
        int outsize = 0;
        int ret = 0;
        
-       AVCodecContextc = video_stream->codec;
+       AVCodecContext *c = video_stream->codec;
        /* get the delayed frames */
        while (1) {
                AVPacket packet;
        /* get the delayed frames */
        while (1) {
                AVPacket packet;
@@ -830,12 +932,11 @@ void flush_ffmpeg(void)
                        break;
                }
                if (c->coded_frame->pts != AV_NOPTS_VALUE) {
                        break;
                }
                if (c->coded_frame->pts != AV_NOPTS_VALUE) {
-                       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);
-               } else {
-                       fprintf(stderr, "Video Frame PTS: not set\n");
+                       packet.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_stream->time_base);
+                       PRINT("Video Frame PTS: %d\n", (int) packet.pts);
+               }
+               else {
+                       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;
@@ -853,16 +954,16 @@ void flush_ffmpeg(void)
 }
 
 /* **********************************************************************
 }
 
 /* **********************************************************************
  * public interface
  ********************************************************************** */
* * public interface
* ********************************************************************** */
 
 /* Get the output filename-- similar to the other output formats */
 
 /* Get the output filename-- similar to the other output formats */
-void filepath_ffmpeg(char* string, RenderData* rd)
+void BKE_ffmpeg_filepath_get(char *string, RenderData *rd)
 {
        char autosplit[20];
 
 {
        char autosplit[20];
 
-       const char ** exts = get_file_extensions(rd->ffcodecdata.type);
-       const char ** fe = exts;
+       const char **exts = get_file_extensions(rd->ffcodecdata.type);
+       const char **fe = exts;
 
        if (!string || !exts) return;
 
 
        if (!string || !exts) return;
 
@@ -878,26 +979,26 @@ void filepath_ffmpeg(char* string, RenderData* rd)
        }
 
        while (*fe) {
        }
 
        while (*fe) {
-               if (BLI_strcasecmp(string + strlen(string) - strlen(*fe), 
-                                  *fe) == 0) {
+               if (BLI_strcasecmp(string + strlen(string) - strlen(*fe), *fe) == 0) {
                        break;
                }
                fe++;
        }
 
                        break;
                }
                fe++;
        }
 
-       if (!*fe) {
+       if (*fe == NULL) {
                strcat(string, autosplit);
 
                BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
                strcat(string, *exts);
                strcat(string, autosplit);
 
                BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
                strcat(string, *exts);
-       } else {
+       }
+       else {
                *(string + strlen(string) - strlen(*fe)) = 0;
                strcat(string, autosplit);
                strcat(string, *fe);
        }
 }
 
                *(string + strlen(string) - strlen(*fe)) = 0;
                strcat(string, autosplit);
                strcat(string, *fe);
        }
 }
 
-int start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports)
+int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports)
 {
        int success;
 
 {
        int success;
 
@@ -905,12 +1006,16 @@ int start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty, Repo
 
        success = start_ffmpeg_impl(rd, rectx, recty, reports);
 #ifdef WITH_AUDASPACE
 
        success = start_ffmpeg_impl(rd, rectx, recty, reports);
 #ifdef WITH_AUDASPACE
-       if(audio_stream)
-       {
-               AVCodecContext* c = audio_stream->codec;
+       if (audio_stream) {
+               AVCodecContext *c = audio_stream->codec;
                AUD_DeviceSpecs specs;
                specs.channels = c->channels;
                AUD_DeviceSpecs specs;
                specs.channels = c->channels;
-               specs.format = AUD_FORMAT_S16;
+               if (c->sample_fmt == AV_SAMPLE_FMT_FLT) {
+                       specs.format = AUD_FORMAT_FLOAT32;
+               }
+               else {
+                       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
                specs.rate = rd->ffcodecdata.audio_mixrate;
                audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->ffcodecdata.audio_volume);
 #ifdef FFMPEG_CODEC_TIME_BASE
@@ -922,7 +1027,7 @@ int start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty, Repo
        return success;
 }
 
        return success;
 }
 
-void end_ffmpeg(void);
+static void end_ffmpeg_impl(int is_autosplit);
 
 #ifdef WITH_AUDASPACE
 static void write_audio_frames(double to_pts)
 
 #ifdef WITH_AUDASPACE
 static void write_audio_frames(double to_pts)
@@ -930,34 +1035,32 @@ static void write_audio_frames(double to_pts)
        int finished = 0;
 
        while (audio_stream && !finished) {
        int finished = 0;
 
        while (audio_stream && !finished) {
-               if((audio_time >= to_pts) ||
-                  (write_audio_frame())) {
+               if ((audio_time >= to_pts) ||
+                   (write_audio_frame()))
+               {
                        finished = 1;
                }
        }
 }
 #endif
 
                        finished = 1;
                }
        }
 }
 #endif
 
-int append_ffmpeg(RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, ReportList *reports)
+int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, ReportList *reports)
 {
 {
-       AVFrameavframe;
+       AVFrame *avframe;
        int success = 1;
 
        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?
+/* 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));
 
 //     write_audio_frames(frame / (((double)rd->frs_sec) / rd->frs_sec_base));
 
-       if(video_stream)
-       {
-               avframe= generate_video_frame((unsigned char*) pixels, reports);
-               success= (avframe && write_video_frame(rd, frame - start_frame, avframe, reports));
+       if (video_stream) {
+               avframe = generate_video_frame((unsigned char *) pixels, reports);
+               success = (avframe && write_video_frame(rd, frame - start_frame, avframe, reports));
 
                if (ffmpeg_autosplit) {
                        if (avio_tell(outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) {
 
                if (ffmpeg_autosplit) {
                        if (avio_tell(outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) {
-                               end_ffmpeg();
+                               end_ffmpeg_impl(TRUE);
                                ffmpeg_autosplit_count++;
                                success &= start_ffmpeg_impl(rd, rectx, recty, reports);
                        }
                                ffmpeg_autosplit_count++;
                                success &= start_ffmpeg_impl(rd, rectx, recty, reports);
                        }
@@ -965,32 +1068,35 @@ int append_ffmpeg(RenderData *rd, int start_frame, int frame, int *pixels, int r
        }
 
 #ifdef WITH_AUDASPACE
        }
 
 #ifdef WITH_AUDASPACE
-       write_audio_frames((frame - rd->sfra) / (((double)rd->frs_sec) / rd->frs_sec_base));
+       write_audio_frames((frame - rd->sfra) / (((double)rd->frs_sec) / (double)rd->frs_sec_base));
 #endif
        return success;
 }
 
 #endif
        return success;
 }
 
-void end_ffmpeg(void)
+static void end_ffmpeg_impl(int is_autosplit)
 {
        unsigned int i;
        
 {
        unsigned int i;
        
-       fprintf(stderr, "Closing ffmpeg...\n");
+       PRINT("Closing ffmpeg...\n");
 
 
-/*     if (audio_stream) { SEE UPPER
+#if 0
+       if (audio_stream) { /* SEE UPPER */
                write_audio_frames();
                write_audio_frames();
-       }*/
+       }
+#endif
 
 #ifdef WITH_AUDASPACE
 
 #ifdef WITH_AUDASPACE
-       if(audio_mixdown_device)
-       {
-               AUD_closeReadDevice(audio_mixdown_device);
-               audio_mixdown_device = 0;
+       if (is_autosplit == FALSE) {
+               if (audio_mixdown_device) {
+                       AUD_closeReadDevice(audio_mixdown_device);
+                       audio_mixdown_device = 0;
+               }
        }
 #endif
 
        if (video_stream && video_stream->codec) {
        }
 #endif
 
        if (video_stream && video_stream->codec) {
-               fprintf(stderr, "Flushing delayed frames...\n");
-               flush_ffmpeg ();                
+               PRINT("Flushing delayed frames...\n");
+               flush_ffmpeg();
        }
        
        if (outfile) {
        }
        
        if (outfile) {
@@ -1001,7 +1107,7 @@ void end_ffmpeg(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;
        }
 
@@ -1047,12 +1153,17 @@ void end_ffmpeg(void)
        }
 }
 
        }
 }
 
+void BKE_ffmpeg_end(void)
+{
+       end_ffmpeg_impl(FALSE);
+}
+
 /* properties */
 
 /* properties */
 
-void ffmpeg_property_del(RenderData *rd, void *type, void *prop_)
+void BKE_ffmpeg_property_del(RenderData *rd, void *type, void *prop_)
 {
        struct IDProperty *prop = (struct IDProperty *) prop_;
 {
        struct IDProperty *prop = (struct IDProperty *) prop_;
-       IDProperty * group;
+       IDProperty *group;
        
        if (!rd->ffcodecdata.properties) {
                return;
        
        if (!rd->ffcodecdata.properties) {
                return;
@@ -1066,27 +1177,26 @@ void ffmpeg_property_del(RenderData *rd, void *type, void *prop_)
        }
 }
 
        }
 }
 
-IDProperty *ffmpeg_property_add(RenderData *rd, const char *type, int opt_index, int parent_index)
+IDProperty *BKE_ffmpeg_property_add(RenderData *rd, const char *type, int opt_index, int parent_index)
 {
        AVCodecContext c;
 {
        AVCodecContext c;
-       const AVOption * o;
-       const AVOption * parent;
-       IDProperty * group;
-       IDProperty * prop;
+       const AVOption *o;
+       const AVOption *parent;
+       IDProperty *group;
+       IDProperty *prop;
        IDPropertyTemplate val;
        int idp_type;
        char name[256];
        
        val.i = 0;
 
        IDPropertyTemplate val;
        int idp_type;
        char name[256];
        
        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;
 
        if (!rd->ffcodecdata.properties) {
 
        o = c.av_class->option + opt_index;
        parent = c.av_class->option + parent_index;
 
        if (!rd->ffcodecdata.properties) {
-               rd->ffcodecdata.properties 
-                       = IDP_New(IDP_GROUP, &val, "ffmpeg"); 
+               rd->ffcodecdata.properties = IDP_New(IDP_GROUP, &val, "ffmpeg"); 
        }
 
        group = IDP_GetPropertyFromGroup(rd->ffcodecdata.properties, type);
        }
 
        group = IDP_GetPropertyFromGroup(rd->ffcodecdata.properties, type);
@@ -1098,12 +1208,12 @@ IDProperty *ffmpeg_property_add(RenderData *rd, const char *type, int opt_index,
 
        if (parent_index) {
                BLI_snprintf(name, sizeof(name), "%s:%s", parent->name, o->name);
 
        if (parent_index) {
                BLI_snprintf(name, sizeof(name), "%s:%s", parent->name, o->name);
-       } else {
+       }
+       else {
                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) {
@@ -1111,28 +1221,28 @@ IDProperty *ffmpeg_property_add(RenderData *rd, const char *type, int opt_index,
        }
 
        switch (o->type) {
        }
 
        switch (o->type) {
-       case FF_OPT_TYPE_INT:
-       case FF_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:
-               val.f = FFMPEG_DEF_OPT_VAL_DOUBLE(o);
-               idp_type = IDP_FLOAT;
-               break;
-       case FF_OPT_TYPE_STRING:
-               val.string.str = (char *)"                                                                               ";
-               val.string.len = 80;
+               case AV_OPT_TYPE_INT:
+               case AV_OPT_TYPE_INT64:
+                       val.i = FFMPEG_DEF_OPT_VAL_INT(o);
+                       idp_type = IDP_INT;
+                       break;
+               case AV_OPT_TYPE_DOUBLE:
+               case AV_OPT_TYPE_FLOAT:
+                       val.f = FFMPEG_DEF_OPT_VAL_DOUBLE(o);
+                       idp_type = IDP_FLOAT;
+                       break;
+               case AV_OPT_TYPE_STRING:
+                       val.string.str = (char *)"                                                                               ";
+                       val.string.len = 80;
 /*             val.str = (char *)"                                                                               ";*/
 /*             val.str = (char *)"                                                                               ";*/
-               idp_type = IDP_STRING;
-               break;
-       case FF_OPT_TYPE_CONST:
-               val.i = 1;
-               idp_type = IDP_INT;
-               break;
-       default:
-               return NULL;
+                       idp_type = IDP_STRING;
+                       break;
+               case AV_OPT_TYPE_CONST:
+                       val.i = 1;
+                       idp_type = IDP_INT;
+                       break;
+               default:
+                       return NULL;
        }
        prop = IDP_New(idp_type, &val, name);
        IDP_AddToGroup(group, prop);
        }
        prop = IDP_New(idp_type, &val, name);
        IDP_AddToGroup(group, prop);
@@ -1141,31 +1251,33 @@ IDProperty *ffmpeg_property_add(RenderData *rd, const char *type, int opt_index,
 
 /* not all versions of ffmpeg include that, so here we go ... */
 
 
 /* not all versions of ffmpeg include that, so here we go ... */
 
-static const AVOption *my_av_find_opt(void *v, const char *name, 
-                                         const char *unit, int mask, int flags){
-       AVClass *c= *(AVClass**)v; 
-       const AVOption *o= c->option;
-
-       for(;o && o->name; o++){
-               if(!strcmp(o->name, name) && 
-                  (!unit || (o->unit && !strcmp(o->unit, unit))) && 
-                  (o->flags & mask) == flags )
+static const AVOption *my_av_find_opt(void *v, const char *name, const char *unit, int mask, int flags)
+{
+       AVClass *c = *(AVClass **)v;
+       const AVOption *o = c->option;
+
+       for (; o && o->name; o++) {
+               if (!strcmp(o->name, name) &&
+                   (!unit || (o->unit && !strcmp(o->unit, unit))) &&
+                   (o->flags & mask) == flags)
+               {
                        return o;
                        return o;
+               }
        }
        return NULL;
 }
 
        }
        return NULL;
 }
 
-int ffmpeg_property_add_string(RenderData *rd, const char * type, const char * str)
+int BKE_ffmpeg_property_add_string(RenderData *rd, const char *type, const char *str)
 {
        AVCodecContext c;
 {
        AVCodecContext c;
-       const AVOption * o = 0;
-       const AVOption * p = 0;
+       const AVOption *o = 0;
+       const AVOption *p = 0;
        char name_[128];
        char name_[128];
-       char * name;
-       char * param;
-       IDProperty * prop;
+       char *name;
+       char *param;
+       IDProperty *prop = NULL;
        
        
-       avcodec_get_context_defaults(&c);
+       avcodec_get_context_defaults3(&c, NULL);
 
        strncpy(name_, str, sizeof(name_));
 
 
        strncpy(name_, str, sizeof(name_));
 
@@ -1182,21 +1294,21 @@ int ffmpeg_property_add_string(RenderData *rd, const char * type, const char * s
                while (*param == ' ') param++;
        }
        
                while (*param == ' ') param++;
        }
        
-       o = my_av_find_opt(&c, name, NULL, 0, 0);       
+       o = my_av_find_opt(&c, name, NULL, 0, 0);
        if (!o) {
                return 0;
        }
        if (!o) {
                return 0;
        }
-       if (param && o->type == FF_OPT_TYPE_CONST) {
+       if (param && o->type == AV_OPT_TYPE_CONST) {
                return 0;
        }
                return 0;
        }
-       if (param && o->type != FF_OPT_TYPE_CONST && o->unit) {
-               p = my_av_find_opt(&c, param, o->unit, 0, 0);   
-               prop = ffmpeg_property_add(rd,
-                       (char*) type, p - c.av_class->option, 
-                       o - c.av_class->option);
-       } else {
-               prop = ffmpeg_property_add(rd,
-                       (char*) type, o - c.av_class->option, 0);
+       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);
+               }
+       }
+       else {
+               prop = BKE_ffmpeg_property_add(rd, (char *) type, o - c.av_class->option, 0);
        }
                
 
        }
                
 
@@ -1206,15 +1318,15 @@ int ffmpeg_property_add_string(RenderData *rd, const char * type, const char * s
 
        if (param && !p) {
                switch (prop->type) {
 
        if (param && !p) {
                switch (prop->type) {
-               case IDP_INT:
-                       IDP_Int(prop) = atoi(param);
-                       break;
-               case IDP_FLOAT:
-                       IDP_Float(prop) = atof(param);
-                       break;
-               case IDP_STRING:
-                       strncpy(IDP_String(prop), param, prop->len);
-                       break;
+                       case IDP_INT:
+                               IDP_Int(prop) = atoi(param);
+                               break;
+                       case IDP_FLOAT:
+                               IDP_Float(prop) = atof(param);
+                               break;
+                       case IDP_STRING:
+                               strncpy(IDP_String(prop), param, prop->len);
+                               break;
                }
        }
        return 1;
                }
        }
        return 1;
@@ -1224,10 +1336,10 @@ static void ffmpeg_set_expert_options(RenderData *rd)
 {
        int codec_id = rd->ffcodecdata.codec;
 
 {
        int codec_id = rd->ffcodecdata.codec;
 
-       if(rd->ffcodecdata.properties)
+       if (rd->ffcodecdata.properties)
                IDP_FreeProperty(rd->ffcodecdata.properties);
 
                IDP_FreeProperty(rd->ffcodecdata.properties);
 
-       if(codec_id == CODEC_ID_H264) {
+       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"
                /*
                 * All options here are for x264, but must be set via ffmpeg.
                 * The names are therefore different - Search for "x264 to FFmpeg option mapping"
@@ -1238,188 +1350,204 @@ static void ffmpeg_set_expert_options(RenderData *rd)
                 * Use CABAC coder. Using "coder:1", which should be equivalent,
                 * crashes Blender for some reason. Either way - this is no big deal.
                 */
                 * 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");
+               BKE_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
 
                /*
                 * 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");
+               BKE_ffmpeg_property_add_string(rd, "video", "cmp:chroma");
+               BKE_ffmpeg_property_add_string(rd, "video", "partitions:parti4x4");
+               BKE_ffmpeg_property_add_string(rd, "video", "partitions:partp8x8");
+               BKE_ffmpeg_property_add_string(rd, "video", "partitions:partb8x8");
+               BKE_ffmpeg_property_add_string(rd, "video", "me:hex");
+               BKE_ffmpeg_property_add_string(rd, "video", "subq:6");
+               BKE_ffmpeg_property_add_string(rd, "video", "me_range:16");
+               BKE_ffmpeg_property_add_string(rd, "video", "qdiff:4");
+               BKE_ffmpeg_property_add_string(rd, "video", "keyint_min:25");
+               BKE_ffmpeg_property_add_string(rd, "video", "sc_threshold:40");
+               BKE_ffmpeg_property_add_string(rd, "video", "i_qfactor:0.71");
+               BKE_ffmpeg_property_add_string(rd, "video", "b_strategy:1");
+               BKE_ffmpeg_property_add_string(rd, "video", "bf:3");
+               BKE_ffmpeg_property_add_string(rd, "video", "refs:2");
+               BKE_ffmpeg_property_add_string(rd, "video", "qcomp:0.6");
+               BKE_ffmpeg_property_add_string(rd, "video", "directpred:3");
+               BKE_ffmpeg_property_add_string(rd, "video", "trellis:0");
+               BKE_ffmpeg_property_add_string(rd, "video", "flags2:wpred");
+               BKE_ffmpeg_property_add_string(rd, "video", "flags2:dct8x8");
+               BKE_ffmpeg_property_add_string(rd, "video", "flags2:fastpskip");
+               BKE_ffmpeg_property_add_string(rd, "video", "wpredp:2");
+
+               if (rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT)
+                       BKE_ffmpeg_property_add_string(rd, "video", "cqp:0");
+       }
+       else if (codec_id == CODEC_ID_DNXHD) {
+               if (rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT)
+                       BKE_ffmpeg_property_add_string(rd, "video", "mbd:rd");
        }
        }
-#endif
 }
 
 }
 
-void ffmpeg_set_preset(RenderData *rd, int preset)
+void BKE_ffmpeg_preset_set(RenderData *rd, int preset)
 {
        int isntsc = (rd->frs_sec != 25);
 
 {
        int isntsc = (rd->frs_sec != 25);
 
-       if(rd->ffcodecdata.properties)
+       if (rd->ffcodecdata.properties)
                IDP_FreeProperty(rd->ffcodecdata.properties);
 
        switch (preset) {
                IDP_FreeProperty(rd->ffcodecdata.properties);
 
        switch (preset) {
-       case FFMPEG_PRESET_VCD:
-               rd->ffcodecdata.type = FFMPEG_MPEG1;
-               rd->ffcodecdata.video_bitrate = 1150;
-               rd->xsch = 352;
-               rd->ysch = isntsc ? 240 : 288;
-               rd->ffcodecdata.gop_size = isntsc ? 18 : 15;
-               rd->ffcodecdata.rc_max_rate = 1150;
-               rd->ffcodecdata.rc_min_rate = 1150;
-               rd->ffcodecdata.rc_buffer_size = 40*8;
-               rd->ffcodecdata.mux_packet_size = 2324;
-               rd->ffcodecdata.mux_rate = 2352 * 75 * 8;
-               break;
-
-       case FFMPEG_PRESET_SVCD:
-               rd->ffcodecdata.type = FFMPEG_MPEG2;
-               rd->ffcodecdata.video_bitrate = 2040;
-               rd->xsch = 480;
-               rd->ysch = isntsc ? 480 : 576;
-               rd->ffcodecdata.gop_size = isntsc ? 18 : 15;
-               rd->ffcodecdata.rc_max_rate = 2516;
-               rd->ffcodecdata.rc_min_rate = 0;
-               rd->ffcodecdata.rc_buffer_size = 224*8;
-               rd->ffcodecdata.mux_packet_size = 2324;
-               rd->ffcodecdata.mux_rate = 0;
-               break;
-
-       case FFMPEG_PRESET_DVD:
-               rd->ffcodecdata.type = FFMPEG_MPEG2;
-               rd->ffcodecdata.video_bitrate = 6000;
-
-               /* 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;
-               rd->ffcodecdata.rc_buffer_size = 224*8;
-               rd->ffcodecdata.mux_packet_size = 2048;
-               rd->ffcodecdata.mux_rate = 10080000;
-               break;
-
-       case FFMPEG_PRESET_DV:
-               rd->ffcodecdata.type = FFMPEG_DV;
-               rd->xsch = 720;
-               rd->ysch = isntsc ? 480 : 576;
-               break;
-
-       case FFMPEG_PRESET_H264:
-               rd->ffcodecdata.type = FFMPEG_AVI;
-               rd->ffcodecdata.codec = CODEC_ID_H264;
-               rd->ffcodecdata.video_bitrate = 6000;
-               rd->ffcodecdata.gop_size = isntsc ? 18 : 15;
-               rd->ffcodecdata.rc_max_rate = 9000;
-               rd->ffcodecdata.rc_min_rate = 0;
-               rd->ffcodecdata.rc_buffer_size = 224*8;
-               rd->ffcodecdata.mux_packet_size = 2048;
-               rd->ffcodecdata.mux_rate = 10080000;
-
-               break;
-
-       case FFMPEG_PRESET_THEORA:
-       case FFMPEG_PRESET_XVID:
-               if(preset == FFMPEG_PRESET_XVID) {
+               case FFMPEG_PRESET_VCD:
+                       rd->ffcodecdata.type = FFMPEG_MPEG1;
+                       rd->ffcodecdata.video_bitrate = 1150;
+                       rd->xsch = 352;
+                       rd->ysch = isntsc ? 240 : 288;
+                       rd->ffcodecdata.gop_size = isntsc ? 18 : 15;
+                       rd->ffcodecdata.rc_max_rate = 1150;
+                       rd->ffcodecdata.rc_min_rate = 1150;
+                       rd->ffcodecdata.rc_buffer_size = 40 * 8;
+                       rd->ffcodecdata.mux_packet_size = 2324;
+                       rd->ffcodecdata.mux_rate = 2352 * 75 * 8;
+                       break;
+
+               case FFMPEG_PRESET_SVCD:
+                       rd->ffcodecdata.type = FFMPEG_MPEG2;
+                       rd->ffcodecdata.video_bitrate = 2040;
+                       rd->xsch = 480;
+                       rd->ysch = isntsc ? 480 : 576;
+                       rd->ffcodecdata.gop_size = isntsc ? 18 : 15;
+                       rd->ffcodecdata.rc_max_rate = 2516;
+                       rd->ffcodecdata.rc_min_rate = 0;
+                       rd->ffcodecdata.rc_buffer_size = 224 * 8;
+                       rd->ffcodecdata.mux_packet_size = 2324;
+                       rd->ffcodecdata.mux_rate = 0;
+                       break;
+
+               case FFMPEG_PRESET_DVD:
+                       rd->ffcodecdata.type = FFMPEG_MPEG2;
+                       rd->ffcodecdata.video_bitrate = 6000;
+
+                       /* 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;
+                       rd->ffcodecdata.rc_buffer_size = 224 * 8;
+                       rd->ffcodecdata.mux_packet_size = 2048;
+                       rd->ffcodecdata.mux_rate = 10080000;
+                       break;
+
+               case FFMPEG_PRESET_DV:
+                       rd->ffcodecdata.type = FFMPEG_DV;
+                       rd->xsch = 720;
+                       rd->ysch = isntsc ? 480 : 576;
+                       break;
+
+               case FFMPEG_PRESET_H264:
                        rd->ffcodecdata.type = FFMPEG_AVI;
                        rd->ffcodecdata.type = FFMPEG_AVI;
-                       rd->ffcodecdata.codec = CODEC_ID_MPEG4;
-               }
-               else if(preset == FFMPEG_PRESET_THEORA) {
-                       rd->ffcodecdata.type = FFMPEG_OGG; // XXX broken
-                       rd->ffcodecdata.codec = CODEC_ID_THEORA;
-               }
+                       rd->ffcodecdata.codec = CODEC_ID_H264;
+                       rd->ffcodecdata.video_bitrate = 6000;
+                       rd->ffcodecdata.gop_size = isntsc ? 18 : 15;
+                       rd->ffcodecdata.rc_max_rate = 9000;
+                       rd->ffcodecdata.rc_min_rate = 0;
+                       rd->ffcodecdata.rc_buffer_size = 224 * 8;
+                       rd->ffcodecdata.mux_packet_size = 2048;
+                       rd->ffcodecdata.mux_rate = 10080000;
+
+                       break;
+
+               case FFMPEG_PRESET_THEORA:
+               case FFMPEG_PRESET_XVID:
+                       if (preset == FFMPEG_PRESET_XVID) {
+                               rd->ffcodecdata.type = FFMPEG_AVI;
+                               rd->ffcodecdata.codec = CODEC_ID_MPEG4;
+                       }
+                       else if (preset == FFMPEG_PRESET_THEORA) {
+                               rd->ffcodecdata.type = FFMPEG_OGG; // XXX broken
+                               rd->ffcodecdata.codec = CODEC_ID_THEORA;
+                       }
 
 
-               rd->ffcodecdata.video_bitrate = 6000;
-               rd->ffcodecdata.gop_size = isntsc ? 18 : 15;
-               rd->ffcodecdata.rc_max_rate = 9000;
-               rd->ffcodecdata.rc_min_rate = 0;
-               rd->ffcodecdata.rc_buffer_size = 224*8;
-               rd->ffcodecdata.mux_packet_size = 2048;
-               rd->ffcodecdata.mux_rate = 10080000;
-               break;
+                       rd->ffcodecdata.video_bitrate = 6000;
+                       rd->ffcodecdata.gop_size = isntsc ? 18 : 15;
+                       rd->ffcodecdata.rc_max_rate = 9000;
+                       rd->ffcodecdata.rc_min_rate = 0;
+                       rd->ffcodecdata.rc_buffer_size = 224 * 8;
+                       rd->ffcodecdata.mux_packet_size = 2048;
+                       rd->ffcodecdata.mux_rate = 10080000;
+                       break;
 
        }
 
        ffmpeg_set_expert_options(rd);
 }
 
 
        }
 
        ffmpeg_set_expert_options(rd);
 }
 
-void ffmpeg_verify_image_type(RenderData *rd, ImageFormatData *imf)
+void BKE_ffmpeg_image_type_verify(RenderData *rd, ImageFormatData *imf)
 {
 {
-       int audio= 0;
-
-       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) {
-
+       int audio = 0;
+
+       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;
 
                        rd->ffcodecdata.codec = CODEC_ID_MPEG2VIDEO;
 
-                       ffmpeg_set_preset(rd, FFMPEG_PRESET_DVD);
+                       BKE_ffmpeg_preset_set(rd, FFMPEG_PRESET_DVD);
                }
                }
-               if(rd->ffcodecdata.type == FFMPEG_OGG) {
+               if (rd->ffcodecdata.type == FFMPEG_OGG) {
                        rd->ffcodecdata.type = FFMPEG_MPEG2;
                }
 
                        rd->ffcodecdata.type = FFMPEG_MPEG2;
                }
 
-               audio= 1;
+               audio = 1;
        }
        }
-       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 (imf->imtype == R_IMF_IMTYPE_H264) {
+               if (rd->ffcodecdata.codec != CODEC_ID_H264) {
+                       BKE_ffmpeg_preset_set(rd, FFMPEG_PRESET_H264);
+                       audio = 1;
                }
        }
                }
        }
-       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 (imf->imtype == R_IMF_IMTYPE_XVID) {
+               if (rd->ffcodecdata.codec != CODEC_ID_MPEG4) {
+                       BKE_ffmpeg_preset_set(rd, FFMPEG_PRESET_XVID);
+                       audio = 1;
                }
        }
                }
        }
-       else if(imf->imtype == R_IMF_IMTYPE_THEORA) {
-               if(rd->ffcodecdata.codec != CODEC_ID_THEORA) {
-                       ffmpeg_set_preset(rd, FFMPEG_PRESET_THEORA);
-                       audio= 1;
+       else if (imf->imtype == R_IMF_IMTYPE_THEORA) {
+               if (rd->ffcodecdata.codec != CODEC_ID_THEORA) {
+                       BKE_ffmpeg_preset_set(rd, FFMPEG_PRESET_THEORA);
+                       audio = 1;
                }
        }
 
                }
        }
 
-       if(audio && rd->ffcodecdata.audio_codec < 0) {
+       if (audio && rd->ffcodecdata.audio_codec < 0) {
                rd->ffcodecdata.audio_codec = CODEC_ID_NONE;
                rd->ffcodecdata.audio_bitrate = 128;
        }
 }
 
                rd->ffcodecdata.audio_codec = CODEC_ID_NONE;
                rd->ffcodecdata.audio_bitrate = 128;
        }
 }
 
-void ffmpeg_verify_codec_settings(RenderData *rd)
+void BKE_ffmpeg_codec_settings_verify(RenderData *rd)
 {
        ffmpeg_set_expert_options(rd);
 }
 
 {
        ffmpeg_set_expert_options(rd);
 }
 
+int BKE_ffmpeg_alpha_channel_is_supported(RenderData *rd)
+{
+       int codec = rd->ffcodecdata.codec;
+
+       if (codec == CODEC_ID_QTRLE)
+               return TRUE;
+
+       if (codec == CODEC_ID_PNG)
+               return TRUE;
+
+#ifdef FFMPEG_FFV1_ALPHA_SUPPORTED
+       if (codec == CODEC_ID_FFV1)
+               return TRUE;
+#endif
+
+       return FALSE;
+}
+
 #endif
 #endif