lotsa movie cleanups, added truecolor mve support, standalone mveplayer

This commit is contained in:
Bradley Bell 2003-02-12 08:58:38 +00:00
parent 5c138be691
commit e1c12d4452
8 changed files with 2356 additions and 1198 deletions

View file

@ -1,10 +1,6 @@
#ifndef INCLUDED_MVE_AUDIO_H
#define INCLUDED_MVE_AUDIO_H
#define MVE_AUDIO_FLAGS_STEREO 1
#define MVE_AUDIO_FLAGS_16BIT 2
#define MVE_AUDIO_FLAGS_COMPRESSED 4
void mveaudio_uncompress(short *buffer, unsigned char *data, int length);
#endif /* INCLUDED_MVE_AUDIO_H */

View file

@ -19,12 +19,14 @@ typedef struct MVEFILE
/*
* open a .MVE file
*/
MVEFILE *mvefile_open(int filehandle);
MVEFILE *mvefile_open(const char *filename);
MVEFILE *mvefile_open_filehandle(int filehandle);
/*
* close a .MVE file
*/
void mvefile_close(MVEFILE *movie);
void mvefile_close_filehandle(MVEFILE *movie);
/*
* get size of next segment in chunk (-1 if no more segments in chunk)
@ -75,12 +77,14 @@ typedef struct MVESTREAM
/*
* open an MVE stream
*/
MVESTREAM *mve_open(int filehandle);
MVESTREAM *mve_open(const char *filename);
MVESTREAM *mve_open_filehandle(int filehandle);
/*
* close an MVE stream
*/
void mve_close(MVESTREAM *movie);
void mve_close_filehandle(MVESTREAM *movie);
/*
* set segment type handler

717
main/decoder16.c Normal file
View file

@ -0,0 +1,717 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int g_width, g_height;
extern void *g_vBackBuf1, *g_vBackBuf2;
/* 16 bit decoding routines */
static unsigned short *backBuf1, *backBuf2;
static int lookup_initialized;
static void dispatchDecoder16(unsigned short **pFrame, unsigned char codeType, unsigned char **pData, unsigned char **pOffData, int *pDataRemain, int *curXb, int *curYb);
static void genLoopkupTable();
void decodeFrame16(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain)
{
unsigned char *pOrig;
unsigned char *pOffData, *pEnd;
unsigned short offset;
int length;
int op;
int i, j;
int xb, yb;
if (!lookup_initialized) {
genLoopkupTable();
}
backBuf1 = (unsigned short *)g_vBackBuf1;
backBuf2 = (unsigned short *)g_vBackBuf2;
xb = g_width >> 3;
yb = g_height >> 3;
offset = pData[0]|(pData[1]<<8);
pOffData = pData + offset;
pEnd = pData + offset;
pData += 2;
pOrig = pData;
length = offset - 2; /*dataRemain-2;*/
for (j=0; j<yb; j++)
{
for (i=0; i<xb/2; i++)
{
op = (*pMap) & 0xf;
dispatchDecoder16((unsigned short **)&pFrame, op, &pData, &pOffData, &dataRemain, &i, &j);
/*
if ((unsigned short *)pFrame < backBuf1)
fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
else if ((unsigned short *)pFrame >= backBuf1 + g_width*g_height)
fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
*/
op = ((*pMap) >> 4) & 0xf;
dispatchDecoder16((unsigned short **)&pFrame, op, &pData, &pOffData, &dataRemain, &i, &j);
/*
if ((unsigned short *)pFrame < backBuf1)
fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
else if ((unsigned short *)pFrame >= backBuf1 + g_width*g_height)
fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
*/
++pMap;
--mapRemain;
}
pFrame += 7*g_width*2;
}
if ((length-(pData-pOrig)) != 0) {
fprintf(stderr, "DEBUG: junk left over: %d,%d,%d\n", (pData-pOrig), length, (length-(pData-pOrig)));
}
}
static unsigned short GETPIXEL(unsigned char **buf, int off)
{
unsigned short val = (*buf)[0+off] | ((*buf)[1+off] << 8);
return val;
}
static unsigned short GETPIXELI(unsigned char **buf, int off)
{
unsigned short val = (*buf)[0+off] | ((*buf)[1+off] << 8);
(*buf) += 2;
return val;
}
static void relClose(int i, int *x, int *y)
{
int ma, mi;
ma = i >> 4;
mi = i & 0xf;
*x = mi - 8;
*y = ma - 8;
}
static void relFar(int i, int sign, int *x, int *y)
{
if (i < 56)
{
*x = sign * (8 + (i % 7));
*y = sign * (i / 7);
}
else
{
*x = sign * (-14 + (i - 56) % 29);
*y = sign * (8 + (i - 56) / 29);
}
}
static int close_table[512];
static int far_p_table[512];
static int far_n_table[512];
static void genLoopkupTable()
{
int i;
int x, y;
for (i = 0; i < 256; i++) {
relClose(i, &x, &y);
close_table[i*2+0] = x;
close_table[i*2+1] = y;
relFar(i, 1, &x, &y);
far_p_table[i*2+0] = x;
far_p_table[i*2+1] = y;
relFar(i, -1, &x, &y);
far_n_table[i*2+0] = x;
far_n_table[i*2+1] = y;
}
lookup_initialized = 1;
}
static void copyFrame(unsigned short *pDest, unsigned short *pSrc)
{
int i;
for (i=0; i<8; i++)
{
memcpy(pDest, pSrc, 16);
pDest += g_width;
pSrc += g_width;
}
}
static void patternRow4Pixels(unsigned short *pFrame,
unsigned char pat0, unsigned char pat1,
unsigned short *p)
{
unsigned short mask=0x0003;
unsigned short shift=0;
unsigned short pattern = (pat1 << 8) | pat0;
while (mask != 0)
{
*pFrame++ = p[(mask & pattern) >> shift];
mask <<= 2;
shift += 2;
}
}
static void patternRow4Pixels2(unsigned short *pFrame,
unsigned char pat0,
unsigned short *p)
{
unsigned char mask=0x03;
unsigned char shift=0;
unsigned short pel;
/* ORIGINAL VERSION IS BUGGY
int skip=1;
while (mask != 0)
{
pel = p[(mask & pat0) >> shift];
pFrame[0] = pel;
pFrame[2] = pel;
pFrame[g_width + 0] = pel;
pFrame[g_width + 2] = pel;
pFrame += skip;
skip = 4 - skip;
mask <<= 2;
shift += 2;
}
*/
while (mask != 0)
{
pel = p[(mask & pat0) >> shift];
pFrame[0] = pel;
pFrame[1] = pel;
pFrame[g_width + 0] = pel;
pFrame[g_width + 1] = pel;
pFrame += 2;
mask <<= 2;
shift += 2;
}
}
static void patternRow4Pixels2x1(unsigned short *pFrame, unsigned char pat,
unsigned short *p)
{
unsigned char mask=0x03;
unsigned char shift=0;
unsigned short pel;
while (mask != 0)
{
pel = p[(mask & pat) >> shift];
pFrame[0] = pel;
pFrame[1] = pel;
pFrame += 2;
mask <<= 2;
shift += 2;
}
}
static void patternQuadrant4Pixels(unsigned short *pFrame,
unsigned char pat0, unsigned char pat1, unsigned char pat2,
unsigned char pat3, unsigned short *p)
{
unsigned long mask = 0x00000003UL;
int shift=0;
int i;
unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0;
for (i=0; i<16; i++)
{
pFrame[i&3] = p[(pat & mask) >> shift];
if ((i&3) == 3)
pFrame += g_width;
mask <<= 2;
shift += 2;
}
}
static void patternRow2Pixels(unsigned short *pFrame, unsigned char pat,
unsigned short *p)
{
unsigned char mask=0x01;
while (mask != 0)
{
*pFrame++ = p[(mask & pat) ? 1 : 0];
mask <<= 1;
}
}
static void patternRow2Pixels2(unsigned short *pFrame, unsigned char pat,
unsigned short *p)
{
unsigned short pel;
unsigned char mask=0x1;
/* ORIGINAL VERSION IS BUGGY
int skip=1;
while (mask != 0x10)
{
pel = p[(mask & pat) ? 1 : 0];
pFrame[0] = pel;
pFrame[2] = pel;
pFrame[g_width + 0] = pel;
pFrame[g_width + 2] = pel;
pFrame += skip;
skip = 4 - skip;
mask <<= 1;
}
*/
while (mask != 0x10) {
pel = p[(mask & pat) ? 1 : 0];
pFrame[0] = pel;
pFrame[1] = pel;
pFrame[g_width + 0] = pel;
pFrame[g_width + 1] = pel;
pFrame += 2;
mask <<= 1;
}
}
static void patternQuadrant2Pixels(unsigned short *pFrame, unsigned char pat0,
unsigned char pat1, unsigned short *p)
{
unsigned short mask = 0x0001;
int i;
unsigned short pat = (pat1 << 8) | pat0;
for (i=0; i<16; i++)
{
pFrame[i&3] = p[(pat & mask) ? 1 : 0];
if ((i&3) == 3)
pFrame += g_width;
mask <<= 1;
}
}
static void dispatchDecoder16(unsigned short **pFrame, unsigned char codeType, unsigned char **pData, unsigned char **pOffData, int *pDataRemain, int *curXb, int *curYb)
{
unsigned short p[4];
unsigned char pat[16];
int i, j, k;
int x, y;
unsigned short *pDstBak;
pDstBak = *pFrame;
switch(codeType)
{
case 0x0:
copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1));
case 0x1:
break;
case 0x2: /*
relFar(*(*pOffData)++, 1, &x, &y);
*/
k = *(*pOffData)++;
x = far_p_table[k*2+0];
y = far_p_table[k*2+1];
copyFrame(*pFrame, *pFrame + x + y*g_width);
--*pDataRemain;
break;
case 0x3: /*
relFar(*(*pOffData)++, -1, &x, &y);
*/
k = *(*pOffData)++;
x = far_n_table[k*2+0];
y = far_n_table[k*2+1];
copyFrame(*pFrame, *pFrame + x + y*g_width);
--*pDataRemain;
break;
case 0x4: /*
relClose(*(*pOffData)++, &x, &y);
*/
k = *(*pOffData)++;
x = close_table[k*2+0];
y = close_table[k*2+1];
copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1) + x + y*g_width);
--*pDataRemain;
break;
case 0x5:
x = (char)*(*pData)++;
y = (char)*(*pData)++;
copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1) + x + y*g_width);
*pDataRemain -= 2;
break;
case 0x6:
fprintf(stderr, "STUB: encoding 6 not tested\n");
for (i=0; i<2; i++)
{
*pFrame += 16;
if (++*curXb == (g_width >> 3))
{
*pFrame += 7*g_width;
*curXb = 0;
if (++*curYb == (g_height >> 3))
return;
}
}
break;
case 0x7:
p[0] = GETPIXELI(pData, 0);
p[1] = GETPIXELI(pData, 0);
if (!((p[0]/*|p[1]*/)&0x8000))
{
for (i=0; i<8; i++)
{
patternRow2Pixels(*pFrame, *(*pData), p);
(*pData)++;
*pFrame += g_width;
}
}
else
{
for (i=0; i<2; i++)
{
patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p);
*pFrame += 2*g_width;
patternRow2Pixels2(*pFrame, *(*pData) >> 4, p);
(*pData)++;
*pFrame += 2*g_width;
}
}
break;
case 0x8:
p[0] = GETPIXEL(pData, 0);
if (!(p[0] & 0x8000))
{
for (i=0; i<4; i++)
{
p[0] = GETPIXELI(pData, 0);
p[1] = GETPIXELI(pData, 0);
pat[0] = (*pData)[0];
pat[1] = (*pData)[1];
(*pData) += 2;
patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
if (i & 1)
*pFrame -= (4*g_width - 4);
else
*pFrame += 4*g_width;
}
} else {
p[2] = GETPIXEL(pData, 8);
if (!(p[2]&0x8000)) {
for (i=0; i<4; i++)
{
if ((i & 1) == 0)
{
p[0] = GETPIXELI(pData, 0);
p[1] = GETPIXELI(pData, 0);
}
pat[0] = *(*pData)++;
pat[1] = *(*pData)++;
patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
if (i & 1)
*pFrame -= (4*g_width - 4);
else
*pFrame += 4*g_width;
}
} else {
for (i=0; i<8; i++)
{
if ((i & 3) == 0)
{
p[0] = GETPIXELI(pData, 0);
p[1] = GETPIXELI(pData, 0);
}
patternRow2Pixels(*pFrame, *(*pData), p);
(*pData)++;
*pFrame += g_width;
}
}
}
break;
case 0x9:
p[0] = GETPIXELI(pData, 0);
p[1] = GETPIXELI(pData, 0);
p[2] = GETPIXELI(pData, 0);
p[3] = GETPIXELI(pData, 0);
*pDataRemain -= 8;
if (!(p[0] & 0x8000))
{
if (!(p[2] & 0x8000))
{
for (i=0; i<8; i++)
{
pat[0] = (*pData)[0];
pat[1] = (*pData)[1];
(*pData) += 2;
patternRow4Pixels(*pFrame, pat[0], pat[1], p);
*pFrame += g_width;
}
*pDataRemain -= 16;
}
else
{
patternRow4Pixels2(*pFrame, (*pData)[0], p);
*pFrame += 2*g_width;
patternRow4Pixels2(*pFrame, (*pData)[1], p);
*pFrame += 2*g_width;
patternRow4Pixels2(*pFrame, (*pData)[2], p);
*pFrame += 2*g_width;
patternRow4Pixels2(*pFrame, (*pData)[3], p);
(*pData) += 4;
*pDataRemain -= 4;
}
}
else
{
if (!(p[2] & 0x8000))
{
for (i=0; i<8; i++)
{
pat[0] = (*pData)[0];
(*pData) += 1;
patternRow4Pixels2x1(*pFrame, pat[0], p);
*pFrame += g_width;
}
*pDataRemain -= 8;
}
else
{
for (i=0; i<4; i++)
{
pat[0] = (*pData)[0];
pat[1] = (*pData)[1];
(*pData) += 2;
patternRow4Pixels(*pFrame, pat[0], pat[1], p);
*pFrame += g_width;
patternRow4Pixels(*pFrame, pat[0], pat[1], p);
*pFrame += g_width;
}
*pDataRemain -= 8;
}
}
break;
case 0xa:
p[0] = GETPIXEL(pData, 0);
if (!(p[0] & 0x8000))
{
for (i=0; i<4; i++)
{
p[0] = GETPIXELI(pData, 0);
p[1] = GETPIXELI(pData, 0);
p[2] = GETPIXELI(pData, 0);
p[3] = GETPIXELI(pData, 0);
pat[0] = (*pData)[0];
pat[1] = (*pData)[1];
pat[2] = (*pData)[2];
pat[3] = (*pData)[3];
(*pData) += 4;
patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
if (i & 1)
*pFrame -= (4*g_width - 4);
else
*pFrame += 4*g_width;
}
}
else
{
p[0] = GETPIXEL(pData, 16);
if (!(p[0] & 0x8000))
{
for (i=0; i<4; i++)
{
if ((i&1) == 0)
{
p[0] = GETPIXELI(pData, 0);
p[1] = GETPIXELI(pData, 0);
p[2] = GETPIXELI(pData, 0);
p[3] = GETPIXELI(pData, 0);
}
pat[0] = (*pData)[0];
pat[1] = (*pData)[1];
pat[2] = (*pData)[2];
pat[3] = (*pData)[3];
(*pData) += 4;
patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
if (i & 1)
*pFrame -= (4*g_width - 4);
else
*pFrame += 4*g_width;
}
}
else
{
for (i=0; i<8; i++)
{
if ((i&3) == 0)
{
p[0] = GETPIXELI(pData, 0);
p[1] = GETPIXELI(pData, 0);
p[2] = GETPIXELI(pData, 0);
p[3] = GETPIXELI(pData, 0);
}
pat[0] = (*pData)[0];
pat[1] = (*pData)[1];
patternRow4Pixels(*pFrame, pat[0], pat[1], p);
*pFrame += g_width;
(*pData) += 2;
}
}
}
break;
case 0xb:
for (i=0; i<8; i++)
{
memcpy(*pFrame, *pData, 16);
*pFrame += g_width;
*pData += 16;
*pDataRemain -= 16;
}
break;
case 0xc:
for (i=0; i<4; i++)
{
p[0] = GETPIXEL(pData, 0);
p[1] = GETPIXEL(pData, 2);
p[2] = GETPIXEL(pData, 4);
p[3] = GETPIXEL(pData, 6);
for (j=0; j<2; j++)
{
for (k=0; k<4; k++)
{
(*pFrame)[j+2*k] = p[k];
(*pFrame)[g_width+j+2*k] = p[k];
}
*pFrame += g_width;
}
*pData += 8;
*pDataRemain -= 8;
}
break;
case 0xd:
for (i=0; i<2; i++)
{
p[0] = GETPIXEL(pData, 0);
p[1] = GETPIXEL(pData, 2);
for (j=0; j<4; j++)
{
for (k=0; k<4; k++)
{
(*pFrame)[k*g_width+j] = p[0];
(*pFrame)[k*g_width+j+4] = p[1];
}
}
*pFrame += 4*g_width;
*pData += 4;
*pDataRemain -= 4;
}
break;
case 0xe:
p[0] = GETPIXEL(pData, 0);
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
(*pFrame)[j] = p[0];
}
*pFrame += g_width;
}
*pData += 2;
*pDataRemain -= 2;
break;
case 0xf:
p[0] = GETPIXEL(pData, 0);
p[1] = GETPIXEL(pData, 1);
for (i=0; i<8; i++)
{
for (j=0; j<8; j++)
{
(*pFrame)[j] = p[(i+j)&1];
}
*pFrame += g_width;
}
*pData += 4;
*pDataRemain -= 4;
break;
default:
break;
}
*pFrame = pDstBak+8;
}

872
main/decoder8.c Normal file
View file

@ -0,0 +1,872 @@
#include <stdio.h>
#include <string.h>
extern int g_width, g_height;
extern void *g_vBackBuf1, *g_vBackBuf2;
/* 8 bit decoding routines */
static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb);
void decodeFrame8(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain)
{
int i, j;
int xb, yb;
xb = g_width >> 3;
yb = g_height >> 3;
for (j=0; j<yb; j++)
{
for (i=0; i<xb/2; i++)
{
dispatchDecoder(&pFrame, (*pMap) & 0xf, &pData, &dataRemain, &i, &j);
if (pFrame < (unsigned char *)g_vBackBuf1)
fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
else if (pFrame >= ((unsigned char *)g_vBackBuf1) + g_width*g_height)
fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
dispatchDecoder(&pFrame, (*pMap) >> 4, &pData, &dataRemain, &i, &j);
if (pFrame < (unsigned char *)g_vBackBuf1)
fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
else if (pFrame >= ((unsigned char *)g_vBackBuf1) + g_width*g_height)
fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
++pMap;
--mapRemain;
}
pFrame += 7*g_width;
}
}
static void relClose(int i, int *x, int *y)
{
int ma, mi;
ma = i >> 4;
mi = i & 0xf;
*x = mi - 8;
*y = ma - 8;
}
static void relFar(int i, int sign, int *x, int *y)
{
if (i < 56)
{
*x = sign * (8 + (i % 7));
*y = sign * (i / 7);
}
else
{
*x = sign * (-14 + (i - 56) % 29);
*y = sign * (8 + (i - 56) / 29);
}
}
/* copies an 8x8 block from pSrc to pDest.
pDest and pSrc are both g_width bytes wide */
static void copyFrame(unsigned char *pDest, unsigned char *pSrc)
{
int i;
for (i=0; i<8; i++)
{
memcpy(pDest, pSrc, 8);
pDest += g_width;
pSrc += g_width;
}
}
// Fill in the next eight bytes with p[0], p[1], p[2], or p[3],
// depending on the corresponding two-bit value in pat0 and pat1
static void patternRow4Pixels(unsigned char *pFrame,
unsigned char pat0, unsigned char pat1,
unsigned char *p)
{
unsigned short mask=0x0003;
unsigned short shift=0;
unsigned short pattern = (pat1 << 8) | pat0;
while (mask != 0)
{
*pFrame++ = p[(mask & pattern) >> shift];
mask <<= 2;
shift += 2;
}
}
// Fill in the next four 2x2 pixel blocks with p[0], p[1], p[2], or p[3],
// depending on the corresponding two-bit value in pat0.
static void patternRow4Pixels2(unsigned char *pFrame,
unsigned char pat0,
unsigned char *p)
{
unsigned char mask=0x03;
unsigned char shift=0;
unsigned char pel;
while (mask != 0)
{
pel = p[(mask & pat0) >> shift];
pFrame[0] = pel;
pFrame[1] = pel;
pFrame[g_width + 0] = pel;
pFrame[g_width + 1] = pel;
pFrame += 2;
mask <<= 2;
shift += 2;
}
}
// Fill in the next four 2x1 pixel blocks with p[0], p[1], p[2], or p[3],
// depending on the corresponding two-bit value in pat.
static void patternRow4Pixels2x1(unsigned char *pFrame, unsigned char pat, unsigned char *p)
{
unsigned char mask=0x03;
unsigned char shift=0;
unsigned char pel;
while (mask != 0)
{
pel = p[(mask & pat) >> shift];
pFrame[0] = pel;
pFrame[1] = pel;
pFrame += 2;
mask <<= 2;
shift += 2;
}
}
// Fill in the next 4x4 pixel block with p[0], p[1], p[2], or p[3],
// depending on the corresponding two-bit value in pat0, pat1, pat2, and pat3.
static void patternQuadrant4Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char pat2, unsigned char pat3, unsigned char *p)
{
unsigned long mask = 0x00000003UL;
int shift=0;
int i;
unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0;
for (i=0; i<16; i++)
{
pFrame[i&3] = p[(pat & mask) >> shift];
if ((i&3) == 3)
pFrame += g_width;
mask <<= 2;
shift += 2;
}
}
// fills the next 8 pixels with either p[0] or p[1], depending on pattern
static void patternRow2Pixels(unsigned char *pFrame, unsigned char pat, unsigned char *p)
{
unsigned char mask=0x01;
while (mask != 0)
{
*pFrame++ = p[(mask & pat) ? 1 : 0];
mask <<= 1;
}
}
// fills the next four 2 x 2 pixel boxes with either p[0] or p[1], depending on pattern
static void patternRow2Pixels2(unsigned char *pFrame, unsigned char pat, unsigned char *p)
{
unsigned char pel;
unsigned char mask=0x1;
while (mask != 0x10)
{
pel = p[(mask & pat) ? 1 : 0];
pFrame[0] = pel; // upper-left
pFrame[1] = pel; // upper-right
pFrame[g_width + 0] = pel; // lower-left
pFrame[g_width + 1] = pel; // lower-right
pFrame += 2;
mask <<= 1;
}
}
// fills pixels in the next 4 x 4 pixel boxes with either p[0] or p[1], depending on pat0 and pat1.
static void patternQuadrant2Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char *p)
{
unsigned char pel;
unsigned short mask = 0x0001;
int i, j;
unsigned short pat = (pat1 << 8) | pat0;
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
pel = p[(pat & mask) ? 1 : 0];
pFrame[j + i * g_width] = pel;
mask <<= 1;
}
}
}
static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb)
{
unsigned char p[4];
unsigned char pat[16];
int i, j, k;
int x, y;
/* Data is processed in 8x8 pixel blocks.
There are 16 ways to encode each block.
*/
switch(codeType)
{
case 0x0:
/* block is copied from block in current frame */
copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1));
case 0x1:
/* block is unchanged from two frames ago */
*pFrame += 8;
break;
case 0x2:
/* Block is copied from nearby (below and/or to the right) within the
new frame. The offset within the buffer from which to grab the
patch of 8 pixels is given by grabbing a byte B from the data
stream, which is broken into a positive x and y offset according
to the following mapping:
if B < 56:
x = 8 + (B % 7)
y = B / 7
else
x = -14 + ((B - 56) % 29)
y = 8 + ((B - 56) / 29)
*/
relFar(*(*pData)++, 1, &x, &y);
copyFrame(*pFrame, *pFrame + x + y*g_width);
*pFrame += 8;
--*pDataRemain;
break;
case 0x3:
/* Block is copied from nearby (above and/or to the left) within the
new frame.
if B < 56:
x = -(8 + (B % 7))
y = -(B / 7)
else
x = -(-14 + ((B - 56) % 29))
y = -( 8 + ((B - 56) / 29))
*/
relFar(*(*pData)++, -1, &x, &y);
copyFrame(*pFrame, *pFrame + x + y*g_width);
*pFrame += 8;
--*pDataRemain;
break;
case 0x4:
/* Similar to 0x2 and 0x3, except this method copies from the
"current" frame, rather than the "new" frame, and instead of the
lopsided mapping they use, this one uses one which is symmetric
and centered around the top-left corner of the block. This uses
only 1 byte still, though, so the range is decreased, since we
have to encode all directions in a single byte. The byte we pull
from the data stream, I'll call B. Call the highest 4 bits of B
BH and the lowest 4 bytes BL. Then the offset from which to copy
the data is:
x = -8 + BL
y = -8 + BH
*/
relClose(*(*pData)++, &x, &y);
copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1) + x + y*g_width);
*pFrame += 8;
--*pDataRemain;
break;
case 0x5:
/* Similar to 0x4, but instead of one byte for the offset, this uses
two bytes to encode a larger range, the first being the x offset
as a signed 8-bit value, and the second being the y offset as a
signed 8-bit value.
*/
x = (signed char)*(*pData)++;
y = (signed char)*(*pData)++;
copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1) + x + y*g_width);
*pFrame += 8;
*pDataRemain -= 2;
break;
case 0x6:
/* I can't figure out how any file containing a block of this type
could still be playable, since it appears that it would leave the
internal bookkeeping in an inconsistent state in the BG player
code. Ahh, well. Perhaps it was a bug in the BG player code that
just didn't happen to be exposed by any of the included movies.
Anyway, this skips the next two blocks, doing nothing to them.
Note that if you've reached the end of a row, this means going on
to the next row.
*/
for (i=0; i<2; i++)
{
*pFrame += 16;
if (++*curXb == (g_width >> 3))
{
*pFrame += 7*g_width;
*curXb = 0;
if (++*curYb == (g_height >> 3))
return;
}
}
break;
case 0x7:
/* Ok, here's where it starts to get really...interesting. This is,
incidentally, the part where they started using self-modifying
code. So, most of the following encodings are "patterned" blocks,
where we are given a number of pixel values and then bitmapped
values to specify which pixel values belong to which squares. For
this encoding, we are given the following in the data stream:
P0 P1
These are pixel values (i.e. 8-bit indices into the palette). If
P0 <= P1, we then get 8 more bytes from the data stream, one for
each row in the block:
B0 B1 B2 B3 B4 B5 B6 B7
For each row, the leftmost pixel is represented by the low-order
bit, and the rightmost by the high-order bit. Use your imagination
in between. If a bit is set, the pixel value is P1 and if it is
unset, the pixel value is P0.
So, for example, if we had:
11 22 fe 83 83 83 83 83 83 fe
This would represent the following layout:
11 22 22 22 22 22 22 22 ; fe == 11111110
22 22 11 11 11 11 11 22 ; 83 == 10000011
22 22 11 11 11 11 11 22 ; 83 == 10000011
22 22 11 11 11 11 11 22 ; 83 == 10000011
22 22 11 11 11 11 11 22 ; 83 == 10000011
22 22 11 11 11 11 11 22 ; 83 == 10000011
22 22 11 11 11 11 11 22 ; 83 == 10000011
11 22 22 22 22 22 22 22 ; fe == 11111110
If, on the other hand, P0 > P1, we get two more bytes from the
data stream:
B0 B1
Each of these bytes contains two 4-bit patterns. These patterns
work like the patterns above with 8 bytes, except each bit
represents a 2x2 pixel region.
B0 contains the pattern for the top two rows and B1 contains
the pattern for the bottom two rows. Note that the low-order
nibble of each byte contains the pattern for the upper of the
two rows that that byte controls.
So if we had:
22 11 7e 83
The output would be:
11 11 22 22 22 22 22 22 ; e == 1 1 1 0
11 11 22 22 22 22 22 22 ;
22 22 22 22 22 22 11 11 ; 7 == 0 1 1 1
22 22 22 22 22 22 11 11 ;
11 11 11 11 11 11 22 22 ; 3 == 1 0 0 0
11 11 11 11 11 11 22 22 ;
22 22 22 22 11 11 11 11 ; 8 == 0 0 1 1
22 22 22 22 11 11 11 11 ;
*/
p[0] = *(*pData)++;
p[1] = *(*pData)++;
if (p[0] <= p[1])
{
for (i=0; i<8; i++)
{
patternRow2Pixels(*pFrame, *(*pData)++, p);
*pFrame += g_width;
}
}
else
{
for (i=0; i<2; i++)
{
patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p);
*pFrame += 2*g_width;
patternRow2Pixels2(*pFrame, *(*pData)++ >> 4, p);
*pFrame += 2*g_width;
}
}
*pFrame -= (8*g_width - 8);
break;
case 0x8:
/* Ok, this one is basically like encoding 0x7, only more
complicated. Again, we start out by getting two bytes on the data
stream:
P0 P1
if P0 <= P1 then we get the following from the data stream:
B0 B1
P2 P3 B2 B3
P4 P5 B4 B5
P6 P7 B6 B7
P0 P1 and B0 B1 are used for the top-left corner, P2 P3 B2 B3 for
the bottom-left corner, P4 P5 B4 B5 for the top-right, P6 P7 B6 B7
for the bottom-right. (So, each codes for a 4x4 pixel array.)
Since we have 16 bits in B0 B1, there is one bit for each pixel in
the array. The convention for the bit-mapping is, again, left to
right and top to bottom.
So, basically, the top-left quarter of the block is an arbitrary
pattern with 2 pixels, the bottom-left a different arbitrary
pattern with 2 different pixels, and so on.
For example if the next 16 bytes were:
00 22 f9 9f 44 55 aa 55 11 33 cc 33 66 77 01 ef
We'd draw:
22 22 22 22 | 11 11 33 33 ; f = 1111, c = 1100
22 00 00 22 | 11 11 33 33 ; 9 = 1001, c = 1100
22 00 00 22 | 33 33 11 11 ; 9 = 1001, 3 = 0011
22 22 22 22 | 33 33 11 11 ; f = 1111, 3 = 0011
------------+------------
44 55 44 55 | 66 66 66 66 ; a = 1010, 0 = 0000
44 55 44 55 | 77 66 66 66 ; a = 1010, 1 = 0001
55 44 55 44 | 66 77 77 77 ; 5 = 0101, e = 1110
55 44 55 44 | 77 77 77 77 ; 5 = 0101, f = 1111
I've added a dividing line in the above to clearly delineate the
quadrants.
Now, if P0 > P1 then we get 10 more bytes from the data stream:
B0 B1 B2 B3 P2 P3 B4 B5 B6 B7
Now, if P2 <= P3, then the first six bytes [P0 P1 B0 B1 B2 B3]
represent the left half of the block and the latter six bytes
[P2 P3 B4 B5 B6 B7] represent the right half.
For example:
22 00 01 37 f7 31 11 66 8c e6 73 31
yeilds:
22 22 22 22 | 11 11 11 66 ; 0: 0000 | 8: 1000
00 22 22 22 | 11 11 66 66 ; 1: 0001 | C: 1100
00 00 22 22 | 11 66 66 66 ; 3: 0011 | e: 1110
00 00 00 22 | 11 66 11 66 ; 7: 0111 | 6: 0101
00 00 00 00 | 66 66 66 11 ; f: 1111 | 7: 0111
00 00 00 22 | 66 66 11 11 ; 7: 0111 | 3: 0011
00 00 22 22 | 66 66 11 11 ; 3: 0011 | 3: 0011
00 22 22 22 | 66 11 11 11 ; 1: 0001 | 1: 0001
On the other hand, if P0 > P1 and P2 > P3, then
[P0 P1 B0 B1 B2 B3] represent the top half of the
block and [P2 P3 B4 B5 B6 B7] represent the bottom half.
For example:
22 00 cc 66 33 19 66 11 18 24 42 81
yeilds:
22 22 00 00 22 22 00 00 ; cc: 11001100
22 00 00 22 22 00 00 22 ; 66: 01100110
00 00 22 22 00 00 22 22 ; 33: 00110011
00 22 22 00 00 22 22 22 ; 19: 00011001
-----------------------
66 66 66 11 11 66 66 66 ; 18: 00011000
66 66 11 66 66 11 66 66 ; 24: 00100100
66 11 66 66 66 66 11 66 ; 42: 01000010
11 66 66 66 66 66 66 11 ; 81: 10000001
*/
if ( (*pData)[0] <= (*pData)[1])
{
// four quadrant case
for (i=0; i<4; i++)
{
p[0] = *(*pData)++;
p[1] = *(*pData)++;
pat[0] = *(*pData)++;
pat[1] = *(*pData)++;
patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
// alternate between moving down and moving up and right
if (i & 1)
*pFrame += 4 - 4*g_width; // up and right
else
*pFrame += 4*g_width; // down
}
}
else if ( (*pData)[6] <= (*pData)[7])
{
// split horizontal
for (i=0; i<4; i++)
{
if ((i & 1) == 0)
{
p[0] = *(*pData)++;
p[1] = *(*pData)++;
}
pat[0] = *(*pData)++;
pat[1] = *(*pData)++;
patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
if (i & 1)
*pFrame -= (4*g_width - 4);
else
*pFrame += 4*g_width;
}
}
else
{
// split vertical
for (i=0; i<8; i++)
{
if ((i & 3) == 0)
{
p[0] = *(*pData)++;
p[1] = *(*pData)++;
}
patternRow2Pixels(*pFrame, *(*pData)++, p);
*pFrame += g_width;
}
*pFrame -= (8*g_width - 8);
}
break;
case 0x9:
/* Similar to the previous 2 encodings, only more complicated. And
it will get worse before it gets better. No longer are we dealing
with patterns over two pixel values. Now we are dealing with
patterns over 4 pixel values with 2 bits assigned to each pixel
(or block of pixels).
So, first on the data stream are our 4 pixel values:
P0 P1 P2 P3
Now, if P0 <= P1 AND P2 <= P3, we get 16 bytes of pattern, each
2 bits representing a 1x1 pixel (00=P0, 01=P1, 10=P2, 11=P3). The
ordering is again left to right and top to bottom. The most
significant bits represent the left side at the top, and so on.
If P0 <= P1 AND P2 > P3, we get 4 bytes of pattern, each 2 bits
representing a 2x2 pixel. Ordering is left to right and top to
bottom.
if P0 > P1 AND P2 <= P3, we get 8 bytes of pattern, each 2 bits
representing a 2x1 pixel (i.e. 2 pixels wide, and 1 high).
if P0 > P1 AND P2 > P3, we get 8 bytes of pattern, each 2 bits
representing a 1x2 pixel (i.e. 1 pixel wide, and 2 high).
*/
if ( (*pData)[0] <= (*pData)[1])
{
if ( (*pData)[2] <= (*pData)[3])
{
p[0] = *(*pData)++;
p[1] = *(*pData)++;
p[2] = *(*pData)++;
p[3] = *(*pData)++;
for (i=0; i<8; i++)
{
pat[0] = *(*pData)++;
pat[1] = *(*pData)++;
patternRow4Pixels(*pFrame, pat[0], pat[1], p);
*pFrame += g_width;
}
*pFrame -= (8*g_width - 8);
}
else
{
p[0] = *(*pData)++;
p[1] = *(*pData)++;
p[2] = *(*pData)++;
p[3] = *(*pData)++;
patternRow4Pixels2(*pFrame, *(*pData)++, p);
*pFrame += 2*g_width;
patternRow4Pixels2(*pFrame, *(*pData)++, p);
*pFrame += 2*g_width;
patternRow4Pixels2(*pFrame, *(*pData)++, p);
*pFrame += 2*g_width;
patternRow4Pixels2(*pFrame, *(*pData)++, p);
*pFrame -= (6*g_width - 8);
}
}
else
{
if ( (*pData)[2] <= (*pData)[3])
{
// draw 2x1 strips
p[0] = *(*pData)++;
p[1] = *(*pData)++;
p[2] = *(*pData)++;
p[3] = *(*pData)++;
for (i=0; i<8; i++)
{
pat[0] = *(*pData)++;
patternRow4Pixels2x1(*pFrame, pat[0], p);
*pFrame += g_width;
}
*pFrame -= (8*g_width - 8);
}
else
{
// draw 1x2 strips
p[0] = *(*pData)++;
p[1] = *(*pData)++;
p[2] = *(*pData)++;
p[3] = *(*pData)++;
for (i=0; i<4; i++)
{
pat[0] = *(*pData)++;
pat[1] = *(*pData)++;
patternRow4Pixels(*pFrame, pat[0], pat[1], p);
*pFrame += g_width;
patternRow4Pixels(*pFrame, pat[0], pat[1], p);
*pFrame += g_width;
}
*pFrame -= (8*g_width - 8);
}
}
break;
case 0xa:
/* Similar to the previous, only a little more complicated.
We are still dealing with patterns over 4 pixel values with 2 bits
assigned to each pixel (or block of pixels).
So, first on the data stream are our 4 pixel values:
P0 P1 P2 P3
Now, if P0 <= P1, the block is divided into 4 quadrants, ordered
(as with opcode 0x8) TL, BL, TR, BR. In this case the next data
in the data stream should be:
B0 B1 B2 B3
P4 P5 P6 P7 B4 B5 B6 B7
P8 P9 P10 P11 B8 B9 B10 B11
P12 P13 P14 P15 B12 B13 B14 B15
Each 2 bits represent a 1x1 pixel (00=P0, 01=P1, 10=P2, 11=P3).
The ordering is again left to right and top to bottom. The most
significant bits represent the right side at the top, and so on.
If P0 > P1 then the next data on the data stream is:
B0 B1 B2 B3 B4 B5 B6 B7
P4 P5 P6 P7 B8 B9 B10 B11 B12 B13 B14 B15
Now, in this case, if P4 <= P5,
[P0 P1 P2 P3 B0 B1 B2 B3 B4 B5 B6 B7] represent the left half of
the block and the other bytes represent the right half. If P4 >
P5, then [P0 P1 P2 P3 B0 B1 B2 B3 B4 B5 B6 B7] represent the top
half of the block and the other bytes represent the bottom half.
*/
if ( (*pData)[0] <= (*pData)[1])
{
for (i=0; i<4; i++)
{
p[0] = *(*pData)++;
p[1] = *(*pData)++;
p[2] = *(*pData)++;
p[3] = *(*pData)++;
pat[0] = *(*pData)++;
pat[1] = *(*pData)++;
pat[2] = *(*pData)++;
pat[3] = *(*pData)++;
patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
if (i & 1)
*pFrame -= (4*g_width - 4);
else
*pFrame += 4*g_width;
}
}
else
{
if ( (*pData)[12] <= (*pData)[13])
{
// split vertical
for (i=0; i<4; i++)
{
if ((i&1) == 0)
{
p[0] = *(*pData)++;
p[1] = *(*pData)++;
p[2] = *(*pData)++;
p[3] = *(*pData)++;
}
pat[0] = *(*pData)++;
pat[1] = *(*pData)++;
pat[2] = *(*pData)++;
pat[3] = *(*pData)++;
patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
if (i & 1)
*pFrame -= (4*g_width - 4);
else
*pFrame += 4*g_width;
}
}
else
{
// split horizontal
for (i=0; i<8; i++)
{
if ((i&3) == 0)
{
p[0] = *(*pData)++;
p[1] = *(*pData)++;
p[2] = *(*pData)++;
p[3] = *(*pData)++;
}
pat[0] = *(*pData)++;
pat[1] = *(*pData)++;
patternRow4Pixels(*pFrame, pat[0], pat[1], p);
*pFrame += g_width;
}
*pFrame -= (8*g_width - 8);
}
}
break;
case 0xb:
/* In this encoding we get raw pixel data in the data stream -- 64
bytes of pixel data. 1 byte for each pixel, and in the standard
order (l->r, t->b).
*/
for (i=0; i<8; i++)
{
memcpy(*pFrame, *pData, 8);
*pFrame += g_width;
*pData += 8;
*pDataRemain -= 8;
}
*pFrame -= (8*g_width - 8);
break;
case 0xc:
/* In this encoding we get raw pixel data in the data stream -- 16
bytes of pixel data. 1 byte for each block of 2x2 pixels, and in
the standard order (l->r, t->b).
*/
for (i=0; i<4; i++)
{
for (j=0; j<2; j++)
{
for (k=0; k<4; k++)
{
(*pFrame)[2*k] = (*pData)[k];
(*pFrame)[2*k+1] = (*pData)[k];
}
*pFrame += g_width;
}
*pData += 4;
*pDataRemain -= 4;
}
*pFrame -= (8*g_width - 8);
break;
case 0xd:
/* In this encoding we get raw pixel data in the data stream -- 4
bytes of pixel data. 1 byte for each block of 4x4 pixels, and in
the standard order (l->r, t->b).
*/
for (i=0; i<2; i++)
{
for (j=0; j<4; j++)
{
for (k=0; k<4; k++)
{
(*pFrame)[k*g_width+j] = (*pData)[0];
(*pFrame)[k*g_width+j+4] = (*pData)[1];
}
}
*pFrame += 4*g_width;
*pData += 2;
*pDataRemain -= 2;
}
*pFrame -= (8*g_width - 8);
break;
case 0xe:
/* This encoding represents a solid 8x8 frame. We get 1 byte of pixel
data from the data stream.
*/
for (i=0; i<8; i++)
{
memset(*pFrame, **pData, 8);
*pFrame += g_width;
}
++*pData;
--*pDataRemain;
*pFrame -= (8*g_width - 8);
break;
case 0xf:
/* This encoding represents a "dithered" frame, which is
checkerboarded with alternate pixels of two colors. We get 2
bytes of pixel data from the data stream, and these bytes are
alternated:
P0 P1 P0 P1 P0 P1 P0 P1
P1 P0 P1 P0 P1 P0 P1 P0
...
P0 P1 P0 P1 P0 P1 P0 P1
P1 P0 P1 P0 P1 P0 P1 P0
*/
for (i=0; i<8; i++)
{
for (j=0; j<8; j++)
{
(*pFrame)[j] = (*pData)[(i+j)&1];
}
*pFrame += g_width;
}
*pData += 2;
*pDataRemain -= 2;
*pFrame -= (8*g_width - 8);
break;
default:
break;
}
}

View file

@ -1,4 +1,4 @@
/* $Id: movie.c,v 1.14 2003-01-09 00:57:42 btb Exp $ */
/* $Id: movie.c,v 1.15 2003-02-12 08:58:38 btb Exp $ */
/*
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
@ -17,7 +17,7 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
#endif
#ifdef RCS
static char rcsid[] = "$Id: movie.c,v 1.14 2003-01-09 00:57:42 btb Exp $";
static char rcsid[] = "$Id: movie.c,v 1.15 2003-02-12 08:58:38 btb Exp $";
#endif
#define DEBUG_LEVEL CON_NORMAL
@ -282,7 +282,7 @@ int RunMovie(char *filename, int hires_flag, int must_have,int dx,int dy)
FontHires = FontHiresAvailable && hires_flag;
mve = mve_open(filehndl);
mve = mve_open_filehandle(filehndl);
mve_bitmap = gr_create_bitmap(w, h); // w, h must match the mve exactly!
@ -364,7 +364,7 @@ int RotateRobot()
mveplay_shutdownMovie(Robo_mve);
mve_close(Robo_mve);
lseek(RoboFile, Robo_filepos, SEEK_SET);
Robo_mve = mve_open(RoboFile);
Robo_mve = mve_open_filehandle(RoboFile);
mveplay_initializeMovie(Robo_mve, Robo_bitmap);
}
@ -394,7 +394,7 @@ int InitRobotMovie(char *filename)
Robo_filepos = lseek(RoboFile, 0, SEEK_CUR);
Robo_mve = mve_open(RoboFile);
Robo_mve = mve_open_filehandle(RoboFile);
Robo_bitmap = gr_create_bitmap(MenuHires?320:160, MenuHires?200:88);

51
main/mve_main.c Normal file
View file

@ -0,0 +1,51 @@
#include <SDL/SDL.h>
#include "mvelib.h"
extern int g_spdFactorNum;
void initializeMovie(MVESTREAM *mve);
void playMovie(MVESTREAM *mve);
void shutdownMovie(MVESTREAM *mve);
static void usage(void)
{
fprintf(stderr, "usage: mveplay filename\n");
exit(1);
}
static int doPlay(const char *filename)
{
MVESTREAM *mve = mve_open(filename);
if (mve == NULL)
{
fprintf(stderr, "can't open MVE file '%s'\n", filename);
return 1;
}
initializeMovie(mve);
playMovie(mve);
shutdownMovie(mve);
mve_close(mve);
return 0;
}
int main(int c, char **v)
{
if (c != 2 && c != 3)
usage();
if (c == 3)
g_spdFactorNum = atoi(v[2]);
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
{
fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
exit(1);
}
atexit(SDL_Quit);
return doPlay(v[1]);
}

View file

@ -1,5 +1,8 @@
#include <string.h> // for mem* functions
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "mvelib.h"
@ -12,13 +15,16 @@ static const short MVE_HDRCONST3 = 0x1133;
* private utility functions
*/
static short _mve_get_short(unsigned char *data);
static unsigned short _mve_get_ushort(unsigned char *data);
/*
* private functions for mvefile
*/
static MVEFILE *_mvefile_alloc(void);
static void _mvefile_free(MVEFILE *movie);
static int _mvefile_open(MVEFILE *movie, int filehandle);
static void _mvefile_free_filehandle(MVEFILE *movie);
static int _mvefile_open(MVEFILE *movie, const char *filename);
static int _mvefile_open_filehandle(MVEFILE *movie, int filehandle);
static int _mvefile_read_header(MVEFILE *movie);
static void _mvefile_set_buffer_size(MVEFILE *movie, int buf_size);
static int _mvefile_fetch_next_chunk(MVEFILE *movie);
@ -28,7 +34,9 @@ static int _mvefile_fetch_next_chunk(MVEFILE *movie);
*/
static MVESTREAM *_mvestream_alloc(void);
static void _mvestream_free(MVESTREAM *movie);
static int _mvestream_open(MVESTREAM *movie, int filehandle);
static void _mvestream_free_filehandle(MVESTREAM *movie);
static int _mvestream_open(MVESTREAM *movie, const char *filename);
static int _mvestream_open_filehandle(MVESTREAM *movie, int filehandle);
/************************************************************
* public MVEFILE functions
@ -37,13 +45,13 @@ static int _mvestream_open(MVESTREAM *movie, int filehandle);
/*
* open an MVE file
*/
MVEFILE *mvefile_open(filehandle)
MVEFILE *mvefile_open(const char *filename)
{
MVEFILE *file;
/* create the file */
file = _mvefile_alloc();
if (! _mvefile_open(file, filehandle))
if (! _mvefile_open(file, filename))
{
_mvefile_free(file);
return NULL;
@ -65,6 +73,34 @@ MVEFILE *mvefile_open(filehandle)
return file;
}
MVEFILE *mvefile_open_filehandle(int filehandle)
{
MVEFILE *file;
/* create the file */
file = _mvefile_alloc();
if (! _mvefile_open_filehandle(file, filehandle))
{
_mvefile_free_filehandle(file);
return NULL;
}
/* initialize the file */
_mvefile_set_buffer_size(file, 1024);
/* verify the file's header */
if (! _mvefile_read_header(file))
{
_mvefile_free_filehandle(file);
return NULL;
}
/* now, prefetch the next chunk */
_mvefile_fetch_next_chunk(file);
return file;
}
/*
* close a MVE file
*/
@ -73,6 +109,11 @@ void mvefile_close(MVEFILE *movie)
_mvefile_free(movie);
}
void mvefile_close_filehandle(MVEFILE *movie)
{
_mvefile_free_filehandle(movie);
}
/*
* get the size of the next segment
*/
@ -157,7 +198,7 @@ void mvefile_advance_segment(MVEFILE *movie)
/* else, advance to next segment */
movie->next_segment +=
(4 + _mve_get_short(movie->cur_chunk + movie->next_segment));
(4 + _mve_get_ushort(movie->cur_chunk + movie->next_segment));
}
/*
@ -175,7 +216,7 @@ int mvefile_fetch_next_chunk(MVEFILE *movie)
/*
* open an MVE stream
*/
MVESTREAM *mve_open(int filehandle)
MVESTREAM *mve_open(const char *filename)
{
MVESTREAM *movie;
@ -183,7 +224,7 @@ MVESTREAM *mve_open(int filehandle)
movie = _mvestream_alloc();
/* open */
if (! _mvestream_open(movie, filehandle))
if (! _mvestream_open(movie, filename))
{
_mvestream_free(movie);
return NULL;
@ -192,6 +233,23 @@ MVESTREAM *mve_open(int filehandle)
return movie;
}
MVESTREAM *mve_open_filehandle(int filehandle)
{
MVESTREAM *movie;
/* allocate */
movie = _mvestream_alloc();
/* open */
if (! _mvestream_open_filehandle(movie, filehandle))
{
_mvestream_free_filehandle(movie);
return NULL;
}
return movie;
}
/*
* close an MVE stream
*/
@ -200,6 +258,11 @@ void mve_close(MVESTREAM *movie)
_mvestream_free(movie);
}
void mve_close_filehandle(MVESTREAM *movie)
{
_mvestream_free_filehandle(movie);
}
/*
* set segment type handler
*/
@ -263,7 +326,7 @@ int mve_play_next_chunk(MVESTREAM *movie)
static MVEFILE *_mvefile_alloc(void)
{
MVEFILE *file = (MVEFILE *)malloc(sizeof(MVEFILE));
file->stream = 0;
file->stream = -1;
file->cur_chunk = NULL;
file->buf_size = 0;
file->cur_fill = 0;
@ -278,7 +341,28 @@ static MVEFILE *_mvefile_alloc(void)
static void _mvefile_free(MVEFILE *movie)
{
/* free the stream */
movie->stream = 0;
if (movie->stream != -1)
close(movie->stream);
movie->stream = -1;
/* free the buffer */
if (movie->cur_chunk)
free(movie->cur_chunk);
movie->cur_chunk = NULL;
/* not strictly necessary */
movie->buf_size = 0;
movie->cur_fill = 0;
movie->next_segment = 0;
/* free the struct */
free(movie);
}
static void _mvefile_free_filehandle(MVEFILE *movie)
{
/* free the stream */
movie->stream = -1;
/* free the buffer */
if (movie->cur_chunk)
@ -297,9 +381,20 @@ static void _mvefile_free(MVEFILE *movie)
/*
* open the file stream in thie object
*/
static int _mvefile_open(MVEFILE *file, int filehandle)
static int _mvefile_open(MVEFILE *file, const char *filename)
{
file->stream = open(filename, O_RDONLY);
if (file->stream == -1)
return 0;
return 1;
}
static int _mvefile_open_filehandle(MVEFILE *file, int filehandle)
{
file->stream = filehandle;
if (file->stream == -1)
return 0;
return 1;
}
@ -312,7 +407,7 @@ static int _mvefile_read_header(MVEFILE *movie)
unsigned char buffer[26];
/* check the file is open */
if (movie->stream == 0)
if (movie->stream == -1)
return 0;
/* check the file is long enough */
@ -345,7 +440,7 @@ static void _mvefile_set_buffer_size(MVEFILE *movie, int buf_size)
/* allocate new buffer */
new_len = 100 + buf_size;
new_buffer = malloc(new_len);
new_buffer = (unsigned char *)malloc(new_len);
/* copy old data */
if (movie->cur_chunk && movie->cur_fill)
@ -369,7 +464,7 @@ static int _mvefile_fetch_next_chunk(MVEFILE *movie)
unsigned short length;
/* fail if not open */
if (movie->stream == 0)
if (movie->stream == -1)
return 0;
/* fail if we can't read the next segment descriptor */
@ -398,6 +493,13 @@ static short _mve_get_short(unsigned char *data)
return value;
}
static unsigned short _mve_get_ushort(unsigned char *data)
{
unsigned short value;
value = data[0] | (data[1] << 8);
return value;
}
/*
* allocate an MVESTREAM
*/
@ -429,12 +531,31 @@ static void _mvestream_free(MVESTREAM *movie)
memset(movie->handlers, 0, sizeof(movie->handlers));
}
static void _mvestream_free_filehandle(MVESTREAM *movie)
{
/* close MVEFILE */
if (movie->movie)
mvefile_close_filehandle(movie->movie);
movie->movie = NULL;
/* clear context and handlers */
movie->context = NULL;
memset(movie->handlers, 0, sizeof(movie->handlers));
}
/*
* open an MVESTREAM object
*/
static int _mvestream_open(MVESTREAM *movie, int filehandle)
static int _mvestream_open(MVESTREAM *movie, const char *filename)
{
movie->movie = mvefile_open(filehandle);
movie->movie = mvefile_open(filename);
return (movie->movie == NULL) ? 0 : 1;
}
static int _mvestream_open_filehandle(MVESTREAM *movie, int filehandle)
{
movie->movie = mvefile_open_filehandle(filehandle);
return (movie->movie == NULL) ? 0 : 1;
}

File diff suppressed because it is too large Load diff