Cycles: svn merge -r41225:41232 ^/trunk/blender
[blender.git] / source / blender / blenkernel / intern / writeffmpeg.c
index fe7a7a181777830aa7ee00ec6f8751b62f4816f3..ed0a351716c417c5fd72ff775733016af57cd030 100644 (file)
@@ -1,8 +1,4 @@
-/** \file blender/blenkernel/intern/writeffmpeg.c
- *  \ingroup bke
- */
 /*
- * $Id$
  *
  * ffmpeg-write support
  *
  *
  */
 
+/** \file blender/blenkernel/intern/writeffmpeg.c
+ *  \ingroup bke
+ */
+
 #ifdef WITH_FFMPEG
 #include <string.h>
 #include <stdio.h>
 #include <libswscale/swscale.h>
 #include <libavcodec/opt.h>
 
-#if defined(WIN32) && (!(defined snprintf))
-#define snprintf _snprintf
-#endif
-
 #include "MEM_guardedalloc.h"
 
 #include "DNA_scene_types.h"
@@ -410,8 +406,7 @@ static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char
                return;
        }
        
-       prop = IDP_GetPropertyFromGroup(
-               rd->ffcodecdata.properties, (char*) prop_name);
+       prop = IDP_GetPropertyFromGroup(rd->ffcodecdata.properties, prop_name);
        if (!prop) {
                return;
        }
@@ -493,6 +488,12 @@ static AVStream* alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
                c->qmax=51;
        }
        
+       // Keep lossless encodes in the RGB domain.
+       if (codec_id == CODEC_ID_HUFFYUV || codec_id == CODEC_ID_FFV1) {
+               /* HUFFYUV was PIX_FMT_YUV422P before */
+               c->pix_fmt = PIX_FMT_RGB32;
+       }
+
        if ((of->oformat->flags & AVFMT_GLOBALHEADER)
 //             || !strcmp(of->oformat->name, "mp4")
 //         || !strcmp(of->oformat->name, "mov")
@@ -522,8 +523,8 @@ static AVStream* alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
                return NULL;
        }
 
-       video_buffersize = 2000000;
-       video_buffer = (uint8_t*)MEM_mallocN(video_buffersize
+       video_buffersize = avpicture_get_size(c->pix_fmt, c->width, c->height);
+       video_buffer = (uint8_t*)MEM_mallocN(video_buffersize*sizeof(uint8_t),
                                                 "FFMPEG video buffer");
        
        current_frame = alloc_picture(c->pix_fmt, c->width, c->height);
@@ -555,7 +556,7 @@ static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
        c->sample_rate = rd->ffcodecdata.audio_mixrate;
        c->bit_rate = ffmpeg_audio_bitrate*1000;
        c->sample_fmt = SAMPLE_FMT_S16;
-       c->channels = 2;
+       c->channels = rd->ffcodecdata.audio_channels;
        codec = avcodec_find_encoder(c->codec_id);
        if (!codec) {
                //XXX error("Couldn't find a valid audio codec");
@@ -569,6 +570,11 @@ static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
                return NULL;
        }
 
+       /* need to prevent floating point exception when using vorbis audio codec,
+          initialize this value in the same way as it's done in FFmpeg iteslf (sergey) */
+       st->codec->time_base.num= 1;
+       st->codec->time_base.den= st->codec->sample_rate;
+
        audio_outbuf_size = FF_MIN_BUFFER_SIZE;
 
        if((c->codec_id >= CODEC_ID_PCM_S16LE) && (c->codec_id <= CODEC_ID_PCM_DVD))
@@ -580,12 +586,11 @@ static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
                        audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4;
        }
 
-       audio_output_buffer = (uint8_t*)MEM_mallocN(
-               audio_outbuf_size, "FFMPEG audio encoder input buffer");
+       audio_output_buffer = (uint8_t*)av_malloc(
+               audio_outbuf_size);
 
-       audio_input_buffer = (uint8_t*)MEM_mallocN(
-               audio_input_samples * c->channels * sizeof(int16_t),
-               "FFMPEG audio encoder output buffer");
+       audio_input_buffer = (uint8_t*)av_malloc(
+               audio_input_samples * c->channels * sizeof(int16_t));
 
        audio_time = 0.0f;
 
@@ -653,7 +658,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
 
        fmt->audio_codec = ffmpeg_audio_codec;
 
-       snprintf(of->filename, sizeof(of->filename), "%s", name);
+       BLI_snprintf(of->filename, sizeof(of->filename), "%s", name);
        /* set the codec to the user's selection */
        switch(ffmpeg_type) {
        case FFMPEG_AVI:
@@ -709,7 +714,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
        
        if (ffmpeg_type == FFMPEG_DV) {
                fmt->audio_codec = CODEC_ID_PCM_S16LE;
-               if (ffmpeg_audio_codec != CODEC_ID_NONE && rd->ffcodecdata.audio_mixrate != 48000) {
+               if (ffmpeg_audio_codec != CODEC_ID_NONE && rd->ffcodecdata.audio_mixrate != 48000 && rd->ffcodecdata.audio_channels != 2) {
                        BKE_report(reports, RPT_ERROR, "FFMPEG only supports 48khz / stereo audio for DV!");
                        return 0;
                }
@@ -742,7 +747,11 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
                }
        }
 
-       av_write_header(of);
+       if (av_write_header(of) < 0) {
+               BKE_report(reports, RPT_ERROR, "Could not initialize streams. Probably unsupported codec combination.");
+               return 0;
+       }
+
        outfile = of;
        av_dump_format(of, 0, name, 1);
 
@@ -813,7 +822,8 @@ void flush_ffmpeg(void)
    ********************************************************************** */
 
 /* Get the output filename-- similar to the other output formats */
-void filepath_ffmpeg(char* string, RenderData* rd) {
+void filepath_ffmpeg(char* string, RenderData* rd)
+{
        char autosplit[20];
 
        const char ** exts = get_file_extensions(rd->ffcodecdata.type);
@@ -868,6 +878,10 @@ int start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty, Repo
                specs.format = AUD_FORMAT_S16;
                specs.rate = rd->ffcodecdata.audio_mixrate;
                audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->ffcodecdata.audio_volume);
+#ifdef FFMPEG_CODEC_TIME_BASE
+               c->time_base.den = specs.rate;
+               c->time_base.num = 1;
+#endif
        }
 #endif
        return success;
@@ -984,11 +998,11 @@ void end_ffmpeg(void)
                video_buffer = 0;
        }
        if (audio_output_buffer) {
-               MEM_freeN(audio_output_buffer);
+               av_free(audio_output_buffer);
                audio_output_buffer = 0;
        }
        if (audio_input_buffer) {
-               MEM_freeN(audio_input_buffer);
+               av_free(audio_input_buffer);
                audio_input_buffer = 0;
        }
 
@@ -1009,8 +1023,7 @@ void ffmpeg_property_del(RenderData *rd, void *type, void *prop_)
                return;
        }
 
-       group = IDP_GetPropertyFromGroup(
-               rd->ffcodecdata.properties, (char*) type);
+       group = IDP_GetPropertyFromGroup(rd->ffcodecdata.properties, type);
        if (group && prop) {
                IDP_RemFromGroup(group, prop);
                IDP_FreeProperty(prop);
@@ -1041,11 +1054,10 @@ IDProperty *ffmpeg_property_add(RenderData *rd, char * type, int opt_index, int
                        = IDP_New(IDP_GROUP, val, "ffmpeg"); 
        }
 
-       group = IDP_GetPropertyFromGroup(
-               rd->ffcodecdata.properties, (char*) type);
+       group = IDP_GetPropertyFromGroup(rd->ffcodecdata.properties, type);
        
        if (!group) {
-               group = IDP_New(IDP_GROUP, val, (char*) type); 
+               group = IDP_New(IDP_GROUP, val, type);
                IDP_AddToGroup(rd->ffcodecdata.properties, group);
        }