Fix Debug build failure with ffmpeg enabled on MSVC 8
[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
36 #if LIBAVFORMAT_VERSION_INT < (49 << 16)
37 #define FFMPEG_OLD_FRAME_RATE 1
38 #else
39 #define FFMPEG_CODEC_IS_POINTER 1
40 #define FFMPEG_CODEC_TIME_BASE  1
41 #endif
42
43 #if defined(WIN32) && (!(defined snprintf))
44 #define snprintf _snprintf
45 #endif
46
47 #include "BKE_writeffmpeg.h"
48
49 #include "MEM_guardedalloc.h"
50 #include "BLI_blenlib.h"
51
52 #include "BKE_bad_level_calls.h"
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 #include "blendef.h"
62
63 #ifdef HAVE_CONFIG_H
64 #include <config.h>
65 #endif
66
67 extern void do_init_ffmpeg();
68 void makeffmpegstring(char* string);
69
70 static int ffmpeg_type = 0;
71 static int ffmpeg_codec = CODEC_ID_MPEG4;
72 static int ffmpeg_audio_codec = CODEC_ID_MP2;
73 static int ffmpeg_video_bitrate = 1150;
74 static int ffmpeg_audio_bitrate = 128;
75 static int ffmpeg_gop_size = 12;
76 static int ffmpeg_multiplex_audio = 1;
77 static int ffmpeg_autosplit = 0;
78 static int ffmpeg_autosplit_count = 0;
79
80 static AVFormatContext* outfile = 0;
81 static AVStream* video_stream = 0;
82 static AVStream* audio_stream = 0;
83 static AVFrame* current_frame = 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_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_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                 img_convert((AVPicture*)current_frame, c->pix_fmt, 
321                         (AVPicture*)rgb_frame, PIX_FMT_RGBA32, width, height);
322                 delete_picture(rgb_frame);
323         }
324         return current_frame;
325 }
326
327 /* prepare a video stream for the output file */
328
329 static AVStream* alloc_video_stream(int codec_id, AVFormatContext* of,
330                                     int rectx, int recty) 
331 {
332         AVStream* st;
333         AVCodecContext* c;
334         AVCodec* codec;
335         st = av_new_stream(of, 0);
336         if (!st) return NULL;
337
338         /* Set up the codec context */
339         
340         c = get_codec_from_stream(st);
341         c->codec_id = codec_id;
342         c->codec_type = CODEC_TYPE_VIDEO;
343
344
345         /* Get some values from the current render settings */
346         
347         c->width = rectx;
348         c->height = recty;
349
350 #ifdef FFMPEG_CODEC_TIME_BASE
351         /* FIXME: Really bad hack (tm) for NTSC support */
352         if (ffmpeg_type == FFMPEG_DV && G.scene->r.frs_sec != 25) {
353                 c->time_base.den = 2997;
354                 c->time_base.num = 100;
355         } else {
356                 c->time_base.den = G.scene->r.frs_sec;
357                 c->time_base.num = 1;
358         }
359 #else
360         /* FIXME: Really bad hack (tm) for NTSC support */
361         if (ffmpeg_type == FFMPEG_DV && G.scene->r.frs_sec != 25) {
362                 c->frame_rate = 2997;
363                 c->frame_rate_base = 100;
364         } else {
365                 c->frame_rate = G.scene->r.frs_sec;
366                 c->frame_rate_base = 1;
367         }
368 #endif
369         
370         c->gop_size = ffmpeg_gop_size;
371         c->bit_rate = ffmpeg_video_bitrate*1000;
372         c->rc_max_rate = G.scene->r.ffcodecdata.rc_max_rate*1000;
373         c->rc_min_rate = G.scene->r.ffcodecdata.rc_min_rate*1000;
374         c->rc_buffer_size = G.scene->r.ffcodecdata.rc_buffer_size * 1024;
375         c->rc_initial_buffer_occupancy 
376                 = G.scene->r.ffcodecdata.rc_buffer_size*3/4;
377         c->rc_buffer_aggressivity = 1.0;
378         c->me_method = ME_EPZS;
379         
380         codec = avcodec_find_encoder(c->codec_id);
381         if (!codec) return NULL;
382         
383         /* Be sure to use the correct pixel format(e.g. RGB, YUV) */
384         
385         if (codec->pix_fmts) {
386                 c->pix_fmt = codec->pix_fmts[0];
387         } else {
388                 /* makes HuffYUV happy ... */
389                 c->pix_fmt = PIX_FMT_YUV422P;
390         }
391
392         if (codec_id == CODEC_ID_XVID) {
393                 /* arghhhh ... */
394                 c->pix_fmt = PIX_FMT_YUV420P;
395         }
396         
397         if (!strcmp(of->oformat->name, "mp4") || 
398             !strcmp(of->oformat->name, "mov") ||
399             !strcmp(of->oformat->name, "3gp")) {
400                 fprintf(stderr, "Using global header\n");
401                 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
402         }
403         
404         /* Determine whether we are encoding interlaced material or not */
405         if (G.scene->r.mode & (1 << 6)) {
406                 fprintf(stderr, "Encoding interlaced video\n");
407                 c->flags |= CODEC_FLAG_INTERLACED_DCT;
408                 c->flags |= CODEC_FLAG_INTERLACED_ME;
409         }       
410         c->sample_aspect_ratio.num = G.scene->r.xasp;
411         c->sample_aspect_ratio.den = G.scene->r.yasp;
412         
413         if (avcodec_open(c, codec) < 0) {
414                 error("Couldn't initialize codec");
415                 return NULL;
416         }
417
418         video_buffersize = 2000000;
419         video_buffer = (uint8_t*)MEM_mallocN(video_buffersize, 
420                                              "FFMPEG video buffer");
421         
422         current_frame = alloc_picture(c->pix_fmt, c->width, c->height);
423         return st;
424 }
425
426 /* Prepare an audio stream for the output file */
427
428 static AVStream* alloc_audio_stream(int codec_id, AVFormatContext* of) 
429 {
430         AVStream* st;
431         AVCodecContext* c;
432         AVCodec* codec;
433
434         st = av_new_stream(of, 1);
435         if (!st) return NULL;
436
437         c = get_codec_from_stream(st);
438         c->codec_id = codec_id;
439         c->codec_type = CODEC_TYPE_AUDIO;
440
441         c->sample_rate = G.scene->audio.mixrate;
442         c->bit_rate = ffmpeg_audio_bitrate*1000;
443         c->channels = 2;
444         codec = avcodec_find_encoder(c->codec_id);
445         if (!codec) {
446                 error("Couldn't find a valid audio codec");
447                 return NULL;
448         }
449         if (avcodec_open(c, codec) < 0) {
450                 error("Couldn't initialize audio codec");
451                 return NULL;
452         }
453
454         /* FIXME: Should be user configurable */
455         audio_outbuf_size = 10000;
456         audio_output_buffer = (uint8_t*)MEM_mallocN(
457                 audio_outbuf_size, "FFMPEG audio encoder input buffer");
458
459        /* ugly hack for PCM codecs */
460
461         if (c->frame_size <= 1) {
462                 audio_input_frame_size = audio_outbuf_size / c->channels;
463                 switch(c->codec_id) {
464                 case CODEC_ID_PCM_S16LE:
465                 case CODEC_ID_PCM_S16BE:
466                 case CODEC_ID_PCM_U16LE:
467                 case CODEC_ID_PCM_U16BE:
468                         audio_input_frame_size >>= 1;
469                         break;
470                 default:
471                         break;
472                 }
473         } else {
474                 audio_input_frame_size = c->frame_size;
475         }
476
477         audio_input_buffer = (uint8_t*)MEM_mallocN(
478                 audio_input_frame_size * sizeof(short) * c->channels, 
479                 "FFMPEG audio encoder output buffer");
480
481         return st;
482 }
483 /* essential functions -- start, append, end */
484
485 void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty)
486 {
487         /* Handle to the output file */
488         AVFormatContext* of;
489         AVOutputFormat* fmt;
490         char name[256];
491         const char ** exts;
492
493         ffmpeg_type = rd->ffcodecdata.type;
494         ffmpeg_codec = rd->ffcodecdata.codec;
495         ffmpeg_audio_codec = rd->ffcodecdata.audio_codec;
496         ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate;
497         ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate;
498         ffmpeg_gop_size = rd->ffcodecdata.gop_size;
499         ffmpeg_multiplex_audio = rd->ffcodecdata.flags
500                 & FFMPEG_MULTIPLEX_AUDIO;
501         ffmpeg_autosplit = rd->ffcodecdata.flags
502                 & FFMPEG_AUTOSPLIT_OUTPUT;
503         
504         do_init_ffmpeg();
505
506         /* Determine the correct filename */
507         makeffmpegstring(name);
508         fprintf(stderr, "Starting output to %s(ffmpeg)...\n"
509                 "  Using type=%d, codec=%d, audio_codec=%d,\n"
510                 "  video_bitrate=%d, audio_bitrate=%d,\n"
511                 "  gop_size=%d, multiplex=%d, autosplit=%d\n"
512                 "  render width=%d, render height=%d\n", 
513                 name, ffmpeg_type, ffmpeg_codec, ffmpeg_audio_codec,
514                 ffmpeg_video_bitrate, ffmpeg_audio_bitrate,
515                 ffmpeg_gop_size, ffmpeg_multiplex_audio,
516                 ffmpeg_autosplit, rectx, recty);
517         
518         exts = get_file_extensions(ffmpeg_type);
519         if (!exts) {
520                 G.afbreek = 1; /* Abort render */
521                 error("No valid formats found");
522                 return;
523         }
524         fmt = guess_format(NULL, exts[0], NULL);
525         if (!fmt) {
526                 G.afbreek = 1; /* Abort render */
527                 error("No valid formats found");
528                 return;
529         }
530
531         of = av_alloc_format_context();
532         if (!of) {
533                 G.afbreek = 1;
534                 error("Error opening output file");
535                 return;
536         }
537         
538         of->oformat = fmt;
539         of->packet_size= G.scene->r.ffcodecdata.mux_packet_size;
540         if (ffmpeg_multiplex_audio) {
541                 of->mux_rate = G.scene->r.ffcodecdata.mux_rate;
542         } else {
543                 of->mux_rate = 0;
544         }
545
546         of->preload = (int)(0.5*AV_TIME_BASE);
547         of->max_delay = (int)(0.7*AV_TIME_BASE);
548
549         snprintf(of->filename, sizeof(of->filename), "%s", name);
550         /* set the codec to the user's selection */
551         switch(ffmpeg_type) {
552         case FFMPEG_AVI:
553         case FFMPEG_MOV:
554                 fmt->video_codec = ffmpeg_codec;
555                 break;
556         case FFMPEG_DV:
557                 fmt->video_codec = CODEC_ID_DVVIDEO;
558                 break;
559         case FFMPEG_MPEG1:
560                 fmt->video_codec = CODEC_ID_MPEG1VIDEO;
561                 break;
562         case FFMPEG_MPEG2:
563                 fmt->video_codec = CODEC_ID_MPEG2VIDEO;
564                 break;
565         case FFMPEG_H264:
566                 fmt->video_codec = CODEC_ID_H264;
567                 break;
568         case FFMPEG_XVID:
569                 fmt->video_codec = CODEC_ID_XVID;
570                 break;
571         case FFMPEG_MPEG4:
572         default:
573                 fmt->video_codec = CODEC_ID_MPEG4;
574                 break;
575         }
576         if (fmt->video_codec == CODEC_ID_DVVIDEO) {
577                 if (rectx != 720) {
578                         G.afbreek = 1;
579                         error("Render width has to be 720 pixels for DV!");
580                         return;
581                 }
582                 if (G.scene->r.frs_sec != 25 && recty != 480) {
583                         G.afbreek = 1;
584                         error("Render height has to be 480 pixels "
585                               "for DV-NTSC!");
586                         return;
587                         
588                 }
589                 if (G.scene->r.frs_sec == 25 && recty != 576) {
590                         G.afbreek = 1;
591                         error("Render height has to be 576 pixels "
592                               "for DV-PAL!");
593                         return;
594                 }
595         }
596         if (ffmpeg_type == FFMPEG_DV) {
597                 fmt->audio_codec = CODEC_ID_PCM_S16LE;
598                 if (ffmpeg_multiplex_audio 
599                     && G.scene->audio.mixrate != 48000) {
600                         G.afbreek = 1;
601                         error("FFMPEG only supports 48khz / stereo "
602                               "audio for DV!");
603                         return;
604                 }
605         }
606         
607         video_stream = alloc_video_stream(fmt->video_codec, of, rectx, recty);
608         if (!video_stream) {
609                 G.afbreek = 1;
610                 error("Error initializing video stream");
611                 return;
612         }
613         
614         if (ffmpeg_multiplex_audio) {
615                 audio_stream = alloc_audio_stream(fmt->audio_codec, of);
616                 if (!audio_stream) {
617                         G.afbreek = 1;
618                         error("Error initializing audio stream");
619                         return;
620                 }
621                 audiostream_play(SFRA, 0, 1);
622         }
623         if (av_set_parameters(of, NULL) < 0) {
624                 G.afbreek = 1;
625                 error("Error setting output parameters");
626                 return;
627         }
628         if (!(fmt->flags & AVFMT_NOFILE)) {
629                 if (url_fopen(&of->pb, name, URL_WRONLY) < 0) {
630                         G.afbreek = 1;
631                         error("Could not open file for writing");
632                         return;
633                 }
634         }
635
636         av_write_header(of);
637         outfile = of;
638         dump_format(of, 0, name, 1);
639 }
640
641 /* **********************************************************************
642    * public interface
643    ********************************************************************** */
644
645 /* Get the output filename-- similar to the other output formats */
646 void makeffmpegstring(char* string) {
647         
648         char txt[FILE_MAXDIR+FILE_MAXFILE];
649         char autosplit[20];
650
651         const char ** exts = get_file_extensions(G.scene->r.ffcodecdata.type);
652         const char ** fe = exts;
653
654         if (!string || !exts) return;
655
656         strcpy(string, G.scene->r.pic);
657         BLI_convertstringcode(string, G.sce, G.scene->r.cfra);
658
659         BLI_make_existing_file(string);
660
661         autosplit[0] = 0;
662
663         if ((G.scene->r.ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT) != 0) {
664                 sprintf(autosplit, "_%03d", ffmpeg_autosplit_count);
665         }
666
667         while (*fe) {
668                 if (BLI_strcasecmp(string + strlen(string) - strlen(*fe), 
669                                    *fe) == 0) {
670                         break;
671                 }
672                 fe++;
673         }
674
675         if (!*fe) {
676                 strcat(string, autosplit);
677                 sprintf(txt, "%04d_%04d%s", (G.scene->r.sfra), 
678                         (G.scene->r.efra), *exts);
679                 strcat(string, txt);
680         } else {
681                 *(string + strlen(string) - strlen(*fe)) = 0;
682                 strcat(string, autosplit);
683                 strcat(string, *fe);
684         }
685 }
686
687
688 void start_ffmpeg(RenderData *rd, int rectx, int recty)
689 {
690         ffmpeg_autosplit_count = 0;
691
692         ffmpeg_renderdata = rd;
693
694         start_ffmpeg_impl(rd, rectx, recty);
695 }
696
697 void end_ffmpeg(void);
698
699 void append_ffmpeg(int frame, int *pixels, int rectx, int recty) 
700 {
701         fprintf(stderr, "Writing frame %i, "
702                 "render width=%d, render height=%d\n", frame,
703                 rectx, recty);
704         while (ffmpeg_multiplex_audio && 
705                (((double)audio_stream->pts.val 
706                  * audio_stream->time_base.num / audio_stream->time_base.den)
707                 < 
708                 ((double)video_stream->pts.val 
709                  * video_stream->time_base.num / video_stream->time_base.den)
710                        )) {
711                 write_audio_frame();
712         }
713         write_video_frame(generate_video_frame((unsigned char*) pixels));
714
715         if (ffmpeg_autosplit) {
716                 if (url_ftell(&outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) {
717                         end_ffmpeg();
718                         ffmpeg_autosplit_count++;
719                         start_ffmpeg_impl(ffmpeg_renderdata,
720                                           rectx, recty);
721                 }
722         }
723 }
724
725
726 void end_ffmpeg(void)
727 {
728         int i;
729         
730         fprintf(stderr, "Closing ffmpeg...\n");
731
732         if (outfile) {
733                 av_write_trailer(outfile);
734         }
735         
736         /* Close the video codec */
737
738         if (video_stream && get_codec_from_stream(video_stream)) {
739                 avcodec_close(get_codec_from_stream(video_stream));
740                 video_stream = 0;
741         }
742
743         
744         /* Close the output file */
745         if (outfile) {
746                 for (i = 0; i < outfile->nb_streams; i++) {
747                         if (&outfile->streams[i]) {
748                                 av_freep(&outfile->streams[i]);
749                         }
750                 }
751         }
752         /* free the temp buffer */
753         if (current_frame) {
754                 delete_picture(current_frame);
755                 current_frame = 0;
756         }
757         if (outfile && outfile->oformat) {
758                 if (!(outfile->oformat->flags & AVFMT_NOFILE)) {
759                         url_fclose(&outfile->pb);
760                 }
761         }
762         if (outfile) {
763                 av_free(outfile);
764                 outfile = 0;
765         }
766         if (video_buffer) {
767                 MEM_freeN(video_buffer);
768                 video_buffer = 0;
769         }
770         if (audio_output_buffer) {
771                 MEM_freeN(audio_output_buffer);
772                 audio_output_buffer = 0;
773         }
774         if (audio_input_buffer) {
775                 MEM_freeN(audio_input_buffer);
776                 audio_input_buffer = 0;
777         }
778 }
779 #endif
780