[xiph-commits] r11078 - in experimental/giles: . mng

giles at svn.xiph.org giles at svn.xiph.org
Sun Apr 2 01:50:04 PST 2006


Author: giles
Date: 2006-04-02 01:50:03 -0800 (Sun, 02 Apr 2006)
New Revision: 11078

Added:
   experimental/giles/mng/
   experimental/giles/mng/Makefile
   experimental/giles/mng/mngplay.c
Log:
Import the SDL-based mngplay from the libmng-1.0.8 distribution.


Added: experimental/giles/mng/Makefile
===================================================================
--- experimental/giles/mng/Makefile	2006-04-01 14:23:16 UTC (rev 11077)
+++ experimental/giles/mng/Makefile	2006-04-02 09:50:03 UTC (rev 11078)
@@ -0,0 +1,22 @@
+# GNU makefile for mng stuff
+
+PROGS = mngplay
+
+CFLAGS = -g -O2 #-Wall
+
+mngplay_SRCS = mngplay.c
+mngplay_OBJS = $(mngplay_SRCS:.c=.o)
+mngplay_CFLAGS = `sdl-config --cflags`
+mngplay_LIBS = `sdl-config --libs` -lmng -lz -ljpeg -llcms
+
+all : $(PROGS)
+
+clean :
+	$(RM) $(mngplay_OBJS)
+	$(RM) $(PROGS)
+
+.PHONY: all clean
+
+mngplay : CFLAGS += $(mngplay_CFLAGS)
+mngplay : LDFLAGS += $(mngplay_LIBS)
+mngplay : $(mngplay_OBJS)

Added: experimental/giles/mng/mngplay.c
===================================================================
--- experimental/giles/mng/mngplay.c	2006-04-01 14:23:16 UTC (rev 11077)
+++ experimental/giles/mng/mngplay.c	2006-04-02 09:50:03 UTC (rev 11078)
@@ -0,0 +1,507 @@
+/*
+	mngplay
+
+	$Date: 2003/12/07 09:45:16 $
+
+	Ralph Giles <giles :at: ashlu.bc.ca>
+
+	This program my be redistributed under the terms of the
+	GNU General Public Licence, version 2, or at your preference,
+	any later version.
+
+	(this assuming there's no problem with libmng not being GPL...)
+
+
+	this is an SDL based mng player. the code is very rough;
+	patches welcome.
+
+
+	GRR 20010708:  added SDL/libmng/zlib/libjpeg version info, mouse-click
+			handling (alternate quit mode); improved automake setup
+
+	Raphael Assenat <raph :at: raphnet.net>
+	2003/11/26:    added command line options to run in alternate color depths.
+	               
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <SDL/SDL.h>
+#include <libmng.h>
+
+#include <libgen.h> // basename
+
+
+#define DEFAULT_SDL_VIDEO_DEPTH 32
+
+/* structure for keeping track of our mng stream inside the callbacks */
+typedef struct {
+	FILE		*file;	   /* pointer to the file we're decoding */
+	char		*filename; /* pointer to the file's path/name */
+	SDL_Surface	*surface;  /* SDL display */
+	mng_uint32	delay;     /* ticks to wait before resuming decode */
+	int			sdl_video_depth;  /* The depth for SDL_SetVideoMode */
+} mngstuff;
+
+/* callbacks for the mng decoder */
+
+/* memory allocation; data must be zeroed */
+mng_ptr mymngalloc(mng_uint32 size)
+{
+	return (mng_ptr)calloc(1, size);
+}
+
+/* memory deallocation */
+void mymngfree(mng_ptr p, mng_uint32 size)
+{
+	free(p);
+	return;
+}
+
+mng_bool mymngopenstream(mng_handle mng)
+{
+	mngstuff	*mymng;
+
+	/* look up our stream struct */
+        mymng = (mngstuff*)mng_get_userdata(mng);
+	
+	/* open the file */
+	mymng->file = fopen(mymng->filename, "rb");
+	if (mymng->file == NULL) {
+		fprintf(stderr, "unable to open '%s'\n", mymng->filename);
+		return MNG_FALSE;
+	}
+
+	return MNG_TRUE;
+}
+
+mng_bool mymngclosestream(mng_handle mng)
+{
+	mngstuff	*mymng;
+
+	/* look up our stream struct */
+        mymng = (mngstuff*)mng_get_userdata(mng);
+
+	/* close the file */
+	fclose(mymng->file);
+	mymng->file = NULL;	/* for safety */
+
+	return MNG_TRUE;
+}
+
+/* feed data to the decoder */
+mng_bool mymngreadstream(mng_handle mng, mng_ptr buffer,
+		mng_uint32 size, mng_uint32 *bytesread)
+{
+	mngstuff *mymng;
+
+	/* look up our stream struct */
+	mymng = (mngstuff*)mng_get_userdata(mng);
+
+	/* read the requested amount of data from the file */
+	*bytesread = fread(buffer, 1, size, mymng->file);
+
+	return MNG_TRUE;
+}
+
+/* the header's been read. set up the display stuff */
+mng_bool mymngprocessheader(mng_handle mng,
+		mng_uint32 width, mng_uint32 height)
+{
+	mngstuff	*mymng;
+	SDL_Surface	*screen;
+	char		title[256];
+
+//	fprintf(stderr, "our mng is %dx%d\n", width,height);
+
+	/* retreive our user data */
+ 	mymng = (mngstuff*)mng_get_userdata(mng);
+	
+	screen = SDL_SetVideoMode(width,height, mymng->sdl_video_depth, SDL_SWSURFACE);
+	if (screen == NULL) {
+		fprintf(stderr, "unable to allocate %dx%d video memory: %s\n", 
+			width, height, SDL_GetError());
+		return MNG_FALSE;
+	}
+
+	printf("SDL Video Mode: %dx%d bpp=%d\n", width, height, mymng->sdl_video_depth);
+	
+	/* save the surface pointer */
+	mymng->surface = screen;
+
+	/* set a descriptive window title */
+	snprintf(title, 256, "mngplay: %s", mymng->filename);
+	SDL_WM_SetCaption(title, "mngplay");
+
+	/* in necessary, lock the drawing surface to the decoder
+	   can safely fill it. We'll unlock elsewhere before display */
+	if (SDL_MUSTLOCK(mymng->surface)) {
+		if ( SDL_LockSurface(mymng->surface) < 0 ) {
+			fprintf(stderr, "could not lock display surface\n");
+			exit(1);
+		}
+	}
+
+/*
+	printf("RGBA Masks: %08X %08X %08X %08X\n", 
+				mymng->surface->format->Rmask,
+				mymng->surface->format->Gmask,
+				mymng->surface->format->Bmask,
+				mymng->surface->format->Amask);
+	printf("RGBA Shifts: %08X %08X %08X %08X\n", 
+				mymng->surface->format->Rshift,
+				mymng->surface->format->Gshift,
+				mymng->surface->format->Bshift,
+				mymng->surface->format->Ashift);
+*/
+	/* Choose a canvas style which matches the SDL_Surface pixel format */
+	switch(mymng->surface->format->BitsPerPixel)
+	{
+		case 32:
+			if (mymng->surface->format->Amask==0) {
+				/* No alpha (padding byte) */
+				if (mymng->surface->format->Bshift==0) {
+					/* Blue first */
+					mng_set_canvasstyle(mng, MNG_CANVAS_BGRX8);
+				} else {
+					/* Red first */
+					fprintf(stderr, "No matching mng canvas for sdl pixel format. Colors may be wrong.\n");
+					mng_set_canvasstyle(mng, MNG_CANVAS_BGRX8);
+				}
+			}
+			else {
+				/* Real alpha */
+				if (mymng->surface->format->Bshift==0) {
+					/* Blue first */
+					mng_set_canvasstyle(mng, MNG_CANVAS_BGRA8);
+				} else {
+					/* Red first */
+					mng_set_canvasstyle(mng, MNG_CANVAS_RGBA8);
+				}
+			}
+			break;
+		case 24:
+			if (mymng->surface->format->Amask==0) {
+				/* No alpha here should mean true rgb24bit */
+				if (mymng->surface->format->Bshift==0) {
+					/* Blue first */
+					mng_set_canvasstyle(mng, MNG_CANVAS_BGR8);
+				} else {
+					/* Red first */
+					mng_set_canvasstyle(mng, MNG_CANVAS_RGB8);
+				}
+			}
+			else {
+				/* If there is an alpha and we are in 24 bpp, this must
+				 * mean rgb5658 */
+				if (mymng->surface->format->Bshift==0) {
+					/* Blue first */
+					mng_set_canvasstyle(mng, MNG_CANVAS_BGRA565);
+				} else {
+					/* Red first */
+					mng_set_canvasstyle(mng, MNG_CANVAS_RGBA565);
+				}
+			}
+			break;
+		case 16:
+			if (mymng->surface->format->Bshift==0) {
+				/* Blue first */
+				mng_set_canvasstyle(mng, MNG_CANVAS_BGR565);
+			} else {
+				/* Red first */
+				mng_set_canvasstyle(mng, MNG_CANVAS_RGB565);
+			}			
+			break;
+		default:
+			return MNG_FALSE;
+	}
+
+	return MNG_TRUE;
+}
+
+/* return a row pointer for the decoder to fill */
+mng_ptr mymnggetcanvasline(mng_handle mng, mng_uint32 line)
+{
+	mngstuff	*mymng;
+	SDL_Surface	*surface;
+	mng_ptr		row;
+
+	/* dereference our structure */
+	mymng = (mngstuff*)mng_get_userdata(mng);
+
+	/* we assume any necessary locking has happened 
+	   outside, in the frame level code */
+	row = mymng->surface->pixels + mymng->surface->pitch*line;
+
+//	fprintf(stderr, "   returning pointer to line %d (%p)\n", line, row);
+ 
+	return (row);	
+}
+
+/* timer */
+mng_uint32 mymnggetticks(mng_handle mng)
+{
+	mng_uint32 ticks;
+
+	ticks = (mng_uint32)SDL_GetTicks();
+//	fprintf(stderr, "  %d\t(returning tick count)\n",ticks);
+
+	return(ticks);
+}
+
+mng_bool mymngrefresh(mng_handle mng, mng_uint32 x, mng_uint32 y,
+			mng_uint32 w, mng_uint32 h)
+{
+	mngstuff	*mymng;
+	SDL_Rect	frame;
+
+	frame.x = x;
+	frame.y = y;
+	frame.w = w;
+	frame.h = h;
+
+	/* dereference our structure */
+        mymng = (mngstuff*)mng_get_userdata(mng);
+
+	/* if necessary, unlock the display */
+	if (SDL_MUSTLOCK(mymng->surface)) {
+                SDL_UnlockSurface(mymng->surface);
+        }
+
+        /* refresh the screen with the new frame */
+        SDL_UpdateRects(mymng->surface, 1, &frame);
+	
+	/* in necessary, relock the drawing surface */
+        if (SDL_MUSTLOCK(mymng->surface)) {
+                if ( SDL_LockSurface(mymng->surface) < 0 ) {
+                        fprintf(stderr, "could not lock display surface\n");
+                        return MNG_FALSE;
+                }
+        }
+	
+
+	return MNG_TRUE;
+}
+
+/* interframe delay callback */
+mng_bool mymngsettimer(mng_handle mng, mng_uint32 msecs)
+{
+	mngstuff	*mymng;
+
+//	fprintf(stderr,"  pausing for %d ms\n", msecs);
+	
+	/* look up our stream struct */
+        mymng = (mngstuff*)mng_get_userdata(mng);
+
+	/* set the timer for when the decoder wants to be woken */
+	mymng->delay = msecs;
+
+	return MNG_TRUE;
+	
+}
+
+mng_bool mymngerror(mng_handle mng, mng_int32 code, mng_int8 severity,
+	mng_chunkid chunktype, mng_uint32 chunkseq,
+	mng_int32 extra1, mng_int32 extra2, mng_pchar text)
+{
+	mngstuff	*mymng;
+	char		chunk[5];
+	
+        /* dereference our data so we can get the filename */
+        mymng = (mngstuff*)mng_get_userdata(mng);
+
+	/* pull out the chuck type as a string */
+	// FIXME: does this assume unsigned char?
+	chunk[0] = (char)((chunktype >> 24) & 0xFF);
+	chunk[1] = (char)((chunktype >> 16) & 0xFF);
+	chunk[2] = (char)((chunktype >>  8) & 0xFF);
+	chunk[3] = (char)((chunktype      ) & 0xFF);
+	chunk[4] = '\0';
+
+	/* output the error */
+	fprintf(stderr, "error playing '%s' chunk %s (%d):\n",
+		mymng->filename, chunk, chunkseq);
+	fprintf(stderr, "%s\n", text);
+
+	return (0);
+}
+
+int mymngquit(mng_handle mng)
+{
+	mngstuff	*mymng;
+
+	/* dereference our data so we can free it */
+	mymng = (mngstuff*)mng_get_userdata(mng);
+
+	/* cleanup. this will call mymngclosestream */
+        mng_cleanup(&mng);
+
+	/* free our data */
+	free(mymng);
+	
+	/* quit */
+	exit(0);
+}
+
+int checkevents(mng_handle mng)
+{
+	SDL_Event	event;
+
+	/* check if there's an event pending */
+	if (!SDL_PollEvent(&event)) {
+		return 0;	/* no events pending */
+	}
+
+	/* we have an event; process it */
+	switch (event.type) {
+		case SDL_QUIT:
+			mymngquit(mng);	/* quit */ 
+			break;
+		case SDL_MOUSEBUTTONDOWN:
+		case SDL_MOUSEBUTTONUP:
+			mymngquit(mng);
+			break;
+		case SDL_KEYUP:
+			switch (event.key.keysym.sym) {
+				case SDLK_ESCAPE:
+				case SDLK_q:
+					mymngquit(mng);
+					break;
+			}
+			/* FALL THROUGH */
+		default:
+			return 1;
+	}
+
+	return 0;   /* GRR ADDED:  non-void function */
+}
+
+int main(int argc, char *argv[])
+{
+	mngstuff	*mymng;
+	mng_handle	mng;
+	SDL_Rect	updaterect;
+
+	if (argc < 2) {
+		const SDL_version *pSDLver = SDL_Linked_Version();
+
+		fprintf(stderr, "Usage:  %s mngfile [depth]\n\n", basename(argv[0]));
+		fprintf(stderr, "        where 'depth' is 15,16,24 or 32\n");
+		fprintf(stderr,
+			"  Compiled with SDL %d.%d.%d; using SDL %d.%d.%d.\n",
+			SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL,
+			pSDLver->major, pSDLver->minor, pSDLver->patch);
+		fprintf(stderr, "  Compiled with libmng %s; using libmng %s.\n",
+			MNG_VERSION_TEXT, mng_version_text());
+		fprintf(stderr, "  Compiled with zlib %s; using zlib %s.\n",
+			ZLIB_VERSION, zlib_version);
+#ifdef JPEG_LIB_VERSION
+		{
+			int major = JPEG_LIB_VERSION / 10;
+			int minor = JPEG_LIB_VERSION % 10;
+			char minoralpha[2];
+
+			if (minor) {
+				minoralpha[0] = (char)(minor - 1 + 'a');
+				minoralpha[1] = '\0';
+			} else
+				minoralpha[0] = '\0';
+			fprintf(stderr, "  Compiled with libjpeg %d%s.\n",
+				major, minoralpha);
+		}
+#endif
+		fprintf(stderr,
+			"\nPress Esc or Q, or click mouse button, to quit.\n");
+		exit(1);
+	}
+
+	/* allocate our stream data structure */
+	mymng = (mngstuff*)calloc(1, sizeof(*mymng));
+	if (mymng == NULL) {
+		fprintf(stderr, "could not allocate stream structure.\n");
+		exit(0);
+	}
+
+	/* pass the name of the file we want to play */
+	mymng->filename = argv[1];
+
+	/* pass the color depth we wish to use */
+	if (argc>=3) {
+		mymng->sdl_video_depth = atoi(argv[2]);
+		switch(mymng->sdl_video_depth) {
+			case 15:
+			case 16:
+			case 24:
+			case 32:
+				break;
+			default:
+				fprintf(stderr, "Unsupported color depth. Choices are: 15, 16, 24 and 32\n");
+				exit(1);
+		}
+	}
+	else {
+		mymng->sdl_video_depth = DEFAULT_SDL_VIDEO_DEPTH;
+	}
+	
+	/* set up the mng decoder for our stream */
+        mng = mng_initialize(mymng, mymngalloc, mymngfree, MNG_NULL);
+        if (mng == MNG_NULL) {
+                fprintf(stderr, "could not initialize libmng.\n");
+                exit(1);
+        }
+
+	/* set the callbacks */
+	mng_setcb_errorproc(mng, mymngerror);
+	mng_setcb_openstream(mng, mymngopenstream);
+	mng_setcb_closestream(mng, mymngclosestream);
+	mng_setcb_readdata(mng, mymngreadstream);
+	mng_setcb_gettickcount(mng, mymnggetticks);
+	mng_setcb_settimer(mng, mymngsettimer);
+	mng_setcb_processheader(mng, mymngprocessheader);
+	mng_setcb_getcanvasline(mng, mymnggetcanvasline);
+	mng_setcb_refresh(mng, mymngrefresh);
+	/* FIXME: should check for errors here */
+
+	/* initialize SDL */
+        if (SDL_Init(SDL_INIT_VIDEO) < 0) {
+                fprintf(stderr, "%s: Unable to initialize SDL (%s)\n",
+                        argv[0], SDL_GetError());
+                exit(1);
+        }
+	/* arrange to call the shutdown routine before we exit */
+        atexit(SDL_Quit);
+
+	/* restrict event handling to the relevant bits */
+	SDL_EventState(SDL_KEYDOWN, SDL_IGNORE); /* keyup only */
+	SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
+//	SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_IGNORE);
+//	SDL_EventState(SDL_MOUSEBUTTONUP, SDL_IGNORE);
+
+//	fprintf(stderr, "playing mng...maybe.\n");
+
+	mng_readdisplay(mng);
+
+	/* loop though the frames */
+	while (mymng->delay) {
+//		fprintf(stderr, "  waiting for %d ms\n", mymng->delay);
+		SDL_Delay(mymng->delay);
+
+		/* reset the delay in case the decoder
+		   doesn't update it again */
+		mymng->delay = 0;
+
+		mng_display_resume(mng);
+
+		/* check for user input (just quit at this point) */
+		checkevents(mng);
+	}
+
+	/* ¿hay alguno? pause before quitting */
+	fprintf(stderr, "pausing before shutdown...\n");
+	SDL_Delay(1000);
+
+	/* cleanup and quit */
+	mymngquit(mng);
+}
+



More information about the commits mailing list