Blender V2.61 - r43446

writeffmpeg.c

Go to the documentation of this file.
00001 /*
00002  *
00003  * ffmpeg-write support
00004  *
00005  * Partial Copyright (c) 2006 Peter Schlaile
00006  *
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  */
00018 
00023 #ifdef WITH_FFMPEG
00024 #include <string.h>
00025 #include <stdio.h>
00026 
00027 #if defined(_WIN32) && defined(DEBUG) && !defined(__MINGW32__) && !defined(__CYGWIN__)
00028 /* This does not seem necessary or present on MSVC 8, but may be needed in earlier versions? */
00029 #if _MSC_VER < 1400
00030 #include <stdint.h>
00031 #endif
00032 #endif
00033 
00034 #include <stdlib.h>
00035 
00036 #include <libavformat/avformat.h>
00037 #include <libavcodec/avcodec.h>
00038 #include <libavutil/rational.h>
00039 #include <libswscale/swscale.h>
00040 #include <libavcodec/opt.h>
00041 
00042 #include "MEM_guardedalloc.h"
00043 
00044 #include "DNA_scene_types.h"
00045 
00046 #include "BLI_blenlib.h"
00047 
00048 #ifdef WITH_AUDASPACE
00049 #  include "AUD_C-API.h"
00050 #endif
00051 
00052 #include "BKE_global.h"
00053 #include "BKE_idprop.h"
00054 #include "BKE_main.h"
00055 #include "BKE_report.h"
00056 #include "BKE_sound.h"
00057 #include "BKE_writeffmpeg.h"
00058 
00059 #include "IMB_imbuf_types.h"
00060 #include "IMB_imbuf.h"
00061 
00062 #include "ffmpeg_compat.h"
00063 
00064 extern void do_init_ffmpeg(void);
00065 
00066 static int ffmpeg_type = 0;
00067 static int ffmpeg_codec = CODEC_ID_MPEG4;
00068 static int ffmpeg_audio_codec = CODEC_ID_NONE;
00069 static int ffmpeg_video_bitrate = 1150;
00070 static int ffmpeg_audio_bitrate = 128;
00071 static int ffmpeg_gop_size = 12;
00072 static int ffmpeg_autosplit = 0;
00073 static int ffmpeg_autosplit_count = 0;
00074 
00075 static AVFormatContext* outfile = 0;
00076 static AVStream* video_stream = 0;
00077 static AVStream* audio_stream = 0;
00078 static AVFrame* current_frame = 0;
00079 static struct SwsContext *img_convert_ctx = 0;
00080 
00081 static uint8_t* video_buffer = 0;
00082 static int video_buffersize = 0;
00083 
00084 static uint8_t* audio_input_buffer = 0;
00085 static int audio_input_samples = 0;
00086 static uint8_t* audio_output_buffer = 0;
00087 static int audio_outbuf_size = 0;
00088 static double audio_time = 0.0f;
00089 
00090 #ifdef WITH_AUDASPACE
00091 static AUD_Device* audio_mixdown_device = 0;
00092 #endif
00093 
00094 #define FFMPEG_AUTOSPLIT_SIZE 2000000000
00095 
00096 /* Delete a picture buffer */
00097 
00098 static void delete_picture(AVFrame* f)
00099 {
00100     if (f) {
00101         if (f->data[0]) MEM_freeN(f->data[0]);
00102         av_free(f);
00103     }
00104 }
00105 
00106 #ifdef WITH_AUDASPACE
00107 static int write_audio_frame(void) 
00108 {
00109     AVCodecContext* c = NULL;
00110     AVPacket pkt;
00111 
00112     c = audio_stream->codec;
00113 
00114     av_init_packet(&pkt);
00115     pkt.size = 0;
00116 
00117     AUD_readDevice(audio_mixdown_device, audio_input_buffer, audio_input_samples);
00118     audio_time += (double) audio_input_samples / (double) c->sample_rate;
00119 
00120     pkt.size = avcodec_encode_audio(c, audio_output_buffer,
00121                     audio_outbuf_size,
00122                     (short*) audio_input_buffer);
00123 
00124     if(pkt.size < 0)
00125     {
00126         // XXX error("Error writing audio packet");
00127         return -1;
00128     }
00129 
00130     pkt.data = audio_output_buffer;
00131 
00132     if(c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE)
00133     {
00134         pkt.pts = av_rescale_q(c->coded_frame->pts,
00135                        c->time_base, audio_stream->time_base);
00136         fprintf(stderr, "Audio Frame PTS: %d\n", (int)pkt.pts);
00137     }
00138 
00139     pkt.stream_index = audio_stream->index;
00140 
00141     pkt.flags |= AV_PKT_FLAG_KEY;
00142 
00143     if (av_interleaved_write_frame(outfile, &pkt) != 0) {
00144         fprintf(stderr, "Error writing audio packet!\n");
00145         return -1;
00146     }
00147     return 0;
00148 }
00149 #endif // #ifdef WITH_AUDASPACE
00150 
00151 /* Allocate a temporary frame */
00152 static AVFrame* alloc_picture(int pix_fmt, int width, int height) 
00153 {
00154     AVFrame* f;
00155     uint8_t* buf;
00156     int size;
00157     
00158     /* allocate space for the struct */
00159     f = avcodec_alloc_frame();
00160     if (!f) return NULL;
00161     size = avpicture_get_size(pix_fmt, width, height);
00162     /* allocate the actual picture buffer */
00163     buf = MEM_mallocN(size, "AVFrame buffer");
00164     if (!buf) {
00165         free(f);
00166         return NULL;
00167     }
00168     avpicture_fill((AVPicture*)f, buf, pix_fmt, width, height);
00169     return f;
00170 }
00171 
00172 /* Get the correct file extensions for the requested format,
00173    first is always desired guess_format parameter */
00174 static const char** get_file_extensions(int format) 
00175 {
00176     switch(format) {
00177     case FFMPEG_DV: {
00178         static const char * rv[] = { ".dv", NULL };
00179         return rv;
00180     }
00181     case FFMPEG_MPEG1: {
00182         static const char * rv[] = { ".mpg", ".mpeg", NULL };
00183         return rv;
00184     }
00185     case FFMPEG_MPEG2: {
00186         static const char * rv[] = { ".dvd", ".vob", ".mpg", ".mpeg",
00187                          NULL };
00188         return rv;
00189     }
00190     case FFMPEG_MPEG4: {
00191         static const char * rv[] = { ".mp4", ".mpg", ".mpeg", NULL };
00192         return rv;
00193     }
00194     case FFMPEG_AVI: {
00195         static const char * rv[] = { ".avi", NULL };
00196         return rv;
00197     }
00198     case FFMPEG_MOV: {
00199         static const char * rv[] = { ".mov", NULL };
00200         return rv;
00201     }
00202     case FFMPEG_H264: {
00203         /* FIXME: avi for now... */
00204         static const char * rv[] = { ".avi", NULL };
00205         return rv;
00206     }
00207 
00208     case FFMPEG_XVID: {
00209         /* FIXME: avi for now... */
00210         static const char * rv[] = { ".avi", NULL };
00211         return rv;
00212     }
00213     case FFMPEG_FLV: {
00214         static const char * rv[] = { ".flv", NULL };
00215         return rv;
00216     }
00217     case FFMPEG_MKV: {
00218         static const char * rv[] = { ".mkv", NULL };
00219         return rv;
00220     }
00221     case FFMPEG_OGG: {
00222         static const char * rv[] = { ".ogg", ".ogv", NULL };
00223         return rv;
00224     }
00225     case FFMPEG_MP3: {
00226         static const char * rv[] = { ".mp3", NULL };
00227         return rv;
00228     }
00229     case FFMPEG_WAV: {
00230         static const char * rv[] = { ".wav", NULL };
00231         return rv;
00232     }
00233     default:
00234         return NULL;
00235     }
00236 }
00237 
00238 /* Write a frame to the output file */
00239 static int write_video_frame(RenderData *rd, int cfra, AVFrame* frame, ReportList *reports)
00240 {
00241     int outsize = 0;
00242     int ret, success= 1;
00243     AVCodecContext* c = video_stream->codec;
00244 
00245     frame->pts = cfra;
00246 
00247     if (rd->mode & R_FIELDS) {
00248         frame->top_field_first = ((rd->mode & R_ODDFIELD) != 0);
00249     }
00250 
00251     outsize = avcodec_encode_video(c, video_buffer, video_buffersize, 
00252                        frame);
00253     if (outsize != 0) {
00254         AVPacket packet;
00255         av_init_packet(&packet);
00256 
00257         if (c->coded_frame->pts != AV_NOPTS_VALUE) {
00258             packet.pts = av_rescale_q(c->coded_frame->pts,
00259                           c->time_base,
00260                           video_stream->time_base);
00261             fprintf(stderr, "Video Frame PTS: %d\n", (int)packet.pts);
00262         } else {
00263             fprintf(stderr, "Video Frame PTS: not set\n");
00264         }
00265         if (c->coded_frame->key_frame)
00266             packet.flags |= AV_PKT_FLAG_KEY;
00267         packet.stream_index = video_stream->index;
00268         packet.data = video_buffer;
00269         packet.size = outsize;
00270         ret = av_interleaved_write_frame(outfile, &packet);
00271     } else {
00272         ret = 0;
00273     }
00274 
00275     if (ret != 0) {
00276         success= 0;
00277         BKE_report(reports, RPT_ERROR, "Error writing frame.");
00278     }
00279 
00280     return success;
00281 }
00282 
00283 /* read and encode a frame of audio from the buffer */
00284 static AVFrame* generate_video_frame(uint8_t* pixels, ReportList *reports) 
00285 {
00286     uint8_t* rendered_frame;
00287 
00288     AVCodecContext* c = video_stream->codec;
00289     int width = c->width;
00290     int height = c->height;
00291     AVFrame* rgb_frame;
00292 
00293     if (c->pix_fmt != PIX_FMT_BGR32) {
00294         rgb_frame = alloc_picture(PIX_FMT_BGR32, width, height);
00295         if (!rgb_frame) {
00296             BKE_report(reports, RPT_ERROR, "Couldn't allocate temporary frame.");
00297             return NULL;
00298         }
00299     } else {
00300         rgb_frame = current_frame;
00301     }
00302 
00303     rendered_frame = pixels;
00304 
00305     /* Do RGBA-conversion and flipping in one step depending
00306        on CPU-Endianess */
00307 
00308     if (ENDIAN_ORDER == L_ENDIAN) {
00309         int y;
00310         for (y = 0; y < height; y++) {
00311             uint8_t* target = rgb_frame->data[0]
00312                 + width * 4 * (height - y - 1);
00313             uint8_t* src = rendered_frame + width * 4 * y;
00314             uint8_t* end = src + width * 4;
00315             while (src != end) {
00316                 target[3] = src[3];
00317                 target[2] = src[2];
00318                 target[1] = src[1];
00319                 target[0] = src[0];
00320 
00321                 target += 4;
00322                 src += 4;
00323             }
00324         }
00325     } else {
00326         int y;
00327         for (y = 0; y < height; y++) {
00328             uint8_t* target = rgb_frame->data[0]
00329                 + width * 4 * (height - y - 1);
00330             uint8_t* src = rendered_frame + width * 4 * y;
00331             uint8_t* end = src + width * 4;
00332             while (src != end) {
00333                 target[3] = src[0];
00334                 target[2] = src[1];
00335                 target[1] = src[2];
00336                 target[0] = src[3];
00337 
00338                 target += 4;
00339                 src += 4;
00340             }
00341         }
00342     }
00343 
00344     if (c->pix_fmt != PIX_FMT_BGR32) {
00345         sws_scale(img_convert_ctx, (const uint8_t * const*) rgb_frame->data,
00346                   rgb_frame->linesize, 0, c->height,
00347                   current_frame->data, current_frame->linesize);
00348         delete_picture(rgb_frame);
00349     }
00350     return current_frame;
00351 }
00352 
00353 static void set_ffmpeg_property_option(AVCodecContext* c, IDProperty * prop)
00354 {
00355     char name[128];
00356     char * param;
00357     const AVOption * rv = NULL;
00358 
00359     fprintf(stderr, "FFMPEG expert option: %s: ", prop->name);
00360 
00361     BLI_strncpy(name, prop->name, sizeof(name));
00362 
00363     param = strchr(name, ':');
00364 
00365     if (param) {
00366         *param++ = 0;
00367     }
00368 
00369     switch(prop->type) {
00370     case IDP_STRING:
00371         fprintf(stderr, "%s.\n", IDP_String(prop));
00372         av_set_string3(c, prop->name, IDP_String(prop), 1, &rv);
00373         break;
00374     case IDP_FLOAT:
00375         fprintf(stderr, "%g.\n", IDP_Float(prop));
00376         rv = av_set_double(c, prop->name, IDP_Float(prop));
00377         break;
00378     case IDP_INT:
00379         fprintf(stderr, "%d.\n", IDP_Int(prop));
00380         
00381         if (param) {
00382             if (IDP_Int(prop)) {
00383                 av_set_string3(c, name, param, 1, &rv);
00384             } else {
00385                 return;
00386             }
00387         } else {
00388             rv = av_set_int(c, prop->name, IDP_Int(prop));
00389         }
00390         break;
00391     }
00392 
00393     if (!rv) {
00394         fprintf(stderr, "ffmpeg-option not supported: %s! Skipping.\n",
00395             prop->name);
00396     }
00397 }
00398 
00399 static int ffmpeg_proprty_valid(AVCodecContext *c, const char *prop_name, IDProperty *curr)
00400 {
00401     int valid= 1;
00402 
00403     if(strcmp(prop_name, "video")==0) {
00404         if(strcmp(curr->name, "bf")==0) {
00405             /* flash codec doesn't support b frames */
00406             valid&= c->codec_id!=CODEC_ID_FLV1;
00407         }
00408     }
00409 
00410     return valid;
00411 }
00412 
00413 static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char * prop_name)
00414 {
00415     IDProperty * prop;
00416     void * iter;
00417     IDProperty * curr;
00418 
00419     if (!rd->ffcodecdata.properties) {
00420         return;
00421     }
00422     
00423     prop = IDP_GetPropertyFromGroup(rd->ffcodecdata.properties, prop_name);
00424     if (!prop) {
00425         return;
00426     }
00427 
00428     iter = IDP_GetGroupIterator(prop);
00429 
00430     while ((curr = IDP_GroupIterNext(iter)) != NULL) {
00431         if(ffmpeg_proprty_valid(c, prop_name, curr))
00432             set_ffmpeg_property_option(c, curr);
00433     }
00434 }
00435 
00436 /* prepare a video stream for the output file */
00437 
00438 static AVStream* alloc_video_stream(RenderData *rd, int codec_id, AVFormatContext* of,
00439                     int rectx, int recty) 
00440 {
00441     AVStream* st;
00442     AVCodecContext* c;
00443     AVCodec* codec;
00444     st = av_new_stream(of, 0);
00445     if (!st) return NULL;
00446 
00447     /* Set up the codec context */
00448     
00449     c = st->codec;
00450     c->codec_id = codec_id;
00451     c->codec_type = AVMEDIA_TYPE_VIDEO;
00452 
00453 
00454     /* Get some values from the current render settings */
00455     
00456     c->width = rectx;
00457     c->height = recty;
00458 
00459     /* FIXME: Really bad hack (tm) for NTSC support */
00460     if (ffmpeg_type == FFMPEG_DV && rd->frs_sec != 25) {
00461         c->time_base.den = 2997;
00462         c->time_base.num = 100;
00463     } else if ((double) ((int) rd->frs_sec_base) == 
00464            rd->frs_sec_base) {
00465         c->time_base.den = rd->frs_sec;
00466         c->time_base.num = (int) rd->frs_sec_base;
00467     } else {
00468         c->time_base.den = rd->frs_sec * 100000;
00469         c->time_base.num = ((double) rd->frs_sec_base) * 100000;
00470     }
00471     
00472     c->gop_size = ffmpeg_gop_size;
00473     c->bit_rate = ffmpeg_video_bitrate*1000;
00474     c->rc_max_rate = rd->ffcodecdata.rc_max_rate*1000;
00475     c->rc_min_rate = rd->ffcodecdata.rc_min_rate*1000;
00476     c->rc_buffer_size = rd->ffcodecdata.rc_buffer_size * 1024;
00477     c->rc_initial_buffer_occupancy 
00478         = rd->ffcodecdata.rc_buffer_size*3/4;
00479     c->rc_buffer_aggressivity = 1.0;
00480     c->me_method = ME_EPZS;
00481     
00482     codec = avcodec_find_encoder(c->codec_id);
00483     if (!codec) return NULL;
00484     
00485     /* Be sure to use the correct pixel format(e.g. RGB, YUV) */
00486     
00487     if (codec->pix_fmts) {
00488         c->pix_fmt = codec->pix_fmts[0];
00489     } else {
00490         /* makes HuffYUV happy ... */
00491         c->pix_fmt = PIX_FMT_YUV422P;
00492     }
00493 
00494     if (ffmpeg_type == FFMPEG_XVID) {
00495         /* arghhhh ... */
00496         c->pix_fmt = PIX_FMT_YUV420P;
00497         c->codec_tag = (('D'<<24) + ('I'<<16) + ('V'<<8) + 'X');
00498     }
00499 
00500     if (codec_id == CODEC_ID_H264) {
00501         /* correct wrong default ffmpeg param which crash x264 */
00502         c->qmin=10;
00503         c->qmax=51;
00504     }
00505     
00506     // Keep lossless encodes in the RGB domain.
00507     if (codec_id == CODEC_ID_HUFFYUV || codec_id == CODEC_ID_FFV1) {
00508         /* HUFFYUV was PIX_FMT_YUV422P before */
00509         c->pix_fmt = PIX_FMT_RGB32;
00510     }
00511 
00512     if ((of->oformat->flags & AVFMT_GLOBALHEADER)
00513 //      || !strcmp(of->oformat->name, "mp4")
00514 //      || !strcmp(of->oformat->name, "mov")
00515 //      || !strcmp(of->oformat->name, "3gp")
00516         ) {
00517         fprintf(stderr, "Using global header\n");
00518         c->flags |= CODEC_FLAG_GLOBAL_HEADER;
00519     }
00520     
00521     /* Determine whether we are encoding interlaced material or not */
00522     if (rd->mode & R_FIELDS) {
00523         fprintf(stderr, "Encoding interlaced video\n");
00524         c->flags |= CODEC_FLAG_INTERLACED_DCT;
00525         c->flags |= CODEC_FLAG_INTERLACED_ME;
00526     }
00527 
00528     /* xasp & yasp got float lately... */
00529 
00530     st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q(
00531         ((double) rd->xasp / (double) rd->yasp), 255);
00532 
00533     set_ffmpeg_properties(rd, c, "video");
00534     
00535     if (avcodec_open(c, codec) < 0) {
00536         //
00537         //XXX error("Couldn't initialize codec");
00538         return NULL;
00539     }
00540 
00541     video_buffersize = avpicture_get_size(c->pix_fmt, c->width, c->height);
00542     video_buffer = (uint8_t*)MEM_mallocN(video_buffersize*sizeof(uint8_t),
00543                          "FFMPEG video buffer");
00544     
00545     current_frame = alloc_picture(c->pix_fmt, c->width, c->height);
00546 
00547     img_convert_ctx = sws_getContext(c->width, c->height,
00548                      PIX_FMT_BGR32,
00549                      c->width, c->height,
00550                      c->pix_fmt,
00551                      SWS_BICUBIC,
00552                      NULL, NULL, NULL);
00553     return st;
00554 }
00555 
00556 /* Prepare an audio stream for the output file */
00557 
00558 static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContext* of) 
00559 {
00560     AVStream* st;
00561     AVCodecContext* c;
00562     AVCodec* codec;
00563 
00564     st = av_new_stream(of, 1);
00565     if (!st) return NULL;
00566 
00567     c = st->codec;
00568     c->codec_id = codec_id;
00569     c->codec_type = AVMEDIA_TYPE_AUDIO;
00570 
00571     c->sample_rate = rd->ffcodecdata.audio_mixrate;
00572     c->bit_rate = ffmpeg_audio_bitrate*1000;
00573     c->sample_fmt = SAMPLE_FMT_S16;
00574     c->channels = rd->ffcodecdata.audio_channels;
00575     codec = avcodec_find_encoder(c->codec_id);
00576     if (!codec) {
00577         //XXX error("Couldn't find a valid audio codec");
00578         return NULL;
00579     }
00580 
00581     set_ffmpeg_properties(rd, c, "audio");
00582 
00583     if (avcodec_open(c, codec) < 0) {
00584         //XXX error("Couldn't initialize audio codec");
00585         return NULL;
00586     }
00587 
00588     /* need to prevent floating point exception when using vorbis audio codec,
00589        initialize this value in the same way as it's done in FFmpeg iteslf (sergey) */
00590     st->codec->time_base.num= 1;
00591     st->codec->time_base.den= st->codec->sample_rate;
00592 
00593     audio_outbuf_size = FF_MIN_BUFFER_SIZE;
00594 
00595     if((c->codec_id >= CODEC_ID_PCM_S16LE) && (c->codec_id <= CODEC_ID_PCM_DVD))
00596         audio_input_samples = audio_outbuf_size * 8 / c->bits_per_coded_sample / c->channels;
00597     else
00598     {
00599         audio_input_samples = c->frame_size;
00600         if(c->frame_size * c->channels * sizeof(int16_t) * 4 > audio_outbuf_size)
00601             audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4;
00602     }
00603 
00604     audio_output_buffer = (uint8_t*)av_malloc(
00605         audio_outbuf_size);
00606 
00607     audio_input_buffer = (uint8_t*)av_malloc(
00608         audio_input_samples * c->channels * sizeof(int16_t));
00609 
00610     audio_time = 0.0f;
00611 
00612     return st;
00613 }
00614 /* essential functions -- start, append, end */
00615 
00616 static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, ReportList *reports)
00617 {
00618     /* Handle to the output file */
00619     AVFormatContext* of;
00620     AVOutputFormat* fmt;
00621     char name[256];
00622     const char ** exts;
00623 
00624     ffmpeg_type = rd->ffcodecdata.type;
00625     ffmpeg_codec = rd->ffcodecdata.codec;
00626     ffmpeg_audio_codec = rd->ffcodecdata.audio_codec;
00627     ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate;
00628     ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate;
00629     ffmpeg_gop_size = rd->ffcodecdata.gop_size;
00630     ffmpeg_autosplit = rd->ffcodecdata.flags
00631         & FFMPEG_AUTOSPLIT_OUTPUT;
00632     
00633     do_init_ffmpeg();
00634 
00635     /* Determine the correct filename */
00636     filepath_ffmpeg(name, rd);
00637     fprintf(stderr, "Starting output to %s(ffmpeg)...\n"
00638         "  Using type=%d, codec=%d, audio_codec=%d,\n"
00639         "  video_bitrate=%d, audio_bitrate=%d,\n"
00640         "  gop_size=%d, autosplit=%d\n"
00641         "  render width=%d, render height=%d\n", 
00642         name, ffmpeg_type, ffmpeg_codec, ffmpeg_audio_codec,
00643         ffmpeg_video_bitrate, ffmpeg_audio_bitrate,
00644         ffmpeg_gop_size, ffmpeg_autosplit, rectx, recty);
00645     
00646     exts = get_file_extensions(ffmpeg_type);
00647     if (!exts) {
00648         BKE_report(reports, RPT_ERROR, "No valid formats found.");
00649         return 0;
00650     }
00651     fmt = av_guess_format(NULL, exts[0], NULL);
00652     if (!fmt) {
00653         BKE_report(reports, RPT_ERROR, "No valid formats found.");
00654         return 0;
00655     }
00656 
00657     of = avformat_alloc_context();
00658     if (!of) {
00659         BKE_report(reports, RPT_ERROR, "Error opening output file");
00660         return 0;
00661     }
00662     
00663     of->oformat = fmt;
00664     of->packet_size= rd->ffcodecdata.mux_packet_size;
00665     if (ffmpeg_audio_codec != CODEC_ID_NONE) {
00666         of->mux_rate = rd->ffcodecdata.mux_rate;
00667     } else {
00668         of->mux_rate = 0;
00669     }
00670 
00671     of->preload = (int)(0.5*AV_TIME_BASE);
00672     of->max_delay = (int)(0.7*AV_TIME_BASE);
00673 
00674     fmt->audio_codec = ffmpeg_audio_codec;
00675 
00676     BLI_snprintf(of->filename, sizeof(of->filename), "%s", name);
00677     /* set the codec to the user's selection */
00678     switch(ffmpeg_type) {
00679     case FFMPEG_AVI:
00680     case FFMPEG_MOV:
00681     case FFMPEG_MKV:
00682         fmt->video_codec = ffmpeg_codec;
00683         break;
00684     case FFMPEG_OGG:
00685         fmt->video_codec = CODEC_ID_THEORA;
00686         break;
00687     case FFMPEG_DV:
00688         fmt->video_codec = CODEC_ID_DVVIDEO;
00689         break;
00690     case FFMPEG_MPEG1:
00691         fmt->video_codec = CODEC_ID_MPEG1VIDEO;
00692         break;
00693     case FFMPEG_MPEG2:
00694         fmt->video_codec = CODEC_ID_MPEG2VIDEO;
00695         break;
00696     case FFMPEG_H264:
00697         fmt->video_codec = CODEC_ID_H264;
00698         break;
00699     case FFMPEG_XVID:
00700         fmt->video_codec = CODEC_ID_MPEG4;
00701         break;
00702     case FFMPEG_FLV:
00703         fmt->video_codec = CODEC_ID_FLV1;
00704         break;
00705     case FFMPEG_MP3:
00706         fmt->audio_codec = CODEC_ID_MP3;
00707     case FFMPEG_WAV:
00708         fmt->video_codec = CODEC_ID_NONE;
00709         break;
00710     case FFMPEG_MPEG4:
00711     default:
00712         fmt->video_codec = CODEC_ID_MPEG4;
00713         break;
00714     }
00715     if (fmt->video_codec == CODEC_ID_DVVIDEO) {
00716         if (rectx != 720) {
00717             BKE_report(reports, RPT_ERROR, "Render width has to be 720 pixels for DV!");
00718             return 0;
00719         }
00720         if (rd->frs_sec != 25 && recty != 480) {
00721             BKE_report(reports, RPT_ERROR, "Render height has to be 480 pixels for DV-NTSC!");
00722             return 0;
00723         }
00724         if (rd->frs_sec == 25 && recty != 576) {
00725             BKE_report(reports, RPT_ERROR, "Render height has to be 576 pixels for DV-PAL!");
00726             return 0;
00727         }
00728     }
00729     
00730     if (ffmpeg_type == FFMPEG_DV) {
00731         fmt->audio_codec = CODEC_ID_PCM_S16LE;
00732         if (ffmpeg_audio_codec != CODEC_ID_NONE && rd->ffcodecdata.audio_mixrate != 48000 && rd->ffcodecdata.audio_channels != 2) {
00733             BKE_report(reports, RPT_ERROR, "FFMPEG only supports 48khz / stereo audio for DV!");
00734             return 0;
00735         }
00736     }
00737     
00738     if (fmt->video_codec != CODEC_ID_NONE) {
00739         video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty);
00740         printf("alloc video stream %p\n", video_stream);
00741         if (!video_stream) {
00742             BKE_report(reports, RPT_ERROR, "Error initializing video stream.");
00743             return 0;
00744         }
00745     }
00746 
00747     if (ffmpeg_audio_codec != CODEC_ID_NONE) {
00748         audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of);
00749         if (!audio_stream) {
00750             BKE_report(reports, RPT_ERROR, "Error initializing audio stream.");
00751             return 0;
00752         }
00753     }
00754     if (av_set_parameters(of, NULL) < 0) {
00755         BKE_report(reports, RPT_ERROR, "Error setting output parameters.");
00756         return 0;
00757     }
00758     if (!(fmt->flags & AVFMT_NOFILE)) {
00759         if (avio_open(&of->pb, name, AVIO_FLAG_WRITE) < 0) {
00760             BKE_report(reports, RPT_ERROR, "Could not open file for writing.");
00761             return 0;
00762         }
00763     }
00764 
00765     if (av_write_header(of) < 0) {
00766         BKE_report(reports, RPT_ERROR, "Could not initialize streams. Probably unsupported codec combination.");
00767         return 0;
00768     }
00769 
00770     outfile = of;
00771     av_dump_format(of, 0, name, 1);
00772 
00773     return 1;
00774 }
00775 
00793 void flush_ffmpeg(void)
00794 {
00795     int outsize = 0;
00796     int ret = 0;
00797     
00798     AVCodecContext* c = video_stream->codec;
00799     /* get the delayed frames */
00800     while (1) {
00801         AVPacket packet;
00802         av_init_packet(&packet);
00803         
00804         outsize = avcodec_encode_video(c, video_buffer, video_buffersize, NULL);
00805         if (outsize < 0) {
00806             fprintf(stderr, "Error encoding delayed frame %d\n", outsize);
00807             break;
00808         }
00809         if (outsize == 0) {
00810             break;
00811         }
00812         if (c->coded_frame->pts != AV_NOPTS_VALUE) {
00813             packet.pts = av_rescale_q(c->coded_frame->pts,
00814                           c->time_base,
00815                           video_stream->time_base);
00816             fprintf(stderr, "Video Frame PTS: %d\n", (int)packet.pts);
00817         } else {
00818             fprintf(stderr, "Video Frame PTS: not set\n");
00819         }
00820         if (c->coded_frame->key_frame) {
00821             packet.flags |= AV_PKT_FLAG_KEY;
00822         }
00823         packet.stream_index = video_stream->index;
00824         packet.data = video_buffer;
00825         packet.size = outsize;
00826         ret = av_interleaved_write_frame(outfile, &packet);
00827         if (ret != 0) {
00828             fprintf(stderr, "Error writing delayed frame %d\n", ret);
00829             break;
00830         }
00831     }
00832     avcodec_flush_buffers(video_stream->codec);
00833 }
00834 
00835 /* **********************************************************************
00836    * public interface
00837    ********************************************************************** */
00838 
00839 /* Get the output filename-- similar to the other output formats */
00840 void filepath_ffmpeg(char* string, RenderData* rd)
00841 {
00842     char autosplit[20];
00843 
00844     const char ** exts = get_file_extensions(rd->ffcodecdata.type);
00845     const char ** fe = exts;
00846 
00847     if (!string || !exts) return;
00848 
00849     strcpy(string, rd->pic);
00850     BLI_path_abs(string, G.main->name);
00851 
00852     BLI_make_existing_file(string);
00853 
00854     autosplit[0] = 0;
00855 
00856     if ((rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT) != 0) {
00857         sprintf(autosplit, "_%03d", ffmpeg_autosplit_count);
00858     }
00859 
00860     while (*fe) {
00861         if (BLI_strcasecmp(string + strlen(string) - strlen(*fe), 
00862                    *fe) == 0) {
00863             break;
00864         }
00865         fe++;
00866     }
00867 
00868     if (!*fe) {
00869         strcat(string, autosplit);
00870 
00871         BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
00872         strcat(string, *exts);
00873     } else {
00874         *(string + strlen(string) - strlen(*fe)) = 0;
00875         strcat(string, autosplit);
00876         strcat(string, *fe);
00877     }
00878 }
00879 
00880 int start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports)
00881 {
00882     int success;
00883 
00884     ffmpeg_autosplit_count = 0;
00885 
00886     success = start_ffmpeg_impl(rd, rectx, recty, reports);
00887 #ifdef WITH_AUDASPACE
00888     if(audio_stream)
00889     {
00890         AVCodecContext* c = audio_stream->codec;
00891         AUD_DeviceSpecs specs;
00892         specs.channels = c->channels;
00893         specs.format = AUD_FORMAT_S16;
00894         specs.rate = rd->ffcodecdata.audio_mixrate;
00895         audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->ffcodecdata.audio_volume);
00896 #ifdef FFMPEG_CODEC_TIME_BASE
00897         c->time_base.den = specs.rate;
00898         c->time_base.num = 1;
00899 #endif
00900     }
00901 #endif
00902     return success;
00903 }
00904 
00905 void end_ffmpeg(void);
00906 
00907 #ifdef WITH_AUDASPACE
00908 static void write_audio_frames(double to_pts)
00909 {
00910     int finished = 0;
00911 
00912     while (audio_stream && !finished) {
00913         if((audio_time >= to_pts) ||
00914            (write_audio_frame())) {
00915             finished = 1;
00916         }
00917     }
00918 }
00919 #endif
00920 
00921 int append_ffmpeg(RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, ReportList *reports)
00922 {
00923     AVFrame* avframe;
00924     int success = 1;
00925 
00926     fprintf(stderr, "Writing frame %i, "
00927         "render width=%d, render height=%d\n", frame,
00928         rectx, recty);
00929 
00930 // why is this done before writing the video frame and again at end_ffmpeg?
00931 //  write_audio_frames(frame / (((double)rd->frs_sec) / rd->frs_sec_base));
00932 
00933     if(video_stream)
00934     {
00935         avframe= generate_video_frame((unsigned char*) pixels, reports);
00936         success= (avframe && write_video_frame(rd, frame - start_frame, avframe, reports));
00937 
00938         if (ffmpeg_autosplit) {
00939             if (avio_tell(outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) {
00940                 end_ffmpeg();
00941                 ffmpeg_autosplit_count++;
00942                 success &= start_ffmpeg_impl(rd, rectx, recty, reports);
00943             }
00944         }
00945     }
00946 
00947 #ifdef WITH_AUDASPACE
00948     write_audio_frames((frame - rd->sfra) / (((double)rd->frs_sec) / rd->frs_sec_base));
00949 #endif
00950     return success;
00951 }
00952 
00953 void end_ffmpeg(void)
00954 {
00955     unsigned int i;
00956     
00957     fprintf(stderr, "Closing ffmpeg...\n");
00958 
00959 /*  if (audio_stream) { SEE UPPER
00960         write_audio_frames();
00961     }*/
00962 
00963 #ifdef WITH_AUDASPACE
00964     if(audio_mixdown_device)
00965     {
00966         AUD_closeReadDevice(audio_mixdown_device);
00967         audio_mixdown_device = 0;
00968     }
00969 #endif
00970 
00971     if (video_stream && video_stream->codec) {
00972         fprintf(stderr, "Flushing delayed frames...\n");
00973         flush_ffmpeg ();        
00974     }
00975     
00976     if (outfile) {
00977         av_write_trailer(outfile);
00978     }
00979     
00980     /* Close the video codec */
00981 
00982     if (video_stream && video_stream->codec) {
00983         avcodec_close(video_stream->codec);
00984         printf("zero video stream %p\n", video_stream);
00985         video_stream = 0;
00986     }
00987 
00988     
00989     /* Close the output file */
00990     if (outfile) {
00991         for (i = 0; i < outfile->nb_streams; i++) {
00992             if (&outfile->streams[i]) {
00993                 av_freep(&outfile->streams[i]);
00994             }
00995         }
00996     }
00997     /* free the temp buffer */
00998     if (current_frame) {
00999         delete_picture(current_frame);
01000         current_frame = 0;
01001     }
01002     if (outfile && outfile->oformat) {
01003         if (!(outfile->oformat->flags & AVFMT_NOFILE)) {
01004             avio_close(outfile->pb);
01005         }
01006     }
01007     if (outfile) {
01008         av_free(outfile);
01009         outfile = 0;
01010     }
01011     if (video_buffer) {
01012         MEM_freeN(video_buffer);
01013         video_buffer = 0;
01014     }
01015     if (audio_output_buffer) {
01016         av_free(audio_output_buffer);
01017         audio_output_buffer = 0;
01018     }
01019     if (audio_input_buffer) {
01020         av_free(audio_input_buffer);
01021         audio_input_buffer = 0;
01022     }
01023 
01024     if (img_convert_ctx) {
01025         sws_freeContext(img_convert_ctx);
01026         img_convert_ctx = 0;
01027     }
01028 }
01029 
01030 /* properties */
01031 
01032 void ffmpeg_property_del(RenderData *rd, void *type, void *prop_)
01033 {
01034     struct IDProperty *prop = (struct IDProperty *) prop_;
01035     IDProperty * group;
01036     
01037     if (!rd->ffcodecdata.properties) {
01038         return;
01039     }
01040 
01041     group = IDP_GetPropertyFromGroup(rd->ffcodecdata.properties, type);
01042     if (group && prop) {
01043         IDP_RemFromGroup(group, prop);
01044         IDP_FreeProperty(prop);
01045         MEM_freeN(prop);
01046     }
01047 }
01048 
01049 IDProperty *ffmpeg_property_add(RenderData *rd, const char *type, int opt_index, int parent_index)
01050 {
01051     AVCodecContext c;
01052     const AVOption * o;
01053     const AVOption * parent;
01054     IDProperty * group;
01055     IDProperty * prop;
01056     IDPropertyTemplate val;
01057     int idp_type;
01058     char name[256];
01059     
01060     val.i = 0;
01061 
01062     avcodec_get_context_defaults(&c);
01063 
01064     o = c.av_class->option + opt_index;
01065     parent = c.av_class->option + parent_index;
01066 
01067     if (!rd->ffcodecdata.properties) {
01068         rd->ffcodecdata.properties 
01069             = IDP_New(IDP_GROUP, &val, "ffmpeg"); 
01070     }
01071 
01072     group = IDP_GetPropertyFromGroup(rd->ffcodecdata.properties, type);
01073     
01074     if (!group) {
01075         group = IDP_New(IDP_GROUP, &val, type);
01076         IDP_AddToGroup(rd->ffcodecdata.properties, group);
01077     }
01078 
01079     if (parent_index) {
01080         BLI_snprintf(name, sizeof(name), "%s:%s", parent->name, o->name);
01081     } else {
01082         BLI_strncpy(name, o->name, sizeof(name));
01083     }
01084 
01085     fprintf(stderr, "ffmpeg_property_add: %s %d %d %s\n",
01086         type, parent_index, opt_index, name);
01087 
01088     prop = IDP_GetPropertyFromGroup(group, name);
01089     if (prop) {
01090         return prop;
01091     }
01092 
01093     switch (o->type) {
01094     case FF_OPT_TYPE_INT:
01095     case FF_OPT_TYPE_INT64:
01096         val.i = FFMPEG_DEF_OPT_VAL_INT(o);
01097         idp_type = IDP_INT;
01098         break;
01099     case FF_OPT_TYPE_DOUBLE:
01100     case FF_OPT_TYPE_FLOAT:
01101         val.f = FFMPEG_DEF_OPT_VAL_DOUBLE(o);
01102         idp_type = IDP_FLOAT;
01103         break;
01104     case FF_OPT_TYPE_STRING:
01105         val.string.str = (char *)"                                                                               ";
01106         val.string.len = 80;
01107 /*      val.str = (char *)"                                                                               ";*/
01108         idp_type = IDP_STRING;
01109         break;
01110     case FF_OPT_TYPE_CONST:
01111         val.i = 1;
01112         idp_type = IDP_INT;
01113         break;
01114     default:
01115         return NULL;
01116     }
01117     prop = IDP_New(idp_type, &val, name);
01118     IDP_AddToGroup(group, prop);
01119     return prop;
01120 }
01121 
01122 /* not all versions of ffmpeg include that, so here we go ... */
01123 
01124 static const AVOption *my_av_find_opt(void *v, const char *name, 
01125                       const char *unit, int mask, int flags){
01126     AVClass *c= *(AVClass**)v; 
01127     const AVOption *o= c->option;
01128 
01129     for(;o && o->name; o++){
01130         if(!strcmp(o->name, name) && 
01131            (!unit || (o->unit && !strcmp(o->unit, unit))) && 
01132            (o->flags & mask) == flags )
01133             return o;
01134     }
01135     return NULL;
01136 }
01137 
01138 int ffmpeg_property_add_string(RenderData *rd, const char * type, const char * str)
01139 {
01140     AVCodecContext c;
01141     const AVOption * o = 0;
01142     const AVOption * p = 0;
01143     char name_[128];
01144     char * name;
01145     char * param;
01146     IDProperty * prop;
01147     
01148     avcodec_get_context_defaults(&c);
01149 
01150     strncpy(name_, str, sizeof(name_));
01151 
01152     name = name_;
01153     while (*name == ' ') name++;
01154 
01155     param = strchr(name, ':');
01156 
01157     if (!param) {
01158         param = strchr(name, ' ');
01159     }
01160     if (param) {
01161         *param++ = 0;
01162         while (*param == ' ') param++;
01163     }
01164     
01165     o = my_av_find_opt(&c, name, NULL, 0, 0);   
01166     if (!o) {
01167         return 0;
01168     }
01169     if (param && o->type == FF_OPT_TYPE_CONST) {
01170         return 0;
01171     }
01172     if (param && o->type != FF_OPT_TYPE_CONST && o->unit) {
01173         p = my_av_find_opt(&c, param, o->unit, 0, 0);   
01174         prop = ffmpeg_property_add(rd,
01175             (char*) type, p - c.av_class->option, 
01176             o - c.av_class->option);
01177     } else {
01178         prop = ffmpeg_property_add(rd,
01179             (char*) type, o - c.av_class->option, 0);
01180     }
01181         
01182 
01183     if (!prop) {
01184         return 0;
01185     }
01186 
01187     if (param && !p) {
01188         switch (prop->type) {
01189         case IDP_INT:
01190             IDP_Int(prop) = atoi(param);
01191             break;
01192         case IDP_FLOAT:
01193             IDP_Float(prop) = atof(param);
01194             break;
01195         case IDP_STRING:
01196             strncpy(IDP_String(prop), param, prop->len);
01197             break;
01198         }
01199     }
01200     return 1;
01201 }
01202 
01203 static void ffmpeg_set_expert_options(RenderData *rd, int preset)
01204 {
01205     if(rd->ffcodecdata.properties)
01206         IDP_FreeProperty(rd->ffcodecdata.properties);
01207 
01208     if(preset == FFMPEG_PRESET_H264) {
01209         /*
01210          * All options here are for x264, but must be set via ffmpeg.
01211          * The names are therefore different - Search for "x264 to FFmpeg option mapping"
01212          * to get a list.
01213          */
01214 
01215         /*
01216          * Use CABAC coder. Using "coder:1", which should be equivalent,
01217          * crashes Blender for some reason. Either way - this is no big deal.
01218          */
01219         ffmpeg_property_add_string(rd, "video", "coder:vlc");
01220 
01221         /*
01222          * The other options were taken from the libx264-default.preset
01223          * included in the ffmpeg distribution.
01224          */
01225         ffmpeg_property_add_string(rd, "video", "flags:loop");
01226         ffmpeg_property_add_string(rd, "video", "cmp:chroma");
01227         ffmpeg_property_add_string(rd, "video", "partitions:parti4x4");
01228         ffmpeg_property_add_string(rd, "video", "partitions:partp8x8");
01229         ffmpeg_property_add_string(rd, "video", "partitions:partb8x8");
01230         ffmpeg_property_add_string(rd, "video", "me:hex");
01231         ffmpeg_property_add_string(rd, "video", "subq:6");
01232         ffmpeg_property_add_string(rd, "video", "me_range:16");
01233         ffmpeg_property_add_string(rd, "video", "qdiff:4");
01234         ffmpeg_property_add_string(rd, "video", "keyint_min:25");
01235         ffmpeg_property_add_string(rd, "video", "sc_threshold:40");
01236         ffmpeg_property_add_string(rd, "video", "i_qfactor:0.71");
01237         ffmpeg_property_add_string(rd, "video", "b_strategy:1");
01238         ffmpeg_property_add_string(rd, "video", "bf:3");
01239         ffmpeg_property_add_string(rd, "video", "refs:2");
01240         ffmpeg_property_add_string(rd, "video", "qcomp:0.6");
01241         ffmpeg_property_add_string(rd, "video", "directpred:3");
01242         ffmpeg_property_add_string(rd, "video", "trellis:0");
01243         ffmpeg_property_add_string(rd, "video", "flags2:wpred");
01244         ffmpeg_property_add_string(rd, "video", "flags2:dct8x8");
01245         ffmpeg_property_add_string(rd, "video", "flags2:fastpskip");
01246         ffmpeg_property_add_string(rd, "video", "wpredp:2");
01247 
01248         if(rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT)
01249             ffmpeg_property_add_string(rd, "video", "cqp:0");
01250     }
01251 }
01252 
01253 void ffmpeg_set_preset(RenderData *rd, int preset)
01254 {
01255     int isntsc = (rd->frs_sec != 25);
01256 
01257     if(rd->ffcodecdata.properties)
01258         IDP_FreeProperty(rd->ffcodecdata.properties);
01259 
01260     switch (preset) {
01261     case FFMPEG_PRESET_VCD:
01262         rd->ffcodecdata.type = FFMPEG_MPEG1;
01263         rd->ffcodecdata.video_bitrate = 1150;
01264         rd->xsch = 352;
01265         rd->ysch = isntsc ? 240 : 288;
01266         rd->ffcodecdata.gop_size = isntsc ? 18 : 15;
01267         rd->ffcodecdata.rc_max_rate = 1150;
01268         rd->ffcodecdata.rc_min_rate = 1150;
01269         rd->ffcodecdata.rc_buffer_size = 40*8;
01270         rd->ffcodecdata.mux_packet_size = 2324;
01271         rd->ffcodecdata.mux_rate = 2352 * 75 * 8;
01272         break;
01273 
01274     case FFMPEG_PRESET_SVCD:
01275         rd->ffcodecdata.type = FFMPEG_MPEG2;
01276         rd->ffcodecdata.video_bitrate = 2040;
01277         rd->xsch = 480;
01278         rd->ysch = isntsc ? 480 : 576;
01279         rd->ffcodecdata.gop_size = isntsc ? 18 : 15;
01280         rd->ffcodecdata.rc_max_rate = 2516;
01281         rd->ffcodecdata.rc_min_rate = 0;
01282         rd->ffcodecdata.rc_buffer_size = 224*8;
01283         rd->ffcodecdata.mux_packet_size = 2324;
01284         rd->ffcodecdata.mux_rate = 0;
01285         break;
01286 
01287     case FFMPEG_PRESET_DVD:
01288         rd->ffcodecdata.type = FFMPEG_MPEG2;
01289         rd->ffcodecdata.video_bitrate = 6000;
01290 
01291         /* Don't set resolution, see [#21351]
01292          * rd->xsch = 720;
01293          * rd->ysch = isntsc ? 480 : 576; */
01294 
01295         rd->ffcodecdata.gop_size = isntsc ? 18 : 15;
01296         rd->ffcodecdata.rc_max_rate = 9000;
01297         rd->ffcodecdata.rc_min_rate = 0;
01298         rd->ffcodecdata.rc_buffer_size = 224*8;
01299         rd->ffcodecdata.mux_packet_size = 2048;
01300         rd->ffcodecdata.mux_rate = 10080000;
01301         break;
01302 
01303     case FFMPEG_PRESET_DV:
01304         rd->ffcodecdata.type = FFMPEG_DV;
01305         rd->xsch = 720;
01306         rd->ysch = isntsc ? 480 : 576;
01307         break;
01308 
01309     case FFMPEG_PRESET_H264:
01310         rd->ffcodecdata.type = FFMPEG_AVI;
01311         rd->ffcodecdata.codec = CODEC_ID_H264;
01312         rd->ffcodecdata.video_bitrate = 6000;
01313         rd->ffcodecdata.gop_size = isntsc ? 18 : 15;
01314         rd->ffcodecdata.rc_max_rate = 9000;
01315         rd->ffcodecdata.rc_min_rate = 0;
01316         rd->ffcodecdata.rc_buffer_size = 224*8;
01317         rd->ffcodecdata.mux_packet_size = 2048;
01318         rd->ffcodecdata.mux_rate = 10080000;
01319 
01320         ffmpeg_set_expert_options(rd, preset);
01321         break;
01322 
01323     case FFMPEG_PRESET_THEORA:
01324     case FFMPEG_PRESET_XVID:
01325         if(preset == FFMPEG_PRESET_XVID) {
01326             rd->ffcodecdata.type = FFMPEG_AVI;
01327             rd->ffcodecdata.codec = CODEC_ID_MPEG4;
01328         }
01329         else if(preset == FFMPEG_PRESET_THEORA) {
01330             rd->ffcodecdata.type = FFMPEG_OGG; // XXX broken
01331             rd->ffcodecdata.codec = CODEC_ID_THEORA;
01332         }
01333 
01334         rd->ffcodecdata.video_bitrate = 6000;
01335         rd->ffcodecdata.gop_size = isntsc ? 18 : 15;
01336         rd->ffcodecdata.rc_max_rate = 9000;
01337         rd->ffcodecdata.rc_min_rate = 0;
01338         rd->ffcodecdata.rc_buffer_size = 224*8;
01339         rd->ffcodecdata.mux_packet_size = 2048;
01340         rd->ffcodecdata.mux_rate = 10080000;
01341         break;
01342 
01343     }
01344 }
01345 
01346 void ffmpeg_verify_image_type(RenderData *rd, ImageFormatData *imf)
01347 {
01348     int audio= 0;
01349 
01350     if(imf->imtype == R_IMF_IMTYPE_FFMPEG) {
01351         if(rd->ffcodecdata.type <= 0 ||
01352            rd->ffcodecdata.codec <= 0 ||
01353            rd->ffcodecdata.audio_codec <= 0 ||
01354            rd->ffcodecdata.video_bitrate <= 1) {
01355 
01356             rd->ffcodecdata.codec = CODEC_ID_MPEG2VIDEO;
01357 
01358             ffmpeg_set_preset(rd, FFMPEG_PRESET_DVD);
01359         }
01360         if(rd->ffcodecdata.type == FFMPEG_OGG) {
01361             rd->ffcodecdata.type = FFMPEG_MPEG2;
01362         }
01363 
01364         audio= 1;
01365     }
01366     else if(imf->imtype == R_IMF_IMTYPE_H264) {
01367         if(rd->ffcodecdata.codec != CODEC_ID_H264) {
01368             ffmpeg_set_preset(rd, FFMPEG_PRESET_H264);
01369             audio= 1;
01370         }
01371     }
01372     else if(imf->imtype == R_IMF_IMTYPE_XVID) {
01373         if(rd->ffcodecdata.codec != CODEC_ID_MPEG4) {
01374             ffmpeg_set_preset(rd, FFMPEG_PRESET_XVID);
01375             audio= 1;
01376         }
01377     }
01378     else if(imf->imtype == R_IMF_IMTYPE_THEORA) {
01379         if(rd->ffcodecdata.codec != CODEC_ID_THEORA) {
01380             ffmpeg_set_preset(rd, FFMPEG_PRESET_THEORA);
01381             audio= 1;
01382         }
01383     }
01384 
01385     if(audio && rd->ffcodecdata.audio_codec < 0) {
01386         rd->ffcodecdata.audio_codec = CODEC_ID_NONE;
01387         rd->ffcodecdata.audio_bitrate = 128;
01388     }
01389 }
01390 
01391 void ffmpeg_verify_lossless_format(RenderData *rd, ImageFormatData *imf)
01392 {
01393     if(imf->imtype == R_IMF_IMTYPE_H264) {
01394         ffmpeg_set_expert_options(rd, FFMPEG_PRESET_H264);
01395     }
01396 }
01397 
01398 #endif