1 #include "mvelib.h" /* next buffer */
12 #define MIN(a,b) ((a)<(b)?(a):(b))
15 int doPlay(const char *filename);
19 fprintf(stderr, "usage: mveplay filename\n");
24 int g_spdFactorDenom=10;
26 void initializeMovie(MVESTREAM *mve);
27 void playMovie(MVESTREAM *mve);
28 void shutdownMovie(MVESTREAM *mve);
30 short get_short(unsigned char *data)
33 value = data[0] | (data[1] << 8);
37 int get_int(unsigned char *data)
40 value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
44 int default_seg_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
46 fprintf(stderr, "unknown chunk type %02x/%02x\n", major, minor);
50 /*************************
52 *************************/
53 int end_movie_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
58 /*************************
60 *************************/
65 int micro_frame_delay=0;
67 struct timeval timer_expire = {0, 0};
69 int create_timer_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
72 micro_frame_delay = get_int(data) * (int)get_short(data+4);
73 if (g_spdFactorNum != 0)
75 temp = micro_frame_delay;
76 temp *= g_spdFactorNum;
77 temp /= g_spdFactorDenom;
78 micro_frame_delay = (int)temp;
84 void timer_start(void)
87 gettimeofday(&timer_expire, NULL);
88 timer_expire.tv_usec += micro_frame_delay;
89 if (timer_expire.tv_usec > 1000000)
91 nsec = timer_expire.tv_usec / 1000000;
92 timer_expire.tv_sec += nsec;
93 timer_expire.tv_usec -= nsec*1000000;
98 void do_timer_wait(void)
101 struct timespec ts, tsRem;
106 gettimeofday(&tv, NULL);
107 if (tv.tv_sec > timer_expire.tv_sec)
109 else if (tv.tv_sec == timer_expire.tv_sec && tv.tv_usec >= timer_expire.tv_usec)
112 ts.tv_sec = timer_expire.tv_sec - tv.tv_sec;
113 ts.tv_nsec = 1000 * (timer_expire.tv_usec - tv.tv_usec);
116 ts.tv_nsec += 1000000000UL;
119 if (nanosleep(&ts, &tsRem) == -1 && errno == EINTR)
123 timer_expire.tv_usec += micro_frame_delay;
124 if (timer_expire.tv_usec > 1000000)
126 nsec = timer_expire.tv_usec / 1000000;
127 timer_expire.tv_sec += nsec;
128 timer_expire.tv_usec -= nsec*1000000;
132 /*************************
134 *************************/
135 void mve_audio_callback(void *userdata, Uint8 *stream, int len);
136 short *mve_audio_buffers[64];
137 int mve_audio_buflens[64];
138 int mve_audio_curbuf_curpos=0;
139 int mve_audio_bufhead=0;
140 int mve_audio_buftail=0;
141 int mve_audio_playing=0;
142 int mve_audio_canplay=0;
143 SDL_AudioSpec *mve_audio_spec=NULL;
144 pthread_mutex_t mve_audio_mutex = PTHREAD_MUTEX_INITIALIZER;
146 void mve_audio_callback(void *userdata, Uint8 *stream, int len)
150 if (mve_audio_bufhead == mve_audio_buftail)
153 fprintf(stderr, "+ <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
155 pthread_mutex_lock(&mve_audio_mutex);
157 while (mve_audio_bufhead != mve_audio_buftail /* while we have more buffers */
158 && len > (mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos)) /* and while we need more data */
160 length = mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos;
161 __builtin_memcpy(stream, /* cur output position */
162 mve_audio_buffers[mve_audio_bufhead]+mve_audio_curbuf_curpos, /* cur input position */
163 length); /* cur input length */
166 stream += length; /* advance output */
167 len -= length; /* decrement avail ospace */
168 free(mve_audio_buffers[mve_audio_bufhead]); /* free the buffer */
169 mve_audio_buffers[mve_audio_bufhead]=NULL; /* free the buffer */
170 mve_audio_buflens[mve_audio_bufhead]=0; /* free the buffer */
172 if (++mve_audio_bufhead == 64) /* next buffer */
173 mve_audio_bufhead = 0;
174 mve_audio_curbuf_curpos = 0;
177 fprintf(stderr, "= <%d (%d), %d, %d>: %d\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len, total);
180 if (len != 0 /* ospace remaining */
181 && mve_audio_bufhead != mve_audio_buftail) /* buffers remaining */
183 __builtin_memcpy(stream, /* dest */
184 mve_audio_buffers[mve_audio_bufhead] + mve_audio_curbuf_curpos, /* src */
187 mve_audio_curbuf_curpos += len; /* advance input */
188 stream += len; /* advance output (unnecessary) */
189 len -= len; /* advance output (unnecessary) */
191 if (mve_audio_curbuf_curpos >= mve_audio_buflens[mve_audio_bufhead]) /* if this ends the current chunk */
193 free(mve_audio_buffers[mve_audio_bufhead]); /* free buffer */
194 mve_audio_buffers[mve_audio_bufhead]=NULL;
195 mve_audio_buflens[mve_audio_bufhead]=0;
197 if (++mve_audio_bufhead == 64) /* next buffer */
198 mve_audio_bufhead = 0;
199 mve_audio_curbuf_curpos = 0;
203 fprintf(stderr, "- <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
204 pthread_mutex_unlock(&mve_audio_mutex);
207 int create_audiobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
212 fprintf(stderr, "creating audio buffers\n");
214 sample_rate = get_short(data + 4);
215 desired_buffer = get_int(data + 6);
216 mve_audio_spec = (SDL_AudioSpec *)malloc(sizeof(SDL_AudioSpec));
217 mve_audio_spec->freq = sample_rate;
218 mve_audio_spec->format = AUDIO_S16LSB;
219 mve_audio_spec->channels = 2;
220 mve_audio_spec->samples = 32768;
221 mve_audio_spec->callback = mve_audio_callback;
222 mve_audio_spec->userdata = NULL;
223 if (SDL_OpenAudio(mve_audio_spec, NULL) >= 0)
225 fprintf(stderr, " success\n");
226 mve_audio_canplay = 1;
230 fprintf(stderr, " failure : %s\n", SDL_GetError());
231 mve_audio_canplay = 0;
234 memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
235 memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
240 int play_audio_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
242 if (mve_audio_canplay && !mve_audio_playing && mve_audio_bufhead != mve_audio_buftail)
245 mve_audio_playing = 1;
251 int audio_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
253 const int selected_chan=1;
256 if (mve_audio_canplay)
258 if (mve_audio_playing)
261 chan = get_short(data + 2);
262 nsamp = get_short(data + 4);
263 if (chan & selected_chan)
265 pthread_mutex_lock(&mve_audio_mutex);
266 mve_audio_buflens[mve_audio_buftail] = nsamp;
267 mve_audio_buffers[mve_audio_buftail] = (short *)malloc(nsamp);
269 mveaudio_uncompress(mve_audio_buffers[mve_audio_buftail], data, -1); /* XXX */
271 memset(mve_audio_buffers[mve_audio_buftail], 0, nsamp); /* XXX */
273 if (++mve_audio_buftail == 64)
274 mve_audio_buftail = 0;
276 if (mve_audio_buftail == mve_audio_bufhead)
277 fprintf(stderr, "d'oh! buffer ring overrun (%d)\n", mve_audio_bufhead);
278 pthread_mutex_unlock(&mve_audio_mutex);
281 if (mve_audio_playing)
288 /*************************
290 *************************/
291 SDL_Surface *g_screen;
292 int g_screenWidth, g_screenHeight;
293 int g_width, g_height;
294 unsigned char g_palette[768];
295 unsigned char *g_vBackBuf1, *g_vBackBuf2;
296 unsigned char *g_pCurMap=NULL;
299 int create_videobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
303 h = get_short(data+2);
306 g_vBackBuf1 = malloc(g_width * g_height);
307 g_vBackBuf2 = malloc(g_width * g_height);
308 memset(g_vBackBuf1, 0, g_width * g_height);
309 memset(g_vBackBuf2, 0, g_width * g_height);
314 int display_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
317 unsigned char *pal = g_palette;
318 unsigned char *pDest;
319 unsigned char *pixels = g_vBackBuf1;
320 SDL_Surface *screenSprite;
324 SDL_Surface *initSprite = SDL_CreateRGBSurface(SDL_SWSURFACE, g_width, g_height, 8, 0, 0, 0, 0);
325 for(i = 0; i < 256; i++)
327 initSprite->format->palette->colors[i].r = (*pal++) << 2;
328 initSprite->format->palette->colors[i].g = (*pal++) << 2;
329 initSprite->format->palette->colors[i].b = (*pal++) << 2;
330 initSprite->format->palette->colors[i].unused = 0;
333 pDest = initSprite->pixels;
334 for (i=0; i<g_height; i++)
336 memcpy(pDest, pixels, g_width);
338 pDest += initSprite->pitch;
341 screenSprite = SDL_DisplayFormat(initSprite);
342 SDL_FreeSurface(initSprite);
344 if (g_screenWidth > screenSprite->w) x = (g_screenWidth - screenSprite->w) >> 1;
346 if (g_screenHeight > screenSprite->h) y = (g_screenHeight - screenSprite->h) >> 1;
350 renderArea.w = MIN(g_screenWidth - x, screenSprite->w);
351 renderArea.h = MIN(g_screenHeight - y, screenSprite->h);
352 SDL_BlitSurface(screenSprite, NULL, g_screen, &renderArea);
353 if ( (g_screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF )
356 SDL_UpdateRects(g_screen, 1, &renderArea);
357 SDL_FreeSurface(screenSprite);
361 int init_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
364 width = get_short(data);
365 height = get_short(data+2);
366 g_screen = SDL_SetVideoMode(width, height, 16, SDL_ANYFORMAT);
367 g_screenWidth = width;
368 g_screenHeight = height;
369 memset(g_palette, 0, 768);
373 int video_palette_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
376 start = get_short(data);
377 count = get_short(data+2);
378 memcpy(g_palette + 3*start, data+4, 3*count);
382 int video_codemap_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
389 void decodeFrame(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain);
391 int video_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
393 short nFrameHot, nFrameCold;
394 short nXoffset, nYoffset;
395 short nXsize, nYsize;
399 nFrameHot = get_short(data);
400 nFrameCold = get_short(data+2);
401 nXoffset = get_short(data+4);
402 nYoffset = get_short(data+6);
403 nXsize = get_short(data+8);
404 nYsize = get_short(data+10);
405 nFlags = get_short(data+12);
410 g_vBackBuf1 = g_vBackBuf2;
414 /* convert the frame */
415 decodeFrame(g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
420 int end_chunk_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
426 void initializeMovie(MVESTREAM *mve)
428 mve_set_handler(mve, 0x00, end_movie_handler);
429 mve_set_handler(mve, 0x01, end_chunk_handler);
430 mve_set_handler(mve, 0x02, create_timer_handler);
431 mve_set_handler(mve, 0x03, create_audiobuf_handler);
432 mve_set_handler(mve, 0x04, play_audio_handler);
433 mve_set_handler(mve, 0x05, create_videobuf_handler);
434 mve_set_handler(mve, 0x07, display_video_handler);
435 mve_set_handler(mve, 0x08, audio_data_handler);
436 mve_set_handler(mve, 0x09, audio_data_handler);
437 mve_set_handler(mve, 0x0a, init_video_handler);
438 mve_set_handler(mve, 0x0c, video_palette_handler);
439 mve_set_handler(mve, 0x0f, video_codemap_handler);
440 mve_set_handler(mve, 0x11, video_data_handler);
443 void playMovie(MVESTREAM *mve)
449 cont = mve_play_next_chunk(mve);
450 if (micro_frame_delay && !init_timer)
460 void shutdownMovie(MVESTREAM *mve)
464 void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb);
466 void decodeFrame(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain)
475 for (i=0; i<xb/2; i++)
477 dispatchDecoder(&pFrame, (*pMap) & 0xf, &pData, &dataRemain, &i, &j);
478 if (pFrame < g_vBackBuf1)
479 fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
480 else if (pFrame >= g_vBackBuf1 + g_width*g_height)
481 fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
482 dispatchDecoder(&pFrame, (*pMap) >> 4, &pData, &dataRemain, &i, &j);
483 if (pFrame < g_vBackBuf1)
484 fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
485 else if (pFrame >= g_vBackBuf1 + g_width*g_height)
486 fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
496 void relClose(int i, int *x, int *y)
507 void relFar(int i, int sign, int *x, int *y)
511 *x = sign * (8 + (i % 7));
516 *x = sign * (-14 + (i - 56) % 29);
517 *y = sign * (8 + (i - 56) / 29);
521 void copyFrame(unsigned char *pDest, unsigned char *pSrc)
527 memcpy(pDest, pSrc, 8);
533 void patternRow4Pixels(unsigned char *pFrame,
534 unsigned char pat0, unsigned char pat1,
537 unsigned short mask=0x0003;
538 unsigned short shift=0;
539 unsigned short pattern = (pat1 << 8) | pat0;
543 *pFrame++ = p[(mask & pattern) >> shift];
549 void patternRow4Pixels2(unsigned char *pFrame,
553 unsigned char mask=0x03;
554 unsigned char shift=0;
560 pel = p[(mask & pat0) >> shift];
563 pFrame[g_width + 0] = pel;
564 pFrame[g_width + 2] = pel;
572 void patternRow4Pixels2x1(unsigned char *pFrame, unsigned char pat, unsigned char *p)
574 unsigned char mask=0x03;
575 unsigned char shift=0;
580 pel = p[(mask & pat) >> shift];
589 void patternQuadrant4Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char pat2, unsigned char pat3, unsigned char *p)
591 unsigned long mask = 0x00000003UL;
594 unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0;
598 pFrame[i&3] = p[(pat & mask) >> shift];
609 void patternRow2Pixels(unsigned char *pFrame, unsigned char pat, unsigned char *p)
611 unsigned char mask=0x01;
615 *pFrame++ = p[(mask & pat) ? 1 : 0];
620 void patternRow2Pixels2(unsigned char *pFrame, unsigned char pat, unsigned char *p)
623 unsigned char mask=0x1;
628 pel = p[(mask & pat) ? 1 : 0];
631 pFrame[g_width + 0] = pel;
632 pFrame[g_width + 2] = pel;
639 void patternQuadrant2Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char *p)
641 unsigned short mask = 0x0001;
643 unsigned short pat = (pat1 << 8) | pat0;
647 pFrame[i&3] = p[(pat & mask) ? 1 : 0];
656 void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb)
659 unsigned char pat[16];
666 copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1));
672 relFar(*(*pData)++, 1, &x, &y);
673 copyFrame(*pFrame, *pFrame + x + y*g_width);
679 relFar(*(*pData)++, -1, &x, &y);
680 copyFrame(*pFrame, *pFrame + x + y*g_width);
686 relClose(*(*pData)++, &x, &y);
687 copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1) + x + y*g_width);
693 x = (char)*(*pData)++;
694 y = (char)*(*pData)++;
695 copyFrame(*pFrame, *pFrame + (g_vBackBuf2 - g_vBackBuf1) + x + y*g_width);
704 if (++*curXb == (g_width >> 3))
706 *pFrame += 7*g_width;
708 if (++*curYb == (g_height >> 3))
721 patternRow2Pixels(*pFrame, *(*pData)++, p);
729 patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p);
730 *pFrame += 2*g_width;
731 patternRow2Pixels2(*pFrame, *(*pData)++ >> 4, p);
732 *pFrame += 2*g_width;
735 *pFrame -= (8*g_width - 8);
739 if ( (*pData)[0] <= (*pData)[1])
745 pat[0] = *(*pData)++;
746 pat[1] = *(*pData)++;
747 patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
750 *pFrame -= (4*g_width - 4);
752 *pFrame += 4*g_width;
755 else if ( (*pData)[6] <= (*pData)[7])
764 pat[0] = *(*pData)++;
765 pat[1] = *(*pData)++;
766 patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
769 *pFrame -= (4*g_width - 4);
771 *pFrame += 4*g_width;
783 patternRow2Pixels(*pFrame, *(*pData)++, p);
786 *pFrame -= (8*g_width - 8);
791 if ( (*pData)[0] <= (*pData)[1])
793 if ( (*pData)[2] <= (*pData)[3])
802 pat[0] = *(*pData)++;
803 pat[1] = *(*pData)++;
804 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
808 *pFrame -= (8*g_width - 8);
817 patternRow4Pixels2(*pFrame, *(*pData)++, p);
818 *pFrame += 2*g_width;
819 patternRow4Pixels2(*pFrame, *(*pData)++, p);
820 *pFrame += 2*g_width;
821 patternRow4Pixels2(*pFrame, *(*pData)++, p);
822 *pFrame += 2*g_width;
823 patternRow4Pixels2(*pFrame, *(*pData)++, p);
824 *pFrame -= (6*g_width - 8);
829 if ( (*pData)[2] <= (*pData)[3])
838 pat[0] = *(*pData)++;
839 patternRow4Pixels2x1(*pFrame, pat[0], p);
843 *pFrame -= (8*g_width - 8);
854 pat[0] = *(*pData)++;
855 pat[1] = *(*pData)++;
856 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
858 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
862 *pFrame -= (8*g_width - 8);
868 if ( (*pData)[0] <= (*pData)[1])
876 pat[0] = *(*pData)++;
877 pat[1] = *(*pData)++;
878 pat[2] = *(*pData)++;
879 pat[3] = *(*pData)++;
881 patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
884 *pFrame -= (4*g_width - 4);
886 *pFrame += 4*g_width;
891 if ( (*pData)[12] <= (*pData)[13])
903 pat[0] = *(*pData)++;
904 pat[1] = *(*pData)++;
905 pat[2] = *(*pData)++;
906 pat[3] = *(*pData)++;
908 patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
911 *pFrame -= (4*g_width - 4);
913 *pFrame += 4*g_width;
928 pat[0] = *(*pData)++;
929 pat[1] = *(*pData)++;
930 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
934 *pFrame -= (8*g_width - 8);
942 memcpy(*pFrame, *pData, 8);
947 *pFrame -= (8*g_width - 8);
957 (*pFrame)[j+2*k] = (*pData)[k];
958 (*pFrame)[g_width+j+2*k] = (*pData)[k];
965 *pFrame -= (8*g_width - 8);
975 (*pFrame)[k*g_width+j] = (*pData)[0];
976 (*pFrame)[k*g_width+j+4] = (*pData)[1];
979 *pFrame += 4*g_width;
983 *pFrame -= (8*g_width - 8);
989 memset(*pFrame, **pData, 8);
994 *pFrame -= (8*g_width - 8);
1002 (*pFrame)[j] = (*pData)[(i+j)&1];
1008 *pFrame -= (8*g_width - 8);