mirror of
https://github.com/ioquake/jedi-outcast.git
synced 2024-11-10 07:11:42 +00:00
248 lines
6.1 KiB
C
248 lines
6.1 KiB
C
#include "ParamImSeq.h"
|
|
#include "MpegDecoder.h"
|
|
#include "Param.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "im.h"
|
|
#include "Zim.h"
|
|
|
|
extern int globalRoqWidth;
|
|
extern int globalRoqHeight;
|
|
extern int globalRoqHorizOffset;
|
|
extern int globalRoqVertOffset;
|
|
|
|
TagTable *ParamImSeqNextImageFromParam(ParamImSeq *self);
|
|
|
|
void ParamImSeqFree(ParamImSeq *self)
|
|
{
|
|
free(self);
|
|
}
|
|
|
|
ParamImSeq *ParamImSeqNew(Param *paramobj)
|
|
{
|
|
ParamImSeq *self;
|
|
|
|
self = calloc(1, sizeof(ParamImSeq));
|
|
|
|
/*mpeg setup*/
|
|
if (ParamTimecode(paramobj))
|
|
{
|
|
self->skipFields = YES;
|
|
}
|
|
else
|
|
{
|
|
self->skipFields = NO;
|
|
}
|
|
globalRoqWidth = ParamMpegCropWidth(paramobj);
|
|
globalRoqHeight = ParamMpegCropHeight(paramobj);
|
|
globalRoqHorizOffset = ParamMpegCropXOrigin(paramobj);
|
|
globalRoqVertOffset = ParamMpegCropYOrigin(paramobj);
|
|
|
|
self->mpegFirstFrame = 0;
|
|
self->mpegLastFrame = -1;
|
|
|
|
self->param = paramobj;
|
|
self->mpeg = NULL;
|
|
self->currentImageFilename[0] = '\0';
|
|
self->hasAlpha = NO;
|
|
self->frameNum = -1;//on first increment it will be 0
|
|
self->start = 0;
|
|
return self;
|
|
}
|
|
|
|
const char * ParamImSeqCurrentImageFilename(ParamImSeq *self)
|
|
{
|
|
return self->currentImageFilename;
|
|
}
|
|
|
|
BOOL ParamImSeqMoreFrames(ParamImSeq *self)
|
|
{
|
|
BOOL ret;
|
|
|
|
ret = NO;
|
|
|
|
if (self->mpeg != NULL)
|
|
{
|
|
ret = MpegDecoderMoreFrames(self->mpeg);
|
|
}
|
|
|
|
if (! ret)
|
|
{
|
|
ret = ParamMoreFrames(self->param);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
double ParamImSeqCurrentFade(ParamImSeq *self)
|
|
{
|
|
return ParamFadeFromFrame(self->param, self->frameNum);
|
|
}
|
|
|
|
TagTable *ParamImSeqNextImage(ParamImSeq *self)
|
|
{
|
|
ImVfb *vfb;
|
|
TagTable *frameTagTable;
|
|
time_t now;
|
|
float rate;
|
|
|
|
self->frameNum++;
|
|
if (self->frameNum ==1) //The first frame (#0) could include a large amount of time seeking
|
|
{
|
|
self->start = time(NULL);
|
|
}
|
|
frameTagTable = ParamImSeqNextImageFromParam(self);
|
|
|
|
if (ParamImSeqCurrentFade(self) != 1.0)
|
|
{
|
|
TagEntryQValue(TagTableQDirect(frameTagTable, "image vfb", 0), &vfb);
|
|
ImVfbFade(vfb, ParamImSeqCurrentFade(self), IMVFBRGB, vfb);
|
|
}
|
|
self ->hasAlpha = ZimHasAlpha(frameTagTable);
|
|
|
|
if (ParamScaleDown(self->param))
|
|
{
|
|
TagTable *old;
|
|
old = frameTagTable;
|
|
frameTagTable = ZimExtractField(frameTagTable);
|
|
ZimFree(old);
|
|
}
|
|
now = time(NULL);
|
|
rate = 60.0f*(float) self->frameNum/((float) now - self->start);
|
|
printf("\nParamImSeq: on %s frame %d out of %d, rate = %0.2f frames/min, ETA = %0.2f min\n\n", self ->currentImageFilename, self->frameNum, ParamNumberOfFrames(self->param), rate, ((float) ParamNumberOfFrames(self->param) - self->frameNum)/rate);
|
|
return frameTagTable;
|
|
}
|
|
|
|
TagTable *ParamImSeqNextImageFromParam(ParamImSeq *self)
|
|
{
|
|
const char *str;
|
|
char *ext;
|
|
TagTable *nextImage = NULL, *unusedImage;
|
|
int mpegSkipNum;
|
|
|
|
if (self->mpeg)
|
|
{
|
|
if (MpegDecoderMoreFrames(self->mpeg))
|
|
{
|
|
nextImage = MpegDecoderNextImage(self->mpeg);
|
|
if (self->skipFields)
|
|
{
|
|
sprintf(self->currentImageFilename, "%s%.06db",MpegDecoderCurrentFilename(self->mpeg),MpegDecoderBitstreamFrameNum(self->mpeg));
|
|
}
|
|
else
|
|
{
|
|
sprintf(self->currentImageFilename, "%s%.06d",MpegDecoderCurrentFilename(self->mpeg),MpegDecoderBitstreamFrameNum(self->mpeg));
|
|
}
|
|
if (self->mpegSkipNum > 1)
|
|
{ // skip the required number of images so we're primed for the next pass
|
|
mpegSkipNum = self->mpegSkipNum -1;
|
|
while (mpegSkipNum--)
|
|
{
|
|
unusedImage = MpegDecoderNextImage(self->mpeg);
|
|
ZimFree(unusedImage);
|
|
}
|
|
}
|
|
|
|
return nextImage;
|
|
}
|
|
else
|
|
{
|
|
MpegDecoderFree(self->mpeg);
|
|
self->mpeg = NULL;
|
|
}
|
|
}
|
|
if (ParamMoreFrames(self->param) == YES)
|
|
{
|
|
str = ParamGetNextImageFilename(self->param);
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
if ((str == NULL) || (str[0] == '\0'))
|
|
{
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
strcpy(self->currentImageFilename, str);
|
|
}
|
|
if( (ext = strstr(self->currentImageFilename , ".mpg")) || (ext = strstr(self->currentImageFilename, ".m2v")))
|
|
{
|
|
char *margv[] =
|
|
{
|
|
"mpegstream", "-b", NULL, "-r", "-o6", "-v0", NULL, NULL
|
|
};
|
|
int margc = 6;
|
|
char *fn;
|
|
char *frameNum;
|
|
|
|
self->mpegFirstFrame = 0;
|
|
self->mpegLastFrame = 999999;
|
|
self->mpegSkipNum = 1;
|
|
if (ext[4] != '\0')
|
|
{
|
|
ParamGetCurrentRange(self->param, &self->mpegFirstFrame, &self->mpegLastFrame, &self->mpegSkipNum ,YES);
|
|
if (self->mpegLastFrame ==999999) //we didn't have a range
|
|
{
|
|
self->mpegLastFrame = atoi(&ext[4]); //use the number by itself, only one frame
|
|
}
|
|
}
|
|
|
|
fn = strdup(self->currentImageFilename);
|
|
frameNum = strrchr(fn, '.')+4;
|
|
*frameNum = '\0';//remove frame number so mpeg object can open the file
|
|
margv[2] = fn;
|
|
|
|
if (! self->skipFields) //specify frame flag
|
|
{
|
|
margv[margc++] = "-f";
|
|
}
|
|
|
|
self->mpeg = MpegDecoderNew(margc, margv, self->mpegFirstFrame, self->mpegLastFrame);
|
|
return ParamImSeqNextImage(self);/*in case it's an empty mpg...*/
|
|
}
|
|
else
|
|
{
|
|
char *secondFilename,firstFilename[MAXPATHLEN+1];
|
|
TagTable *image1tt ;
|
|
ImVfb *img, *image1;
|
|
int fields;
|
|
|
|
if (!(secondFilename= strchr(self->currentImageFilename,'\n')))
|
|
{ //one filename, no compositing
|
|
nextImage = ZimImageTagTableFromFile(self->currentImageFilename, "");
|
|
}
|
|
else
|
|
{
|
|
strncpy(firstFilename,self->currentImageFilename,secondFilename-self->currentImageFilename);
|
|
firstFilename[secondFilename-self->currentImageFilename]='\0';
|
|
secondFilename++;//point past the \n
|
|
image1tt = ZimImageTagTableFromFile(firstFilename, "");
|
|
nextImage = ZimImageTagTableFromFile(secondFilename, "");//result will be in here
|
|
TagEntryQValue(TagTableQDirect(image1tt, "image vfb", 0), &image1);
|
|
TagEntryQValue(TagTableQDirect(nextImage, "image vfb", 0), &img);
|
|
|
|
//image is the composite of those two
|
|
fields = IMRED | IMGREEN | IMBLUE;
|
|
if (ImVfbQFields(img) && IMVFBALPHA)
|
|
{
|
|
fields |= IMALPHA;
|
|
}
|
|
|
|
ImVfbComp(image1, 0, 0, ImVfbQWidth(img), ImVfbQHeight(img), fields, IMCOMPOVER, img, 0, 0);
|
|
//free image1tt, it's not needed any more
|
|
ZimFree(image1tt);
|
|
}
|
|
}
|
|
|
|
return nextImage;
|
|
}
|
|
BOOL ParamImSeqCurrentImageHasAlpha(ParamImSeq *self)
|
|
{
|
|
return self->hasAlpha;
|
|
}
|
|
BOOL ParamImSeqCurrentImageHadAlpha(ParamImSeq *self)
|
|
{
|
|
return ParamImSeqCurrentImageHasAlpha(self);
|
|
}
|