[xiph-commits] r11090 - experimental/giles/mng
giles at svn.xiph.org
giles at svn.xiph.org
Mon Apr 3 00:29:51 PDT 2006
Author: giles
Date: 2006-04-03 00:29:49 -0700 (Mon, 03 Apr 2006)
New Revision: 11090
Modified:
experimental/giles/mng/Makefile
experimental/giles/mng/mngplay.c
Log:
Add code to play MNG streams out of Ogg files. We only try to find the
first matching substream. Hasn't been tested at all.
Modified: experimental/giles/mng/Makefile
===================================================================
--- experimental/giles/mng/Makefile 2006-04-03 02:31:05 UTC (rev 11089)
+++ experimental/giles/mng/Makefile 2006-04-03 07:29:49 UTC (rev 11090)
@@ -7,7 +7,7 @@
mngplay_SRCS = mngplay.c
mngplay_OBJS = $(mngplay_SRCS:.c=.o)
mngplay_CFLAGS = `sdl-config --cflags`
-mngplay_LIBS = `sdl-config --libs` -lmng -lz -ljpeg -llcms
+mngplay_LIBS = `sdl-config --libs` -lmng -lz -ljpeg -llcms -logg
all : $(PROGS)
Modified: experimental/giles/mng/mngplay.c
===================================================================
--- experimental/giles/mng/mngplay.c 2006-04-03 02:31:05 UTC (rev 11089)
+++ experimental/giles/mng/mngplay.c 2006-04-03 07:29:49 UTC (rev 11090)
@@ -22,15 +22,20 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <libgen.h> // basename
+
#include <SDL.h>
#include <libmng.h>
+#include <ogg/ogg.h>
-#include <libgen.h> // basename
+#define MNG_SIGNATURE "\212MNG\r\n\032\n"
-
#define DEFAULT_SDL_VIDEO_DEPTH 32
+#define OGG_MNG_BUFFER_SIZE 4096
+
/* structure for keeping track of our mng stream inside the callbacks */
typedef struct {
FILE *file; /* pointer to the file we're decoding */
@@ -38,6 +43,9 @@
SDL_Surface *surface; /* SDL display */
mng_uint32 delay; /* ticks to wait before resuming decode */
int sdl_video_depth; /* The depth for SDL_SetVideoMode */
+ int is_ogg; /* whether we're parsing an Ogg file */
+ ogg_sync_state ogg_sync; /* libogg parse structures */
+ ogg_stream_state ogg_stream;
} mngstuff;
/* callbacks for the mng decoder */
@@ -55,9 +63,29 @@
return;
}
+/* pull data from the file into our ogg parser */
+int bufferoggdata(mng_handle mng)
+{
+ mngstuff *mymng;
+ unsigned char *buffer;
+ int bytes;
+
+ /* look up our stream struct */
+ mymng = (mngstuff*)mng_get_userdata(mng);
+
+ buffer = ogg_sync_buffer(&mymng->ogg_sync, OGG_MNG_BUFFER_SIZE);
+ bytes = fread(buffer, 1, OGG_MNG_BUFFER_SIZE, mymng->file);
+ ogg_sync_wrote(&mymng->ogg_sync, bytes);
+
+ return bytes;
+}
+
mng_bool mymngopenstream(mng_handle mng)
{
mngstuff *mymng;
+ unsigned char magic[8];
+ ogg_page page;
+ int bytes;
/* look up our stream struct */
mymng = (mngstuff*)mng_get_userdata(mng);
@@ -69,6 +97,52 @@
return MNG_FALSE;
}
+ /* determine file type */
+ mymng->is_ogg = MNG_FALSE;
+ bytes = fread(magic, 1, 8, mymng->file);
+ if (bytes != 8) {
+ fprintf(stderr, "unable to determine file type for '%s'\n", mymng->filename);
+ fclose(mymng->file);
+ return MNG_FALSE;
+ }
+ /* return to the start */
+ fseek(mymng->file, 0, SEEK_SET);
+ if (!memcmp(magic, MNG_SIGNATURE, 8)) {
+ /* We have a normal MNG file; return */
+ return MNG_TRUE;
+ } else if (!memcmp(magic, "OggS", 4)) {
+
+ /* set up the Ogg MNG decoder */
+ ogg_sync_init(&mymng->ogg_sync);
+ bufferoggdata(mng);
+ while (ogg_sync_pageout(&mymng->ogg_sync, &page)>0) {
+ ogg_stream_state test;
+ ogg_packet packet;
+
+ /* ignore non-bos pages */
+ if (!ogg_page_bos(&page)) break;
+ /* set up a parser for each bos page we see */
+ ogg_stream_init(&test, ogg_page_serialno(&page));
+ ogg_stream_pagein(&test,&page);
+ ogg_stream_packetout(&test, &packet);
+ if (packet.bytes >8 &&
+ !memcmp(packet.packet, MNG_SIGNATURE, 8)) {
+ /* we have a MNG stream; save state and return */
+ memcpy(&mymng->ogg_stream, &test, sizeof(test));
+ mymng->is_ogg = MNG_TRUE;
+ /* tell the library to ignore missing CRCs */
+ mng_set_crcmode(mng, 0);
+ return MNG_TRUE;
+ }
+ /* free scratch parser */
+ ogg_stream_clear(&test);
+ }
+
+ /* no MNG streams in this Ogg file */
+ return MNG_FALSE;
+ }
+
+ /* Unknown file magic, try to parse as a raw MNG */
return MNG_TRUE;
}
@@ -79,6 +153,12 @@
/* look up our stream struct */
mymng = (mngstuff*)mng_get_userdata(mng);
+ /* ogg stuff */
+ if (mymng->is_ogg) {
+ ogg_stream_clear(&mymng->ogg_stream);
+ ogg_sync_clear(&mymng->ogg_sync);
+ }
+
/* close the file */
fclose(mymng->file);
mymng->file = NULL; /* for safety */
@@ -95,6 +175,12 @@
/* look up our stream struct */
mymng = (mngstuff*)mng_get_userdata(mng);
+ /* we don't do anything on OggMNG streams */
+ if (mymng->is_ogg) {
+ *bytesread = 0;
+ return MNG_FALSE;
+ }
+
/* read the requested amount of data from the file */
*bytesread = fread(buffer, 1, size, mymng->file);
@@ -130,7 +216,7 @@
snprintf(title, 256, "mngplay: %s", mymng->filename);
SDL_WM_SetCaption(title, "mngplay");
- /* in necessary, lock the drawing surface to the decoder
+ /* in necessary, lock the drawing surface so the decoder
can safely fill it. We'll unlock elsewhere before display */
if (SDL_MUSTLOCK(mymng->surface)) {
if ( SDL_LockSurface(mymng->surface) < 0 ) {
@@ -339,6 +425,42 @@
exit(0);
}
+int pullchunks(mng_handle mng)
+{
+ mngstuff *mymng;
+ int bytes;
+ ogg_page page;
+ ogg_packet packet;
+
+ /* dereference our user data */
+ mymng = (mngstuff*)mng_get_userdata(mng);
+
+ /* make sure we're an OggMNG stream */
+ if (!mymng->is_ogg) return MNG_FALSE;
+
+ /* pull in more data */
+ bytes = bufferoggdata(mng);
+ if (bytes <= 0) return MNG_FALSE;
+
+ /* pull any new pages from the stream */
+ while (ogg_sync_pageout(&mymng->ogg_sync, &page)>0) {
+ /* we don't need the check the serialno,
+ ogg_stream_pagein will discard the packet
+ if it does not match */
+ ogg_stream_pagein(&mymng->ogg_stream, &page);
+ /* pull out any new packets */
+ while (ogg_stream_packetout(&mymng->ogg_stream, &packet)>0) {
+ /* each OggMNG packet is a chunk, minus
+ length and CRC fields */
+ mng_read_pushchunk(mng,
+ packet.packet, packet.bytes,
+ MNG_FALSE);
+ }
+ }
+
+ return MNG_TRUE;
+}
+
int checkevents(mng_handle mng)
{
SDL_Event event;
@@ -379,6 +501,7 @@
{
mngstuff *mymng;
mng_handle mng;
+ mng_retcode ret;
if (argc < 2) {
const SDL_version *pSDLver = SDL_Linked_Version();
@@ -477,7 +600,7 @@
// fprintf(stderr, "playing mng...maybe.\n");
- mng_readdisplay(mng);
+ ret = mng_readdisplay(mng);
/* loop though the frames */
while (mymng->delay) {
@@ -488,7 +611,9 @@
doesn't update it again */
mymng->delay = 0;
- mng_display_resume(mng);
+ ret = mng_display_resume(mng);
+ if (ret == MNG_NEEDMOREDATA && mymng->is_ogg)
+ pullchunks(mng);
/* check for user input (just quit at this point) */
checkevents(mng);
More information about the commits
mailing list