=== Custom Transform Orientation ===
[blender.git] / source / blender / src / writemovie.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 //#ifdef __sgi
34 #if 0
35
36 #include <unistd.h>
37 #include <movie.h>
38 #include <cdaudio.h>
39 #include <dmedia/cl.h>
40 #include <dmedia/cl_cosmo.h>
41 #include <sys/file.h>                   /* flock */
42 #include "MEM_guardedalloc.h"
43
44 #include "BLI_blenlib.h"
45
46 #include "IMB_imbuf_types.h"
47 #include "IMB_imbuf.h"
48
49 #include "BKE_global.h"
50 #include "BKE_utildefines.h"
51
52 #include "BIF_gl.h"
53 #include "BIF_writemovie.h"
54 #include "BIF_toolbox.h"
55
56 #include "render.h"
57
58 #define error(str) {perror(str) ; error("%s", str); G.afbreek= 1;}
59 #define QUIT(str) {error(str); return;}
60
61 #define DIR_UP 1
62 #define DIR_DOWN 2
63 #define DIR_BOTH (DIR_UP | DIR_DOWN)
64
65 #define MAXQUAL R.r.quality
66 #define MINQUAL 30
67
68
69 /* globals */
70
71 static CL_Handle        compr, soft_compr;
72 static MVid             movie, image; 
73 static DMparams *movie_params, *image_params;
74 static int                      compr_params[64];
75 static int                      myindex, qualindex, qualnow, mv_outx, mv_outy, numfields= 2;
76 static char             *comp_buf;
77 static int                      sfra, efra, first = TRUE, maxbufsize;
78 static int                      ntsc = FALSE;
79
80 #define FIRST_IMAGE "FIRST_IMAGE"
81 #define BLENDER_FIRST_IMAGE "BLENDER_1ST_IMG"
82
83
84 static void report_flock(void)
85 {
86         static int flock_reported = FALSE;
87         
88         if (flock_reported) return;
89         flock_reported = TRUE;
90         
91         error("WriteMovie: couldn't flock() moviefile. Ignoring.");
92 }
93
94
95 static void make_movie_name(char *string)
96 {
97         int len;
98         char txt[64];
99
100         if (string==0) return;
101
102         strcpy(string, G.scene->r.pic);
103         BLI_convertstringcode(string, G.sce, G.scene->r.cfra);
104         len= strlen(string);
105
106         BLI_make_existing_file(string);
107
108         if (BLI_strcasecmp(string + len - 3, ".mv")) {
109                 sprintf(txt, "%04d_%04d.mv", sfra, efra);
110                 strcat(string, txt);
111         }
112 }
113
114 static int my_Compress(uint * rect, int *bufsize)
115 {
116         int err = 0;
117         
118         compr_params[qualindex] = qualnow;
119         clSetParams(compr, compr_params, myindex);
120
121         while (clCompress(compr, numfields, rect, bufsize, comp_buf) != numfields) {
122                 if (compr == soft_compr) {
123                         error("clCompress (software)");
124                         return 1;
125                 }
126                 
127                 /* hardware opnieuw initialiseren */
128                 clCloseCompressor(compr);
129                 clOpenCompressor(CL_JPEG_COSMO, &compr);
130
131                 qualnow--;
132                 compr_params[qualindex] = qualnow;
133                 clSetParams(compr, compr_params, myindex);
134                 printf("retrying at quality %d\n", qualnow);
135                 
136                 err= TRUE;
137         }
138         
139         return (err);
140 }
141
142 static void set_sfra_efra(void)
143 {
144         sfra = (G.scene->r.sfra);
145         efra = (G.scene->r.efra);
146 }
147
148 static void open_compressor(void)
149 {
150         int cosmo = FAILURE;
151         
152         /* initialiseren van de compressor */
153         
154         if (clOpenCompressor(CL_JPEG_SOFTWARE, &soft_compr) != SUCCESS) QUIT("clOpenCompressor");
155         
156         if (G.scene->r.mode & R_COSMO) {
157                 cosmo = clOpenCompressor(CL_JPEG_COSMO, &compr);
158                 if (cosmo != SUCCESS && first) error("warning: using software compression");
159                 first = FALSE;
160         }
161         
162         if (cosmo != SUCCESS) compr = soft_compr;
163         
164         myindex = 0;
165
166         compr_params[myindex++]= CL_IMAGE_WIDTH;
167         compr_params[myindex++]= mv_outx;
168
169         compr_params[myindex++]= CL_IMAGE_HEIGHT;
170         compr_params[myindex++]= mv_outy / numfields;
171         
172         compr_params[myindex++]= CL_JPEG_QUALITY_FACTOR;
173         qualindex = myindex;
174         compr_params[myindex++]= R.r.quality;
175
176         compr_params[myindex++]= CL_ORIGINAL_FORMAT;
177         compr_params[myindex++]= CL_RGBX;
178
179         compr_params[myindex++]= CL_ORIENTATION;
180         compr_params[myindex++]= CL_TOP_DOWN;
181
182         compr_params[myindex++]= CL_INTERNAL_FORMAT;
183         compr_params[myindex++]= CL_YUV422;
184
185         /* this parameter must be set for non-queueing mode */
186         compr_params[myindex++]= CL_ENABLE_IMAGEINFO;
187         compr_params[myindex++]= 1;
188
189         /* enable stream headers */
190         compr_params[myindex++]= CL_STREAM_HEADERS;
191         compr_params[myindex++]= TRUE;
192
193         clSetParams(compr, compr_params, myindex);
194         if (compr != soft_compr) clSetParams(soft_compr, compr_params, myindex);
195         
196         maxbufsize = 2 * clGetParam(compr, CL_COMPRESSED_BUFFER_SIZE);
197         comp_buf = MEM_mallocN(maxbufsize, "cosmo_buffer");
198 }
199
200 static void close_compressor(void)
201 {
202         MEM_freeN(comp_buf);
203         comp_buf = 0;
204
205         clCloseCompressor(compr);
206         if (soft_compr != compr) clCloseCompressor(soft_compr);
207 }
208
209 void end_movie(void)
210 {
211 }
212
213 static void new_movie(int fd)
214 {
215         char    string[120];
216
217         if (dmParamsCreate(&movie_params) != DM_SUCCESS) QUIT("dmParamsCreate");
218         if (dmParamsCreate(&image_params) != DM_SUCCESS) QUIT("dmParamsCreate");
219                 
220                 if (mvSetMovieDefaults(movie_params, MV_FORMAT_SGI_3) != DM_SUCCESS) QUIT("mvSetMovieDefaults");
221                 if (dmSetImageDefaults(image_params, mv_outx, mv_outy, DM_PACKING_RGBX) != DM_SUCCESS) QUIT("dmSetImageDefaults");
222                         
223                 mvAddUserParam(BLENDER_FIRST_IMAGE);
224                 sprintf(string, "%04d", sfra);
225                 dmParamsSetString(image_params, BLENDER_FIRST_IMAGE, string);
226         
227                 if (ntsc) dmParamsSetFloat(image_params, DM_IMAGE_RATE, 29.97);
228                 else dmParamsSetFloat(image_params, DM_IMAGE_RATE, 25.0);
229                 
230                 if (numfields == 2) {
231                         if (ntsc) dmParamsSetEnum(image_params, DM_IMAGE_INTERLACING, DM_IMAGE_INTERLACED_ODD);
232                         else dmParamsSetEnum(image_params, DM_IMAGE_INTERLACING, DM_IMAGE_INTERLACED_EVEN);
233                 } else dmParamsSetEnum(image_params, DM_IMAGE_INTERLACING, DM_IMAGE_NONINTERLACED);
234         
235                 dmParamsSetEnum(image_params, DM_IMAGE_ORIENTATION, DM_TOP_TO_BOTTOM);
236                 dmParamsSetString(image_params, DM_IMAGE_COMPRESSION, DM_IMAGE_JPEG);
237         
238                 if (mvCreateFD(fd, movie_params, NULL, &movie) != DM_SUCCESS) QUIT("mvCreateFile");
239                 if (mvAddTrack(movie, DM_IMAGE, image_params, NULL, &image)) QUIT("mvAddTrack");;
240                 if (mvSetLoopMode(movie, MV_LOOP_CONTINUOUSLY) != DM_SUCCESS) QUIT("mvSetMovieDefaults");
241                                                 
242                 if (mvWrite(movie) != DM_SUCCESS) QUIT("mvWrite");
243                 if (mvClose(movie) != DM_SUCCESS) QUIT("mvClose");
244         
245         dmParamsDestroy(image_params);
246         dmParamsDestroy(movie_params);
247 }
248
249
250 void start_movie(void)
251 {
252         char    name[FILE_MAXDIR+FILE_MAXFILE];
253         char    bak[sizeof(name) + 4];
254         int             fd;
255         
256         first = TRUE;
257         
258         set_sfra_efra();
259         
260         /* naam bedenken voor de movie */
261         make_movie_name(name);
262         
263         ntsc = FALSE;
264         
265         switch (R.recty) {
266                 case 480: case 360: case 240: case 120:
267                         ntsc = TRUE;
268         }
269         
270         if (ntsc) {
271                 switch (R.rectx) {
272                 case 360: case 320: case 720: case 640:
273                         mv_outx = R.rectx;
274                         break;
275                 default:
276                         if (R.rectx <= 320) mv_outx = 320;
277                         else if (R.rectx <= 640) mv_outx = 640;
278                         else mv_outx = 720;
279                 }
280         } else {
281                 switch (R.rectx) {
282                 case 360: case 384: case 720: case 768:
283                         mv_outx = R.rectx;
284                         break;
285                 default:
286                         if (R.rectx < 384) mv_outx = 384;
287                         else mv_outx = 768;
288                 }
289         }
290         
291         if (ntsc) {
292                 if (R.recty <= 240) {
293                         mv_outy = 240;
294                         numfields = 1;
295                 } else {
296                         mv_outy = 480;
297                         numfields = 2;
298                 }
299         } else {
300                 if (R.recty <= 288) {
301                         mv_outy = 288;
302                         numfields = 1;
303                 } else {
304                         mv_outy = 576;
305                         numfields = 2;
306                 }
307         }
308                 
309         qualnow = R.r.quality;
310
311         fd = open(name, O_BINARY|O_RDWR);
312         if (fd != -1) {
313                 if (flock(fd, LOCK_EX) == -1) report_flock();
314                 
315                         if (mvOpenFD(fd, &movie) == DM_SUCCESS) {
316                                 if (mvFindTrackByMedium(movie, DM_IMAGE, &image) == DM_SUCCESS) {
317                                         if (mvGetImageWidth(image) == mv_outx) {
318                                                 if (mvGetImageHeight(image) == mv_outy) {
319                                                         mvClose(movie);
320                                                         close(fd);
321                                                         return;
322                                                 }
323                                         }
324                                 }
325                                 strcpy(bak, name);
326                                 strcat(bak, ".bak");
327                                 BLI_rename(name, bak);
328                                 mvClose(movie);
329                         }
330                 
331                 close(fd);
332         }
333         fd = open(name, O_BINARY|O_RDWR | O_CREAT | O_EXCL, 0664);
334         if (fd != -1) {
335                 if (flock(fd, LOCK_EX) == -1) report_flock();
336                         new_movie(fd);
337                         printf("Created movie: %s\n", name);
338                 close(fd);
339         }
340 }
341
342 void append_movie(int cfra)
343 {
344         ImBuf           *ibuf, *tbuf;
345         int                     err, ofsx, ofsy, bufsize, rate, lastqual, qualstep, direction, first_image, num_images;
346         char            name[FILE_MAXDIR+FILE_MAXFILE];
347         const char      *string;
348         int                     fd;
349         float col[4] = {0.0,0.0,0.0,0.0};
350         
351         set_sfra_efra();
352         make_movie_name(name);
353         open_compressor();
354         
355         rate = 1024 * R.r.maximsize;
356         
357         /* veranderd: kopie van rectot maken */
358         ibuf= IMB_allocImBuf(R.rectx, R.recty, 32, IB_rect, 0);
359         memcpy(ibuf->rect, R.rectot, 4*R.rectx*R.recty);
360         
361         if (ibuf->x != mv_outx || ibuf->y != mv_outy) {
362                 tbuf = IMB_allocImBuf(mv_outx, mv_outy, 32, IB_rect, 0);
363                 IMB_rectfill(tbuf,col);
364                 
365                 ofsx = (tbuf->x - ibuf->x) / 2;
366                 ofsy = (tbuf->y - ibuf->y) / 2;
367                 if (numfields == 2) ofsy &= ~1;
368                 
369                 IMB_rectcpy(tbuf, ibuf, ofsx, ofsy, 0, 0, ibuf->x, ibuf->y);
370                 IMB_freeImBuf(ibuf);
371                 strcpy(tbuf->name, ibuf->name);
372                 ibuf = tbuf;
373         }
374         IMB_convert_rgba_to_abgr(ibuf);
375         
376         if (numfields == 2) {
377                 if (ntsc) {
378                         IMB_rectcpy(ibuf, ibuf, 0, 0, 0, 1, ibuf->x, ibuf->y);
379                         IMB_flipy(ibuf);
380                         IMB_de_interlace(ibuf);
381                         if (ntsc) IMB_rectcpy(ibuf, ibuf, 0, 0, 0, 1, ibuf->x, ibuf->y);
382                 } else {
383                         IMB_flipy(ibuf);
384                         IMB_rectcpy(ibuf, ibuf, 0, 0, 0, 1, ibuf->x, ibuf->y);
385                         IMB_de_interlace(ibuf);
386                 }
387         }
388         else {
389                 /* kleine movies anders op de kop */
390                 IMB_flipy(ibuf);
391         }
392         
393         if (rate == 0) {
394                 qualnow = R.r.quality;
395                 my_Compress(ibuf->rect, &bufsize);
396         } else {
397                 qualstep = 4;
398                 direction = 0;
399                 
400                 do {
401                         if (qualnow > MAXQUAL) qualnow = MAXQUAL;
402                         if (qualnow < MINQUAL) qualnow = MINQUAL;
403
404                         compr_params[qualindex] = qualnow;
405                         clSetParams(compr, compr_params, myindex);
406
407                         lastqual = qualnow;
408                         err = my_Compress(ibuf->rect, &bufsize);
409                         
410                         printf(" tried quality: %d, size %d\n", qualnow, bufsize);
411                         
412                         if (bufsize < 0.9 * rate) {
413                                 if (err) {
414                                         /* forget about this frame, retry next frame at old quality settting */
415                                         qualnow = lastqual;
416                                         break;
417                                 }
418                                 if (qualnow == MAXQUAL) break;
419                                 direction |= DIR_UP;
420                                 if (direction == DIR_BOTH) qualstep /= 2;
421                                 qualnow += qualstep;
422                         } else if (bufsize > 1.1 * rate) {
423                                 if (qualnow == MINQUAL) break;
424                                 direction |= DIR_DOWN;
425                                 if (direction == DIR_BOTH) qualstep /= 2;
426                                 qualnow -= qualstep;
427                         } else break;
428                                                                         
429                         if (qualstep == 0) {
430                                 /* this was the last iteration. Make sure that the buffer isn't to big */
431                                 if (bufsize < 1.1 * rate) break;
432                                 else qualnow--;
433                         }
434                 } while (1);
435                 
436                 printf("used quality: %d\n", qualnow);
437                 
438                 if (bufsize < rate) qualnow++;
439                 else qualnow--;
440                 
441         }
442         
443         fd = open(name, O_BINARY|O_RDWR);
444
445         if (fd != -1) {
446                 if (flock(fd, LOCK_EX) == -1) report_flock();
447                         if (mvOpenFD(fd, &movie) == DM_SUCCESS){
448                                 if (mvFindTrackByMedium(movie, DM_IMAGE, &image) == DM_SUCCESS) {
449                                         image_params = mvGetParams(image);
450                                         
451                                         first_image = 1;
452                                         
453                                         string = dmParamsGetString(image_params, FIRST_IMAGE);
454                                         if (string) {
455                                                 first_image = atoi(string);
456                                         }
457                                         string = dmParamsGetString(image_params, BLENDER_FIRST_IMAGE);
458                                         if (string) {
459                                                 first_image = atoi(string);
460                                         }
461                                         
462                                         num_images = mvGetTrackLength(image);
463                                         
464                                         if (cfra >= first_image && cfra <= (first_image + num_images - 1)) {
465                                                 if (mvDeleteFrames(image, cfra - first_image, 1) != DM_SUCCESS) {
466                                                         mvDestroyMovie(movie);
467                                                         error("mvDeleteFrames");
468                                                         G.afbreek = 1;
469                                                 }
470                                         }
471                                         
472                                         if (G.afbreek != 1) {
473                                                 if (mvInsertCompressedImage(image, cfra - first_image, bufsize, comp_buf) == DM_SUCCESS) {
474                                                         printf("added frame %3d (frame %3d in movie): length %6d: ", cfra, cfra - first_image + 1, bufsize);
475                                                         mvClose(movie);
476                                                 } else {
477                                                         mvDestroyMovie(movie);
478                                                         error("mvInsertCompressedImage");
479                                                         G.afbreek = 1;
480                                                 }
481                                         }
482                                 } else {
483                                         mvDestroyMovie(movie);
484                                         error("mvFindTrackByMedium");
485                                         G.afbreek = 1;
486                                 }
487                         }else {
488                                 error("mvOpenFD");
489                                 G.afbreek = 1;
490                         }
491                 close(fd);
492         } else {
493                 error("open movie");
494                 G.afbreek = 1;
495         }
496         
497         IMB_freeImBuf(ibuf);
498         
499         close_compressor();     
500 }
501
502 #endif  /* __sgi */