/* ** $Id: SimpleTest.c,v 1.1 93/05/22 13:42:56 chris Exp $ ** $Revision: 1.1 $ ** ** $Filename: MovieDecode/SimpleTest.c $ ** $Author: chris $ ** $Date: 93/05/22 13:42:56 $ ** ** Simple program to test the movie decoder. ** Usage: SimpleTest */ // #define VERBOSE #include #include #include #include #include #include #include /* Not an official CBM file */ #define MIN(a,b) ((a)<(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b)) #define ID_ANSQ IFFL_MAKE_ID('A','N','S','Q') #define MAXFRAMES 1024 /* Max # of frames for animation (test) */ struct Library *IFFBase; /**************************************************************************** ** Prototypes for the MovieDecode functions */ APTR __asm InitJDecoder(register __d0 ULONG animtype); VOID __asm FreeJDecoder(register __a0 APTR handle); BOOL __asm ModifyJFrame(register __a0 APTR deltas, register __a1 struct BitMap *bm, register __a2 APTR handle); #ifdef VERBOSE /**************************************************************************** ** Not used. Dump a MOVIE frame in ASCII. Ugly code :) */ LONG DumpFrame(ULONG *chunk,struct BitMap *bm) { static WORD frame = 0; int ok = FALSE; UWORD *ptr = (WORD *)(chunk+2); Printf("\nFrame %ld\n", ++frame); for(;;) { WORD bytes, rows, offset; bytes=*ptr++; ptr++; rows=*ptr++; if (bytes==1) { goto onebyte; } else if (bytes==2) { int entries, i; bytes = *ptr++; if ((bytes!=2) && (bytes!=4) && (bytes!=6)) { Printf("Error: Secondary byte count = %ld\n\n", bytes); break; } onebyte: if ((rows<1) || ((rows>8) && (rows!=16) && (rows!=32))) { Printf("Illegal # of rows: %ld\n", rows); break; } entries = *ptr++; Printf(" %ld bytes x %ld rows: %ld times\n", bytes, rows, entries); for (i=0; iBytesPerRow, offset / bm->BytesPerRow); ptr = (void *)(((ULONG)ptr) + bm->Depth * rows * bytes); if ((bytes==1) && (bm->Depth & 1) && (rows & 1)) ptr = (void *)(((ULONG)ptr) + 1); } } else if(bytes == 0) { PutStr("End of frame\n"); ok = TRUE; break; } else { Printf("Error: Primary byte count = %ld\n\n", bytes); break; } } return ok; } #endif /**************************************************************************** ** Generate the next animation frame */ LONG MyModifyFrame(ULONG *form, struct BitMap *bm, APTR decoderhandle) { ULONG *chunk; if (chunk = IFFL_FindChunk(form, ID_ANHD)) { int op = ((struct IFFL_ANHD *)(chunk+2))->Operation; if (op=='J') { if (chunk = IFFL_FindChunk(form, ID_DLTA)) { #ifdef VERBOSE return DumpFrame(chunk, bm); #else return ModifyJFrame(chunk+2, bm, decoderhandle); #endif } } else return (LONG)IFFL_ModifyFrame(form, bm); /* ANIM5... */ } } /**************************************************************************** ** Load & display an animation */ void ShowAnim(char *name) { struct IFFL_BMHD *bmhd; struct BitMap *bm1 = NULL, *bm2 = NULL; struct Screen *screen = NULL; ULONG *form; int numframes = 0, i, swidth, sheight; WORD *ansq, *anptr; ULONG *seq[MAXFRAMES]; APTR decoderhandle = NULL; ULONG *ifffile; BOOL eor; /* ** Load animation to memory */ if (!(ifffile = IFFL_OpenIFF(name, IFFL_MODE_READ))) { PutStr("Not an IFF file!\n"); goto cleanup; } if(*(((ULONG *)ifffile)+2) != ID_ANIM) { PutStr("Not an ANIM file!\n"); goto cleanup; } form = ifffile+3; /* Skip FORM....ANIM */ if (!(bmhd = IFFL_GetBMHD(form))) { PutStr("No BMHD\n"); goto cleanup; } Printf("%ld x %ld x %ld ", bmhd->w, bmhd->h, bmhd->nPlanes); /* ** Calculate the screen size. Movie needs at least a 320 x 200 ** (or 640 x 400 in hires/interlace) screen. */ swidth = bmhd->w; if (swidth < 320) swidth = 320; if ((swidth > 400) && (swidth < 640)) swidth = 640; sheight = bmhd->h; if (sheight < 200) sheight = 200; if ((sheight > 300) && (sheight < 400)) sheight = 400; Printf("Screen size is %ld x %ld\n", swidth, sheight); /* ** Allocate the two bitmaps */ if (!(bm1 = AllocBitMap(swidth, sheight, bmhd->nPlanes, 0/*BMF_DISPLAYABLE*/, NULL))) { PutStr("Can't allocate bitmap 1!\n"); goto cleanup; } if (!(bm2 = AllocBitMap(swidth, sheight, bmhd->nPlanes, 0/*BMF_DISPLAYABLE*/, NULL))) { PutStr("Can't allocate bitmap 2!\n"); goto cleanup; } /* ** Open the screen and set the colors */ if (screen = OpenScreenTags(NULL, SA_Width, swidth, SA_Height, sheight, SA_Depth, bmhd->nPlanes, SA_DisplayID, IFFL_GetViewModes(form), SA_BitMap, bm1, SA_Quiet, TRUE, SA_Behind, TRUE, TAG_DONE )) { UWORD colortab[256]; int colorcount = IFFL_GetColorTab(form, (WORD *)colortab); LoadRGB4(&screen->ViewPort, colortab, colorcount); } else { PutStr("Can't open screen!"); goto cleanup; } /* ** Get pointers to all delta FORMs */ while (form = IFFL_FindChunk(form, 0L)) { UWORD *dlta; if (*form != ID_FORM) break; if (dlta = IFFL_FindChunk(form, ID_DLTA)) { if ((dlta[4]==1) || (dlta[4]==2)) eor=dlta[5]; } else PutStr("No delta!"); seq[numframes++] = form; if (numframes >= MAXFRAMES-1) { PutStr("- Too many frames!"); goto cleanup; } } /* ** Determine the compression type */ if (form = IFFL_FindChunk(ifffile, ID_ANSQ)) { /* ** Initialize the decoder */ if (decoderhandle = InitJDecoder((eor?0x10000L:0) | bm1->Depth)) { Printf(eor ? "Movie reversible, " : "Movie oneway, "); anptr = ansq = (WORD *)(form+2); } else { PutStr("Can't init decoder!\n"); goto cleanup; } } else { Printf("ANIM format, "); ansq = NULL; } Printf("%ld frames.\n", numframes); /* ** Display the first frame */ if (!IFFL_DecodePic(ifffile+3, bm1)) { Printf("Decode error: %ld\n", IFFL_IFFError()); goto cleanup; } if(bmhd->w < 320) ScrollRaster(&screen->RastPort, (bmhd->w-320) / 2, 0, 0, 0, 319, bmhd->h-1); /* ** Display the second frame: copy and modify the first one */ BltBitMap(bm1, 0, 0, bm2, 0, 0, screen->Width, screen->Height, 0xc0, 0xff, NULL); WaitBlit(); if (!MyModifyFrame(seq[0], bm2, decoderhandle)) { PutStr("Can't modify 1st frame\n"); goto cleanup; } ScreenToFront(screen); /* ** The loop: Play animation 3 times */ for(i=0; i<3; ++i) { int frame = 1; for(;;) { struct BitMap *dummy; if (CheckSignal(SIGBREAKF_CTRL_C)) goto cleanup; /* ** Flip BitMaps */ dummy=bm1; bm1=bm2; bm2=dummy; screen->BitMap = *bm1; /* ugly but only a test anyway */ MakeScreen(screen); RethinkDisplay(); #if 01 if (ansq) { if ((anptr[1]>0) && (anptr[1]<200)) Delay(anptr[1]); /* Wait 'anptr[1]' blanks */ } #endif if (!MyModifyFrame(seq[ansq?anptr[0]:frame], bm2, decoderhandle)) { PutStr("Can't decode frame\n"); goto cleanup; } if (ansq) { anptr+=2; if (anptr[1] == -1) { anptr = ansq+2*(anptr[0]-1); break; } } else { if (++frame >= numframes) break; } } } Delay(50); /* Show the last frame for 1 second */ cleanup: PutStr("Cleanup...\n"); if (decoderhandle) FreeJDecoder(decoderhandle); if (screen) CloseScreen(screen); if (bm2) FreeBitMap(bm2); if (bm1) FreeBitMap(bm1); } /**************************************************************************** ** Entry point */ int main(int argc, char **argv) { if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 39))) return RETURN_FAIL; if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 37))) return RETURN_FAIL; if (argc == 2) { if (IFFBase = OpenLibrary(IFFNAME, 19)) { ShowAnim(argv[1]); /* Show the animation */ CloseLibrary(IFFBase); } else PutStr("No iff.library!\n"); } else PutStr("Usage: SimpleTest \n"); CloseLibrary((struct Library *)IntuitionBase); CloseLibrary((struct Library *)GfxBase); return RETURN_OK; }