1 /* $Id: mveplay.c,v 1.6 2003-02-28 11:27:05 btb Exp $ */
15 #include <sys/types.h>
20 #if defined(STANDALONE) || defined(AUDIO)
25 #include "mve_audio.h"
36 #define d_malloc(size) malloc(size)
37 #define d_free(ptr) free(ptr)
41 #define MIN(a,b) ((a)<(b)?(a):(b))
44 #define MVE_OPCODE_ENDOFSTREAM 0x00
45 #define MVE_OPCODE_ENDOFCHUNK 0x01
46 #define MVE_OPCODE_CREATETIMER 0x02
47 #define MVE_OPCODE_INITAUDIOBUFFERS 0x03
48 #define MVE_OPCODE_STARTSTOPAUDIO 0x04
49 #define MVE_OPCODE_INITVIDEOBUFFERS 0x05
51 #define MVE_OPCODE_DISPLAYVIDEO 0x07
52 #define MVE_OPCODE_AUDIOFRAMEDATA 0x08
53 #define MVE_OPCODE_AUDIOFRAMESILENCE 0x09
54 #define MVE_OPCODE_INITVIDEOMODE 0x0A
56 #define MVE_OPCODE_SETPALETTE 0x0C
57 #define MVE_OPCODE_SETPALETTECOMPRESSED 0x0D
59 #define MVE_OPCODE_SETDECODINGMAP 0x0F
61 #define MVE_OPCODE_VIDEODATA 0x11
63 #define MVE_AUDIO_FLAGS_STEREO 1
64 #define MVE_AUDIO_FLAGS_16BIT 2
65 #define MVE_AUDIO_FLAGS_COMPRESSED 4
68 static int g_spdFactorDenom=10;
69 static int g_frameUpdated = 0;
72 static int playing = 1;
73 int g_sdlVidFlags = SDL_ANYFORMAT | SDL_DOUBLEBUF;
76 void initializeMovie(MVESTREAM *mve);
77 void playMovie(MVESTREAM *mve);
78 void shutdownMovie(MVESTREAM *mve);
81 static short get_short(unsigned char *data)
84 value = data[0] | (data[1] << 8);
88 static unsigned short get_ushort(unsigned char *data)
91 value = data[0] | (data[1] << 8);
95 static int get_int(unsigned char *data)
98 value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
102 static unsigned int unhandled_chunks[32*256];
104 static int default_seg_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
106 unhandled_chunks[major<<8|minor]++;
107 //fprintf(stderr, "unknown chunk type %02x/%02x\n", major, minor);
112 /*************************
114 *************************/
115 static int end_movie_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
120 /*************************
122 *************************/
127 static int timer_created = 0;
128 static int micro_frame_delay=0;
129 static int timer_started=0;
130 static struct timeval timer_expire = {0, 0};
133 int nanosleep(struct timespec *ts, void *rem);
137 #include <sys/timeb.h>
141 long int tv_sec; /* Seconds. */
142 long int tv_nsec; /* Nanoseconds. */
145 int gettimeofday(struct timeval *tv, void *tz)
147 static int counter = 0;
150 counter++; /* to avoid collisions */
152 tv->tv_sec = tm.time;
153 tv->tv_usec = (tm.millitm * 1000) + counter;
158 int nanosleep(struct timespec *ts, void *rem)
160 sleep(ts->tv_sec * 1000 + ts->tv_nsec / 1000000);
166 static int create_timer_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
168 __extension__ long long temp;
175 micro_frame_delay = get_int(data) * (int)get_short(data+4);
176 if (g_spdFactorNum != 0)
178 temp = micro_frame_delay;
179 temp *= g_spdFactorNum;
180 temp /= g_spdFactorDenom;
181 micro_frame_delay = (int)temp;
187 static void timer_stop(void)
189 timer_expire.tv_sec = 0;
190 timer_expire.tv_usec = 0;
194 static void timer_start(void)
197 gettimeofday(&timer_expire, NULL);
198 timer_expire.tv_usec += micro_frame_delay;
199 if (timer_expire.tv_usec > 1000000)
201 nsec = timer_expire.tv_usec / 1000000;
202 timer_expire.tv_sec += nsec;
203 timer_expire.tv_usec -= nsec*1000000;
208 static void do_timer_wait(void)
216 gettimeofday(&tv, NULL);
217 if (tv.tv_sec > timer_expire.tv_sec)
219 else if (tv.tv_sec == timer_expire.tv_sec && tv.tv_usec >= timer_expire.tv_usec)
222 ts.tv_sec = timer_expire.tv_sec - tv.tv_sec;
223 ts.tv_nsec = 1000 * (timer_expire.tv_usec - tv.tv_usec);
226 ts.tv_nsec += 1000000000UL;
230 usleep(ts.tv_sec * 1000000 + ts.tv_nsec / 1000);
232 if (nanosleep(&ts, NULL) == -1 && errno == EINTR)
237 timer_expire.tv_usec += micro_frame_delay;
238 if (timer_expire.tv_usec > 1000000)
240 nsec = timer_expire.tv_usec / 1000000;
241 timer_expire.tv_sec += nsec;
242 timer_expire.tv_usec -= nsec*1000000;
246 /*************************
248 *************************/
250 #define TOTAL_AUDIO_BUFFERS 64
252 static int audiobuf_created = 0;
253 static void mve_audio_callback(void *userdata, unsigned char *stream, int len);
254 static short *mve_audio_buffers[TOTAL_AUDIO_BUFFERS];
255 static int mve_audio_buflens[TOTAL_AUDIO_BUFFERS];
256 static int mve_audio_curbuf_curpos=0;
257 static int mve_audio_bufhead=0;
258 static int mve_audio_buftail=0;
259 static int mve_audio_playing=0;
260 static int mve_audio_canplay=0;
261 static int mve_audio_compressed=0;
262 static int mve_audio_enabled = 1;
263 static SDL_AudioSpec *mve_audio_spec=NULL;
265 static void mve_audio_callback(void *userdata, unsigned char *stream, int len)
269 if (mve_audio_bufhead == mve_audio_buftail)
272 //fprintf(stderr, "+ <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
274 while (mve_audio_bufhead != mve_audio_buftail /* while we have more buffers */
275 && len > (mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos)) /* and while we need more data */
277 length = mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos;
278 memcpy(stream, /* cur output position */
279 ((unsigned char *)mve_audio_buffers[mve_audio_bufhead])+mve_audio_curbuf_curpos, /* cur input position */
280 length); /* cur input length */
283 stream += length; /* advance output */
284 len -= length; /* decrement avail ospace */
285 d_free(mve_audio_buffers[mve_audio_bufhead]); /* free the buffer */
286 mve_audio_buffers[mve_audio_bufhead]=NULL; /* free the buffer */
287 mve_audio_buflens[mve_audio_bufhead]=0; /* free the buffer */
289 if (++mve_audio_bufhead == TOTAL_AUDIO_BUFFERS) /* next buffer */
290 mve_audio_bufhead = 0;
291 mve_audio_curbuf_curpos = 0;
294 //fprintf(stderr, "= <%d (%d), %d, %d>: %d\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len, total);
297 if (len != 0 /* ospace remaining */
298 && mve_audio_bufhead != mve_audio_buftail) /* buffers remaining */
300 memcpy(stream, /* dest */
301 ((unsigned char *)mve_audio_buffers[mve_audio_bufhead]) + mve_audio_curbuf_curpos, /* src */
304 mve_audio_curbuf_curpos += len; /* advance input */
305 stream += len; /* advance output (unnecessary) */
306 len -= len; /* advance output (unnecessary) */
308 if (mve_audio_curbuf_curpos >= mve_audio_buflens[mve_audio_bufhead]) /* if this ends the current chunk */
310 d_free(mve_audio_buffers[mve_audio_bufhead]); /* free buffer */
311 mve_audio_buffers[mve_audio_bufhead]=NULL;
312 mve_audio_buflens[mve_audio_bufhead]=0;
314 if (++mve_audio_bufhead == TOTAL_AUDIO_BUFFERS) /* next buffer */
315 mve_audio_bufhead = 0;
316 mve_audio_curbuf_curpos = 0;
320 //fprintf(stderr, "- <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len);
324 static int create_audiobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
337 if (!mve_audio_enabled)
340 if (audiobuf_created)
343 audiobuf_created = 1;
345 flags = get_ushort(data + 2);
346 sample_rate = get_ushort(data + 4);
347 desired_buffer = get_int(data + 6);
349 stereo = (flags & MVE_AUDIO_FLAGS_STEREO) ? 1 : 0;
350 bitsize = (flags & MVE_AUDIO_FLAGS_16BIT) ? 1 : 0;
353 compressed = flags & MVE_AUDIO_FLAGS_COMPRESSED ? 1 : 0;
358 mve_audio_compressed = compressed;
361 #ifdef WORDS_BIGENDIAN
362 format = AUDIO_S16MSB;
364 format = AUDIO_S16LSB;
370 fprintf(stderr, "creating audio buffers:\n");
371 fprintf(stderr, "sample rate = %d, stereo = %d, bitsize = %d, compressed = %d\n",
372 sample_rate, stereo, bitsize ? 16 : 8, compressed);
374 mve_audio_spec = (SDL_AudioSpec *)d_malloc(sizeof(SDL_AudioSpec));
375 mve_audio_spec->freq = sample_rate;
376 mve_audio_spec->format = format;
377 mve_audio_spec->channels = (stereo) ? 2 : 1;
378 mve_audio_spec->samples = 4096;
379 mve_audio_spec->callback = mve_audio_callback;
380 mve_audio_spec->userdata = NULL;
381 if (SDL_OpenAudio(mve_audio_spec, NULL) >= 0)
383 fprintf(stderr, " success\n");
384 mve_audio_canplay = 1;
388 fprintf(stderr, " failure : %s\n", SDL_GetError());
389 mve_audio_canplay = 0;
392 memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
393 memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
399 static int play_audio_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
402 if (mve_audio_canplay && !mve_audio_playing && mve_audio_bufhead != mve_audio_buftail)
405 mve_audio_playing = 1;
411 static int audio_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
414 static const int selected_chan=1;
417 if (mve_audio_canplay)
419 if (mve_audio_playing)
422 chan = get_ushort(data + 2);
423 nsamp = get_ushort(data + 4);
424 if (chan & selected_chan)
426 /* HACK: +4 mveaudio_uncompress adds 4 more bytes */
427 if (major == MVE_OPCODE_AUDIOFRAMEDATA) {
428 if (mve_audio_compressed) {
431 mve_audio_buflens[mve_audio_buftail] = nsamp;
432 mve_audio_buffers[mve_audio_buftail] = (short *)d_malloc(nsamp);
433 mveaudio_uncompress(mve_audio_buffers[mve_audio_buftail], data, -1); /* XXX */
438 mve_audio_buflens[mve_audio_buftail] = nsamp;
439 mve_audio_buffers[mve_audio_buftail] = (short *)d_malloc(nsamp);
440 memcpy(mve_audio_buffers[mve_audio_buftail], data, nsamp);
443 mve_audio_buflens[mve_audio_buftail] = nsamp;
444 mve_audio_buffers[mve_audio_buftail] = (short *)d_malloc(nsamp);
446 memset(mve_audio_buffers[mve_audio_buftail], 0, nsamp); /* XXX */
449 if (++mve_audio_buftail == TOTAL_AUDIO_BUFFERS)
450 mve_audio_buftail = 0;
452 if (mve_audio_buftail == mve_audio_bufhead)
453 fprintf(stderr, "d'oh! buffer ring overrun (%d)\n", mve_audio_bufhead);
456 if (mve_audio_playing)
464 /*************************
466 *************************/
467 static int videobuf_created = 0;
468 static int video_initialized = 0;
469 int g_width, g_height;
470 void *g_vBuffers = NULL, *g_vBackBuf1, *g_vBackBuf2;
473 static SDL_Surface *g_screen;
475 static int g_destX, g_destY;
477 static int g_screenWidth, g_screenHeight;
478 static unsigned char g_palette[768];
479 static unsigned char *g_pCurMap=NULL;
480 static int g_nMapLength=0;
481 static int g_truecolor;
483 static int create_videobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
486 short count, truecolor;
488 if (videobuf_created)
491 videobuf_created = 1;
494 h = get_short(data+2);
497 count = get_short(data+4);
503 truecolor = get_short(data+6);
511 /* TODO: * 4 causes crashes on some files */
512 g_vBackBuf1 = g_vBuffers = d_malloc(g_width * g_height * 8);
514 g_vBackBuf2 = (unsigned short *)g_vBackBuf1 + (g_width * g_height);
516 g_vBackBuf2 = (unsigned char *)g_vBackBuf1 + (g_width * g_height);
519 memset(g_vBackBuf1, 0, g_width * g_height * 4);
522 fprintf(stderr, "DEBUG: w,h=%d,%d count=%d, tc=%d\n", w, h, count, truecolor);
525 g_truecolor = truecolor;
531 static int do_sdl_events()
535 while (SDL_PollEvent(&event)) {
541 if (event.key.keysym.sym == SDLK_ESCAPE)
547 case SDL_MOUSEBUTTONDOWN:
549 if (event.button.button == SDL_BUTTON_LEFT) {
550 printf("GRID: %d,%d (pix:%d,%d)\n",
551 event.button.x / 16, event.button.y / 8,
552 event.button.x, event.button.y);
564 static void ConvertAndDraw()
567 unsigned char *pal = g_palette;
568 unsigned char *pDest;
569 unsigned char *pixels = g_vBackBuf1;
570 SDL_Surface *screenSprite, *initSprite;
574 initSprite = SDL_CreateRGBSurface(SDL_SWSURFACE, g_width, g_height, g_truecolor?16:8, 0x7C00, 0x03E0, 0x001F, 0);
577 for(i = 0; i < 256; i++) {
578 initSprite->format->palette->colors[i].r = (*pal++) << 2;
579 initSprite->format->palette->colors[i].g = (*pal++) << 2;
580 initSprite->format->palette->colors[i].b = (*pal++) << 2;
581 initSprite->format->palette->colors[i].unused = 0;
585 pDest = initSprite->pixels;
587 if (0 /*g_truecolor*/) {
589 unsigned short *pSrcs, *pDests;
591 pSrcs = (unsigned short *)pixels;
592 pDests = (unsigned short *)pDest;
594 for (y=0; y<g_height; y++) {
595 for (x = 0; x < g_width; x++) {
596 pDests[x] = (1<<15)|*pSrcs;
599 pDests += g_screenWidth;
604 for (i=0; i<g_height; i++) {
605 memcpy(pDest, pixels, g_width * (g_truecolor?2:1));
606 pixels += g_width* (g_truecolor?2:1);
607 pDest += initSprite->pitch;
611 screenSprite = SDL_DisplayFormat(initSprite);
612 SDL_FreeSurface(initSprite);
614 if (g_screenWidth > screenSprite->w)
615 x = (g_screenWidth - screenSprite->w) >> 1;
618 if (g_screenHeight > screenSprite->h)
619 y = (g_screenHeight - screenSprite->h) >> 1;
624 renderArea.w = MIN(g_screenWidth - x, screenSprite->w);
625 renderArea.h = MIN(g_screenHeight - y, screenSprite->h);
626 SDL_BlitSurface(screenSprite, NULL, g_screen, &renderArea);
628 SDL_FreeSurface(screenSprite);
632 static int display_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
643 bitmap = gr_create_bitmap_raw(g_width, g_height, g_vBackBuf1);
645 if (g_destX == -1) // center it
646 g_destX = (g_screenWidth - g_width) >> 1;
647 if (g_destY == -1) // center it
648 g_destY = (g_screenHeight - g_height) >> 1;
650 gr_palette_load(g_palette);
652 gr_bitmap(g_destX, g_destY, bitmap);
654 gr_free_sub_bitmap(bitmap);
661 static int init_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
665 if (video_initialized)
668 video_initialized = 1;
670 width = get_short(data);
671 height = get_short(data+2);
673 g_screen = SDL_SetVideoMode(width, height, 16, g_sdlVidFlags);
675 g_screenWidth = width;
676 g_screenHeight = height;
677 memset(g_palette, 0, 765);
678 // 255 needs to default to white, for subtitles, etc
679 memset(g_palette + 765, 63, 3);
684 static int video_palette_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
687 start = get_short(data);
688 count = get_short(data+2);
689 memcpy(g_palette + 3*start, data+4, 3*count);
694 static int video_codemap_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
701 void decodeFrame16(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain);
702 void decodeFrame8(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain);
704 static int video_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
706 short nFrameHot, nFrameCold;
707 short nXoffset, nYoffset;
708 short nXsize, nYsize;
709 unsigned short nFlags;
712 nFrameHot = get_short(data);
713 nFrameCold = get_short(data+2);
714 nXoffset = get_short(data+4);
715 nYoffset = get_short(data+6);
716 nXsize = get_short(data+8);
717 nYsize = get_short(data+10);
718 nFlags = get_ushort(data+12);
722 temp = (unsigned char *)g_vBackBuf1;
723 g_vBackBuf1 = g_vBackBuf2;
727 /* convert the frame */
729 decodeFrame16((unsigned char *)g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
731 decodeFrame8(g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
737 static int end_chunk_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context)
745 void initializeMovie(MVESTREAM *mve)
749 for (i = 0; i < 32; i++)
750 mve_set_handler(mve, i, default_seg_handler);
752 memset(unhandled_chunks, 0, 32*256);
754 mve_set_handler(mve, MVE_OPCODE_ENDOFSTREAM, end_movie_handler);
755 mve_set_handler(mve, MVE_OPCODE_ENDOFCHUNK, end_chunk_handler);
756 mve_set_handler(mve, MVE_OPCODE_CREATETIMER, create_timer_handler);
757 mve_set_handler(mve, MVE_OPCODE_INITAUDIOBUFFERS, create_audiobuf_handler);
758 mve_set_handler(mve, MVE_OPCODE_STARTSTOPAUDIO, play_audio_handler);
759 mve_set_handler(mve, MVE_OPCODE_INITVIDEOBUFFERS, create_videobuf_handler);
761 mve_set_handler(mve, MVE_OPCODE_DISPLAYVIDEO, display_video_handler);
762 mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMEDATA, audio_data_handler);
763 mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMESILENCE, audio_data_handler);
764 mve_set_handler(mve, MVE_OPCODE_INITVIDEOMODE, init_video_handler);
766 mve_set_handler(mve, MVE_OPCODE_SETPALETTE, video_palette_handler);
767 mve_set_handler(mve, MVE_OPCODE_SETPALETTECOMPRESSED, video_palette_handler);
768 mve_set_handler(mve, MVE_OPCODE_SETDECODINGMAP, video_codemap_handler);
770 mve_set_handler(mve, MVE_OPCODE_VIDEODATA, video_data_handler);
773 void playMovie(MVESTREAM *mve)
778 mve_audio_enabled = 1;
780 while (cont && playing)
782 cont = mve_play_next_chunk(mve);
783 if (micro_frame_delay && !init_timer)
791 if (g_loop && !cont) {
798 void shutdownMovie(MVESTREAM *mve)
807 for (i = 0; i < 32*256; i++) {
808 if (unhandled_chunks[i]) {
809 fprintf(stderr, "unhandled chunks of type %02x/%02x: %d\n", i>>8, i&0xFF, unhandled_chunks[i]);
816 static MVESTREAM *mve = NULL;
818 int MVE_rmPrepMovie(int filehandle, int x, int y, int track)
827 mve = mve_open_filehandle(filehandle);
835 for (i = 0; i < 32; i++)
836 mve_set_handler(mve, i, default_seg_handler);
838 mve_set_handler(mve, MVE_OPCODE_ENDOFSTREAM, end_movie_handler);
839 mve_set_handler(mve, MVE_OPCODE_ENDOFCHUNK, end_chunk_handler);
840 mve_set_handler(mve, MVE_OPCODE_CREATETIMER, create_timer_handler);
841 mve_set_handler(mve, MVE_OPCODE_INITAUDIOBUFFERS, create_audiobuf_handler);
842 mve_set_handler(mve, MVE_OPCODE_STARTSTOPAUDIO, play_audio_handler);
843 mve_set_handler(mve, MVE_OPCODE_INITVIDEOBUFFERS, create_videobuf_handler);
845 mve_set_handler(mve, MVE_OPCODE_DISPLAYVIDEO, display_video_handler);
846 mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMEDATA, audio_data_handler);
847 mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMESILENCE, audio_data_handler);
848 mve_set_handler(mve, MVE_OPCODE_INITVIDEOMODE, init_video_handler);
850 mve_set_handler(mve, MVE_OPCODE_SETPALETTE, video_palette_handler);
851 mve_set_handler(mve, MVE_OPCODE_SETPALETTECOMPRESSED, default_seg_handler);
853 mve_set_handler(mve, MVE_OPCODE_SETDECODINGMAP, video_codemap_handler);
855 mve_set_handler(mve, MVE_OPCODE_VIDEODATA, video_data_handler);
860 int MVE_rmStepMovie()
862 static int init_timer=0;
868 while (cont && !g_frameUpdated) // make a "step" be a frame, not a chunk...
869 cont = mve_play_next_chunk(mve);
872 if (micro_frame_delay && !init_timer) {
885 void MVE_rmEndMovie()
895 if (mve_audio_canplay) {
896 // only close audio if we opened it
898 mve_audio_canplay = 0;
900 for (i = 0; i < TOTAL_AUDIO_BUFFERS; i++)
901 if (mve_audio_buffers[i] != NULL)
902 d_free(mve_audio_buffers[i]);
903 memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
904 memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens));
905 mve_audio_curbuf_curpos=0;
910 mve_audio_compressed=0;
912 d_free(mve_audio_spec);
914 audiobuf_created = 0;
921 videobuf_created = 0;
922 video_initialized = 0;
924 mve_close_filehandle(mve);
929 void MVE_rmHoldMovie()
935 void MVE_sndInit(int x)
939 mve_audio_enabled = 0;
941 mve_audio_enabled = 1;