This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/src/writemovie.c
Kent Mein d0e346d544 updated .c files to include:
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

Just need to finish cpp files now :)

Kent
--
mein@cs.umn.edu
2002-11-25 12:02:15 +00:00

519 lines
12 KiB
C

/**
* $Id$
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef __sgi
#include <unistd.h>
#include <movie.h>
#include <cdaudio.h>
#include <dmedia/cl.h>
#include <dmedia/cl_cosmo.h>
#include <sys/file.h> /* flock */
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "BKE_global.h"
#include "BKE_utildefines.h"
#include "BIF_gl.h"
#include "BIF_writemovie.h"
#include "BIF_toolbox.h"
#include "render.h"
#define error(str) {perror(str) ; error("%s", str); G.afbreek= 1;}
#define QUIT(str) {error(str); return;}
#define DIR_UP 1
#define DIR_DOWN 2
#define DIR_BOTH (DIR_UP | DIR_DOWN)
#define MAXQUAL R.r.quality
#define MINQUAL 30
/* globals */
static CL_Handle compr, soft_compr;
static MVid movie, image;
static DMparams *movie_params, *image_params;
static int compr_params[64];
static int myindex, qualindex, qualnow, mv_outx, mv_outy, numfields= 2;
static char *comp_buf;
static int sfra, efra, first = TRUE, maxbufsize;
static int ntsc = FALSE;
#define FIRST_IMAGE "FIRST_IMAGE"
#define BLENDER_FIRST_IMAGE "BLENDER_1ST_IMG"
static void report_flock(void)
{
static int flock_reported = FALSE;
if (flock_reported) return;
flock_reported = TRUE;
error("WriteMovie: couldn't flock() moviefile. Ignoring.");
}
static void make_movie_name(char *string)
{
int len;
char txt[64];
if (string==0) return;
strcpy(string, G.scene->r.pic);
BLI_convertstringcode(string, G.sce, G.scene->r.cfra);
len= strlen(string);
RE_make_existing_file(string);
if (strcasecmp(string + len - 3, ".mv")) {
sprintf(txt, "%04d_%04d.mv", sfra, efra);
strcat(string, txt);
}
}
static int my_Compress(uint * rect, int *bufsize)
{
int err = 0;
compr_params[qualindex] = qualnow;
clSetParams(compr, compr_params, myindex);
while (clCompress(compr, numfields, rect, bufsize, comp_buf) != numfields) {
if (compr == soft_compr) {
error("clCompress (software)");
return 1;
}
/* hardware opnieuw initialiseren */
clCloseCompressor(compr);
clOpenCompressor(CL_JPEG_COSMO, &compr);
qualnow--;
compr_params[qualindex] = qualnow;
clSetParams(compr, compr_params, myindex);
printf("retrying at quality %d\n", qualnow);
err= TRUE;
}
return (err);
}
static void set_sfra_efra(void)
{
sfra = (G.scene->r.sfra);
efra = (G.scene->r.efra);
}
static void open_compressor(void)
{
int cosmo = FAILURE;
/* initialiseren van de compressor */
if (clOpenCompressor(CL_JPEG_SOFTWARE, &soft_compr) != SUCCESS) QUIT("clOpenCompressor");
if (G.scene->r.mode & R_COSMO) {
cosmo = clOpenCompressor(CL_JPEG_COSMO, &compr);
if (cosmo != SUCCESS && first) error("warning: using software compression");
first = FALSE;
}
if (cosmo != SUCCESS) compr = soft_compr;
myindex = 0;
compr_params[myindex++]= CL_IMAGE_WIDTH;
compr_params[myindex++]= mv_outx;
compr_params[myindex++]= CL_IMAGE_HEIGHT;
compr_params[myindex++]= mv_outy / numfields;
compr_params[myindex++]= CL_JPEG_QUALITY_FACTOR;
qualindex = myindex;
compr_params[myindex++]= R.r.quality;
compr_params[myindex++]= CL_ORIGINAL_FORMAT;
compr_params[myindex++]= CL_RGBX;
compr_params[myindex++]= CL_ORIENTATION;
compr_params[myindex++]= CL_TOP_DOWN;
compr_params[myindex++]= CL_INTERNAL_FORMAT;
compr_params[myindex++]= CL_YUV422;
/* this parameter must be set for non-queueing mode */
compr_params[myindex++]= CL_ENABLE_IMAGEINFO;
compr_params[myindex++]= 1;
/* enable stream headers */
compr_params[myindex++]= CL_STREAM_HEADERS;
compr_params[myindex++]= TRUE;
clSetParams(compr, compr_params, myindex);
if (compr != soft_compr) clSetParams(soft_compr, compr_params, myindex);
maxbufsize = 2 * clGetParam(compr, CL_COMPRESSED_BUFFER_SIZE);
comp_buf = MEM_mallocN(maxbufsize, "cosmo_buffer");
}
static void close_compressor(void)
{
MEM_freeN(comp_buf);
comp_buf = 0;
clCloseCompressor(compr);
if (soft_compr != compr) clCloseCompressor(soft_compr);
}
void end_movie(void)
{
}
static void new_movie(int fd)
{
char string[120];
if (dmParamsCreate(&movie_params) != DM_SUCCESS) QUIT("dmParamsCreate");
if (dmParamsCreate(&image_params) != DM_SUCCESS) QUIT("dmParamsCreate");
if (mvSetMovieDefaults(movie_params, MV_FORMAT_SGI_3) != DM_SUCCESS) QUIT("mvSetMovieDefaults");
if (dmSetImageDefaults(image_params, mv_outx, mv_outy, DM_PACKING_RGBX) != DM_SUCCESS) QUIT("dmSetImageDefaults");
mvAddUserParam(BLENDER_FIRST_IMAGE);
sprintf(string, "%04d", sfra);
dmParamsSetString(image_params, BLENDER_FIRST_IMAGE, string);
if (ntsc) dmParamsSetFloat(image_params, DM_IMAGE_RATE, 29.97);
else dmParamsSetFloat(image_params, DM_IMAGE_RATE, 25.0);
if (numfields == 2) {
if (ntsc) dmParamsSetEnum(image_params, DM_IMAGE_INTERLACING, DM_IMAGE_INTERLACED_ODD);
else dmParamsSetEnum(image_params, DM_IMAGE_INTERLACING, DM_IMAGE_INTERLACED_EVEN);
} else dmParamsSetEnum(image_params, DM_IMAGE_INTERLACING, DM_IMAGE_NONINTERLACED);
dmParamsSetEnum(image_params, DM_IMAGE_ORIENTATION, DM_TOP_TO_BOTTOM);
dmParamsSetString(image_params, DM_IMAGE_COMPRESSION, DM_IMAGE_JPEG);
if (mvCreateFD(fd, movie_params, NULL, &movie) != DM_SUCCESS) QUIT("mvCreateFile");
if (mvAddTrack(movie, DM_IMAGE, image_params, NULL, &image)) QUIT("mvAddTrack");;
if (mvSetLoopMode(movie, MV_LOOP_CONTINUOUSLY) != DM_SUCCESS) QUIT("mvSetMovieDefaults");
if (mvWrite(movie) != DM_SUCCESS) QUIT("mvWrite");
if (mvClose(movie) != DM_SUCCESS) QUIT("mvClose");
dmParamsDestroy(image_params);
dmParamsDestroy(movie_params);
}
void start_movie(void)
{
char name[FILE_MAXDIR+FILE_MAXFILE];
char bak[sizeof(name) + 4];
int fd;
first = TRUE;
set_sfra_efra();
/* naam bedenken voor de movie */
make_movie_name(name);
ntsc = FALSE;
switch (R.recty) {
case 480: case 360: case 240: case 120:
ntsc = TRUE;
}
if (ntsc) {
switch (R.rectx) {
case 360: case 320: case 720: case 640:
mv_outx = R.rectx;
break;
default:
if (R.rectx <= 320) mv_outx = 320;
else if (R.rectx <= 640) mv_outx = 640;
else mv_outx = 720;
}
} else {
switch (R.rectx) {
case 360: case 384: case 720: case 768:
mv_outx = R.rectx;
break;
default:
if (R.rectx < 384) mv_outx = 384;
else mv_outx = 768;
}
}
if (ntsc) {
if (R.recty <= 240) {
mv_outy = 240;
numfields = 1;
} else {
mv_outy = 480;
numfields = 2;
}
} else {
if (R.recty <= 288) {
mv_outy = 288;
numfields = 1;
} else {
mv_outy = 576;
numfields = 2;
}
}
if(R.r.mode & R_MOVIECROP) {
if (ntsc) {
if (R.rectx > 640) mv_outx = 720;
else mv_outx = 640;
mv_outy = 480;
numfields = 2;
} else {
if (R.rectx > 720) mv_outx = 768;
else mv_outx = 720;
mv_outy = 576;
numfields = 2;
}
}
qualnow = R.r.quality;
fd = open(name, O_BINARY|O_RDWR);
if (fd != -1) {
if (flock(fd, LOCK_EX) == -1) report_flock();
if (mvOpenFD(fd, &movie) == DM_SUCCESS) {
if (mvFindTrackByMedium(movie, DM_IMAGE, &image) == DM_SUCCESS) {
if (mvGetImageWidth(image) == mv_outx) {
if (mvGetImageHeight(image) == mv_outy) {
mvClose(movie);
close(fd);
return;
}
}
}
strcpy(bak, name);
strcat(bak, ".bak");
BLI_rename(name, bak);
mvClose(movie);
}
close(fd);
}
fd = open(name, O_BINARY|O_RDWR | O_CREAT | O_EXCL, 0664);
if (fd != -1) {
if (flock(fd, LOCK_EX) == -1) report_flock();
new_movie(fd);
printf("Created movie: %s\n", name);
close(fd);
}
}
void append_movie(int cfra)
{
ImBuf *ibuf, *tbuf;
int err, ofsx, ofsy, bufsize, rate, lastqual, qualstep, direction, first_image, num_images;
char name[FILE_MAXDIR+FILE_MAXFILE];
const char *string;
int fd;
set_sfra_efra();
make_movie_name(name);
open_compressor();
rate = 1024 * R.r.maximsize;
/* veranderd: kopie van rectot maken */
ibuf= IMB_allocImBuf(R.rectx, R.recty, 32, IB_rect, 0);
memcpy(ibuf->rect, R.rectot, 4*R.rectx*R.recty);
if (ibuf->x != mv_outx || ibuf->y != mv_outy) {
tbuf = IMB_allocImBuf(mv_outx, mv_outy, 32, IB_rect, 0);
IMB_rectoptot(tbuf, 0, IMB_rectfill, 0x00);
ofsx = (tbuf->x - ibuf->x) / 2;
ofsy = (tbuf->y - ibuf->y) / 2;
if (numfields == 2) ofsy &= ~1;
IMB_rectop(tbuf, ibuf, ofsx, ofsy, 0, 0, 32767, 32767, IMB_rectcpy, 0);
IMB_freeImBuf(ibuf);
strcpy(tbuf->name, ibuf->name);
ibuf = tbuf;
}
IMB_convert_rgba_to_abgr(ibuf->x*ibuf->y, ibuf->rect);
if (numfields == 2) {
if (ntsc) {
IMB_rectop(ibuf, ibuf, 0, 0, 0, 1, 32767, 32767, IMB_rectcpy, 0);
IMB_flipy(ibuf);
IMB_de_interlace(ibuf);
if (ntsc) IMB_rectop(ibuf, ibuf, 0, 0, 0, 1, 32767, 32767, IMB_rectcpy, 0);
} else {
IMB_flipy(ibuf);
IMB_rectop(ibuf, ibuf, 0, 0, 0, 1, 32767, 32767, IMB_rectcpy, 0);
IMB_de_interlace(ibuf);
}
}
else {
/* kleine movies anders op de kop */
IMB_flipy(ibuf);
}
if (rate == 0) {
qualnow = R.r.quality;
my_Compress(ibuf->rect, &bufsize);
} else {
qualstep = 4;
direction = 0;
do {
if (qualnow > MAXQUAL) qualnow = MAXQUAL;
if (qualnow < MINQUAL) qualnow = MINQUAL;
compr_params[qualindex] = qualnow;
clSetParams(compr, compr_params, myindex);
lastqual = qualnow;
err = my_Compress(ibuf->rect, &bufsize);
printf(" tried quality: %d, size %d\n", qualnow, bufsize);
if (bufsize < 0.9 * rate) {
if (err) {
/* forget about this frame, retry next frame at old quality settting */
qualnow = lastqual;
break;
}
if (qualnow == MAXQUAL) break;
direction |= DIR_UP;
if (direction == DIR_BOTH) qualstep /= 2;
qualnow += qualstep;
} else if (bufsize > 1.1 * rate) {
if (qualnow == MINQUAL) break;
direction |= DIR_DOWN;
if (direction == DIR_BOTH) qualstep /= 2;
qualnow -= qualstep;
} else break;
if (qualstep == 0) {
/* this was the last iteration. Make sure that the buffer isn't to big */
if (bufsize < 1.1 * rate) break;
else qualnow--;
}
} while (1);
printf("used quality: %d\n", qualnow);
if (bufsize < rate) qualnow++;
else qualnow--;
}
fd = open(name, O_BINARY|O_RDWR);
if (fd != -1) {
if (flock(fd, LOCK_EX) == -1) report_flock();
if (mvOpenFD(fd, &movie) == DM_SUCCESS){
if (mvFindTrackByMedium(movie, DM_IMAGE, &image) == DM_SUCCESS) {
image_params = mvGetParams(image);
first_image = 1;
string = dmParamsGetString(image_params, FIRST_IMAGE);
if (string) {
first_image = atoi(string);
}
string = dmParamsGetString(image_params, BLENDER_FIRST_IMAGE);
if (string) {
first_image = atoi(string);
}
num_images = mvGetTrackLength(image);
if (cfra >= first_image && cfra <= (first_image + num_images - 1)) {
if (mvDeleteFrames(image, cfra - first_image, 1) != DM_SUCCESS) {
mvDestroyMovie(movie);
error("mvDeleteFrames");
G.afbreek = 1;
}
}
if (G.afbreek != 1) {
if (mvInsertCompressedImage(image, cfra - first_image, bufsize, comp_buf) == DM_SUCCESS) {
printf("added frame %3d (frame %3d in movie): length %6d: ", cfra, cfra - first_image + 1, bufsize);
mvClose(movie);
} else {
mvDestroyMovie(movie);
error("mvInsertCompressedImage");
G.afbreek = 1;
}
}
} else {
mvDestroyMovie(movie);
error("mvFindTrackByMedium");
G.afbreek = 1;
}
}else {
error("mvOpenFD");
G.afbreek = 1;
}
close(fd);
} else {
error("open movie");
G.afbreek = 1;
}
IMB_freeImBuf(ibuf);
close_compressor();
}
#endif /* __sgi */