From 953f0e2f01cbff2f521024b33e489e966ed356bb Mon Sep 17 00:00:00 2001 From: Thomas Vander Stichele Date: Sun, 23 Dec 2001 12:18:18 +0000 Subject: made changes everywhere to accomodate for the headers being in we'll need to conclude this fast becau... Original commit message from CVS: made changes everywhere to accomodate for the headers being in we'll need to conclude this fast because we will also need to change stuff in core real soon for the libs in order to fix everything and I can't do it right now because I disabled all of the plugins here ;) --- TODO | 4 + configure.ac | 20 +- ext/Makefile.am | 20 +- gst-libs/gst/resample/Makefile.am | 10 +- gst-libs/gst/riff/Makefile.am | 11 + gst-libs/gst/riff/riff.c | 226 ++++++++++++++++++++ gst-libs/gst/riff/riff.h | 406 ++++++++++++++++++++++++++++++++++++ gst-libs/gst/riff/riffencode.c | 177 ++++++++++++++++ gst-libs/gst/riff/riffparse.c | 221 ++++++++++++++++++++ gst-libs/gst/riff/riffutil.c | 46 ++++ gst/mpeg1sys/buffer.c | 2 +- gst/mpeg1sys/gstmpeg1systemencode.h | 2 +- gst/passthrough/gstpassthrough.c | 2 +- gst/playondemand/gstplayondemand.c | 2 +- gst/speed/gstspeed.c | 2 +- 15 files changed, 1113 insertions(+), 38 deletions(-) create mode 100644 gst-libs/gst/riff/Makefile.am create mode 100644 gst-libs/gst/riff/riff.c create mode 100644 gst-libs/gst/riff/riff.h create mode 100644 gst-libs/gst/riff/riffencode.c create mode 100644 gst-libs/gst/riff/riffparse.c create mode 100644 gst-libs/gst/riff/riffutil.c diff --git a/TODO b/TODO index bfcbdf4c..1c05ae57 100644 --- a/TODO +++ b/TODO @@ -18,3 +18,7 @@ * check options in a52, it has some arch stuff and some opti stuff that looks dodgy +* what to do with the perftest in mpeg2dec ? + +* riff: do we need those cflags ? + diff --git a/configure.ac b/configure.ac index ba6888c3..e16dc673 100644 --- a/configure.ac +++ b/configure.ac @@ -519,7 +519,8 @@ GST_CHECK_FEATURE(LIBMIKMOD, [mikmod plugin], mikmod, [ dnl *** mpeg2dec *** translit(dnm, m, l) AM_CONDITIONAL(USE_MPEG2DEC, true) GST_CHECK_FEATURE(MPEG2DEC, [mpeg2dec], mpeg2dec, [ - GST_CHECK_LIBHEADER(MPEG2DEC, mpeg2, mpeg2_init,, mpeg2dec/mpeg2.h, MPEG2DEC_LIBS="-lmpeg2") + GST_CHECK_LIBHEADER(MPEG2DEC, mpeg2, mpeg2_init,, mpeg2dec/mpeg2.h, MPEG2DEC_LIBS="-lmpeg2 -lmpeg2dec") + AC_SUBST(MPEG2DEC_LIBS) ]) dnl *** quicktime *** @@ -863,19 +864,6 @@ if test "x$HAVE_LIBDVDREAD" = xyes; then AC_DEFINE(HAVE_LIBDVDREAD) fi -dnl FIXME: I think these can go -if test "x$HAVE_LINUX_CDROM" = xyes; then - AC_DEFINE(HAVE_LINUX_CDROM) -fi - -if test "x$HAVE_LINUX_VIDEODEV" = xyes; then - AC_DEFINE(HAVE_LINUX_VIDEODEV) -fi - -if test "x$HAVE_MPEG2DEC" = xyes; then - AC_DEFINE(HAVE_MPEG2DEC) -fi - if test "x$HAVE_A52DEC" = xyes; then AC_DEFINE(HAVE_A52DEC) fi @@ -907,8 +895,6 @@ AM_CONDITIONAL(EXPERIMENTAL, test "$EXPERIMENTAL" = "$xyes") AM_CONDITIONAL(BROKEN, test "$BROKEN" = "$xyes") AM_CONDITIONAL(HAVE_LIBMIKMOD, test "x$HAVE_LIBMIKMOD" = "xyes") -AM_CONDITIONAL(HAVE_LINUX_CDROM, test "x$HAVE_LINUX_CDROM" = "xyes") -AM_CONDITIONAL(HAVE_LINUX_VIDEODEV, test "x$HAVE_LINUX_VIDEODEV" = "xyes") AM_CONDITIONAL(HAVE_LIBDVDREAD, test "x$HAVE_LIBDVDREAD" = "xyes") AM_CONDITIONAL(HAVE_LIBJPEG, test "x$HAVE_LIBJPEG" = "xyes") AM_CONDITIONAL(HAVE_LIBSDL, test "x$HAVE_LIBSDL" = "xyes") @@ -929,7 +915,6 @@ AM_CONDITIONAL(HAVE_FIG2DEV_PNG, $HAVE_FIG2DEV_PNG) AM_CONDITIONAL(HAVE_FIG2DEV_PDF, $HAVE_FIG2DEV_PDF) AM_CONDITIONAL(HAVE_CDPARANOIA, test "x$HAVE_CDPARANOIA" = "xyes") AM_CONDITIONAL(HAVE_LIBSHOUT, test "x$HAVE_LIBSHOUT" = "xyes") -AM_CONDITIONAL(HAVE_MPEG2DEC, test "x$HAVE_MPEG2DEC" = "xyes") AM_CONDITIONAL(HAVE_A52DEC, test "x$HAVE_A52DEC" = "xyes") AM_CONDITIONAL(HAVE_AVIFILE, test "x$HAVE_AVIFILE" = "xyes") dnl thomas : the next line gives errors, this is how it is in CVS @@ -1104,6 +1089,7 @@ gst-libs/Makefile gst-libs/gst/Makefile gst-libs/gst/audio/Makefile gst-libs/gst/resample/Makefile +gst-libs/gst/riff/Makefile gst-plugins.spec ) diff --git a/ext/Makefile.am b/ext/Makefile.am index b610baad..87883f3c 100644 --- a/ext/Makefile.am +++ b/ext/Makefile.am @@ -1,8 +1,8 @@ -#if USE_A52 -#A52_DIR=a52 -#else -#A52_DIR= -#endif +if USE_A52 +A52_DIR=a52 +else +A52_DIR= +endif if USE_AALIB AALIB_DIR=aalib @@ -41,7 +41,7 @@ MAD_DIR= endif if USE_MPEG2DEC -MPEG2DEC_DIR=mad +MPEG2DEC_DIR=mpeg2dec else MPEG2DEC_DIR= endif @@ -58,10 +58,8 @@ else VORBIS_DIR= endif -#$A52_DIR -SUBDIRS=$(AALIB_DIR) $(ALSA_DIR) $(AUDIOFILE_DIR) $(ESD_DIR) \ - $(LAME_DIR) $(MAD_DIR) $(MPEG2DEC_DIR) \ +SUBDIRS=$(A52_DIR) $(AALIB_DIR) $(ALSA_DIR) $(AUDIOFILE_DIR) $(ESD_DIR) \ + $(LAME_DIR) $(MAD_DIR) $(MPEG2DEC_DIR)\ $(SDL_DIR) $(VORBIS_DIR) -#a52 -DIST_SUBDIRS=aalib alsa audiofile esd lame mad mpeg2dec sdl vorbis +DIST_SUBDIRS=a52 aalib alsa audiofile esd lame mad mpeg2dec sdl vorbis diff --git a/gst-libs/gst/resample/Makefile.am b/gst-libs/gst/resample/Makefile.am index 4fe42224..785abceb 100644 --- a/gst-libs/gst/resample/Makefile.am +++ b/gst-libs/gst/resample/Makefile.am @@ -1,6 +1,6 @@ -libdir = $(libdir)/gst +## libdir = $(libdir)/gst -lib_LTLIBRARIES = libresample.la +lib_LTLIBRARIES = libgstresample.la if HAVE_CPU_I386 ARCHCFLAGS = -march=i486 @@ -12,9 +12,9 @@ ARCHCFLAGS = endif endif -libresample_la_SOURCES = dtos.c functable.c resample.c resample.h -libresample_la_LIBADD = $(GST_LIBS) -libresample_la_CFLAGS = $(GST_CFLAGS) -ffast-math $(ARCHCFLAGS) +libgstresample_la_SOURCES = dtos.c functable.c resample.c resample.h +libgstresample_la_LIBADD = $(GST_LIBS) +libgstresample_la_CFLAGS = $(GST_CFLAGS) -ffast-math $(ARCHCFLAGS) noinst_HEADERS = resample.h diff --git a/gst-libs/gst/riff/Makefile.am b/gst-libs/gst/riff/Makefile.am new file mode 100644 index 00000000..ba4a17ba --- /dev/null +++ b/gst-libs/gst/riff/Makefile.am @@ -0,0 +1,11 @@ +libdir = $(prefix)/lib/gst + +lib_LTLIBRARIES = libgstriff.la + +libgstriff_la_SOURCES = riffparse.c riffencode.c riffutil.c + +libgstriffincludedir = $(includedir)/gst/riff +libgstriffinclude_HEADERS = riff.h + +libgstriff_la_LIBADD = $(GST_LIBS) +libgstriff_la_CFLAGS = $(GST_CFLAGS) -funroll-all-loops -finline-functions -ffast-math diff --git a/gst-libs/gst/riff/riff.c b/gst-libs/gst/riff/riff.c new file mode 100644 index 00000000..e0bb7293 --- /dev/null +++ b/gst-libs/gst/riff/riff.c @@ -0,0 +1,226 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + +//#define debug(format,args...) g_print(format,##args) +#define debug(format,args...) + + +GstRiff *gst_riff_new(GstRiffCallback function, gpointer data) { + GstRiff *riff; + + riff = (GstRiff *)g_malloc(sizeof(GstRiff)); + g_return_val_if_fail(riff != NULL, NULL); + + riff->form = 0; + riff->chunks = NULL; + riff->state = 0; + riff->curoffset = 0; + riff->nextlikely = 0; + riff->new_tag_found = function; + riff->callback_data = data; + riff->incomplete_chunk = NULL; + riff->dataleft = NULL; + + return riff; +} + +gint gst_riff_next_buffer(GstRiff *riff,GstBuffer *buf,gulong off) { + gulong last, size; + GstRiffChunk *chunk; + + g_return_val_if_fail (riff != NULL, GST_RIFF_EINVAL); + g_return_val_if_fail (buf != NULL, GST_RIFF_EINVAL); + g_return_val_if_fail (GST_BUFFER_DATA(buf) != NULL, GST_RIFF_EINVAL); + + size = GST_BUFFER_SIZE(buf); + last = off + size; + + debug("offset new buffer 0x%08lx size 0x%08x\n", off, GST_BUFFER_SIZE(buf)); + + if (riff->dataleft) { + gulong newsize; + + debug("recovering left data\n"); + newsize = riff->dataleft_size + size; + riff->dataleft = g_realloc(riff->dataleft, newsize); + memcpy (riff->dataleft+riff->dataleft_size, GST_BUFFER_DATA(buf), size); + gst_buffer_unref (buf); + + buf = gst_buffer_new (); + GST_BUFFER_DATA(buf) = riff->dataleft; + GST_BUFFER_SIZE(buf) = newsize; + off -= riff->dataleft_size; + //last -= riff->dataleft_size; + riff->dataleft = NULL; + } + + if (off == 0) { + guint32 *words = (guin32 *)GST_BUFFER_DATA(buf); + + // don't even try to parse the head if it's not there FIXME + if (last < 12) { + riff->state = GST_RIFF_ENOTRIFF; + return riff->state; + } + + //g_print("testing is 0x%08lx '%s'\n",words[0],gst_riff_id_to_fourcc(words[0])); + /* verify this is a valid RIFF file, first of all */ + if (GUINT32_FROM_LE (words[0]) != GST_RIFF_TAG_RIFF) { + riff->state = GST_RIFF_ENOTRIFF; + return riff->state; + } + riff->form = GUINT32_FROM_LE (words[2]); + //g_print("form is 0x%08lx '%s'\n",words[2],gst_riff_id_to_fourcc(words[2])); + riff->nextlikely = 12; /* skip 'RIFF', length, and form */ + // all OK here + riff->incomplete_chunk = NULL; + } + + // if we have an incomplete chunk from the previous buffer + if (riff->incomplete_chunk) { + guint leftover; + debug("have incomplete chunk %08x filled\n", riff->incomplete_chunk_size); + leftover = riff->incomplete_chunk->size - riff->incomplete_chunk_size; + if (leftover <= size) { + debug("we can fill it from %08x with %08x bytes = %08x\n", riff->incomplete_chunk_size, leftover, riff->incomplete_chunk_size+leftover); + memcpy(riff->incomplete_chunk->data+riff->incomplete_chunk_size, GST_BUFFER_DATA(buf), leftover); + + if (riff->new_tag_found) { + riff->new_tag_found(riff->incomplete_chunk, riff->callback_data); + } + g_free(riff->incomplete_chunk->data); + g_free(riff->incomplete_chunk); + riff->incomplete_chunk = NULL; + } + else { + debug("we cannot fill it %08x >= %08lx\n", leftover, size); + memcpy(riff->incomplete_chunk->data+riff->incomplete_chunk_size, GST_BUFFER_DATA(buf), size); + riff->incomplete_chunk_size += size; + return 0; + } + } + + if ((riff->nextlikely+12) > last) { + guint left = last - riff->nextlikely; + debug("not enough data next 0x%08x last 0x%08lx %08x %08x\n",riff->nextlikely, last, left, off); + + riff->dataleft = g_malloc(left); + riff->dataleft_size = left; + memcpy(riff->dataleft, GST_BUFFER_DATA(buf)+size-left, left); + + return 0; + } + + debug("next 0x%08x last 0x%08lx offset %08x\n",riff->nextlikely, last, off); + /* loop while the next likely chunk header is in this buffer */ + while ((riff->nextlikely+12) <= last) { + guin32 *words = (guin32 *)((guchar *)GST_BUFFER_DATA(buf) + riff->nextlikely - off ); + + // loop over all of the chunks to check which one is finished + while (riff->chunks) { + chunk = g_list_nth_data(riff->chunks, 0); + + debug("next 0x%08x offset 0x%08lx size 0x%08x\n",riff->nextlikely, chunk->offset, chunk->size); + if (riff->nextlikely >= chunk->offset+chunk->size) { + //g_print("found END LIST\n"); + // we have the end of the chunk on the stack, remove it + riff->chunks = g_list_remove(riff->chunks, chunk); + } + else break; + } + + debug("next likely chunk is at offset 0x%08x\n",riff->nextlikely); + + chunk = (GstRiffChunk *)g_malloc (sizeof (GstRiffChunk)); + g_return_val_if_fail (chunk != NULL, GST_RIFF_ENOMEM); + + chunk->offset = riff->nextlikely+8; /* point to the actual data */ + chunk->id = GUINT32_FROM_LE (words[0])); + chunk->size = GUINT32_FROM_LE (words[1]); + chunk->data = (gchar *)(words+2); + // we need word alignment + //if (chunk->size & 0x01) chunk->size++; + chunk->form = GUINT32_FROM_LE (words[2]); /* fill in the form, might not be valid */ + + + if (chunk->id == GST_RIFF_TAG_LIST) { + //g_print("found LIST %s\n", gst_riff_id_to_fourcc(chunk->form)); + riff->nextlikely += 12; + // we push the list chunk on our 'stack' + riff->chunks = g_list_prepend(riff->chunks,chunk); + // send the buffer to the listener if we have received a function + if (riff->new_tag_found) { + riff->new_tag_found(chunk, riff->callback_data); + } + } + else { + + debug("chunk id offset %08x is 0x%08lx '%s' and is 0x%08lx long\n",riff->nextlikely, words[0], + gst_riff_id_to_fourcc(GUINT32_FROM_LE (words[0])), GUINT32_FROM_LE (words[1])); + + riff->nextlikely += 8 + chunk->size; /* doesn't include hdr */ + // if this buffer is incomplete + if (riff->nextlikely > last) { + guint left = size - (riff->nextlikely - chunk->size - off); + + //g_print("make incomplete buffer %08x\n", left); + chunk->data = g_malloc(chunk->size); + memcpy(chunk->data, (gchar *)(words+2), left); + riff->incomplete_chunk = chunk; + riff->incomplete_chunk_size = left; + } + else { + // send the buffer to the listener if we have received a function + if (riff->new_tag_found) { + riff->new_tag_found(chunk, riff->callback_data); + } + g_free(chunk); + } + + //riff->chunks = g_list_prepend(riff->chunks,chunk); + } + } + + return 0; +} + + +gulong gst_riff_fourcc_to_id(gchar *fourcc) { + g_return_val_if_fail(fourcc != NULL, 0); + + return (fourcc[0] << 0) | (fourcc[1] << 8) | + (fourcc[2] << 16) | (fourcc[3] << 24); +} + +gchar *gst_riff_id_to_fourcc(gulong id) { + gchar *fourcc = (gchar *)g_malloc(5); + + g_return_val_if_fail(fourcc != NULL, NULL); + + fourcc[0] = (id >> 0) & 0xff; + fourcc[1] = (id >> 8) & 0xff; + fourcc[2] = (id >> 16) & 0xff; + fourcc[3] = (id >> 24) & 0xff; + fourcc[4] = 0; + + return fourcc; +} diff --git a/gst-libs/gst/riff/riff.h b/gst-libs/gst/riff/riff.h new file mode 100644 index 00000000..f0e55895 --- /dev/null +++ b/gst-libs/gst/riff/riff.h @@ -0,0 +1,406 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_RIFF_H__ +#define __GST_RIFF_H__ + + +#include + +typedef enum { + GST_RIFF_OK = 0, + GST_RIFF_ENOTRIFF = -1, + GST_RIFF_EINVAL = -2, + GST_RIFF_ENOMEM = -3 +} GstRiffReturn; + +/* states */ +typedef enum { + GST_RIFF_STATE_INITIAL = 0, + GST_RIFF_STATE_HASAVIH = 1, + GST_RIFF_STATE_HASSTRH = 2, + GST_RIFF_STATE_HASSTRF = 3, + GST_RIFF_STATE_MOVI = 4 +} GstRiffParserState; + +#define MAKE_FOUR_CC(a,b,c,d) ( ((guint32)a) | (((guint32)b)<< 8) | \ + ((guint32)c)<<16 | (((guint32)d)<<24) ) + +/* RIFF types */ +#define GST_RIFF_RIFF_WAVE MAKE_FOUR_CC('W','A','V','E') +#define GST_RIFF_RIFF_AVI MAKE_FOUR_CC('A','V','I',' ') + +/* tags */ +#define GST_RIFF_TAG_RIFF MAKE_FOUR_CC('R','I','F','F') +#define GST_RIFF_TAG_RIFX MAKE_FOUR_CC('R','I','F','X') +#define GST_RIFF_TAG_LIST MAKE_FOUR_CC('L','I','S','T') +#define GST_RIFF_TAG_avih MAKE_FOUR_CC('a','v','i','h') +#define GST_RIFF_TAG_strd MAKE_FOUR_CC('s','t','r','d') +#define GST_RIFF_TAG_strh MAKE_FOUR_CC('s','t','r','h') +#define GST_RIFF_TAG_strf MAKE_FOUR_CC('s','t','r','f') +#define GST_RIFF_TAG_vedt MAKE_FOUR_CC('v','e','d','t') +#define GST_RIFF_TAG_JUNK MAKE_FOUR_CC('J','U','N','K') +#define GST_RIFF_TAG_idx1 MAKE_FOUR_CC('i','d','x','1') +/* WAV stuff */ +#define GST_RIFF_TAG_fmt MAKE_FOUR_CC('f','m','t',' ') +#define GST_RIFF_TAG_data MAKE_FOUR_CC('d','a','t','a') + +/* LIST types */ +#define GST_RIFF_LIST_movi MAKE_FOUR_CC('m','o','v','i') +#define GST_RIFF_LIST_hdrl MAKE_FOUR_CC('h','d','r','l') +#define GST_RIFF_LIST_strl MAKE_FOUR_CC('s','t','r','l') + +/* fcc types */ +#define GST_RIFF_FCC_vids MAKE_FOUR_CC('v','i','d','s') +#define GST_RIFF_FCC_auds MAKE_FOUR_CC('a','u','d','s') +#define GST_RIFF_FCC_pads MAKE_FOUR_CC('p','a','d','s') +#define GST_RIFF_FCC_txts MAKE_FOUR_CC('t','x','t','s') +#define GST_RIFF_FCC_vidc MAKE_FOUR_CC('v','i','d','c') +#define GST_RIFF_FCC_iavs MAKE_FOUR_CC('i','a','v','s') +/* fcc handlers */ +#define GST_RIFF_FCCH_RLE MAKE_FOUR_CC('R','L','E',' ') +#define GST_RIFF_FCCH_msvc MAKE_FOUR_CC('m','s','v','c') +#define GST_RIFF_FCCH_MSVC MAKE_FOUR_CC('M','S','V','C') + +/*********Chunk Names***************/ +#define GST_RIFF_FF00 MAKE_FOUR_CC(0xFF,0xFF,0x00,0x00) +#define GST_RIFF_00 MAKE_FOUR_CC( '0', '0',0x00,0x00) +#define GST_RIFF_01 MAKE_FOUR_CC( '0', '1',0x00,0x00) +#define GST_RIFF_02 MAKE_FOUR_CC( '0', '2',0x00,0x00) +#define GST_RIFF_03 MAKE_FOUR_CC( '0', '3',0x00,0x00) +#define GST_RIFF_04 MAKE_FOUR_CC( '0', '4',0x00,0x00) +#define GST_RIFF_05 MAKE_FOUR_CC( '0', '5',0x00,0x00) +#define GST_RIFF_06 MAKE_FOUR_CC( '0', '6',0x00,0x00) +#define GST_RIFF_07 MAKE_FOUR_CC( '0', '7',0x00,0x00) +#define GST_RIFF_00pc MAKE_FOUR_CC( '0', '0', 'p', 'c') +#define GST_RIFF_01pc MAKE_FOUR_CC( '0', '1', 'p', 'c') +#define GST_RIFF_00dc MAKE_FOUR_CC( '0', '0', 'd', 'c') +#define GST_RIFF_00dx MAKE_FOUR_CC( '0', '0', 'd', 'x') +#define GST_RIFF_00db MAKE_FOUR_CC( '0', '0', 'd', 'b') +#define GST_RIFF_00xx MAKE_FOUR_CC( '0', '0', 'x', 'x') +#define GST_RIFF_00id MAKE_FOUR_CC( '0', '0', 'i', 'd') +#define GST_RIFF_00rt MAKE_FOUR_CC( '0', '0', 'r', 't') +#define GST_RIFF_0021 MAKE_FOUR_CC( '0', '0', '2', '1') +#define GST_RIFF_00iv MAKE_FOUR_CC( '0', '0', 'i', 'v') +#define GST_RIFF_0031 MAKE_FOUR_CC( '0', '0', '3', '1') +#define GST_RIFF_0032 MAKE_FOUR_CC( '0', '0', '3', '2') +#define GST_RIFF_00vc MAKE_FOUR_CC( '0', '0', 'v', 'c') +#define GST_RIFF_00xm MAKE_FOUR_CC( '0', '0', 'x', 'm') +#define GST_RIFF_01wb MAKE_FOUR_CC( '0', '1', 'w', 'b') +#define GST_RIFF_01dc MAKE_FOUR_CC( '0', '1', 'd', 'c') +#define GST_RIFF_00__ MAKE_FOUR_CC( '0', '0', '_', '_') + +/*********VIDEO CODECS**************/ +#define GST_RIFF_cram MAKE_FOUR_CC( 'c', 'r', 'a', 'm') +#define GST_RIFF_CRAM MAKE_FOUR_CC( 'C', 'R', 'A', 'M') +#define GST_RIFF_wham MAKE_FOUR_CC( 'w', 'h', 'a', 'm') +#define GST_RIFF_WHAM MAKE_FOUR_CC( 'W', 'H', 'A', 'M') +#define GST_RIFF_rgb MAKE_FOUR_CC(0x00,0x00,0x00,0x00) +#define GST_RIFF_RGB MAKE_FOUR_CC( 'R', 'G', 'B', ' ') +#define GST_RIFF_rle8 MAKE_FOUR_CC(0x01,0x00,0x00,0x00) +#define GST_RIFF_RLE8 MAKE_FOUR_CC( 'R', 'L', 'E', '8') +#define GST_RIFF_rle4 MAKE_FOUR_CC(0x02,0x00,0x00,0x00) +#define GST_RIFF_RLE4 MAKE_FOUR_CC( 'R', 'L', 'E', '4') +#define GST_RIFF_none MAKE_FOUR_CC(0x00,0x00,0xFF,0xFF) +#define GST_RIFF_NONE MAKE_FOUR_CC( 'N', 'O', 'N', 'E') +#define GST_RIFF_pack MAKE_FOUR_CC(0x01,0x00,0xFF,0xFF) +#define GST_RIFF_PACK MAKE_FOUR_CC( 'P', 'A', 'C', 'K') +#define GST_RIFF_tran MAKE_FOUR_CC(0x02,0x00,0xFF,0xFF) +#define GST_RIFF_TRAN MAKE_FOUR_CC( 'T', 'R', 'A', 'N') +#define GST_RIFF_ccc MAKE_FOUR_CC(0x03,0x00,0xFF,0xFF) +#define GST_RIFF_CCC MAKE_FOUR_CC( 'C', 'C', 'C', ' ') +#define GST_RIFF_cyuv MAKE_FOUR_CC( 'c', 'y', 'u', 'v') +#define GST_RIFF_CYUV MAKE_FOUR_CC( 'C', 'Y', 'U', 'V') +#define GST_RIFF_jpeg MAKE_FOUR_CC(0x04,0x00,0xFF,0xFF) +#define GST_RIFF_JPEG MAKE_FOUR_CC( 'J', 'P', 'E', 'G') +#define GST_RIFF_MJPG MAKE_FOUR_CC( 'M', 'J', 'P', 'G') +#define GST_RIFF_mJPG MAKE_FOUR_CC( 'm', 'J', 'P', 'G') +#define GST_RIFF_IJPG MAKE_FOUR_CC( 'I', 'J', 'P', 'G') +#define GST_RIFF_rt21 MAKE_FOUR_CC( 'r', 't', '2', '1') +#define GST_RIFF_RT21 MAKE_FOUR_CC( 'R', 'T', '2', '1') +#define GST_RIFF_iv31 MAKE_FOUR_CC( 'i', 'v', '3', '1') +#define GST_RIFF_IV31 MAKE_FOUR_CC( 'I', 'V', '3', '1') +#define GST_RIFF_iv32 MAKE_FOUR_CC( 'i', 'v', '3', '2') +#define GST_RIFF_IV32 MAKE_FOUR_CC( 'I', 'V', '3', '2') +#define GST_RIFF_iv41 MAKE_FOUR_CC( 'i', 'v', '4', '1') +#define GST_RIFF_IV41 MAKE_FOUR_CC( 'I', 'V', '4', '1') +#define GST_RIFF_iv50 MAKE_FOUR_CC( 'i', 'v', '5', '0') +#define GST_RIFF_IV50 MAKE_FOUR_CC( 'I', 'V', '5', '0') +#define GST_RIFF_cvid MAKE_FOUR_CC( 'c', 'v', 'i', 'd') +#define GST_RIFF_CVID MAKE_FOUR_CC( 'C', 'V', 'I', 'D') +#define GST_RIFF_ULTI MAKE_FOUR_CC( 'U', 'L', 'T', 'I') +#define GST_RIFF_ulti MAKE_FOUR_CC( 'u', 'l', 't', 'i') +#define GST_RIFF_YUV9 MAKE_FOUR_CC( 'Y', 'V', 'U', '9') +#define GST_RIFF_YVU9 MAKE_FOUR_CC( 'Y', 'U', 'V', '9') +#define GST_RIFF_XMPG MAKE_FOUR_CC( 'X', 'M', 'P', 'G') +#define GST_RIFF_xmpg MAKE_FOUR_CC( 'x', 'm', 'p', 'g') +#define GST_RIFF_VDOW MAKE_FOUR_CC( 'V', 'D', 'O', 'W') +#define GST_RIFF_MVI1 MAKE_FOUR_CC( 'M', 'V', 'I', '1') +#define GST_RIFF_v422 MAKE_FOUR_CC( 'v', '4', '2', '2') +#define GST_RIFF_V422 MAKE_FOUR_CC( 'V', '4', '2', '2') +#define GST_RIFF_mvi1 MAKE_FOUR_CC( 'm', 'v', 'i', '1') +#define GST_RIFF_MPIX MAKE_FOUR_CC(0x04,0x00, 'i', '1') /* MotionPixels munged their id */ +#define GST_RIFF_AURA MAKE_FOUR_CC( 'A', 'U', 'R', 'A') +#define GST_RIFF_DMB1 MAKE_FOUR_CC( 'D', 'M', 'B', '1') +#define GST_RIFF_dmb1 MAKE_FOUR_CC( 'd', 'm', 'b', '1') + +#define GST_RIFF_BW10 MAKE_FOUR_CC( 'B', 'W', '1', '0') +#define GST_RIFF_bw10 MAKE_FOUR_CC( 'b', 'w', '1', '0') + +#define GST_RIFF_yuy2 MAKE_FOUR_CC( 'y', 'u', 'y', '2') +#define GST_RIFF_YUY2 MAKE_FOUR_CC( 'Y', 'U', 'Y', '2') +#define GST_RIFF_YUV8 MAKE_FOUR_CC( 'Y', 'U', 'V', '8') +#define GST_RIFF_WINX MAKE_FOUR_CC( 'W', 'I', 'N', 'X') +#define GST_RIFF_WPY2 MAKE_FOUR_CC( 'W', 'P', 'Y', '2') +#define GST_RIFF_m263 MAKE_FOUR_CC( 'm', '2', '6', '3') +#define GST_RIFF_M263 MAKE_FOUR_CC( 'M', '2', '6', '3') + +#define GST_RIFF_Q1_0 MAKE_FOUR_CC( 'Q', '1',0x2e, '0') +#define GST_RIFF_SFMC MAKE_FOUR_CC( 'S', 'F', 'M', 'C') + +#define GST_RIFF_y41p MAKE_FOUR_CC( 'y', '4', '1', 'p') +#define GST_RIFF_Y41P MAKE_FOUR_CC( 'Y', '4', '1', 'P') +#define GST_RIFF_yv12 MAKE_FOUR_CC( 'y', 'v', '1', '2') +#define GST_RIFF_YV12 MAKE_FOUR_CC( 'Y', 'V', '1', '2') +#define GST_RIFF_vixl MAKE_FOUR_CC( 'v', 'i', 'x', 'l') +#define GST_RIFF_VIXL MAKE_FOUR_CC( 'V', 'I', 'X', 'L') +#define GST_RIFF_iyuv MAKE_FOUR_CC( 'i', 'y', 'u', 'v') +#define GST_RIFF_IYUV MAKE_FOUR_CC( 'I', 'Y', 'U', 'V') +#define GST_RIFF_i420 MAKE_FOUR_CC( 'i', '4', '2', '0') +#define GST_RIFF_I420 MAKE_FOUR_CC( 'I', '4', '2', '0') +#define GST_RIFF_vyuy MAKE_FOUR_CC( 'v', 'y', 'u', 'y') +#define GST_RIFF_VYUY MAKE_FOUR_CC( 'V', 'Y', 'U', 'Y') + +#define GST_RIFF_DIV3 MAKE_FOUR_CC( 'D', 'I', 'V', '3') + +#define GST_RIFF_rpza MAKE_FOUR_CC( 'r', 'p', 'z', 'a') +/* And this here's the mistakes that need to be supported */ +#define GST_RIFF_azpr MAKE_FOUR_CC( 'a', 'z', 'p', 'r') /* recognize Apple's rpza mangled? */ + +/*********** FND in MJPG **********/ +#define GST_RIFF_ISFT MAKE_FOUR_CC( 'I', 'S', 'F', 'T') +#define GST_RIFF_IDIT MAKE_FOUR_CC( 'I', 'D', 'I', 'T') + +#define GST_RIFF_00AM MAKE_FOUR_CC( '0', '0', 'A', 'M') +#define GST_RIFF_DISP MAKE_FOUR_CC( 'D', 'I', 'S', 'P') +#define GST_RIFF_ISBJ MAKE_FOUR_CC( 'I', 'S', 'B', 'J') + +#define GST_RIFF_rec MAKE_FOUR_CC( 'r', 'e', 'c', ' ') + +/* common data structures */ +struct _gst_riff_avih { + guint32 us_frame; /* microsec per frame */ + guint32 max_bps; /* byte/s overall */ + guint32 pad_gran; /* pad_gran (???) */ + guint32 flags; +/* flags values */ +#define GST_RIFF_AVIH_HASINDEX 0x00000010 /* has idx1 chunk */ +#define GST_RIFF_AVIH_MUSTUSEINDEX 0x00000020 /* must use idx1 chunk to determine order */ +#define GST_RIFF_AVIH_ISINTERLEAVED 0x00000100 /* AVI file is interleaved */ +#define GST_RIFF_AVIH_WASCAPTUREFILE 0x00010000 /* specially allocated used for capturing real time video */ +#define GST_RIFF_AVIH_COPYRIGHTED 0x00020000 /* contains copyrighted data */ + guint32 tot_frames; /* # of frames (all) */ + guint32 init_frames; /* initial frames (???) */ + guint32 streams; + guint32 bufsize; /* suggested buffer size */ + guint32 width; + guint32 height; + guint32 scale; + guint32 rate; + guint32 start; + guint32 length; +}; + +struct _gst_riff_strh { + guint32 type; /* stream type */ + guint32 fcc_handler; /* fcc_handler */ + guint32 flags; +/* flags values */ +#define GST_RIFF_STRH_DISABLED 0x000000001 +#define GST_RIFF_STRH_VIDEOPALCHANGES 0x000010000 + guint32 priority; + guint32 init_frames; /* initial frames (???) */ + guint32 scale; + guint32 rate; + guint32 start; + guint32 length; + guint32 bufsize; /* suggested buffer size */ + guint32 quality; + guint32 samplesize; + /* XXX 16 bytes ? */ +}; + +struct _gst_riff_strf_vids { /* == BitMapInfoHeader */ + guint32 size; + guint32 width; + guint32 height; + guint16 planes; + guint16 bit_cnt; + guint32 compression; + guint32 image_size; + guint32 xpels_meter; + guint32 ypels_meter; + guint32 num_colors; /* used colors */ + guint32 imp_colors; /* important colors */ + /* may be more for some codecs */ +}; + + +struct _gst_riff_strf_auds { /* == WaveHeader (?) */ + guint16 format; +/**** from public Microsoft RIFF docs ******/ +#define GST_RIFF_WAVE_FORMAT_UNKNOWN (0x0000) +#define GST_RIFF_WAVE_FORMAT_PCM (0x0001) +#define GST_RIFF_WAVE_FORMAT_ADPCM (0x0002) +#define GST_RIFF_WAVE_FORMAT_IBM_CVSD (0x0005) +#define GST_RIFF_WAVE_FORMAT_ALAW (0x0006) +#define GST_RIFF_WAVE_FORMAT_MULAW (0x0007) +#define GST_RIFF_WAVE_FORMAT_OKI_ADPCM (0x0010) +#define GST_RIFF_WAVE_FORMAT_DVI_ADPCM (0x0011) +#define GST_RIFF_WAVE_FORMAT_DIGISTD (0x0015) +#define GST_RIFF_WAVE_FORMAT_DIGIFIX (0x0016) +#define GST_RIFF_WAVE_FORMAT_YAMAHA_ADPCM (0x0020) +#define GST_RIFF_WAVE_FORMAT_DSP_TRUESPEECH (0x0022) +#define GST_RIFF_WAVE_FORMAT_GSM610 (0x0031) +#define GST_RIFF_WAVE_FORMAT_MSN (0x0032) +#define GST_RIFF_WAVE_FORMAT_MPEGL12 (0x0050) +#define GST_RIFF_WAVE_FORMAT_MPEGL3 (0x0055) +#define GST_RIFF_IBM_FORMAT_MULAW (0x0101) +#define GST_RIFF_IBM_FORMAT_ALAW (0x0102) +#define GST_RIFF_IBM_FORMAT_ADPCM (0x0103) +#define GST_RIFF_WAVE_FORMAT_DIVX (0x0160) +#define GST_RIFF_WAVE_FORMAT_divx (0x0161) + guint16 channels; + guint32 rate; + guint32 av_bps; + guint16 blockalign; + guint16 size; +}; + +struct _gst_riff_strf_iavs { + guint32 DVAAuxSrc; + guint32 DVAAuxCtl; + guint32 DVAAuxSrc1; + guint32 DVAAuxCtl1; + guint32 DVVAuxSrc; + guint32 DVVAuxCtl; + guint32 DVReserved1; + guint32 DVReserved2; +}; + +struct _gst_riff_riff { + guint32 id; + guint32 size; + guint32 type; +}; + +struct _gst_riff_list { + guint32 id; + guint32 size; + guint32 type; +}; + +struct _gst_riff_chunk { + guint32 id; + guint32 size; +}; + +struct _gst_riff_index_entry { + guint32 id; + guint32 flags; +#define GST_RIFF_IF_LIST (0x00000001L) +#define GST_RIFF_IF_KEYFRAME (0x00000010L) +#define GST_RIFF_IF_NO_TIME (0x00000100L) +#define GST_RIFF_IF_COMPUSE (0x0FFF0000L) + guint32 offset; + guint32 size; +}; + +typedef struct _gst_riff_riff gst_riff_riff; +typedef struct _gst_riff_list gst_riff_list; +typedef struct _gst_riff_chunk gst_riff_chunk; +typedef struct _gst_riff_index_entry gst_riff_index_entry; + +typedef struct _gst_riff_avih gst_riff_avih; +typedef struct _gst_riff_strh gst_riff_strh; +typedef struct _gst_riff_strf_vids gst_riff_strf_vids; +typedef struct _gst_riff_strf_auds gst_riff_strf_auds; +typedef struct _gst_riff_strf_iavs gst_riff_strf_iavs; +typedef struct _GstRiff GstRiff; +typedef struct _GstRiffChunk GstRiffChunk; + +typedef void (*GstRiffCallback) (GstRiffChunk *chunk, gpointer data); + +struct _GstRiff { + guint32 form; + + /* list of chunks, most recent at the head */ + GList *chunks; + + /* incomplete chunks are assembled here */ + GstRiffChunk *incomplete_chunk; + guint32 incomplete_chunk_size; + /* parse state */ + GstRiffParserState state; + guint32 curoffset; + guint32 nextlikely; + /* leftover data */ + guchar *dataleft; + guint32 dataleft_size; + + /* callback function and data pointer */ + GstRiffCallback new_tag_found; + gpointer callback_data; +}; + +struct _GstRiffChunk { + gulong offset; + + guint32 id; + guint32 size; + guint32 form; /* for list chunks */ + + gchar *data; +}; + + +/* from gstriffparse.c */ +GstRiff* gst_riff_parser_new (GstRiffCallback function, gpointer data); +GstRiffReturn gst_riff_parser_next_buffer (GstRiff *riff, GstBuffer *buf, gulong off); +void gst_riff_parser_resync (GstRiff *riff, gulong offset); + +/* from gstriffencode.c */ +GstRiff* gst_riff_encoder_new (guint32 type); +GstRiffReturn gst_riff_encoder_avih (GstRiff *riff, gst_riff_avih *head, gulong size); +GstRiffReturn gst_riff_encoder_strh (GstRiff *riff, guint32 fcc_type, + gst_riff_strh *head, gulong size); +GstRiffReturn gst_riff_encoder_strf (GstRiff *riff, void *format, gulong size); +GstRiffReturn gst_riff_encoder_chunk (GstRiff *riff, guint32 chunk_type, + void *chunk, gulong size); + +GstBuffer* gst_riff_encoder_get_buffer (GstRiff *riff); +GstBuffer* gst_riff_encoder_get_and_reset_buffer (GstRiff *riff); + +/* from gstriffutil.c */ +gulong gst_riff_fourcc_to_id (gchar *fourcc); +gchar* gst_riff_id_to_fourcc (gulong id); + + +#endif /* __GST_RIFF_H__ */ diff --git a/gst-libs/gst/riff/riffencode.c b/gst-libs/gst/riff/riffencode.c new file mode 100644 index 00000000..a6caed9e --- /dev/null +++ b/gst-libs/gst/riff/riffencode.c @@ -0,0 +1,177 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +//#define DEBUG_ENABLED +#include "riff.h" + +#define GST_RIFF_ENCODER_BUF_SIZE 1024 + +#define ADD_CHUNK(riffenc, chunkid, chunksize) \ +{ \ + gst_riff_chunk *chunk;\ + chunk = (gst_riff_chunk *)(riffenc->dataleft + riffenc->nextlikely);\ + chunk->id = chunkid; \ + chunk->size = chunksize; \ + riffenc->nextlikely += sizeof(gst_riff_chunk); \ +} + +#define ADD_LIST(riffenc, listsize, listtype) \ +{ \ + gst_riff_list *list;\ + list = (gst_riff_list *)(riffenc->dataleft + riffenc->nextlikely); \ + list->id = GST_RIFF_TAG_LIST; \ + list->size = listsize; \ + list->type = listtype; \ + riffenc->nextlikely += sizeof(gst_riff_list); \ +} + + +GstRiff *gst_riff_encoder_new(guint32 type) { + GstRiff *riff; + gst_riff_list *list; + + GST_DEBUG (0,"gst_riff_encoder: making %4.4s encoder\n", (char *)&type); + riff = (GstRiff *)g_malloc(sizeof(GstRiff)); + g_return_val_if_fail(riff != NULL, NULL); + + riff->form = 0; + riff->chunks = NULL; + riff->state = GST_RIFF_STATE_INITIAL; + riff->curoffset = 0; + riff->incomplete_chunk = NULL; + riff->dataleft = g_malloc(GST_RIFF_ENCODER_BUF_SIZE); + riff->dataleft_size = GST_RIFF_ENCODER_BUF_SIZE; + riff->nextlikely = 0; + + list = (gst_riff_list *)riff->dataleft; + list->id = GST_RIFF_TAG_RIFF; + list->size = 0x00FFFFFF; + list->type = GST_RIFF_RIFF_AVI; + + riff->nextlikely += sizeof(gst_riff_list); + + return riff; +} + +gint gst_riff_encoder_avih(GstRiff *riff, gst_riff_avih *head, gulong size) { + gst_riff_chunk *chunk; + + g_return_val_if_fail(riff->state == GST_RIFF_STATE_INITIAL, GST_RIFF_EINVAL); + + GST_DEBUG (0,"gst_riff_encoder: add avih\n"); + + ADD_LIST(riff, 0xB8, GST_RIFF_LIST_hdrl); + + ADD_CHUNK(riff, GST_RIFF_TAG_avih, size); + + chunk = (gst_riff_chunk *)(riff->dataleft + riff->nextlikely); + memcpy(chunk, head, size); + riff->nextlikely += size; + + riff->state = GST_RIFF_STATE_HASAVIH; + return GST_RIFF_OK; +} + +gint gst_riff_encoder_strh(GstRiff *riff, guint32 fcc_type, gst_riff_strh *head, gulong size) { + gst_riff_chunk *chunk; + + g_return_val_if_fail(riff->state == GST_RIFF_STATE_HASAVIH || + riff->state == GST_RIFF_STATE_HASSTRF, GST_RIFF_EINVAL); + + GST_DEBUG (0,"gst_riff_encoder: add strh type %08x (%4.4s)\n", fcc_type, (char *)&fcc_type); + + ADD_LIST(riff, 108, GST_RIFF_LIST_strl); + + ADD_CHUNK(riff, GST_RIFF_TAG_strh, size); + + chunk = (gst_riff_chunk *)(riff->dataleft + riff->nextlikely); + head->type = fcc_type; + memcpy(chunk, head, size); + + riff->nextlikely += size; + + riff->state = GST_RIFF_STATE_HASSTRH; + return GST_RIFF_OK; +} + +gint gst_riff_encoder_strf(GstRiff *riff, void *format, gulong size) { + gst_riff_chunk *chunk; + + g_return_val_if_fail(riff->state == GST_RIFF_STATE_HASSTRH, GST_RIFF_EINVAL); + + GST_DEBUG (0,"gst_riff_encoder: add strf\n"); + + ADD_CHUNK(riff, GST_RIFF_TAG_strf, size); + + chunk = (gst_riff_chunk *)(riff->dataleft + riff->nextlikely); + memcpy(chunk, format, size); + riff->nextlikely += size; + + riff->state = GST_RIFF_STATE_HASSTRF; + return GST_RIFF_OK; +} + +gint gst_riff_encoder_chunk(GstRiff *riff, guint32 chunk_type, void *chunkdata, gulong size) { + gst_riff_chunk *chunk; + + g_return_val_if_fail(riff->state == GST_RIFF_STATE_HASSTRF || + riff->state == GST_RIFF_STATE_MOVI, GST_RIFF_EINVAL); + + if (riff->state != GST_RIFF_STATE_MOVI) { + ADD_LIST(riff, 0x00FFFFFF, GST_RIFF_LIST_movi); + riff->state = GST_RIFF_STATE_MOVI; + } + + GST_DEBUG (0,"gst_riff_encoder: add chunk type %08x (%4.4s)\n", chunk_type, (char *)&chunk_type); + + ADD_CHUNK(riff, chunk_type, size); + + if (chunkdata != NULL) { + chunk = (gst_riff_chunk *)(riff->dataleft + riff->nextlikely); + memcpy(chunk, chunkdata, size); + riff->nextlikely += size + (size&1); + } + + return GST_RIFF_OK; +} + +GstBuffer *gst_riff_encoder_get_buffer(GstRiff *riff) { + GstBuffer *newbuf; + + newbuf = gst_buffer_new(); + GST_BUFFER_DATA(newbuf) = riff->dataleft; + GST_BUFFER_SIZE(newbuf) = riff->nextlikely; + + return newbuf; +} + +GstBuffer *gst_riff_encoder_get_and_reset_buffer(GstRiff *riff) { + GstBuffer *newbuf; + + newbuf = gst_riff_encoder_get_buffer(riff); + + riff->dataleft = g_malloc(GST_RIFF_ENCODER_BUF_SIZE); + riff->dataleft_size = GST_RIFF_ENCODER_BUF_SIZE; + riff->nextlikely = 0; + + return newbuf; +} + diff --git a/gst-libs/gst/riff/riffparse.c b/gst-libs/gst/riff/riffparse.c new file mode 100644 index 00000000..eb4746fc --- /dev/null +++ b/gst-libs/gst/riff/riffparse.c @@ -0,0 +1,221 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +//#define DEBUG_ENABLED +#include + +GstRiff* +gst_riff_parser_new (GstRiffCallback function, gpointer data) +{ + GstRiff *riff; + + riff = (GstRiff *)g_malloc(sizeof(GstRiff)); + g_return_val_if_fail(riff != NULL, NULL); + + riff->form = 0; + riff->chunks = NULL; + riff->state = 0; + riff->curoffset = 0; + riff->nextlikely = 0; + riff->new_tag_found = function; + riff->callback_data = data; + riff->incomplete_chunk = NULL; + riff->dataleft = NULL; + + return riff; +} + +gint +gst_riff_parser_next_buffer (GstRiff *riff, GstBuffer *buf, gulong off) +{ + gulong last, size; + GstRiffChunk *chunk; + + g_return_val_if_fail(riff != NULL, GST_RIFF_EINVAL); + g_return_val_if_fail(buf != NULL, GST_RIFF_EINVAL); + g_return_val_if_fail(GST_BUFFER_DATA(buf) != NULL, GST_RIFF_EINVAL); + + size = GST_BUFFER_SIZE(buf); + last = off + size; + + GST_DEBUG (0,"gst_riff_parser: offset new buffer 0x%08lx size 0x%08x\n", off, GST_BUFFER_SIZE(buf)); + + if (riff->dataleft) { + gulong newsize; + + GST_DEBUG (0,"gst_riff_parser: recovering left data\n"); + newsize = riff->dataleft_size + size; + riff->dataleft = g_realloc(riff->dataleft, newsize); + memcpy(riff->dataleft+riff->dataleft_size, GST_BUFFER_DATA(buf), size); + gst_buffer_unref(buf); + + buf = gst_buffer_new(); + GST_BUFFER_DATA(buf) = riff->dataleft; + size = GST_BUFFER_SIZE(buf) = newsize; + off -= riff->dataleft_size; + //last -= riff->dataleft_size; + riff->dataleft = NULL; + } + + if (off == 0) { + guint32 *words = (guint32 *)GST_BUFFER_DATA(buf); + + // don't even try to parse the head if it's not there FIXME + if (last < 12) { + riff->state = GST_RIFF_ENOTRIFF; + return riff->state; + } + + //g_print("testing is 0x%08lx '%s'\n",words[0],gst_riff_id_to_fourcc(words[0])); + /* verify this is a valid RIFF file, first of all */ + if (GUINT32_FROM_LE (words[0]) != GST_RIFF_TAG_RIFF) { + riff->state = GST_RIFF_ENOTRIFF; + return riff->state; + } + riff->form = GUINT32_FROM_LE (words[2]); + //g_print("form is 0x%08lx '%s'\n",words[2],gst_riff_id_to_fourcc(words[2])); + riff->nextlikely = 12; /* skip 'RIFF', length, and form */ + // all OK here + riff->incomplete_chunk = NULL; + } + + // if we have an incomplete chunk from the previous buffer + if (riff->incomplete_chunk) { + guint leftover; + GST_DEBUG (0,"gst_riff_parser: have incomplete chunk %08x filled\n", riff->incomplete_chunk_size); + leftover = riff->incomplete_chunk->size - riff->incomplete_chunk_size; + if (leftover <= size) { + GST_DEBUG (0,"gst_riff_parser: we can fill it from %08x with %08x bytes = %08x\n", + riff->incomplete_chunk_size, leftover, + riff->incomplete_chunk_size+leftover); + memcpy(riff->incomplete_chunk->data+riff->incomplete_chunk_size, GST_BUFFER_DATA(buf), leftover); + + if (riff->new_tag_found) { + riff->new_tag_found(riff->incomplete_chunk, riff->callback_data); + } + g_free(riff->incomplete_chunk->data); + g_free(riff->incomplete_chunk); + riff->incomplete_chunk = NULL; + } + else { + GST_DEBUG (0,"gst_riff_parser: we cannot fill it %08x >= %08lx\n", leftover, size); + memcpy(riff->incomplete_chunk->data+riff->incomplete_chunk_size, GST_BUFFER_DATA(buf), size); + riff->incomplete_chunk_size += size; + return 0; + } + } + + if (riff->nextlikely & 0x01) riff->nextlikely++; + + GST_DEBUG (0,"gst_riff_parser: next 0x%08x last 0x%08lx offset %08lx\n",riff->nextlikely, last, off); + /* loop while the next likely chunk header is in this buffer */ + while ((riff->nextlikely+12) <= last) { + guint32 *words = (guint32 *)((guchar *)GST_BUFFER_DATA(buf) + riff->nextlikely - off ); + + // loop over all of the chunks to check which one is finished + while (riff->chunks) { + chunk = g_list_nth_data(riff->chunks, 0); + + GST_DEBUG (0,"gst_riff_parser: next 0x%08x offset 0x%08lx size 0x%08x\n",riff->nextlikely, + chunk->offset, chunk->size); + if (riff->nextlikely >= chunk->offset+chunk->size) { + GST_DEBUG (0,"gst_riff_parser: found END LIST\n"); + // we have the end of the chunk on the stack, remove it + riff->chunks = g_list_remove(riff->chunks, chunk); + } + else break; + } + + GST_DEBUG (0,"gst_riff_parser: next likely chunk is at offset 0x%08x\n",riff->nextlikely); + + chunk = (GstRiffChunk *)g_malloc(sizeof(GstRiffChunk)); + g_return_val_if_fail(chunk != NULL, GST_RIFF_ENOMEM); + + chunk->offset = riff->nextlikely+8; /* point to the actual data */ + chunk->id = GUINT32_FROM_LE (words[0]); + chunk->size = GUINT32_FROM_LE (words[1]); + chunk->data = (gchar *)(words+2); + // we need word alignment + //if (chunk->size & 0x01) chunk->size++; + chunk->form = GUINT32_FROM_LE (words[2]); /* fill in the form, might not be valid */ + + + if (chunk->id == GST_RIFF_TAG_LIST) { + GST_DEBUG (0,"found LIST %s\n", gst_riff_id_to_fourcc(chunk->form)); + riff->nextlikely += 12; + // we push the list chunk on our 'stack' + riff->chunks = g_list_prepend(riff->chunks,chunk); + // send the buffer to the listener if we have received a function + if (riff->new_tag_found) { + riff->new_tag_found(chunk, riff->callback_data); + } + } + else { + + GST_DEBUG (0,"gst_riff_parser: chunk id offset %08x is 0x%08x '%s' and is 0x%08x long\n", + riff->nextlikely, GUINT32_FROM_LE (words[0]), + gst_riff_id_to_fourcc(GUINT32_FROM_LE (words[0])), GUINT32_FROM_LE (words[1])); + + riff->nextlikely += 8 + chunk->size; /* doesn't include hdr */ + // if this buffer is incomplete + if (riff->nextlikely > last) { + guint left = size - (riff->nextlikely - chunk->size - off); + + GST_DEBUG (0,"make incomplete buffer %08x\n", left); + chunk->data = g_malloc(chunk->size); + memcpy(chunk->data, (gchar *)(words+2), left); + riff->incomplete_chunk = chunk; + riff->incomplete_chunk_size = left; + } + else { + // send the buffer to the listener if we have received a function + if (riff->new_tag_found) { + riff->new_tag_found(chunk, riff->callback_data); + } + g_free(chunk); + } + if (riff->nextlikely & 0x01) riff->nextlikely++; + + //riff->chunks = g_list_prepend(riff->chunks,chunk); + } + } + if ((riff->nextlikely+12) > last && !riff->incomplete_chunk) { + guint left = last - riff->nextlikely; + GST_DEBUG (0,"gst_riff_parser: not enough data next 0x%08x last 0x%08lx %08x %08lx\n",riff->nextlikely, + last, left, off); + + riff->dataleft = g_malloc(left); + riff->dataleft_size = left; + memcpy(riff->dataleft, GST_BUFFER_DATA(buf)+size-left, left); + + return 0; + } + + return 0; +} + +void +gst_riff_parser_resync (GstRiff *riff, gulong offset) +{ + riff->incomplete_chunk = NULL; + riff->dataleft = NULL; + riff->nextlikely = offset; +} diff --git a/gst-libs/gst/riff/riffutil.c b/gst-libs/gst/riff/riffutil.c new file mode 100644 index 00000000..ca01f6e6 --- /dev/null +++ b/gst-libs/gst/riff/riffutil.c @@ -0,0 +1,46 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + +//#define debug(format,args...) g_print(format,##args) +#define debug(format,args...) + + +gulong gst_riff_fourcc_to_id(gchar *fourcc) { + g_return_val_if_fail(fourcc != NULL, 0); + + return (fourcc[0] << 0) | (fourcc[1] << 8) | + (fourcc[2] << 16) | (fourcc[3] << 24); +} + +gchar *gst_riff_id_to_fourcc(gulong id) { + gchar *fourcc = (gchar *)g_malloc(5); + + g_return_val_if_fail(fourcc != NULL, NULL); + + fourcc[0] = (id >> 0) & 0xff; + fourcc[1] = (id >> 8) & 0xff; + fourcc[2] = (id >> 16) & 0xff; + fourcc[3] = (id >> 24) & 0xff; + fourcc[4] = 0; + + return fourcc; +} diff --git a/gst/mpeg1sys/buffer.c b/gst/mpeg1sys/buffer.c index 933b76e6..8075beb8 100644 --- a/gst/mpeg1sys/buffer.c +++ b/gst/mpeg1sys/buffer.c @@ -21,7 +21,7 @@ /*#define DEBUG_ENABLED */ #include -#include +#include #include "buffer.h" diff --git a/gst/mpeg1sys/gstmpeg1systemencode.h b/gst/mpeg1sys/gstmpeg1systemencode.h index bb24f01d..2b5089d5 100644 --- a/gst/mpeg1sys/gstmpeg1systemencode.h +++ b/gst/mpeg1sys/gstmpeg1systemencode.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include "buffer.h" #include "main.h" diff --git a/gst/passthrough/gstpassthrough.c b/gst/passthrough/gstpassthrough.c index dc50e626..0faa878b 100644 --- a/gst/passthrough/gstpassthrough.c +++ b/gst/passthrough/gstpassthrough.c @@ -20,7 +20,7 @@ #include #include -#include +#include #include "gstpassthrough.h" diff --git a/gst/playondemand/gstplayondemand.c b/gst/playondemand/gstplayondemand.c index 9d2ebff3..2f7ebb08 100644 --- a/gst/playondemand/gstplayondemand.c +++ b/gst/playondemand/gstplayondemand.c @@ -19,7 +19,7 @@ #include #include -#include +#include #include "gstplayondemand.h" diff --git a/gst/speed/gstspeed.c b/gst/speed/gstspeed.c index 51811227..feca2533 100644 --- a/gst/speed/gstspeed.c +++ b/gst/speed/gstspeed.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include "gstspeed.h" /* buffer size to make if no bufferpool is available, must be divisible by -- cgit v1.2.1