/* * Copyright (c) 1994-7 by * PARALLAX GRAPHICS, INCORPORATED, Santa Clara, California. * All rights reserved * * This software is furnished on an as-is basis, and may be used and copied * only with the inclusion of the above copyright notice. * * The information in this software is subject to change without notice. * No committment is made as to the usability or reliability of this * software. * * Parallax Graphics, Inc. * 2500 Condensa Street * Santa Clara, California 95051 * Author: Paul Lovvik */ /* Program: playmovieout Usage: playmovieout jpeg_movie_file Description: This demo illustrates the usage of XPlxPutCImage() to playback a jpeg_movie_file; in addition, the movie is also routed out the output port */ #include #include #include #include #include #include #include #include /* required for gettimeofday */ #include #include #include #include /*#include /* required for movie.h */ #include "movie.h" long ElapsedTime(); void main(argc, argv) int argc; char **argv; { Window win; /* movie playback window */ Display *disp; char *window_name = "playmovie"; XTextProperty windowname; /* used to set up the window name */ int scr, winMask; /* scr= screen, winMask= valuemask of window attributes */ GC outputgc; GC decompressgc; XEvent event; FILE *jpegFile; /* JPEG movie file to play back */ int width, height, depth; /* movie window width, height, and depth */ jpheader header; /* JPEG movie header sturcture */ char instruction; /* movie file instruction byte */ int *indexBuffer; /* frame offset index buffer */ int currentFrame; /* current movie frame */ int qTableSize; /* Q table size */ unsigned char* qTable; /* decompression Q table */ int cImageSize, maximumSize; /* compressed image size & maximum image size */ XPlxCImage *cImage; /* compressed image sturcture */ char *cImageData; /* compressed image data */ XVisualInfo *visualInfo; /* visual info of movie window */ XSetWindowAttributes winAttributes; /* window attrubutes of movie window */ char *audioslice=NULL; int devaudio; int first=1; /* flag to keep track of first XPlxPutCImage */ int FramesPerSecond; /* number of frames per second */ long int mSecondsPerFrame; /* number of milliseconds per frame */ struct timeval starttime, now; /* variable to calculate event-loop time */ int nextFrameTime; int repeat = False; /* SMS */ plx_IO* plxio = NULL; if (argc<2) /* requires movie filename as argument */ { printf("usage: playmovie <-repeat> moviefile\n"); exit(1); } if(argc > 2 && strcmp(argv[1], "-repeat") == 0) { repeat = True; } jpegFile=fopen(argv[argc-1],"r"); if (jpegFile==NULL) { printf("Can't open input file\n"); exit(1); } fread((char*)&header,sizeof(jpheader),1,jpegFile); /* read in jpheader info of movie */ FramesPerSecond = header.fps; /* Get frames per second */ mSecondsPerFrame = (long int)(1000 / (float)(FramesPerSecond)); /* if (header.tracks>0) /* check whether there's audio recorded in movie */ /* { /* audioslice=(char*)malloc(header.audioslice); /* initialize audio device */ /* devaudio=open("/dev/audio",O_WRONLY,0); /* if (devaudio<0) /* printf("Can't open /dev/audio\n"); /* } */ width=header.width; /* set window width to that of movie */ height=header.height; /* set window height to that of movie */ fseek(jpegFile,header.indexbuf,0); /* skip file to read frame offset locations */ indexBuffer=(int*)malloc(header.frames*sizeof(int)); /* create index buffer according to number of movie frames */ fread((char*)indexBuffer,sizeof(int),header.frames,jpegFile); /* Read in frame offsets to buffer */ currentFrame=0; /* frame index starts at 0 */ disp=XOpenDisplay(""); scr=(int)XDefaultScreen(disp); visualInfo = XPlxGetVideoVisual(scr, disp); /* Get a proper Visual for using 24-bit video in a window */ depth = visualInfo->depth; winMask=CWBackPixel|CWColormap|CWBorderPixel; winAttributes.colormap=XCreateColormap(disp, XRootWindow(disp, scr), visualInfo->visual,AllocNone); winAttributes.background_pixel=BlackPixel(disp,scr); winAttributes.border_pixel=WhitePixel(disp,scr); win=XCreateWindow(disp,XRootWindow(disp,scr), 0,0,width,height, /* x, y, width and height */ 0, /* border width */ depth, /* window depth */ InputOutput,visualInfo->visual, winMask,&winAttributes); XStringListToTextProperty(&window_name, 1, &windowname); /* Set up the window title */ XSetWMProperties(disp, win, &windowname, &windowname, argv, argc, NULL, NULL, NULL); outputgc=XCreateGC(disp,win,0,0); /* create GC for movie window */ decompressgc=XCreateGC(disp,win,0,0); /* create GC for movie window */ XSelectInput(disp,win,ExposureMask | ButtonPressMask); XMapWindow(disp,win); qTableSize=MakeQTables(header.qfactor,&qTable); /* generate Q table according to Q factor from header */ XPlxPutTable(disp,win,decompressgc,(char *)qTable,qTableSize,1); /* load Q table to CCube chip for decompression */ maximumSize=width*height*3/5; /* calculate maximum compressed image data size, for one frame of movie */ /* assume minimum compression of 5:1 */ cImageData=malloc(maximumSize); /* allocate data area in memory */ cImage=(XPlxCImage*)XPlxCreateCImage(disp,cImageData, maximumSize,width,height); /* assign allocated memory for XPlxCImage */ gettimeofday(&starttime, NULL); while (1) { if (XPending(disp)) { XNextEvent(disp,&event); first=1; } /* SMS - Make output on the window 1st */ if (first) { plxio = XPlxQueryConfig(disp,win,outputgc); XPlxVideoOutputSelect(disp, win, outputgc, PLX_OUTPUT_0, /* Per Paul */ PLX_PAL, PLX_COMP, PLX_RGB24); XPlxVideoScaleOutput(disp, win, outputgc, 0, 0, width, height, /* Whatever movie is */ (640-width)/2, (480-height)/2, width, height); /* 0, 0, 640, 480); /* full NTSC size */ printf("ScaleOutput is 1st operation on window\n"); first = 0; } gettimeofday(&now, NULL); /* nextFrameTime = (int)((unsigned int)(mSecondsPerFrame * (currentFrame+1)) - (unsigned int)(ElapsedTime(starttime, now))); */ nextFrameTime = 1; if(nextFrameTime >= 0) /* Are we late for this frame? */ { XPlxSleep(nextFrameTime * 1000); /* No, display a new image. */ fseek(jpegFile,indexBuffer[currentFrame],0); /* skip to start of frame pointed to by index offset */ fread(&instruction,1,1,jpegFile); /* this is to skip the opcode instruction */ if ((instruction&0x00ff)==LOAD_AUDIO_0) /* if instruction is to load audio */ { int i; /* if (audioslice==NULL) /* abort(); */ i=fread(audioslice,1,header.audioslice,jpegFile); /* read audio data from file */ /* write(devaudio,audioslice,header.audioslice); /* send data to device */ fread(&instruction,1,1,jpegFile); /* read the opcode instruction. */ } if ((instruction&0x00ff)==LOAD_JPEG) /* if instruction is to load jpeg data */ { fread(&cImageSize,4,1,jpegFile); /* read in the frame data size */ fread(cImageData,cImageSize,1,jpegFile); /* read in the jpeg data of the frame */ cImage->size=cImageSize; XPlxPutCImage(disp,win,decompressgc,cImage, 0,0,width,height, 0,0,width,height, 0); /* set to crop image if necessary */ if (first) { first=0; /* refresh with background color before drawing */ } /* the next image */ } } else { /* frame was late, skip it. */ } if (++currentFrame>=header.frames-1) /* allows loopback when it's end of movie */ { if(repeat == False) { XFreeGC(disp, outputgc); XFreeGC(disp, decompressgc); XCloseDisplay(disp); exit(1); } else { currentFrame=0; gettimeofday(&starttime, NULL); } } if (event.type == ButtonPress) { XFreeGC(disp, outputgc); XFreeGC(disp, decompressgc); XCloseDisplay(disp); exit(1); } } } long ElapsedTime(before, after) struct timeval* before; struct timeval* after; { return(((after->tv_sec - before->tv_sec) * 1000) + /* Convert the seconds part to milliseconds */ ((after->tv_usec - before->tv_usec) /1000)); /* Convert the microseconds part to milliseconds */ } /* end function ElapsedTime */