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