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