Blender  V2.59
writeavi.c
Go to the documentation of this file.
00001 /*
00002  * Functions for writing avi-format files.
00003  * Added interface for generic movie support (ton)
00004  *
00005  * $Id: writeavi.c 38597 2011-07-22 00:34:03Z campbellbarton $
00006  *
00007  * ***** BEGIN GPL LICENSE BLOCK *****
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU General Public License
00011  * as published by the Free Software Foundation; either version 2
00012  * of the License, or (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software Foundation,
00021  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00022  *
00023  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00024  * All rights reserved.
00025  *
00026  * The Original Code is: all of this file.
00027  *
00028  * Contributor(s): Robert Wenzlaff
00029  *
00030  * ***** END GPL LICENSE BLOCK *****
00031  * 
00032  */
00033 
00039 #include <string.h>
00040 
00041 #include "MEM_guardedalloc.h"
00042 
00043 #include "DNA_scene_types.h"
00044 
00045 #include "BLI_blenlib.h"
00046 #include "BLI_utildefines.h"
00047 
00048 #include "BKE_global.h"
00049 #include "BKE_main.h"
00050 #include "BKE_report.h"
00051 
00052 #include "BKE_writeavi.h"
00053 #include "AVI_avi.h"
00054 
00055 /* callbacks */
00056 static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports);
00057 static void end_avi(void);
00058 static int append_avi(RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports);
00059 static void filepath_avi(char *string, RenderData *rd);
00060 
00061 /* ********************** general blender movie support ***************************** */
00062 
00063 #ifdef WITH_QUICKTIME
00064 #include "quicktime_export.h"
00065 #endif
00066 
00067 #ifdef WITH_FFMPEG
00068 #include "BKE_writeffmpeg.h"
00069 #endif
00070 
00071 #include "BKE_writeframeserver.h"
00072 
00073 bMovieHandle *BKE_get_movie_handle(int imtype)
00074 {
00075         static bMovieHandle mh;
00076         
00077         /* set the default handle, as builtin */
00078         mh.start_movie= start_avi;
00079         mh.append_movie= append_avi;
00080         mh.end_movie= end_avi;
00081         mh.get_next_frame = NULL;
00082         mh.get_movie_path = filepath_avi;
00083         
00084         /* do the platform specific handles */
00085 #if defined(_WIN32) && !defined(FREE_WINDOWS)
00086         if (imtype == R_AVICODEC) {             
00087                 //XXX mh.start_movie= start_avi_codec;
00088                 //XXX mh.append_movie= append_avi_codec;
00089                 //XXX mh.end_movie= end_avi_codec;
00090         }
00091 #endif
00092 #ifdef WITH_QUICKTIME
00093         if (imtype == R_QUICKTIME) {
00094                 mh.start_movie= start_qt;
00095                 mh.append_movie= append_qt;
00096                 mh.end_movie= end_qt;
00097                 mh.get_movie_path = filepath_qt;
00098         }
00099 #endif
00100 #ifdef WITH_FFMPEG
00101         if (ELEM4(imtype, R_FFMPEG, R_H264, R_XVID, R_THEORA)) {
00102                 mh.start_movie = start_ffmpeg;
00103                 mh.append_movie = append_ffmpeg;
00104                 mh.end_movie = end_ffmpeg;
00105                 mh.get_movie_path = filepath_ffmpeg;
00106         }
00107 #endif
00108 #ifdef WITH_FRAMESERVER
00109         if (imtype == R_FRAMESERVER) {
00110                 mh.start_movie = start_frameserver;
00111                 mh.append_movie = append_frameserver;
00112                 mh.end_movie = end_frameserver;
00113                 mh.get_next_frame = frameserver_loop;
00114         }
00115 #endif
00116 
00117         /* incase all above are disabled */
00118         (void)imtype;
00119 
00120         return &mh;
00121 }
00122 
00123 /* ****************************************************************** */
00124 
00125 
00126 static AviMovie *avi=NULL;
00127 static int sframe;
00128 
00129 static void filepath_avi (char *string, RenderData *rd)
00130 {
00131         if (string==NULL) return;
00132 
00133         strcpy(string, rd->pic);
00134         BLI_path_abs(string, G.main->name);
00135 
00136         BLI_make_existing_file(string);
00137 
00138         if (!BLI_testextensie(string, ".avi")) {
00139                 BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
00140                 strcat(string, ".avi");
00141         }
00142 }
00143 
00144 static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports)
00145 {
00146         int x, y;
00147         char name[256];
00148         AviFormat format;
00149         int quality;
00150         double framerate;
00151         
00152         (void)scene; /* unused */
00153         
00154         filepath_avi(name, rd);
00155 
00156         sframe = (rd->sfra);
00157         x = rectx;
00158         y = recty;
00159 
00160         quality= rd->quality;
00161         framerate= (double) rd->frs_sec / (double) rd->frs_sec_base;
00162         
00163         avi = MEM_mallocN (sizeof(AviMovie), "avimovie");
00164 
00165         /* RPW 11-21-2002 
00166         if (rd->imtype != AVI_FORMAT_MJPEG) format = AVI_FORMAT_AVI_RGB;
00167         */
00168         if (rd->imtype != R_AVIJPEG ) format = AVI_FORMAT_AVI_RGB;
00169         else format = AVI_FORMAT_MJPEG;
00170 
00171         if (AVI_open_compress (name, avi, 1, format) != AVI_ERROR_NONE) {
00172                 BKE_report(reports, RPT_ERROR, "Cannot open or start AVI movie file.");
00173                 MEM_freeN (avi);
00174                 avi = NULL;
00175                 return 0;
00176         }
00177                         
00178         AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_WIDTH, &x);
00179         AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_HEIGHT, &y);
00180         AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_QUALITY, &quality);           
00181         AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_FRAMERATE, &framerate);
00182 
00183         avi->interlace= 0;
00184         avi->odd_fields= 0;
00185 /*      avi->interlace= rd->mode & R_FIELDS; */
00186 /*      avi->odd_fields= (rd->mode & R_ODDFIELD)?1:0; */
00187         
00188         printf("Created avi: %s\n", name);
00189         return 1;
00190 }
00191 
00192 static int append_avi(RenderData *UNUSED(rd), int frame, int *pixels, int rectx, int recty, ReportList *UNUSED(reports))
00193 {
00194         unsigned int *rt1, *rt2, *rectot;
00195         int x, y;
00196         char *cp, rt;
00197         
00198         if (avi == NULL)
00199                 return 0;
00200 
00201         /* note that libavi free's the buffer... stupid interface - zr */
00202         rectot= MEM_mallocN(rectx*recty*sizeof(int), "rectot");
00203         rt1= rectot;
00204         rt2= (unsigned int*)pixels + (recty-1)*rectx;
00205         /* flip y and convert to abgr */
00206         for (y=0; y < recty; y++, rt1+= rectx, rt2-= rectx) {
00207                 memcpy (rt1, rt2, rectx*sizeof(int));
00208                 
00209                 cp= (char *)rt1;
00210                 for(x= rectx; x>0; x--) {
00211                         rt= cp[0];
00212                         cp[0]= cp[3];
00213                         cp[3]= rt;
00214                         rt= cp[1];
00215                         cp[1]= cp[2];
00216                         cp[2]= rt;
00217                         cp+= 4;
00218                 }
00219         }
00220         
00221         AVI_write_frame (avi, (frame-sframe), AVI_FORMAT_RGB32, rectot, rectx*recty*4);
00222 //      printf ("added frame %3d (frame %3d in avi): ", frame, frame-sframe);
00223 
00224         return 1;
00225 }
00226 
00227 static void end_avi(void)
00228 {
00229         if (avi == NULL) return;
00230 
00231         AVI_close_compress (avi);
00232         MEM_freeN (avi);
00233         avi= NULL;
00234 }
00235 
00236 /* similar to BKE_makepicstring() */
00237 void BKE_makeanimstring(char *string, RenderData *rd)
00238 {
00239         bMovieHandle *mh= BKE_get_movie_handle(rd->imtype);
00240         if(mh->get_movie_path)
00241                 mh->get_movie_path(string, rd);
00242         else
00243                 string[0]= '\0';
00244 }