Filling in branch from trunk
[blender.git] / source / blender / blenkernel / intern / writeffmpeg.c
1 /*
2  * ffmpeg-write support
3  *
4  * Partial Copyright (c) 2006 Peter Schlaile
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  */
17
18
19 #ifdef WITH_FFMPEG
20 #include <string.h>
21 #include <stdio.h>
22
23 #if defined(_WIN32) && defined(_DEBUG) && !defined(__MINGW32__) && !defined(__CYGWIN__)
24 /* This does not seem necessary or present on MSVC 8, but may be needed in earlier versions? */
25 #if _MSC_VER < 1400
26 #include <stdint.h>
27 #endif
28 #endif
29
30 #include <stdlib.h>
31
32 #include <ffmpeg/avformat.h>
33 #include <ffmpeg/avcodec.h>
34 #include <ffmpeg/rational.h>
35 #include <ffmpeg/swscale.h>
36
37 #if LIBAVFORMAT_VERSION_INT < (49 << 16)
38 #define FFMPEG_OLD_FRAME_RATE 1
39 #else
40 #define FFMPEG_CODEC_IS_POINTER 1
41 #define FFMPEG_CODEC_TIME_BASE  1
42 #endif
43
44 #if defined(WIN32) && (!(defined snprintf))
45 #define snprintf _snprintf
46 #endif
47
48 #include "BKE_writeffmpeg.h"
49
50 #include "MEM_guardedalloc.h"
51 #include "BLI_blenlib.h"
52
53 #include "BKE_bad_level_calls.h"
54 #include "BKE_global.h"
55
56 #include "IMB_imbuf_types.h"
57 #include "IMB_imbuf.h"
58
59 #include "BSE_seqaudio.h"
60
61 #include "DNA_scene_types.h"
62 #include "blendef.h"
63
64 #ifdef HAVE_CONFIG_H
65 #include <config.h>
66 #endif
67
68 extern void do_init_ffmpeg();
69 void makeffmpegstring(char* string);
70
71 static int ffmpeg_type = 0;
72 static int ffmpeg_codec = CODEC_ID_MPEG4;
73 static int ffmpeg_audio_codec = CODEC_ID_MP2;
74 static int ffmpeg_video_bitrate = 1150;
75 static int ffmpeg_audio_bitrate = 128;
76 static int ffmpeg_gop_size = 12;
77 static int ffmpeg_multiplex_audio = 1;
78 static int ffmpeg_autosplit = 0;
79 static int ffmpeg_autosplit_count = 0;
80
81 static AVFormatContext* outfile = 0;
82 static AVStream* video_stream = 0;
83 static AVStream* audio_stream = 0;
84 static AVFrame* current_frame = 0;
85 static struct SwsContext *img_convert_ctx = 0;
86
87 static uint8_t* video_buffer = 0;
88 static int video_buffersize = 0;
89
90 static uint8_t* audio_input_buffer = 0;
91 static int audio_input_frame_size = 0;
92 static uint8_t* audio_output_buffer = 0;
93 static int audio_outbuf_size = 0;
94
95 static RenderData *ffmpeg_renderdata = 0;
96
97 #define FFMPEG_AUTOSPLIT_SIZE 2000000000
98
99 /* Delete a picture buffer */
100
101 static void delete_picture(AVFrame* f)
102 {
103         if (f) {
104                 if (f->data[0]) MEM_freeN(f->data[0]);
105                 av_free(f);
106         }
107 }
108
109 #ifdef FFMPEG_CODEC_IS_POINTER
110 static AVCodecContext* get_codec_from_stream(AVStream* stream)
111 {
112         return stream->codec;
113 }
114 #else
115 static AVCodecContext* get_codec_from_stream(AVStream* stream)
116 {
117         return &stream->codec;
118 }
119 #endif
120
121 static int write_audio_frame(void) 
122 {
123         AVCodecContext* c = NULL;
124         AVPacket pkt;
125
126         c = get_codec_from_stream(audio_stream);
127
128         audiostream_fill(audio_input_buffer, 
129                          audio_input_frame_size 
130                          * sizeof(short) * c->channels);
131
132         av_init_packet(&pkt);
133
134         pkt.size = avcodec_encode_audio(c, audio_output_buffer,
135                                         audio_outbuf_size, 
136                                         (short*) audio_input_buffer);
137         pkt.data = audio_output_buffer;
138 #ifdef FFMPEG_CODEC_TIME_BASE
139         pkt.pts = av_rescale_q(c->coded_frame->pts, 
140                                c->time_base, audio_stream->time_base);
141 #else
142         pkt.pts = c->coded_frame->pts;
143 #endif
144         fprintf(stderr, "Audio Frame PTS: %lld\n", pkt.pts);
145
146         pkt.stream_index = audio_stream->index;
147         pkt.flags |= PKT_FLAG_KEY;
148         if (av_interleaved_write_frame(outfile, &pkt) != 0) {
149                 error("Error writing audio packet");
150                 return -1;
151         }
152         return 0;
153 }
154
155 /* Allocate a temporary frame */
156 static AVFrame* alloc_picture(int pix_fmt, int width, int height) 
157 {
158         AVFrame* f;
159         uint8_t* buf;
160         int size;
161         
162         /* allocate space for the struct */
163         f = avcodec_alloc_frame();
164         if (!f) return NULL;
165         size = avpicture_get_size(pix_fmt, width, height);
166         /* allocate the actual picture buffer */
167         buf = MEM_mallocN(size, "AVFrame buffer");
168         if (!buf) {
169                 free(f);
170                 return NULL;
171         }
172         avpicture_fill((AVPicture*)f, buf, pix_fmt, width, height);
173         return f;
174 }
175
176 /* Get the correct file extensions for the requested format,
177    first is always desired guess_format parameter */
178 static const char** get_file_extensions(int format) 
179 {
180         switch(format) {
181         case FFMPEG_DV: {
182                 static const char * rv[] = { ".dv", NULL };
183                 return rv;
184         }
185         case FFMPEG_MPEG1: {
186                 static const char * rv[] = { ".mpg", ".mpeg", NULL };
187                 return rv;
188         }
189         case FFMPEG_MPEG2: {
190                 static const char * rv[] = { ".dvd", ".vob", ".mpg", ".mpeg",
191                                              NULL };
192                 return rv;
193         }
194         case FFMPEG_MPEG4: {
195                 static const char * rv[] = { ".mp4", ".mpg", ".mpeg", NULL };
196                 return rv;
197         }
198         case FFMPEG_AVI: {
199                 static const char * rv[] = { ".avi", NULL };
200                 return rv;
201         }
202         case FFMPEG_MOV: {
203                 static const char * rv[] = { ".mov", NULL };
204                 return rv;
205         }
206         case FFMPEG_H264: {
207                 /* FIXME: avi for now... */
208                 static const char * rv[] = { ".avi", NULL };
209                 return rv;
210         }
211
212         case FFMPEG_XVID: {
213                 /* FIXME: avi for now... */
214                 static const char * rv[] = { ".avi", NULL };
215                 return rv;
216         }
217         default:
218                 return NULL;
219         }
220 }
221
222 /* Write a frame to the output file */
223 static void write_video_frame(AVFrame* frame) 
224 {
225         int outsize = 0;
226         int ret;
227         AVCodecContext* c = get_codec_from_stream(video_stream);
228 #ifdef FFMPEG_CODEC_TIME_BASE
229         frame->pts = G.scene->r.cfra - G.scene->r.sfra;
230 #endif
231
232         outsize = avcodec_encode_video(c, video_buffer, video_buffersize, 
233                                        frame);
234         if (outsize != 0) {
235                 AVPacket packet;
236                 av_init_packet(&packet);
237
238 #ifdef FFMPEG_CODEC_TIME_BASE
239                 packet.pts = av_rescale_q(c->coded_frame->pts,
240                                           c->time_base,
241                                           video_stream->time_base);
242 #else
243                 packet.pts = c->coded_frame->pts;
244 #endif
245                 fprintf(stderr, "Video Frame PTS: %lld\n", packet.pts);
246                 if (c->coded_frame->key_frame)
247                         packet.flags |= PKT_FLAG_KEY;
248                 packet.stream_index = video_stream->index;
249                 packet.data = video_buffer;
250                 packet.size = outsize;
251                 ret = av_interleaved_write_frame(outfile, &packet);
252         } else ret = 0;
253         if (ret != 0) {
254                 G.afbreek = 1;
255                 error("Error writing frame");
256         }
257 }
258
259 /* read and encode a frame of audio from the buffer */
260 static AVFrame* generate_video_frame(uint8_t* pixels) 
261 {
262         uint8_t* rendered_frame;
263
264         AVCodecContext* c = get_codec_from_stream(video_stream);
265         int width = c->width;
266         int height = c->height;
267         AVFrame* rgb_frame;
268
269         if (c->pix_fmt != PIX_FMT_RGBA32) {
270                 rgb_frame = alloc_picture(PIX_FMT_RGBA32, width, height);
271                 if (!rgb_frame) {
272                         G.afbreek=1;
273                         error("Couldn't allocate temporary frame");
274                         return NULL;
275                 }
276         } else {
277                 rgb_frame = current_frame;
278         }
279
280         rendered_frame = pixels;
281
282         /* Do RGBA-conversion and flipping in one step depending
283            on CPU-Endianess */
284
285         if (G.order == L_ENDIAN) {
286                 int y;
287                 for (y = 0; y < height; y++) {
288                         uint8_t* target = rgb_frame->data[0]
289                                 + width * 4 * (height - y - 1);
290                         uint8_t* src = rendered_frame + width * 4 * y;
291                         uint8_t* end = src + width * 4;
292                         while (src != end) {
293                                 target[3] = src[3];
294                                 target[2] = src[0];
295                                 target[1] = src[1];
296                                 target[0] = src[2];
297
298                                 target += 4;
299                                 src += 4;
300                         }
301                 }
302         } else {
303                 int y;
304                 for (y = 0; y < height; y++) {
305                         uint8_t* target = rgb_frame->data[0]
306                                 + width * 4 * (height - y - 1);
307                         uint8_t* src = rendered_frame + width * 4 * y;
308                         uint8_t* end = src + width * 4;
309                         while (src != end) {
310                                 target[3] = src[2];
311                                 target[2] = src[1];
312                                 target[1] = src[0];
313                                 target[0] = src[3];
314
315                                 target += 4;
316                                 src += 4;
317                         }
318                 }
319         }
320
321         if (c->pix_fmt != PIX_FMT_RGBA32) {
322                 sws_scale(img_convert_ctx, rgb_frame->data,
323                           rgb_frame->linesize, 0, c->height, 
324                           current_frame->data, current_frame->linesize);
325                 delete_picture(rgb_frame);
326         }
327         return current_frame;
328 }
329
330 /* prepare a video stream for the output file */
331
332 static AVStream* alloc_video_stream(int codec_id, AVFormatContext* of,
333                                     int rectx, int recty) 
334 {
335         AVStream* st;
336         AVCodecContext* c;
337         AVCodec* codec;
338         st = av_new_stream(of, 0);
339         if (!st) return NULL;
340
341         /* Set up the codec context */
342         
343         c = get_codec_from_stream(st);
344         c->codec_id = codec_id;
345         c->codec_type = CODEC_TYPE_VIDEO;
346
347
348         /* Get some values from the current render settings */
349         
350         c->width = rectx;
351         c->height = recty;
352
353 #ifdef FFMPEG_CODEC_TIME_BASE
354         /* FIXME: Really bad hack (tm) for NTSC support */
355         if (ffmpeg_type == FFMPEG_DV && G.scene->r.frs_sec != 25) {
356                 c->time_base.den = 2997;
357                 c->time_base.num = 100;
358         } else if ((double) ((int) G.scene->r.frs_sec_base) == 
359                    G.scene->r.frs_sec_base) {
360                 c->time_base.den = G.scene->r.frs_sec;
361                 c->time_base.num = (int) G.scene->r.frs_sec_base;
362         } else {
363                 c->time_base.den = G.scene->r.frs_sec * 100000;
364                 c->time_base.num = ((double) G.scene->r.frs_sec_base) * 100000;
365         }
366 #else
367         /* FIXME: Really bad hack (tm) for NTSC support */
368         if (ffmpeg_type == FFMPEG_DV && G.scene->r.frs_sec != 25) {
369                 c->frame_rate = 2997;
370                 c->frame_rate_base = 100;
371         } else if ((double) ((int) G.scene->r.frs_sec_base) == 
372                    G.scene->r.frs_sec_base) {
373                 c->frame_rate = G.scene->r.frs_sec;
374                 c->frame_rate_base = G.scene->r.frs_sec_base;
375         } else {
376                 c->frame_rate = G.scene->r.frs_sec * 100000;
377                 c->frame_rate_base = ((double) G.scene->r.frs_sec_base)*100000;
378         }
379 #endif
380         
381         c->gop_size = ffmpeg_gop_size;
382         c->bit_rate = ffmpeg_video_bitrate*1000;
383         c->rc_max_rate = G.scene->r.ffcodecdata.rc_max_rate*1000;
384         c->rc_min_rate = G.scene->r.ffcodecdata.rc_min_rate*1000;
385         c->rc_buffer_size = G.scene->r.ffcodecdata.rc_buffer_size * 1024;
386         c->rc_initial_buffer_occupancy 
387                 = G.scene->r.ffcodecdata.rc_buffer_size*3/4;
388         c->rc_buffer_aggressivity = 1.0;
389         c->me_method = ME_EPZS;
390         
391         codec = avcodec_find_encoder(c->codec_id);
392         if (!codec) return NULL;
393         
394         /* Be sure to use the correct pixel format(e.g. RGB, YUV) */
395         
396         if (codec->pix_fmts) {
397                 c->pix_fmt = codec->pix_fmts[0];
398         } else {
399                 /* makes HuffYUV happy ... */
400                 c->pix_fmt = PIX_FMT_YUV422P;
401         }
402
403         if (codec_id == CODEC_ID_XVID) {
404                 /* arghhhh ... */
405                 c->pix_fmt = PIX_FMT_YUV420P;
406         }
407         
408         if (!strcmp(of->oformat->name, "mp4") || 
409             !strcmp(of->oformat->name, "mov") ||
410             !strcmp(of->oformat->name, "3gp")) {
411                 fprintf(stderr, "Using global header\n");
412                 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
413         }
414         
415         /* Determine whether we are encoding interlaced material or not */
416         if (G.scene->r.mode & (1 << 6)) {
417                 fprintf(stderr, "Encoding interlaced video\n");
418                 c->flags |= CODEC_FLAG_INTERLACED_DCT;
419                 c->flags |= CODEC_FLAG_INTERLACED_ME;
420         }       
421         c->sample_aspect_ratio.num = G.scene->r.xasp;
422         c->sample_aspect_ratio.den = G.scene->r.yasp;
423         
424         if (avcodec_open(c, codec) < 0) {
425                 error("Couldn't initialize codec");
426                 return NULL;
427         }
428
429         video_buffersize = 2000000;
430         video_buffer = (uint8_t*)MEM_mallocN(video_buffersize, 
431                                              "FFMPEG video buffer");
432         
433         current_frame = alloc_picture(c->pix_fmt, c->width, c->height);
434
435         img_convert_ctx = sws_getContext(c->width, c->height,
436                                          PIX_FMT_RGBA32,
437                                          c->width, c->height,
438                                          c->pix_fmt,
439                                          SWS_BICUBIC,
440                                          NULL, NULL, NULL);
441         return st;
442 }
443
444 /* Prepare an audio stream for the output file */
445
446 static AVStream* alloc_audio_stream(int codec_id, AVFormatContext* of) 
447 {
448         AVStream* st;
449         AVCodecContext* c;
450         AVCodec* codec;
451
452         st = av_new_stream(of, 1);
453         if (!st) return NULL;
454
455         c = get_codec_from_stream(st);
456         c->codec_id = codec_id;
457         c->codec_type = CODEC_TYPE_AUDIO;
458
459         c->sample_rate = G.scene->audio.mixrate;
460         c->bit_rate = ffmpeg_audio_bitrate*1000;
461         c->channels = 2;
462         codec = avcodec_find_encoder(c->codec_id);
463         if (!codec) {
464                 error("Couldn't find a valid audio codec");
465                 return NULL;
466         }
467         if (avcodec_open(c, codec) < 0) {
468                 error("Couldn't initialize audio codec");
469                 return NULL;
470         }
471
472         /* FIXME: Should be user configurable */
473         if (ffmpeg_type == FFMPEG_DV) {
474                 /* this is a hack around the poor ffmpeg dv multiplexer. */
475                 /* only fixes PAL for now 
476                    (NTSC is a lot more complicated here...)! */
477                 audio_outbuf_size = 7680;
478         } else {
479                 audio_outbuf_size = 10000;
480         }
481         audio_output_buffer = (uint8_t*)MEM_mallocN(
482                 audio_outbuf_size, "FFMPEG audio encoder input buffer");
483
484        /* ugly hack for PCM codecs */
485
486         if (c->frame_size <= 1) {
487                 audio_input_frame_size = audio_outbuf_size / c->channels;
488                 switch(c->codec_id) {
489                 case CODEC_ID_PCM_S16LE:
490                 case CODEC_ID_PCM_S16BE:
491                 case CODEC_ID_PCM_U16LE:
492                 case CODEC_ID_PCM_U16BE:
493                         audio_input_frame_size >>= 1;
494                         break;
495                 default:
496                         break;
497                 }
498         } else {
499                 audio_input_frame_size = c->frame_size;
500         }
501
502         audio_input_buffer = (uint8_t*)MEM_mallocN(
503                 audio_input_frame_size * sizeof(short) * c->channels, 
504                 "FFMPEG audio encoder output buffer");
505
506         return st;
507 }
508 /* essential functions -- start, append, end */
509
510 void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty)
511 {
512         /* Handle to the output file */
513         AVFormatContext* of;
514         AVOutputFormat* fmt;
515         char name[256];
516         const char ** exts;
517
518         ffmpeg_type = rd->ffcodecdata.type;
519         ffmpeg_codec = rd->ffcodecdata.codec;
520         ffmpeg_audio_codec = rd->ffcodecdata.audio_codec;
521         ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate;
522         ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate;
523         ffmpeg_gop_size = rd->ffcodecdata.gop_size;
524         ffmpeg_multiplex_audio = rd->ffcodecdata.flags
525                 & FFMPEG_MULTIPLEX_AUDIO;
526         ffmpeg_autosplit = rd->ffcodecdata.flags
527                 & FFMPEG_AUTOSPLIT_OUTPUT;
528         
529         do_init_ffmpeg();
530
531         /* Determine the correct filename */
532         makeffmpegstring(name);
533         fprintf(stderr, "Starting output to %s(ffmpeg)...\n"
534                 "  Using type=%d, codec=%d, audio_codec=%d,\n"
535                 "  video_bitrate=%d, audio_bitrate=%d,\n"
536                 "  gop_size=%d, multiplex=%d, autosplit=%d\n"
537                 "  render width=%d, render height=%d\n", 
538                 name, ffmpeg_type, ffmpeg_codec, ffmpeg_audio_codec,
539                 ffmpeg_video_bitrate, ffmpeg_audio_bitrate,
540                 ffmpeg_gop_size, ffmpeg_multiplex_audio,
541                 ffmpeg_autosplit, rectx, recty);
542         
543         exts = get_file_extensions(ffmpeg_type);
544         if (!exts) {
545                 G.afbreek = 1; /* Abort render */
546                 error("No valid formats found");
547                 return;
548         }
549         fmt = guess_format(NULL, exts[0], NULL);
550         if (!fmt) {
551                 G.afbreek = 1; /* Abort render */
552                 error("No valid formats found");
553                 return;
554         }
555
556         of = av_alloc_format_context();
557         if (!of) {
558                 G.afbreek = 1;
559                 error("Error opening output file");
560                 return;
561         }
562         
563         of->oformat = fmt;
564         of->packet_size= G.scene->r.ffcodecdata.mux_packet_size;
565         if (ffmpeg_multiplex_audio) {
566                 of->mux_rate = G.scene->r.ffcodecdata.mux_rate;
567         } else {
568                 of->mux_rate = 0;
569         }
570
571         of->preload = (int)(0.5*AV_TIME_BASE);
572         of->max_delay = (int)(0.7*AV_TIME_BASE);
573
574         snprintf(of->filename, sizeof(of->filename), "%s", name);
575         /* set the codec to the user's selection */
576         switch(ffmpeg_type) {
577         case FFMPEG_AVI:
578         case FFMPEG_MOV:
579                 fmt->video_codec = ffmpeg_codec;
580                 break;
581         case FFMPEG_DV:
582                 fmt->video_codec = CODEC_ID_DVVIDEO;
583                 break;
584         case FFMPEG_MPEG1:
585                 fmt->video_codec = CODEC_ID_MPEG1VIDEO;
586                 break;
587         case FFMPEG_MPEG2:
588                 fmt->video_codec = CODEC_ID_MPEG2VIDEO;
589                 break;
590         case FFMPEG_H264:
591                 fmt->video_codec = CODEC_ID_H264;
592                 break;
593         case FFMPEG_XVID:
594                 fmt->video_codec = CODEC_ID_XVID;
595                 break;
596         case FFMPEG_MPEG4:
597         default:
598                 fmt->video_codec = CODEC_ID_MPEG4;
599                 break;
600         }
601         if (fmt->video_codec == CODEC_ID_DVVIDEO) {
602                 if (rectx != 720) {
603                         G.afbreek = 1;
604                         error("Render width has to be 720 pixels for DV!");
605                         return;
606                 }
607                 if (G.scene->r.frs_sec != 25 && recty != 480) {
608                         G.afbreek = 1;
609                         error("Render height has to be 480 pixels "
610                               "for DV-NTSC!");
611                         return;
612                         
613                 }
614                 if (G.scene->r.frs_sec == 25 && recty != 576) {
615                         G.afbreek = 1;
616                         error("Render height has to be 576 pixels "
617                               "for DV-PAL!");
618                         return;
619                 }
620         }
621         if (ffmpeg_type == FFMPEG_DV) {
622                 fmt->audio_codec = CODEC_ID_PCM_S16LE;
623                 if (ffmpeg_multiplex_audio 
624                     && G.scene->audio.mixrate != 48000) {
625                         G.afbreek = 1;
626                         error("FFMPEG only supports 48khz / stereo "
627                               "audio for DV!");
628                         return;
629                 }
630         }
631         
632         video_stream = alloc_video_stream(fmt->video_codec, of, rectx, recty);
633         if (!video_stream) {
634                 G.afbreek = 1;
635                 error("Error initializing video stream");
636                 return;
637         }
638         
639         if (ffmpeg_multiplex_audio) {
640                 audio_stream = alloc_audio_stream(fmt->audio_codec, of);
641                 if (!audio_stream) {
642                         G.afbreek = 1;
643                         error("Error initializing audio stream");
644                         return;
645                 }
646                 audiostream_play(SFRA, 0, 1);
647         }
648         if (av_set_parameters(of, NULL) < 0) {
649                 G.afbreek = 1;
650                 error("Error setting output parameters");
651                 return;
652         }
653         if (!(fmt->flags & AVFMT_NOFILE)) {
654                 if (url_fopen(&of->pb, name, URL_WRONLY) < 0) {
655                         G.afbreek = 1;
656                         error("Could not open file for writing");
657                         return;
658                 }
659         }
660
661         av_write_header(of);
662         outfile = of;
663         dump_format(of, 0, name, 1);
664 }
665
666 /* **********************************************************************
667    * public interface
668    ********************************************************************** */
669
670 /* Get the output filename-- similar to the other output formats */
671 void makeffmpegstring(char* string) {
672         
673         char txt[FILE_MAXDIR+FILE_MAXFILE];
674         char autosplit[20];
675
676         const char ** exts = get_file_extensions(G.scene->r.ffcodecdata.type);
677         const char ** fe = exts;
678
679         if (!string || !exts) return;
680
681         strcpy(string, G.scene->r.pic);
682         BLI_convertstringcode(string, G.sce, G.scene->r.cfra);
683
684         BLI_make_existing_file(string);
685
686         autosplit[0] = 0;
687
688         if ((G.scene->r.ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT) != 0) {
689                 sprintf(autosplit, "_%03d", ffmpeg_autosplit_count);
690         }
691
692         while (*fe) {
693                 if (BLI_strcasecmp(string + strlen(string) - strlen(*fe), 
694                                    *fe) == 0) {
695                         break;
696                 }
697                 fe++;
698         }
699
700         if (!*fe) {
701                 strcat(string, autosplit);
702                 sprintf(txt, "%04d_%04d%s", (G.scene->r.sfra), 
703                         (G.scene->r.efra), *exts);
704                 strcat(string, txt);
705         } else {
706                 *(string + strlen(string) - strlen(*fe)) = 0;
707                 strcat(string, autosplit);
708                 strcat(string, *fe);
709         }
710 }
711
712
713 void start_ffmpeg(RenderData *rd, int rectx, int recty)
714 {
715         ffmpeg_autosplit_count = 0;
716
717         ffmpeg_renderdata = rd;
718
719         start_ffmpeg_impl(rd, rectx, recty);
720 }
721
722 void end_ffmpeg(void);
723
724 static void write_audio_frames()
725 {
726         int finished = 0;
727
728         while (ffmpeg_multiplex_audio && !finished) {
729                 double a_pts = ((double)audio_stream->pts.val 
730                                 * audio_stream->time_base.num 
731                                 / audio_stream->time_base.den);
732                 double v_pts = ((double)video_stream->pts.val 
733                                 * video_stream->time_base.num 
734                                 / video_stream->time_base.den);
735                 
736                 if (a_pts < v_pts) {
737                         write_audio_frame();
738                 } else {
739                         finished = 1;
740                 }
741         }
742 }
743
744 void append_ffmpeg(int frame, int *pixels, int rectx, int recty) 
745 {
746         fprintf(stderr, "Writing frame %i, "
747                 "render width=%d, render height=%d\n", frame,
748                 rectx, recty);
749
750         write_audio_frames();
751         write_video_frame(generate_video_frame((unsigned char*) pixels));
752
753         if (ffmpeg_autosplit) {
754                 if (url_ftell(&outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) {
755                         end_ffmpeg();
756                         ffmpeg_autosplit_count++;
757                         start_ffmpeg_impl(ffmpeg_renderdata,
758                                           rectx, recty);
759                 }
760         }
761 }
762
763
764 void end_ffmpeg(void)
765 {
766         int i;
767         
768         fprintf(stderr, "Closing ffmpeg...\n");
769
770         if (audio_stream) {
771                 write_audio_frames();
772         }
773         
774         if (outfile) {
775                 av_write_trailer(outfile);
776         }
777         
778         /* Close the video codec */
779
780         if (video_stream && get_codec_from_stream(video_stream)) {
781                 avcodec_close(get_codec_from_stream(video_stream));
782                 video_stream = 0;
783         }
784
785         
786         /* Close the output file */
787         if (outfile) {
788                 for (i = 0; i < outfile->nb_streams; i++) {
789                         if (&outfile->streams[i]) {
790                                 av_freep(&outfile->streams[i]);
791                         }
792                 }
793         }
794         /* free the temp buffer */
795         if (current_frame) {
796                 delete_picture(current_frame);
797                 current_frame = 0;
798         }
799         if (outfile && outfile->oformat) {
800                 if (!(outfile->oformat->flags & AVFMT_NOFILE)) {
801                         url_fclose(&outfile->pb);
802                 }
803         }
804         if (outfile) {
805                 av_free(outfile);
806                 outfile = 0;
807         }
808         if (video_buffer) {
809                 MEM_freeN(video_buffer);
810                 video_buffer = 0;
811         }
812         if (audio_output_buffer) {
813                 MEM_freeN(audio_output_buffer);
814                 audio_output_buffer = 0;
815         }
816         if (audio_input_buffer) {
817                 MEM_freeN(audio_input_buffer);
818                 audio_input_buffer = 0;
819         }
820
821         if (img_convert_ctx) {
822                 sws_freeContext(img_convert_ctx);
823                 img_convert_ctx = 0;
824         }
825 }
826 #endif
827