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