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