gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] gnash ChangeLog Makefile.am configure.ac backen...


From: Tomas Groth
Subject: [Gnash-commit] gnash ChangeLog Makefile.am configure.ac backen...
Date: Thu, 27 Sep 2007 23:59:57 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Tomas Groth <tgc>       07/09/27 23:59:57

Modified files:
        .              : ChangeLog Makefile.am configure.ac 
        backend        : Makefile.am 
        gui            : Makefile.am 
        libbase        : FLVParser.h 
        server         : Makefile.am video_stream_instance.cpp 
                         video_stream_instance.h 
        server/asobj   : Makefile.am 
        server/parser  : Makefile.am video_stream_def.cpp 
                         video_stream_def.h 
        server/swf     : tag_loaders.cpp 
        server/vm      : Makefile.am 
        testsuite      : Makefile.am 
        testsuite/misc-ming.all: Makefile.am 
        testsuite/movies.all: Makefile.am 
        testsuite/samples: Makefile.am 
        utilities      : Makefile.am 
Added files:
        libmedia       : AudioDecoder.h AudioDecoderNellymoser.cpp 
                         AudioDecoderNellymoser.h AudioDecoderSimple.cpp 
                         AudioDecoderSimple.h FLVParser.cpp FLVParser.h 
                         Makefile.am Makefile.in MediaBuffer.h 
                         MediaDecoder.h MediaParser.h SoundInfo.h 
                         VideoDecoder.h sound_handler.h 
        libmedia/gst   : VideoDecoderGst.cpp VideoDecoderGst.h 
                         gstappbuffer.c gstappbuffer.h gstappsink.c 
                         gstappsink.h gstappsrc.c gstappsrc.h 
                         gstgnashsrc.c gstgnashsrc.h 
                         sound_handler_gst.cpp sound_handler_gst.h 
        libmedia/sdl   : AudioDecoderFfmpeg.cpp AudioDecoderFfmpeg.h 
                         AudioDecoderMad.cpp AudioDecoderMad.h 
                         MediaDecoderSdl.cpp MediaDecoderSdl.h 
                         MediaParserFfmpeg.cpp MediaParserFfmpeg.h 
                         VideoDecoderFfmpeg.cpp VideoDecoderFfmpeg.h 
                         sound_handler_sdl.cpp sound_handler_sdl.h 
Removed files:
        backend        : sound_handler.h sound_handler_gst.cpp 
                         sound_handler_gst.h sound_handler_mp3.cpp 
                         sound_handler_sdl.cpp sound_handler_sdl.h 
        libbase        : embedVideoDecoder.h embedVideoDecoderFfmpeg.cpp 
                         embedVideoDecoderFfmpeg.h 
                         embedVideoDecoderGst.cpp embedVideoDecoderGst.h 

Log message:
                * backend/sound_handler*, libbase/embedVideoDecoder*: Moved to 
libmedia.
                * Makefile.am, configure.ac, backend/Makefile.am, 
gui/Makefile.am, 
                  server/Makefile.am, server/asobj/Makefile.am, 
server/parser/Makefile.am,
                  server/vm/Makefile.am, testsuite/Makefile.am, 
testsuite/misc-ming.all/Makefile.am,
                  testsuite/movies.all/Makefile.am, 
testsuite/samples/Makefile.am,
                  utilities/Makefile.am: Added the new libmedia to the build 
system.
                * libbase/FLVParser.h: Moved some declerations inside the class 
to avoid
                  conflicts with MediaParser.h.
                * server/video_stream_instance.{cpp,h}, 
server/parser/video_stream_def.{cpp,h}:
                  Use VideoDecoder instead of embedVideoDecoder.
                * server/swf/tag_loaders.cpp: Don't decode and resample the 
ADPCM and raw audio
                  before passing to the soundhandler.
                  Read more about libmedia here: 
http://wiki.gnashdev.org/wiki/index.php/Main_Page

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.4454&r2=1.4455
http://cvs.savannah.gnu.org/viewcvs/gnash/Makefile.am?cvsroot=gnash&r1=1.90&r2=1.91
http://cvs.savannah.gnu.org/viewcvs/gnash/configure.ac?cvsroot=gnash&r1=1.423&r2=1.424
http://cvs.savannah.gnu.org/viewcvs/gnash/backend/Makefile.am?cvsroot=gnash&r1=1.61&r2=1.62
http://cvs.savannah.gnu.org/viewcvs/gnash/backend/sound_handler.h?cvsroot=gnash&r1=1.31&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/backend/sound_handler_gst.cpp?cvsroot=gnash&r1=1.65&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/backend/sound_handler_gst.h?cvsroot=gnash&r1=1.18&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/backend/sound_handler_mp3.cpp?cvsroot=gnash&r1=1.7&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/backend/sound_handler_sdl.cpp?cvsroot=gnash&r1=1.85&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/backend/sound_handler_sdl.h?cvsroot=gnash&r1=1.33&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/gui/Makefile.am?cvsroot=gnash&r1=1.107&r2=1.108
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/FLVParser.h?cvsroot=gnash&r1=1.18&r2=1.19
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/embedVideoDecoder.h?cvsroot=gnash&r1=1.9&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/embedVideoDecoderFfmpeg.cpp?cvsroot=gnash&r1=1.22&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/embedVideoDecoderFfmpeg.h?cvsroot=gnash&r1=1.8&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/embedVideoDecoderGst.cpp?cvsroot=gnash&r1=1.11&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/embedVideoDecoderGst.h?cvsroot=gnash&r1=1.5&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/AudioDecoder.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/AudioDecoderNellymoser.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/AudioDecoderNellymoser.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/AudioDecoderSimple.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/AudioDecoderSimple.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/FLVParser.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/FLVParser.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/Makefile.am?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/Makefile.in?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/MediaBuffer.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/MediaDecoder.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/MediaParser.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/SoundInfo.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/VideoDecoder.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sound_handler.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/VideoDecoderGst.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/VideoDecoderGst.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/gstappbuffer.c?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/gstappbuffer.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/gstappsink.c?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/gstappsink.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/gstappsrc.c?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/gstappsrc.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/gstgnashsrc.c?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/gstgnashsrc.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/sound_handler_gst.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/sound_handler_gst.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sdl/AudioDecoderFfmpeg.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sdl/AudioDecoderFfmpeg.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sdl/AudioDecoderMad.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sdl/AudioDecoderMad.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sdl/MediaDecoderSdl.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sdl/MediaDecoderSdl.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sdl/MediaParserFfmpeg.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sdl/MediaParserFfmpeg.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sdl/VideoDecoderFfmpeg.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sdl/VideoDecoderFfmpeg.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sdl/sound_handler_sdl.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sdl/sound_handler_sdl.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/Makefile.am?cvsroot=gnash&r1=1.125&r2=1.126
http://cvs.savannah.gnu.org/viewcvs/gnash/server/video_stream_instance.cpp?cvsroot=gnash&r1=1.39&r2=1.40
http://cvs.savannah.gnu.org/viewcvs/gnash/server/video_stream_instance.h?cvsroot=gnash&r1=1.21&r2=1.22
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/Makefile.am?cvsroot=gnash&r1=1.45&r2=1.46
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/Makefile.am?cvsroot=gnash&r1=1.39&r2=1.40
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/video_stream_def.cpp?cvsroot=gnash&r1=1.17&r2=1.18
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/video_stream_def.h?cvsroot=gnash&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/gnash/server/swf/tag_loaders.cpp?cvsroot=gnash&r1=1.144&r2=1.145
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/Makefile.am?cvsroot=gnash&r1=1.14&r2=1.15
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/Makefile.am?cvsroot=gnash&r1=1.41&r2=1.42
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/misc-ming.all/Makefile.am?cvsroot=gnash&r1=1.155&r2=1.156
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/movies.all/Makefile.am?cvsroot=gnash&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/samples/Makefile.am?cvsroot=gnash&r1=1.20&r2=1.21
http://cvs.savannah.gnu.org/viewcvs/gnash/utilities/Makefile.am?cvsroot=gnash&r1=1.57&r2=1.58

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.4454
retrieving revision 1.4455
diff -u -b -r1.4454 -r1.4455
--- ChangeLog   27 Sep 2007 23:06:55 -0000      1.4454
+++ ChangeLog   27 Sep 2007 23:59:50 -0000      1.4455
@@ -1,3 +1,30 @@
+2007-09-27 Tomas Groth Christensen <address@hidden>
+
+       * libmedia/, libmedia/sdl/, libmedia/gst/,
+         (in libmedia:) AudioDecoder.h, AudioDecoderSimple.{h,cpp}, 
Makefile.am,
+         AudioDecoderNellymoser.{h,cpp}, FLVParser.{h,cpp}, MediaDecoder.h, 
+         MediaParser.h, SoundInfo.h, MediaBuffer.h, VideoDecoder.h, 
sound_handler.h,
+         (in libmedia/sdl:) AudioDecoderFfmpeg.{h,cpp}, 
AudioDecoderMad.{h,cpp},
+         MediaDecoderSdl.{h,cpp}, MediaParserFfmpeg.{cpp,h}, 
VideoDecoderFfmpeg.{h,cpp},
+         sound_handler_sdl.{h,cpp},
+         (in libmedia/gst:) VideoDecoderGst.{h,cpp}, sound_handler_gst.{h,cpp},
+         gstgnashsrc.{h.c}, gstappbuffer.{c,h}, gstappsink.{c,h}, 
gstappsrc.{c,h}:
+         Files added for the new libmedia (finally!!). Some og theese files 
are moved
+         from the backend/ and libbase/ folders (see below). Not all files are 
yet in use.
+       * backend/sound_handler*, libbase/embedVideoDecoder*: Moved to libmedia.
+       * Makefile.am, configure.ac, backend/Makefile.am, gui/Makefile.am, 
+         server/Makefile.am, server/asobj/Makefile.am, 
server/parser/Makefile.am,
+         server/vm/Makefile.am, testsuite/Makefile.am, 
testsuite/misc-ming.all/Makefile.am,
+         testsuite/movies.all/Makefile.am, testsuite/samples/Makefile.am,
+         utilities/Makefile.am: Added the new libmedia to the build system.
+       * libbase/FLVParser.h: Moved some declerations inside the class to avoid
+         conflicts with MediaParser.h.
+       * server/video_stream_instance.{cpp,h}, 
server/parser/video_stream_def.{cpp,h}:
+         Use VideoDecoder instead of embedVideoDecoder.
+       * server/swf/tag_loaders.cpp: Don't decode and resample the ADPCM and 
raw audio
+         before passing to the soundhandler.
+         Read more about libmedia here: 
http://wiki.gnashdev.org/wiki/index.php/Main_Page
+
 2007-09-28 Sandro Santilli <address@hidden>
 
        * server/character.{cpp,h}: drop the get_text_value override here.

Index: Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/Makefile.am,v
retrieving revision 1.90
retrieving revision 1.91
diff -u -b -r1.90 -r1.91
--- Makefile.am 15 Sep 2007 03:06:37 -0000      1.90
+++ Makefile.am 27 Sep 2007 23:59:50 -0000      1.91
@@ -15,7 +15,7 @@
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 # 
 
-# $Id: Makefile.am,v 1.90 2007/09/15 03:06:37 rsavoye Exp $
+# $Id: Makefile.am,v 1.91 2007/09/27 23:59:50 tgc Exp $
 
 ## Process this file with automake to produce Makefile.in
 AUTOMAKE_OPTIONS = 1.6.0
@@ -26,6 +26,7 @@
        libbase \
        libgeometry \
        libamf \
+       libmedia \
        server \
        backend \
        utilities \

Index: configure.ac
===================================================================
RCS file: /sources/gnash/gnash/configure.ac,v
retrieving revision 1.423
retrieving revision 1.424
diff -u -b -r1.423 -r1.424
--- configure.ac        27 Sep 2007 00:29:30 -0000      1.423
+++ configure.ac        27 Sep 2007 23:59:50 -0000      1.424
@@ -15,7 +15,7 @@
 dnl  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 dnl  
 
-dnl $Id: configure.ac,v 1.423 2007/09/27 00:29:30 rsavoye Exp $
+dnl $Id: configure.ac,v 1.424 2007/09/27 23:59:50 tgc Exp $
 
 AC_PREREQ(2.50)
 AC_INIT(gnash, cvs)
@@ -1446,6 +1446,7 @@
 AC_CONFIG_LINKS(testsuite/libbase/gnashrc:testsuite/libbase/gnashrc.in)
 
 AC_OUTPUT(Makefile
+libmedia/Makefile
 po/Makefile
 libbase/Makefile
 libgeometry/Makefile

Index: backend/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/backend/Makefile.am,v
retrieving revision 1.61
retrieving revision 1.62
diff -u -b -r1.61 -r1.62
--- backend/Makefile.am 16 Sep 2007 18:26:49 -0000      1.61
+++ backend/Makefile.am 27 Sep 2007 23:59:50 -0000      1.62
@@ -71,44 +71,21 @@
        render_handler_agg_compat.h \
        render_handler_agg_style.h \
        render_handler_cairo.h \
-       render_handler_tri.h \
-       sound_handler.h \
-       sound_handler_gst.h \
-       sound_handler_sdl.h
+       render_handler_tri.h
 
 # bin_PROGRAMS = gnash
 
 pkglib_LTLIBRARIES = libgnashbackend.la
 
 # RENDER_SOURCES = render_handler_tri.cpp
-SOUND_SOURCES = 
-
-if USE_SOUND_GST
-SOUND_SOURCES += sound_handler_gst.cpp sound_handler_gst.h 
-libgnashbackend_LIBS += $(GSTREAMER_LIBS) 
-libgnashbackend_LIBS += $(LIBXML_LIBS) 
-AM_CPPFLAGS += $(GSTREAMER_CFLAGS)
-AM_CPPFLAGS += $(LIBXML_CFLAGS)
-endif
-
-if USE_SOUND_SDL
-SOUND_SOURCES += sound_handler_sdl.cpp sound_handler_sdl.h
-if USE_FFMPEG_ENGINE
-libgnashbackend_LIBS += $(FFMPEG_LIBS)
-AM_CPPFLAGS += $(FFMPEG_CFLAGS)
-endif
-if USE_MAD_ENGINE
-libgnashbackend_LIBS += $(MAD_LIBS)
-AM_CPPFLAGS += $(MAD_CFLAGS)
-endif
-endif
 
 libgnashbackend_la_LIBADD = \
        $(top_builddir)/libbase/libgnashbase.la \
        $(top_builddir)/server/libgnashserver.la  \
        $(libgnashbackend_LIBS)
 
-libgnashbackend_la_SOURCES = $(SOUND_SOURCES)
+libgnashbackend_la_SOURCES = 
+#$(SOUND_SOURCES)
 
 libgnashbackend_la_LDFLAGS = -release $(VERSION)
 

Index: gui/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/gui/Makefile.am,v
retrieving revision 1.107
retrieving revision 1.108
diff -u -b -r1.107 -r1.108
--- gui/Makefile.am     15 Sep 2007 03:06:38 -0000      1.107
+++ gui/Makefile.am     27 Sep 2007 23:59:51 -0000      1.108
@@ -41,6 +41,9 @@
         -I$(top_srcdir)/libbase \
         -I$(top_srcdir)/backend \
         -I$(top_srcdir)/libgeometry \
+               -I$(top_srcdir)/libmedia \
+               -I$(top_srcdir)/libmedia/sdl \
+               -I$(top_srcdir)/libmedia/gst \
         -DLOCALEDIR=\"$(localedir)\" \
        -DPLUGINSDIR=\"$(pluginsdir)\" \
         $(LIBXML_CFLAGS) \
@@ -88,6 +91,7 @@
 GNASH_LIBS = \
        $(top_builddir)/libamf/libgnashamf.la \
        $(top_builddir)/backend/libgnashbackend.la \
+       $(top_builddir)/libmedia/libgnashmedia.la \
        $(top_builddir)/server/libgnashserver.la \
        $(top_builddir)/libgeometry/libgnashgeo.la \
        $(top_builddir)/libbase/libgnashbase.la

Index: libbase/FLVParser.h
===================================================================
RCS file: /sources/gnash/gnash/libbase/FLVParser.h,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -b -r1.18 -r1.19
--- libbase/FLVParser.h 8 Jul 2007 20:27:39 -0000       1.18
+++ libbase/FLVParser.h 27 Sep 2007 23:59:52 -0000      1.19
@@ -17,7 +17,7 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //
 
-// $Id: FLVParser.h,v 1.18 2007/07/08 20:27:39 martinwguy Exp $
+// $Id: FLVParser.h,v 1.19 2007/09/27 23:59:52 tgc Exp $
 
 // Information about the FLV format can be found at http://osflash.org/flv
 
@@ -30,38 +30,7 @@
 
 namespace gnash {
 
-enum videoCodecType
-{
-       VIDEO_CODEC_H263 = 2,   // H263/SVQ3 video codec
-       VIDEO_CODEC_SCREENVIDEO = 3,    // Screenvideo codec
-       VIDEO_CODEC_VP6 = 4,            // On2 VP6 video codec
-       VIDEO_CODEC_VP6A = 5,           // On2 VP6 Alpha video codec
-       VIDEO_CODEC_SCREENVIDEO2 = 6    // Screenvideo2 codec
-};
 
-enum audioCodecType
-{
-       AUDIO_CODEC_RAW = 0,            // unspecified format.  Useful for 
8-bit sounds???
-       AUDIO_CODEC_ADPCM = 1,  // gnash doesn't pass this through; it 
uncompresses and sends FORMAT_NATIVE16
-       AUDIO_CODEC_MP3 = 2,
-       AUDIO_CODEC_UNCOMPRESSED = 3,   // 16 bits/sample, little-endian
-       AUDIO_CODEC_NELLYMOSER_8HZ_MONO = 5,    // According to ffmpeg
-       AUDIO_CODEC_NELLYMOSER = 6      // Mystery proprietary format; see 
nellymoser.com
-};
-
-enum tagType
-{
-       AUDIO_TAG = 0x08,
-       VIDEO_TAG = 0x09,
-       META_TAG = 0x12
-};
-
-enum videoFrameType
-{
-       KEY_FRAME = 1,
-       INTER_FRAME = 2,
-       DIS_INTER_FRAME = 3
-};
 
 /// \brief
 /// The FLVFrame class contains a video or audio frame, its size, its
@@ -137,7 +106,7 @@
        /// Return true if this video frame is a key frame
        bool isKeyFrame() const
        {
-               return frameType == KEY_FRAME;
+               return frameType == 1 /*KEY_FRAME*/;
        }
 
 };
@@ -170,6 +139,40 @@
 
 public:
 
+       enum videoCodecType
+       {
+               VIDEO_CODEC_H263 = 2,   // H263/SVQ3 video codec
+               VIDEO_CODEC_SCREENVIDEO = 3,    // Screenvideo codec
+               VIDEO_CODEC_VP6 = 4,            // On2 VP6 video codec
+               VIDEO_CODEC_VP6A = 5,           // On2 VP6 Alpha video codec
+               VIDEO_CODEC_SCREENVIDEO2 = 6    // Screenvideo2 codec
+       };
+
+       enum audioCodecType
+       {
+               AUDIO_CODEC_RAW = 0,            // unspecified format.  Useful 
for 8-bit sounds???
+               AUDIO_CODEC_ADPCM = 1,  // gnash doesn't pass this through; it 
uncompresses and sends FORMAT_NATIVE16
+               AUDIO_CODEC_MP3 = 2,
+               AUDIO_CODEC_UNCOMPRESSED = 3,   // 16 bits/sample, little-endian
+               AUDIO_CODEC_NELLYMOSER_8HZ_MONO = 5,    // According to ffmpeg
+               AUDIO_CODEC_NELLYMOSER = 6      // Mystery proprietary format; 
see nellymoser.com
+       };
+
+       enum tagType
+       {
+               AUDIO_TAG = 0x08,
+               VIDEO_TAG = 0x09,
+               META_TAG = 0x12
+       };
+
+       enum videoFrameType
+       {
+               KEY_FRAME = 1,
+               INTER_FRAME = 2,
+               DIS_INTER_FRAME = 3
+       };
+
+
        /// \brief
        /// Create an FLV parser reading input from
        /// the given LoadThread

Index: server/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/server/Makefile.am,v
retrieving revision 1.125
retrieving revision 1.126
diff -u -b -r1.125 -r1.126
--- server/Makefile.am  23 Sep 2007 08:48:17 -0000      1.125
+++ server/Makefile.am  27 Sep 2007 23:59:55 -0000      1.126
@@ -18,7 +18,7 @@
 # 
 #
 
-# $Id: Makefile.am,v 1.125 2007/09/23 08:48:17 cmusick Exp $
+# $Id: Makefile.am,v 1.126 2007/09/27 23:59:55 tgc Exp $
 
 AUTOMAKE_OPTIONS = 
 
@@ -41,6 +41,9 @@
        -I$(top_srcdir)/server/vm \
        -I$(top_srcdir)/libbase \
        -I$(top_srcdir)/libgeometry \
+       -I$(top_srcdir)/libmedia \
+       -I$(top_srcdir)/libmedia/sdl \
+       -I$(top_srcdir)/libmedia/gst \
        -I$(top_srcdir) \
        $(PTHREAD_CFLAGS) \
        $(DMALLOC_CFLAGS) \
@@ -189,6 +192,7 @@
 
 libgnashserver_la_LIBADD = \
        $(top_builddir)/libbase/libgnashbase.la \
+       $(top_builddir)/libmedia/libgnashmedia.la \
        $(top_builddir)/server/asobj/libgnashasobjs.la \
        $(top_builddir)/server/parser/libgnashparser.la \
        $(top_builddir)/server/vm/libgnashvm.la \

Index: server/video_stream_instance.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/video_stream_instance.cpp,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -b -r1.39 -r1.40
--- server/video_stream_instance.cpp    21 Sep 2007 08:29:03 -0000      1.39
+++ server/video_stream_instance.cpp    27 Sep 2007 23:59:56 -0000      1.40
@@ -17,7 +17,7 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 // 
 
-// $Id: video_stream_instance.cpp,v 1.39 2007/09/21 08:29:03 strk Exp $
+// $Id: video_stream_instance.cpp,v 1.40 2007/09/27 23:59:56 tgc Exp $
 
 #include "sprite_instance.h"
 #include "video_stream_instance.h"
@@ -213,7 +213,7 @@
 
                if (size > 0 && data) {
 
-                       std::auto_ptr<image::image_base> i ( 
m_decoder->decodeFrame(data, size) );
+                       std::auto_ptr<image::image_base> 
i(m_decoder->decodeToImage(data, size));
                        if (i.get())
                        {
                                gnash::render::drawVideoFrame(i.get(), &m, 
&bounds);
@@ -221,7 +221,7 @@
                                log_error(_("An error occured while decoding 
video frame"));
                        }
                } else {
-                       log_error(_("An error occured while decoding video 
frame"));
+                       log_error(_("Video frame data is missing - skipping 
decoding"));
                }
        }
 

Index: server/video_stream_instance.h
===================================================================
RCS file: /sources/gnash/gnash/server/video_stream_instance.h,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -b -r1.21 -r1.22
--- server/video_stream_instance.h      21 Sep 2007 08:29:03 -0000      1.21
+++ server/video_stream_instance.h      27 Sep 2007 23:59:56 -0000      1.22
@@ -16,14 +16,14 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 // 
-// $Id: video_stream_instance.h,v 1.21 2007/09/21 08:29:03 strk Exp $
+// $Id: video_stream_instance.h,v 1.22 2007/09/27 23:59:56 tgc Exp $
 
 #ifndef GNASH_VIDEO_STREAM_INSTANCE_H
 #define GNASH_VIDEO_STREAM_INSTANCE_H
 
 #include "character.h" // for inheritance
 #include "video_stream_def.h"
-#include "embedVideoDecoder.h"
+#include "VideoDecoder.h"
 #include "snappingrange.h"
 
 // Forward declarations
@@ -100,7 +100,7 @@
        boost::intrusive_ptr<NetStream> _ns;
 
        /// Decoder for embedded video
-       std::auto_ptr<embedVideoDecoder> m_decoder;
+       std::auto_ptr<VideoDecoder> m_decoder;
 };
 
 void video_class_init(as_object& global);

Index: server/asobj/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/Makefile.am,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -b -r1.45 -r1.46
--- server/asobj/Makefile.am    23 Sep 2007 08:48:18 -0000      1.45
+++ server/asobj/Makefile.am    27 Sep 2007 23:59:56 -0000      1.46
@@ -15,7 +15,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-# $Id: Makefile.am,v 1.45 2007/09/23 08:48:18 cmusick Exp $
+# $Id: Makefile.am,v 1.46 2007/09/27 23:59:56 tgc Exp $
 
 AUTOMAKE_OPTIONS = 
 
@@ -31,6 +31,9 @@
        -I$(top_srcdir)/libgeometry \
        -I$(top_srcdir)/libamf \
        -I$(top_srcdir)/libltdl \
+       -I$(top_srcdir)/libmedia \
+       -I$(top_srcdir)/libmedia/gst \
+       -I$(top_srcdir)/libmedia/sdl \
        -I$(top_srcdir) \
        $(PTHREAD_CFLAGS) \
        $(DMALLOC_CFLAGS) \

Index: server/parser/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/server/parser/Makefile.am,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -b -r1.39 -r1.40
--- server/parser/Makefile.am   24 Sep 2007 15:39:31 -0000      1.39
+++ server/parser/Makefile.am   27 Sep 2007 23:59:56 -0000      1.40
@@ -15,7 +15,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-# $Id: Makefile.am,v 1.39 2007/09/24 15:39:31 cmusick Exp $
+# $Id: Makefile.am,v 1.40 2007/09/27 23:59:56 tgc Exp $
 
 AUTOMAKE_OPTIONS = 
 
@@ -35,6 +35,9 @@
        -I$(top_srcdir)/server/asobj \
         -I$(top_srcdir)/libbase \
         -I$(top_srcdir)/libgeometry \
+        -I$(top_srcdir)/libmedia \
+        -I$(top_srcdir)/libmedia/sdl \
+        -I$(top_srcdir)/libmedia/gst \
         -I$(top_srcdir)/libamf \
         -I$(top_srcdir)        \
        $(LIBXML_CFLAGS) \
@@ -83,7 +86,8 @@
 libgnashparser_la_LIBADD = \
        $(top_builddir)/libamf/libgnashamf.la \
        $(top_builddir)/libgeometry/libgnashgeo.la \
-       $(top_builddir)/libbase/libgnashbase.la
+       $(top_builddir)/libbase/libgnashbase.la \
+       $(top_builddir)/libmedia/libgnashmedia.la
 
 libgnashparser_la_LDFLAGS = $(BOOST_LIBS) -export-dynamic # -release 
$(VERSION) -no-undefined 
 

Index: server/parser/video_stream_def.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/parser/video_stream_def.cpp,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -b -r1.17 -r1.18
--- server/parser/video_stream_def.cpp  17 Sep 2007 12:41:22 -0000      1.17
+++ server/parser/video_stream_def.cpp  27 Sep 2007 23:59:56 -0000      1.18
@@ -16,16 +16,16 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 // 
-// $Id: video_stream_def.cpp,v 1.17 2007/09/17 12:41:22 tgc Exp $
+// $Id: video_stream_def.cpp,v 1.18 2007/09/27 23:59:56 tgc Exp $
 
 #include "video_stream_def.h"
 #include "video_stream_instance.h"
 #include "render.h"
 
 #ifdef USE_FFMPEG
-#include "embedVideoDecoderFfmpeg.h"
+#include "VideoDecoderFfmpeg.h"
 #elif defined(SOUND_GST)
-#include "embedVideoDecoderGst.h"
+#include "VideoDecoderGst.h"
 #endif
 
 namespace gnash {
@@ -66,7 +66,7 @@
                m_deblocking_flags = in->read_uint(2);
                m_smoothing_flags = in->read_bit(); 
 
-               m_codec_id = in->read_u8();
+               m_codec_id = static_cast<videoCodecType>(in->read_u8());
 
        }
        else if (tag == SWF::VIDEOFRAME)
@@ -107,30 +107,31 @@
        return ch;
 }
 
-std::auto_ptr<embedVideoDecoder>
+std::auto_ptr<VideoDecoder>
 video_stream_definition::get_decoder()
 {
 
-       std::auto_ptr<embedVideoDecoder> decoder;
+       std::auto_ptr<VideoDecoder> decoder;
 
        if (m_num_frames == 0) return decoder;
 
 
 #ifdef USE_FFMPEG
-       decoder.reset( new embedVideoDecoderFfmpeg() );
+       decoder.reset( new VideoDecoderFfmpeg() );
 #elif defined(SOUND_GST)
-       decoder.reset( new embedVideoDecoderGst() );
+       decoder.reset( new VideoDecoderGst() );
 #else
-       decoder.reset( new embedVideoDecoder() );
+       decoder.reset( new VideoDecoder() );
 #endif
 
-       decoder->createDecoder(
+       bool ret = decoder->setup(
                                
static_cast<int>(TWIPS_TO_PIXELS(m_bound.width())),// m_width,
                                
static_cast<int>(TWIPS_TO_PIXELS(m_bound.height())), // m_height,
                                m_deblocking_flags,
                                m_smoothing_flags,
                                m_codec_id,
                                gnash::render::videoFrameFormat());
+       if (!ret) log_error("The videodecoder cannot decode this video");
        return decoder;
 
 }

Index: server/parser/video_stream_def.h
===================================================================
RCS file: /sources/gnash/gnash/server/parser/video_stream_def.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- server/parser/video_stream_def.h    17 Sep 2007 12:41:22 -0000      1.11
+++ server/parser/video_stream_def.h    27 Sep 2007 23:59:56 -0000      1.12
@@ -16,7 +16,7 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 // 
-// $Id: video_stream_def.h,v 1.11 2007/09/17 12:41:22 tgc Exp $
+// $Id: video_stream_def.h,v 1.12 2007/09/27 23:59:56 tgc Exp $
 
 #ifndef GNASH_VIDEO_STREAM_DEF_H
 #define GNASH_VIDEO_STREAM_DEF_H
@@ -31,7 +31,7 @@
 #include "swf.h"
 #include "rect.h" // for composition
 #include "execute_tag.h"
-#include "embedVideoDecoder.h"
+#include "VideoDecoder.h"
 #include "image.h"
 #include <map>
 #include <boost/shared_array.hpp>
@@ -94,7 +94,7 @@
        ///
        /// This function *never* returns a NULL pointer.
        ///
-       std::auto_ptr<embedVideoDecoder> get_decoder();
+       std::auto_ptr<VideoDecoder> get_decoder();
 
        /// Get the Video frame associated with the given SWF frame number
        //
@@ -152,7 +152,7 @@
        ///
        /// TODO: define an enumeration for the above values
        ///
-       uint8_t m_codec_id;
+       videoCodecType m_codec_id;
 
        /// Bounds of the video, as read from the DEFINEVIDEOSTREAM tag.
        rect m_bound;

Index: server/swf/tag_loaders.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/swf/tag_loaders.cpp,v
retrieving revision 1.144
retrieving revision 1.145
diff -u -b -r1.144 -r1.145
--- server/swf/tag_loaders.cpp  26 Sep 2007 15:22:12 -0000      1.144
+++ server/swf/tag_loaders.cpp  27 Sep 2007 23:59:56 -0000      1.145
@@ -17,7 +17,7 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //
 
-/* $Id: tag_loaders.cpp,v 1.144 2007/09/26 15:22:12 strk Exp $ */
+/* $Id: tag_loaders.cpp,v 1.145 2007/09/27 23:59:56 tgc Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -55,6 +55,7 @@
 #include "video_stream_def.h"
 #include "sound_definition.h"
 #include "abc_block.h"
+#include "SoundInfo.h"
 
 #ifdef HAVE_ZLIB_H
 #include <zlib.h>
@@ -70,14 +71,6 @@
 
 namespace gnash {
 
-// Forward declaration for functions at end of file
-//
-// Both modify "data" parameter, allocating memory for it.
-
-static void u8_expand(unsigned char* &data, stream* in,
-       int sample_count,  // in stereo, this is number of *pairs* of samples
-       bool stereo);
-
 namespace SWF {
 namespace tag_loaders {
 
@@ -137,291 +130,6 @@
 
 } // anonymous namespace
 
-// ----------------------------------------------------------------------------
-// ADPCMDecoder class
-// ----------------------------------------------------------------------------
-
-/// ADPCM decoder utilities
-//
-/// Algo from 
http://www.circuitcellar.com/pastissues/articles/richey110/text.htm
-/// And also Jansen.
-/// Here's another reference: 
http://www.geocities.com/SiliconValley/8682/aud3.txt
-/// Original IMA spec doesn't seem to be on the web :(
-///
-/// TODO: move in it's own file
-///
-class ADPCMDecoder {
-
-private:
-
-       // Data from Alexis' SWF reference
-       static int _index_update_table_2bits[2];
-       static int _index_update_table_3bits[4];
-       static int _index_update_table_4bits[8];
-       static int _index_update_table_5bits[16];
-
-       static int* s_index_update_tables[4];
-
-       // Data from Jansen.  http://homepages.cwi.nl/~jack/
-       // Check out his Dutch retro punk songs, heh heh :)
-       static const int STEPSIZE_CT = 89;
-       static int s_stepsize[STEPSIZE_CT];
-
-
-       static void doSample(int n_bits, int& sample, int& stepsize_index, int 
raw_code)
-       {
-               assert(raw_code >= 0 && raw_code < (1 << n_bits));              
                                                
-                                                                               
                                                
-               static const int        HI_BIT = (1 << (n_bits - 1));           
                                                
-               int*    index_update_table = s_index_update_tables[n_bits - 2]; 
                                                
-                                                                               
                                                
-               /* Core of ADPCM. */                                            
                                                
-                                                                               
                                                
-               int     code_mag = raw_code & (HI_BIT - 1);                     
                                                
-               bool    code_sign_bit = (raw_code & HI_BIT) ? 1 : 0;            
                                                
-               int     mag = (code_mag << 1) + 1;      /* shift in LSB (they 
do this so that pos & neg zero are different)*/   
-                                                                               
                                                
-               int     stepsize = s_stepsize[stepsize_index];                  
                                                
-                                                                               
                                                
-               /* Compute the new sample.  It's the predicted value            
        */                                      
-               /* (i.e. the previous value), plus a delta.  The delta          
        */                                      
-               /* comes from the code times the stepsize.  going for           
        */                                      
-               /* something like: delta = stepsize * (code * 2 + 1) >> 
code_bits       */                                      
-               int     delta = (stepsize * mag) >> (n_bits - 1);               
                                                
-               if (code_sign_bit) delta = -delta;                              
                                                
-                                                                               
                                                
-               sample += delta;                                                
                                                
-               sample = iclamp(sample, -32768, 32767);                         
                                                
-                                                                               
                                                
-               /* Update our stepsize index.  Use a lookup table. */           
                                                
-               stepsize_index += index_update_table[code_mag];                 
                                                
-               stepsize_index = iclamp(stepsize_index, 0, STEPSIZE_CT - 1);    
                                                
-       }
-
-       /* Uncompress 4096 mono samples of ADPCM. */                            
                                        
-       static void doMonoBlock(int16_t** out_data, int n_bits, int 
sample_count, stream* in, int sample, int stepsize_index)
-       {
-               /* First sample doesn't need to be decompressed. */             
                                                
-               sample_count--;                                                 
                                                
-               *(*out_data)++ = (int16_t) sample;                              
                                                
-                                                                               
                                                
-               while (sample_count--)                                          
                                                
-               {                                                               
                                                
-                       int     raw_code = in->read_uint(n_bits);               
                                                
-                       doSample(n_bits, sample, stepsize_index, raw_code);     
/* sample & stepsize_index are in/out params */ 
-                       *(*out_data)++ = (int16_t) sample;                      
                                                
-               }                                                               
                                                
-       }
-
-
-       /* Uncompress 4096 stereo sample pairs of ADPCM. */                     
                                                
-       static void doStereoBlock(
-                       int16_t** out_data,     // in/out param
-                       int n_bits,
-                       int sample_count,
-                       stream* in,
-                       int left_sample,
-                       int left_stepsize_index,
-                       int right_sample,
-                       int right_stepsize_index
-                       )
-       {
-               /* First samples don't need to be decompressed. */              
                                                
-               sample_count--;                                                 
                                                
-               *(*out_data)++ = (int16_t) left_sample;                         
                                                
-               *(*out_data)++ = (int16_t) right_sample;                        
                                                        
-                                                                               
                                                
-               while (sample_count--)                                          
                                                
-               {                                                               
                                                
-                       int     left_raw_code = in->read_uint(n_bits);          
                                                
-                       doSample(n_bits, left_sample, left_stepsize_index, 
left_raw_code);                                      
-                       *(*out_data)++ = (int16_t) left_sample;                 
                                                
-                                                                               
                                                
-                       int     right_raw_code = in->read_uint(n_bits);         
                                                
-                       doSample(n_bits, right_sample, right_stepsize_index, 
right_raw_code);                                   
-                       *(*out_data)++ = (int16_t) right_sample;                
                                                        
-               }                                                               
                                                
-       }
-
-public:
-
-       // Utility function: uncompress ADPCM data from in stream to
-       // out_data[].  The output buffer must have (sample_count*2)
-       // bytes for mono, or (sample_count*4) bytes for stereo.
-       static void adpcm_expand(
-               unsigned char* &data,
-               stream* in,
-               int sample_count,       // in stereo, this is number of *pairs* 
of samples (TODO: why is this signed at all ??)
-               bool stereo)
-       {
-               int16_t* out_data = new int16_t[stereo ? sample_count*2 : 
sample_count];
-               data = reinterpret_cast<unsigned char *>(out_data);
-
-               // Read header.
-               in->ensureBytes(1); // nbits
-               unsigned int n_bits = in->read_uint(2) + 2;     // 2 to 5 bits 
(TODO: use unsigned...)
-
-
-#ifndef GNASH_TRUST_SWF_INPUT
-
-               // bitsPerCompSample is the number of bits for each comp sample
-               unsigned int bitsPerCompSample = n_bits;
-               if (stereo) bitsPerCompSample *= 2;
-
-               // There's going to be one block every 4096 samples ...
-               unsigned int blocksCount = sample_count/4096;
-
-               // ... or fraction
-               if ( sample_count%4096 ) ++blocksCount;
-
-               // Of the total samples, all but the first sample in a block 
are comp
-               unsigned int compSamples = sample_count - blocksCount;
-
-               // From every block, a fixed 22 bits will be read (16 of which 
are the uncomp sample)
-               unsigned int fixedBitsPerBlock = 22;
-
-               // Total bits needed from stream
-               unsigned long bitsNeeded = (compSamples*bitsPerCompSample) + 
(fixedBitsPerBlock*blocksCount);
-
-               // Now, we convert this number to bytes...
-               unsigned long bytesNeeded = bitsNeeded/8;
-               // ... requiring one more if the bits in excess are more then
-               //     the ones still available in last byte read 
-               unsigned int excessBits = bitsNeeded%8;
-               if ( excessBits > 6 ) ++bytesNeeded;
-
-               // Take note of the current position to later verify if we got 
the 
-               // number of required bytes right
-               unsigned long prevPosition = in->get_position();
-
-               // We substract 1 byte as the 6 excessive of a byte are already 
in the stream,
-               // and we won't require another one unless more then 6 
excessive bits are needed
-               // WARNING: this is currently disabled due to a bug in this 
function often resulting
-               //          in reads past the end of the stream
-               //in->ensureBytes(bytesNeeded-1);
-
-#endif // GNASH_TRUST_SWF_INPUT
-
-               while (sample_count)
-               {
-                       // Read initial sample & index values.
-
-                       int     sample = in->read_sint(16);
-
-                       int     stepsize_index = in->read_uint(6);
-                       assert(STEPSIZE_CT >= (1 << 6));        // ensure we 
don't need to clamp.
-
-                       int     samples_this_block = imin(sample_count, 4096);
-                       sample_count -= samples_this_block;
-
-                       if (stereo == false)
-                       {
-#define DO_MONO(n) doMonoBlock(&out_data, n, samples_this_block, in, sample, 
stepsize_index)
-
-                               switch (n_bits)
-                               {
-                               default: assert(0); break;
-                               case 2: DO_MONO(2); break;
-                               case 3: DO_MONO(3); break;
-                               case 4: DO_MONO(4); break;
-                               case 5: DO_MONO(5); break;
-                               }
-                       }
-                       else
-                       {
-                               // Stereo.
-
-                               // Got values for left channel; now get initial 
sample
-                               // & index for right channel.
-                               int     right_sample = in->read_sint(16);
-
-                               int     right_stepsize_index = in->read_uint(6);
-                               assert(STEPSIZE_CT >= (1 << 6));        // 
ensure we don't need to clamp.
-
-#define DO_STEREO(n)                                   \
-               doStereoBlock(                          \
-                       &out_data, n, samples_this_block,       \
-                       in, sample, stepsize_index,             \
-                       right_sample, right_stepsize_index)
-                               
-                               switch (n_bits)
-                               {
-                               default: assert(0); break;
-                               case 2: DO_STEREO(2); break;
-                               case 3: DO_STEREO(3); break;
-                               case 4: DO_STEREO(4); break;
-                               case 5: DO_STEREO(5); break;
-                               }
-                       }
-               }
-
-#ifndef GNASH_TRUST_SWF_INPUT
-               unsigned long curPos = in->get_position();
-               unsigned long bytesRead = curPos - prevPosition;
-               if ( bytesRead != bytesNeeded )
-               {
-                       // This would happen if the computation of bytesNeeded 
doesn't match the current
-                       // implementation.
-                       // NOTE That the current implementation seems pretty 
much bogus as we *often* end
-                       // up reading past the end of the tag. Once we fix the 
decoding we shoudl also fix
-                       // the computation of bytes needed
-                       log_error("admcp_expand: we expected to read %lu bytes, 
but we read %lu instead (%ld error)",
-                               bytesNeeded, bytesRead, bytesNeeded-bytesRead);
-                       // abort();
-               }
-
-               unsigned long endTagPos = in->get_tag_end_position();
-               if ( curPos > endTagPos )
-               {
-                       // This happens when our decoder reads past the end of 
the tag.
-                       // In general, we should aborth parsing of the current 
tag when this happens,
-                       // anyway, it seems that *some* sound can be heard 
nonetheless so we keep going.
-                       log_error("admcp_expand: read past tag boundary: 
current position: %lu, end of tag position: %lu (overflow: %lu bytes)",
-                               curPos, endTagPos, curPos-endTagPos);
-
-#if 0
-                       log_debug("      stereo:%d, sample_count:%u, 
compressedSamples:%d, bitsPerCompSample:%u, "
-                               "blocksCount:%u, bitsPerBlock:%u, 
bitsNeeded:%lu, excessBits:%u, bytesNeeded:%lu, bytesLeft:%lu",
-                               stereo, sample_count, compSamples, 
bitsPerCompSample, blocksCount, fixedBitsPerBlock,
-                               bitsNeeded, excessBits, bytesNeeded, 
in->get_tag_end_position()-in->get_position());
-#endif
-               }
-#endif // GNASH_TRUST_SWF_INPUT
-
-       }
-
-
-};
-
-int ADPCMDecoder::_index_update_table_2bits[2] = { -1,  2 };
-int ADPCMDecoder::_index_update_table_3bits[4] = { -1, -1,  2,  4 };
-int ADPCMDecoder::_index_update_table_4bits[8] = { -1, -1, -1, -1,  2,  4,  6, 
 8 };
-int ADPCMDecoder::_index_update_table_5bits[16] = { -1, -1, -1, -1, -1, -1, 
-1, -1, 1,  2,  4,  6,  8, 10, 13, 16 };
-
-int* ADPCMDecoder::s_index_update_tables[4] = {
-       ADPCMDecoder::_index_update_table_2bits,
-       ADPCMDecoder::_index_update_table_3bits,
-       ADPCMDecoder::_index_update_table_4bits,
-       ADPCMDecoder::_index_update_table_5bits
-};
-
-int ADPCMDecoder::s_stepsize[STEPSIZE_CT] = {
-       7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
-       19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
-       50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
-       130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
-       337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
-       876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
-       2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
-       5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
-       15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
-};
-
-// ----------------------------------------------------------------------------
-// END OF ADPCMDecoder class
-// ----------------------------------------------------------------------------
-
-
 //
 // Some tag implementations
 //
@@ -1435,10 +1143,10 @@
 //
 
 // Forward declaration
-static void sound_expand(stream *in, sound_handler::format_type &format,
+/*static void sound_expand(stream *in, sound_handler::format_type &format,
        bool sample_16bit, bool stereo, unsigned int &sample_count,
        unsigned char* &data, unsigned &data_bytes);
-
+*/
 // Common data
 static int     s_sample_rate_table[] = { 5512, 11025, 22050, 44100 };
 
@@ -1457,15 +1165,14 @@
 
        uint16_t        character_id = in->read_u16();
 
-       sound_handler::format_type      format = 
static_cast<sound_handler::format_type>(in->read_uint(4));
-       sound_handler::format_type      orgFormat = format;
+       audioCodecType  format = static_cast<audioCodecType>(in->read_uint(4));
        int     sample_rate = in->read_uint(2); // multiples of 5512.5
        bool    sample_16bit = in->read_bit(); 
        bool    stereo = in->read_bit(); 
 
        unsigned int    sample_count = in->read_u32();
 
-       if (format == sound_handler::FORMAT_MP3) {
+       if (format == AUDIO_CODEC_MP3) {
                in->ensureBytes(2);
                int16_t delay_seek = in->read_s16();    // FIXME - not 
implemented/used
                // The DelaySeek field has the following meaning:
@@ -1504,19 +1211,16 @@
                return;
            }
 
-           unsigned char *data; // Expanded audio data ready for playing
-
            // First it is the amount of data from file,
            // then the amount allocated at *data (it may grow)
             unsigned data_bytes = in->get_tag_end_position() - 
in->get_position();
+           unsigned char *data = new unsigned char[data_bytes];
 
-           // sound_expand allocates storage for data[].
-           // and modifies 3 parameters: format, data and data_bytes.
-           sound_expand(in, format, sample_16bit, stereo, sample_count, data, 
data_bytes);
+           in->read((char*)data, data_bytes);
 
            // Store all the data in a SoundInfo object
            std::auto_ptr<SoundInfo> sinfo;
-           sinfo.reset(new SoundInfo(format, orgFormat, stereo, 
s_sample_rate_table[sample_rate], sample_count, sample_16bit));
+           sinfo.reset(new SoundInfo(format, stereo, 
s_sample_rate_table[sample_rate], sample_count, sample_16bit));
 
            // Stores the sounddata in the soundhandler, and the ID returned
            // can be used to starting, stopping and deleting that sound
@@ -1528,6 +1232,7 @@
                sound_sample* sam = new sound_sample(handler_id);
                m->add_sound_sample(character_id, sam);
            }
+
        }
        else
        {
@@ -1594,8 +1299,7 @@
     // extract garbage data
     int        garbage = in->read_uint(8);
 
-    sound_handler::format_type format = 
static_cast<sound_handler::format_type>(in->read_uint(4));
-       sound_handler::format_type orgFormat = format;
+    audioCodecType format = static_cast<audioCodecType>(in->read_uint(4));
     int sample_rate = in->read_uint(2);        // multiples of 5512.5
     bool sample_16bit = in->read_bit(); 
     bool stereo = in->read_bit(); 
@@ -1605,7 +1309,7 @@
 
     unsigned int sample_count = in->read_u16();
        int latency = 0;
-    if (format == sound_handler::FORMAT_MP3) {
+    if (format == AUDIO_CODEC_MP3) {
                latency = in->read_s16();
                garbage = in->read_uint(16);
        }
@@ -1627,25 +1331,9 @@
        return;
     }
 
-    // Tell create_sound what format it will be receiving, in case it cares
-    // at this stage.
-    switch (format) {
-    case sound_handler::FORMAT_ADPCM:
-    case sound_handler::FORMAT_RAW:
-    case sound_handler::FORMAT_UNCOMPRESSED:
-       format = sound_handler::FORMAT_NATIVE16;
-       break;
-    // Shut fussy compilers up...
-    case sound_handler::FORMAT_MP3:
-    case sound_handler::FORMAT_NELLYMOSER:
-    case sound_handler::FORMAT_NATIVE16:
-    case sound_handler::FORMAT_NELLYMOSER_8HZ_MONO:
-       break;
-    }
-
        // Store all the data in a SoundInfo object
        std::auto_ptr<SoundInfo> sinfo;
-       sinfo.reset(new SoundInfo(format, orgFormat, stereo, 
s_sample_rate_table[sample_rate], sample_count, sample_16bit));
+       sinfo.reset(new SoundInfo(format, stereo, 
s_sample_rate_table[sample_rate], sample_count, sample_16bit));
 
        // Stores the sounddata in the soundhandler, and the ID returned
        // can be used to starting, stopping and deleting that sound
@@ -1676,20 +1364,15 @@
     // If there is no SoundInfo something is wrong...
     if (!sinfo) return;
 
-    sound_handler::format_type format = sinfo->getOrgFormat();
+    audioCodecType format = sinfo->getFormat();
     unsigned int sample_count = sinfo->getSampleCount();
 
        // discard garbage data if format is MP3
-    if (format == sound_handler::FORMAT_MP3) in->skip_bytes(4);
+    if (format == AUDIO_CODEC_MP3) in->skip_bytes(4);
 
-    unsigned char *data;       // Storage is allocated by sound_expand()
     unsigned int data_bytes = in->get_tag_end_position() - in->get_position();
-
-    sound_expand(in, format,
-                sinfo->is16bit(), sinfo->isStereo(), sample_count,
-                data, data_bytes);
-    // "format" now reflects what we hand(ed) to the sound drivers.
-    // "data_bytes" now reflects the size of the uncompressed data.
+    unsigned char *data = new unsigned char[data_bytes];
+    in->read((char*)data, data_bytes);
 
     // Fill the data on the apropiate sound, and receives the starting point
     // for later "start playing from this frame" events.
@@ -1702,132 +1385,6 @@
     ssst->read(m, handle_id, start);
 }
 
-// sound_expand: Expand audio data to 16-bit host endian.
-//
-// This modifies three of its parameters:
-// On entry, "format" is the format of the original data. If this routine
-// expands that to 16-bit native-endian, it will also modify "format" to
-// FORMAT_NATIVE16. Otherwise it leaves it alone (MP3 and NELLYMOSER).
-//
-// Storage for "data" is allocated here, and the the "data" pointer is 
modified.
-//
-// On entry, data_bytes is the amount of sound data to be read from "in";
-// on exit it reflects the number of bytes that "data" now points to.
-static void
-sound_expand(stream *in, sound_handler::format_type &format,
-       bool sample_16bit, bool stereo, unsigned int &sample_count,
-       unsigned char* &data, unsigned int &data_bytes)
-{
-
-    // Make sure that an unassigned pointer cannot get through
-    data = NULL;
-
-    switch (format) {
-
-    case sound_handler::FORMAT_ADPCM:
-      {
-       //log_debug("ADPCM format");
-       // Uncompress the ADPCM before handing data to host.
-       if (sample_count == 0) sample_count = data_bytes / ( stereo ? 4 : 2 );
-       ADPCMDecoder::adpcm_expand(data, in, sample_count, stereo);
-       data_bytes = sample_count * (stereo ? 4 : 2);
-       format = sound_handler::FORMAT_NATIVE16;
-       break;
-      }
-    case sound_handler::FORMAT_RAW:
-       //log_debug("RAW format");
-       // 8- or 16-bit mono or stereo host-endian audio
-       // Convert to 16-bit host-endian
-       if (sample_16bit) {
-           // FORMAT_RAW 16-bit is exactly what we want!
-           in->ensureBytes(data_bytes); 
-           data = new unsigned char[data_bytes];
-           in->read((char *)data, data_bytes);
-       } else {
-           // Convert 8-bit signed to 16-bit range
-           // Allocate as many shorts as there are samples
-           if (sample_count == 0) sample_count = data_bytes / (stereo ? 2 : 1);
-           u8_expand(data, in, sample_count, stereo);
-               data_bytes = sample_count * (stereo ? 4 : 2);
-       }
-       format = sound_handler::FORMAT_NATIVE16;
-       break;
-
-    case sound_handler::FORMAT_UNCOMPRESSED:
-       //log_debug("UNCOMPRESSED format");
-       // 8- or 16-bit mono or stereo little-endian audio
-       // Convert to 16-bit host-endian.
-       if (!sample_16bit)
-       {
-           // Convert 8-bit signed to 16-bit range
-           // Allocate as many shorts as there are 8-bit samples
-           if (sample_count == 0) sample_count = data_bytes / (stereo ? 2 : 1);
-           u8_expand(data, in, sample_count, stereo);
-               data_bytes = sample_count * (stereo ? 4 : 2);
-
-       } else {
-           // Read 16-bit data into buffer
-           in->ensureBytes(data_bytes); 
-           data = new unsigned char[data_bytes];
-           in->read((char *)data, data_bytes);
-
-           // Convert 16-bit little-endian data to host-endian.
-
-           // Runtime detection of host endianness costs almost
-           // nothing and is less of a continual maintenance headache
-           // than compile-time detection.
-           union u {
-               uint16_t s;
-               struct {
-                   uint8_t c0;
-                   uint8_t c1;
-               } c;
-           } u = { 0x0001 };
-
-           switch (u.c.c0) {
-           case 0x01:  // Little-endian host: sample is already native.
-               break;
-           case 0x00:  // Big-endian host
-               // Swap sample bytes to get big-endian format.
-               assert(data_bytes & 1 == 0);
-               for (unsigned i = 0; i < data_bytes; i+=2)
-               {
-                   swap(&data[i], &data[i+1]);
-               }
-               break;
-           default:    // Impossible
-               log_error(_("Host endianness not detected in 
define_sound_loader"));
-               // Just carry on anyway...
-           }
-       }
-       format = sound_handler::FORMAT_NATIVE16;
-       break;
-
-    case sound_handler::FORMAT_MP3:
-       //log_debug("MP3 format");
-       // Decompressed elsewhere
-       in->ensureBytes(data_bytes); 
-       data = new unsigned char[data_bytes];
-       in->read((char *)data, data_bytes);
-       break;
-
-    case sound_handler::FORMAT_NELLYMOSER_8HZ_MONO:
-    case sound_handler::FORMAT_NELLYMOSER:
-       //log_debug("NELLYMOSER format");
-       // One day...
-       in->ensureBytes(data_bytes); 
-       in->skip_bytes(data_bytes);
-       data = NULL;
-       break;
-
-    // This is impossible as an input but stops fussy compilers
-    // complaining about unhandled enum values.
-    case sound_handler::FORMAT_NATIVE16:
-       //log_debug("NATIVE16 format");
-       break;
-    }
-}
-
 void
 define_video_loader(stream* in, tag_type tag, movie_definition* m)
 {
@@ -1987,52 +1544,6 @@
 // indent-tabs-mode: t
 // End:
 
-// Expand ADPCM, 8-bit and non-host-endian 16-bit audio to 16-bit host-endian
-//
-// Provides:
-//
-// void        adpcm_expand(unsigned char* &data, stream* in,
-//     int sample_count, // in stereo, this is number of *pairs* of samples
-//     bool stereo)
-//
-//     Uncompress ADPCM data from in stream to out_data[].
-//     The output buffer must have (sample_count*2) bytes for mono,
-//     or (sample_count*4) bytes for stereo.
-//
-// This code has wandered round the Gnash source tree and has still not found
-// its proper home yet.
-
-
-//
-// Unsigned 8-bit expansion (128 is silence)
-//
-// u8_expand allocates the memory for its "data" pointer.
-//
-
-static void u8_expand(
-       unsigned char * &data,
-       stream* in,
-       int sample_count,       // in stereo, this is number of *pairs* of 
samples
-       bool stereo)
-{
-       unsigned total_samples = stereo ? sample_count*2 : sample_count;
-
-       in->ensureBytes(total_samples); 
-
-       boost::scoped_array<uint8_t> in_data ( new uint8_t[total_samples] );
-       int16_t *out_data = new int16_t[total_samples];
-
-       in->read((char *)in_data.get(), total_samples); // Read 8-bit samples
-
-       // Convert 8-bit to 16
-       uint8_t *inp = in_data.get();
-       int16_t *outp = out_data;
-       for (unsigned i=total_samples; i>0; i--) {
-               *outp++ = ((int16_t)(*inp++) - 128) * 256;
-       }
-       
-       data = (unsigned char *)out_data;
-}
 
 
 // @@ lots of macros here!  It seems that VC6 can't correctly

Index: server/vm/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/server/vm/Makefile.am,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -b -r1.14 -r1.15
--- server/vm/Makefile.am       1 Jul 2007 10:54:37 -0000       1.14
+++ server/vm/Makefile.am       27 Sep 2007 23:59:56 -0000      1.15
@@ -15,7 +15,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-# $Id: Makefile.am,v 1.14 2007/07/01 10:54:37 bjacques Exp $
+# $Id: Makefile.am,v 1.15 2007/09/27 23:59:56 tgc Exp $
 
 AUTOMAKE_OPTIONS = 
 
@@ -30,6 +30,9 @@
         -I$(top_srcdir)/libbase \
         -I$(top_srcdir)/libgeometry \
         -I$(top_srcdir)/libamf \
+        -I$(top_srcdir)/libmedia \
+        -I$(top_srcdir)/libmedia/sdl \
+        -I$(top_srcdir)/libmedia/gst \
         -I$(top_srcdir)        \
        $(GLIB_CFLAGS) \
        $(FFMPEG_CFLAGS) \

Index: testsuite/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/testsuite/Makefile.am,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -b -r1.41 -r1.42
--- testsuite/Makefile.am       10 Aug 2007 18:31:01 -0000      1.41
+++ testsuite/Makefile.am       27 Sep 2007 23:59:56 -0000      1.42
@@ -33,11 +33,13 @@
 libtestsuite_la_LIBADD = \
        $(RENDERER_LIBS) \
        $(top_builddir)/backend/libgnashbackend.la \
+       $(top_builddir)/libmedia/libgnashmedia.la \
        $(top_builddir)/server/libgnashserver.la \
        $(top_builddir)/libbase/libgnashbase.la \
        $(NULL)
 libtestsuite_la_CXXFLAGS = \
        -I$(top_srcdir)/libbase \
+       -I$(top_srcdir)/libmedia \
        -I$(top_srcdir)/backend \
        -I$(top_srcdir)/libgeometry \
        -I$(top_srcdir)/server  \

Index: testsuite/misc-ming.all/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/testsuite/misc-ming.all/Makefile.am,v
retrieving revision 1.155
retrieving revision 1.156
diff -u -b -r1.155 -r1.156
--- testsuite/misc-ming.all/Makefile.am 27 Sep 2007 04:40:24 -0000      1.155
+++ testsuite/misc-ming.all/Makefile.am 27 Sep 2007 23:59:56 -0000      1.156
@@ -40,6 +40,7 @@
 AM_CPPFLAGS = -I.. \
        -I$(top_srcdir)         \
        -I$(top_srcdir)/libbase \
+       -I$(top_srcdir)/libmedia \
        -I$(top_srcdir)/backend \
        -I$(top_srcdir)/server  \
        -I$(top_srcdir)/server/parser  \

Index: testsuite/movies.all/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/testsuite/movies.all/Makefile.am,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- testsuite/movies.all/Makefile.am    19 Sep 2007 14:20:52 -0000      1.9
+++ testsuite/movies.all/Makefile.am    27 Sep 2007 23:59:57 -0000      1.10
@@ -39,6 +39,7 @@
 AM_CPPFLAGS = -I.. \
         -I$(top_srcdir)                \
         -I$(top_srcdir)/libbase \
+        -I$(top_srcdir)/libmedia \
         -I$(top_srcdir)/backend \
         -I$(top_srcdir)/server  \
         -I$(top_srcdir)/server/parser  \

Index: testsuite/samples/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/testsuite/samples/Makefile.am,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- testsuite/samples/Makefile.am       30 Jul 2007 22:45:42 -0000      1.20
+++ testsuite/samples/Makefile.am       27 Sep 2007 23:59:57 -0000      1.21
@@ -27,6 +27,7 @@
 AM_CPPFLAGS = -I.. \
         -I$(top_srcdir)                \
         -I$(top_srcdir)/libbase \
+        -I$(top_srcdir)/libmedia \
         -I$(top_srcdir)/backend \
         -I$(top_srcdir)/server  \
         -I$(top_srcdir)/server/parser  \

Index: utilities/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/utilities/Makefile.am,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -b -r1.57 -r1.58
--- utilities/Makefile.am       1 Jul 2007 10:55:15 -0000       1.57
+++ utilities/Makefile.am       27 Sep 2007 23:59:57 -0000      1.58
@@ -26,6 +26,7 @@
 GNASH_LIBS = \
        $(top_builddir)/server/libgnashserver.la \
        $(top_builddir)/libbase/libgnashbase.la \
+       $(top_builddir)/libmedia/libgnashmedia.la \
        $(top_builddir)/backend/libgnashbackend.la \
        $(top_builddir)/libamf/libgnashamf.la
 
@@ -52,6 +53,9 @@
         -I$(top_srcdir)/server \
         -I$(top_srcdir)/server/parser \
         -I$(top_srcdir)/server/vm \
+        -I$(top_srcdir)/libmedia \
+        -I$(top_srcdir)/libmedia/sdl \
+        -I$(top_srcdir)/libmedia/gst \
         -DLOCALEDIR=\"$(localedir)\" \
        $(BOOST_CFLAGS) \
         $(LIBXML_CFLAGS) \

Index: libmedia/AudioDecoder.h
===================================================================
RCS file: libmedia/AudioDecoder.h
diff -N libmedia/AudioDecoder.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/AudioDecoder.h     27 Sep 2007 23:59:52 -0000      1.1
@@ -0,0 +1,42 @@
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+//  $Id:
+
+#ifndef __AUDIODECODER_H__
+#define __AUDIODECODER_H__
+
+#include "MediaParser.h"
+#include "SoundInfo.h"
+
+namespace gnash {
+
+class AudioDecoder {
+       
+public:
+       AudioDecoder() {}
+       ~AudioDecoder() {}
+
+       virtual bool setup(AudioInfo* /*info*/) { return false; }
+       virtual bool setup(SoundInfo* /*info*/) { return false; }
+       virtual uint8_t* decode(uint8_t* /*input*/, uint32_t /*inputSize*/, 
uint32_t& /*outputSize*/, uint32_t& /*decodedData*/, bool /*parse*/) { return 
NULL; }
+
+};
+       
+} // gnash namespace
+
+#endif // __AUDIODECODER_H__

Index: libmedia/AudioDecoderNellymoser.cpp
===================================================================
RCS file: libmedia/AudioDecoderNellymoser.cpp
diff -N libmedia/AudioDecoderNellymoser.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/AudioDecoderNellymoser.cpp 27 Sep 2007 23:59:52 -0000      1.1
@@ -0,0 +1,823 @@
+// AudioDecoderNellymoser.cpp: Nellymoser decoding
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+// Original copyright notice:
+
+/*
+ * Copyright (c) 2007 a840bda5870ba11f19698ff6eb9581dfb0f95fa5,
+ *                    539459aeb7d425140b62a3ec7dbf6dc8e408a306, and
+ *                    520e17cd55896441042b14df2566a6eb610ed444
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "AudioDecoderNellymoser.h"
+#include "utility.h"
+#include <stdlib.h>
+#include <time.h>
+#include <math.h>
+
+namespace gnash {
+
+float nelly_neg_unpack_table[64] = {
+-0.0061359000, -0.0306748003, -0.0551952012, -0.0796824023, -0.1041216031,
+-0.1284981072, -0.1527972072, -0.1770042032, -0.2011045963, -0.2250839025,
+-0.2489275932, -0.2726213932, -0.2961508930, -0.3195019960, -0.3426606953,
+-0.3656130135, -0.3883450031, -0.4108431935, -0.4330937862, -0.4550836086,
+-0.4767991900, -0.4982276857, -0.5193560123, -0.5401715040, -0.5606616139,
+-0.5808140039, -0.6006165147, -0.6200572252, -0.6391243935, -0.6578066945,
+-0.6760926843, -0.6939715147, -0.7114322186, -0.7284644246, -0.7450578213,
+-0.7612023950, -0.7768884897, -0.7921066284, -0.8068475723, -0.8211025000,
+-0.8348628879, -0.8481202722, -0.8608669043, -0.8730949759, -0.8847970963,
+-0.8959661722, -0.9065957069, -0.9166790843, -0.9262102246, -0.9351835251,
+-0.9435935020, -0.9514350295, -0.9587035179, -0.9653943777, -0.9715039134,
+-0.9770280719, -0.9819638729, -0.9863080978, -0.9900581837, -0.9932119250,
+-0.9957674146, -0.9977231026, -0.9990776777, -0.9998306036
+};
+
+float nelly_huff_table[127] = {
+0.0000000000,
+
+-0.8472560048, 0.7224709988,
+
+-1.5247479677, -0.4531480074, 0.3753609955, 1.4717899561,
+
+-1.9822579622, -1.1929379702, -0.5829370022, -0.0693780035, 0.3909569979,
+0.9069200158, 1.4862740040, 2.2215409279,
+
+-2.3887870312, -1.8067539930, -1.4105420113, -1.0773609877, -0.7995010018,
+-0.5558109879, -0.3334020078, -0.1324490011, 0.0568020009, 0.2548770010,
+0.4773550034, 0.7386850119, 1.0443060398, 1.3954459429, 1.8098750114,
+2.3918759823,
+
+-2.3893830776, -1.9884680510, -1.7514040470, -1.5643119812, -1.3922129869,
+-1.2164649963, -1.0469499826, -0.8905100226, -0.7645580173, -0.6454579830,
+-0.5259280205, -0.4059549868, -0.3029719889, -0.2096900046, -0.1239869967,
+-0.0479229987, 0.0257730000, 0.1001340002, 0.1737180054, 0.2585540116,
+0.3522900045, 0.4569880068, 0.5767750144, 0.7003160119, 0.8425520062,
+1.0093879700, 1.1821349859, 1.3534560204, 1.5320819616, 1.7332619429,
+1.9722349644, 2.3978140354,
+
+
+-2.5756309032, -2.0573320389, -1.8984919786, -1.7727810144, -1.6662600040,
+-1.5742180347, -1.4993319511, -1.4316639900, -1.3652280569, -1.3000990152,
+-1.2280930281, -1.1588579416, -1.0921250582, -1.0135740042, -0.9202849865,
+-0.8287050128, -0.7374889851, -0.6447759867, -0.5590940118, -0.4857139885,
+-0.4110319912, -0.3459700048, -0.2851159871, -0.2341620028, -0.1870580018,
+-0.1442500055, -0.1107169986, -0.0739680007, -0.0365610011, -0.0073290002,
+0.0203610007, 0.0479039997, 0.0751969963, 0.0980999991, 0.1220389977,
+0.1458999962, 0.1694349945, 0.1970459968, 0.2252430022, 0.2556869984,
+0.2870100141, 0.3197099864, 0.3525829911, 0.3889069855, 0.4334920049,
+0.4769459963, 0.5204820037, 0.5644530058, 0.6122040153, 0.6685929894,
+0.7341650128, 0.8032159805, 0.8784040213, 0.9566209912, 1.0397069454,
+1.1293770075, 1.2211159468, 1.3080279827, 1.4024800062, 1.5056819916,
+1.6227730513, 1.7724959850, 1.9430880547, 2.2903931141
+};
+
+float nelly_pos_unpack_table[64] = {
+0.9999812245, 0.9995294213, 0.9984756112, 0.9968202710, 0.9945645928,
+0.9917098284, 0.9882575870, 0.9842100739, 0.9795697927, 0.9743394256,
+0.9685220718, 0.9621214271, 0.9551411867, 0.9475855827, 0.9394592047,
+0.9307669997, 0.9215139747, 0.9117059708, 0.9013488293, 0.8904486895,
+0.8790122271, 0.8670461774, 0.8545579910, 0.8415549994, 0.8280450106,
+0.8140363097, 0.7995373011, 0.7845566273, 0.7691032887, 0.7531868219,
+0.7368165851, 0.7200024724, 0.7027546763, 0.6850836873, 0.6669998765,
+0.6485143900, 0.6296381950, 0.6103827953, 0.5907596946, 0.5707806945,
+0.5504580140, 0.5298035741, 0.5088300705, 0.4875501990, 0.4659765065,
+0.4441221058, 0.4220002890, 0.3996241987, 0.3770073950, 0.3541634977,
+0.3311063051, 0.3078495860, 0.2844074965, 0.2607941031, 0.2370236069,
+0.2131102979, 0.1890687048, 0.1649131030, 0.1406581998, 0.1163185984,
+0.0919089988, 0.0674438998, 0.0429382995, 0.0184067003
+};
+
+int nelly_copy_count[23] = {
+2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 9, 10, 12, 14, 15
+};
+
+float nelly_signal_table[64] = {
+0.1250000000, 0.1249623969, 0.1248494014, 0.1246612966, 0.1243980974,
+0.1240599006, 0.1236471012, 0.1231596991, 0.1225982010, 0.1219628006,
+0.1212539002, 0.1204719990, 0.1196174994, 0.1186909974, 0.1176929995,
+0.1166241020, 0.1154849008, 0.1142762005, 0.1129987016, 0.1116530001,
+0.1102401987, 0.1087609008, 0.1072160974, 0.1056066975, 0.1039336994,
+0.1021981016, 0.1004009023, 0.0985433012, 0.0966262966, 0.0946511030,
+0.0926188976, 0.0905309021, 0.0883883014, 0.0861926004, 0.0839449018,
+0.0816465989, 0.0792991966, 0.0769039020, 0.0744623989, 0.0719759986,
+0.0694463030, 0.0668746978, 0.0642627999, 0.0616123006, 0.0589246005,
+0.0562013984, 0.0534444004, 0.0506552011, 0.0478353985, 0.0449868999,
+0.0421111993, 0.0392102003, 0.0362856016, 0.0333391018, 0.0303725004,
+0.0273876991, 0.0243862998, 0.0213702004, 0.0183412991, 0.0153013002,
+0.0122520998, 0.0091955997, 0.0061335000, 0.0030677000
+};
+
+short nelly_init_table[64] = {
+3134, 5342, 6870, 7792, 8569, 9185, 9744, 10191, 10631, 11061, 11434, 11770,
+12116, 12513, 12925, 13300, 13674, 14027, 14352, 14716, 15117, 15477, 15824,
+16157, 16513, 16804, 17090, 17401, 17679, 17948, 18238, 18520, 18764, 19078,
+19381, 19640, 19921, 20205, 20500, 20813, 21162, 21465, 21794, 22137, 22453,
+22756, 23067, 23350, 23636, 23926, 24227, 24521, 24819, 25107, 25414, 25730,
+26120, 26497, 26895, 27344, 27877, 28463, 29426, 31355
+};
+
+float nelly_state_table[128] = {
+0.0061359000, 0.0184067003, 0.0306748003, 0.0429382995, 0.0551952012,
+0.0674438998, 0.0796824023, 0.0919089988, 0.1041216031, 0.1163185984,
+0.1284981072, 0.1406581998, 0.1527972072, 0.1649131030, 0.1770042032,
+0.1890687048, 0.2011045963, 0.2131102979, 0.2250839025, 0.2370236069,
+0.2489275932, 0.2607941031, 0.2726213932, 0.2844074965, 0.2961508930,
+0.3078495860, 0.3195019960, 0.3311063051, 0.3426606953, 0.3541634977,
+0.3656130135, 0.3770073950, 0.3883450031, 0.3996241987, 0.4108431935,
+0.4220002890, 0.4330937862, 0.4441221058, 0.4550836086, 0.4659765065,
+0.4767991900, 0.4875501990, 0.4982276857, 0.5088300705, 0.5193560123,
+0.5298035741, 0.5401715040, 0.5504580140, 0.5606616139, 0.5707806945,
+0.5808140039, 0.5907596946, 0.6006165147, 0.6103827953, 0.6200572252,
+0.6296381950, 0.6391243935, 0.6485143900, 0.6578066945, 0.6669998765,
+0.6760926843, 0.6850836873, 0.6939715147, 0.7027546763, 0.7114322186,
+0.7200024724, 0.7284644246, 0.7368165851, 0.7450578213, 0.7531868219,
+0.7612023950, 0.7691032887, 0.7768884897, 0.7845566273, 0.7921066284,
+0.7995373011, 0.8068475723, 0.8140363097, 0.8211025000, 0.8280450106,
+0.8348628879, 0.8415549994, 0.8481202722, 0.8545579910, 0.8608669043,
+0.8670461774, 0.8730949759, 0.8790122271, 0.8847970963, 0.8904486895,
+0.8959661722, 0.9013488293, 0.9065957069, 0.9117059708, 0.9166790843,
+0.9215139747, 0.9262102246, 0.9307669997, 0.9351835251, 0.9394592047,
+0.9435935020, 0.9475855827, 0.9514350295, 0.9551411867, 0.9587035179,
+0.9621214271, 0.9653943777, 0.9685220718, 0.9715039134, 0.9743394256,
+0.9770280719, 0.9795697927, 0.9819638729, 0.9842100739, 0.9863080978,
+0.9882575870, 0.9900581837, 0.9917098284, 0.9932119250, 0.9945645928,
+0.9957674146, 0.9968202710, 0.9977231026, 0.9984756112, 0.9990776777,
+0.9995294213, 0.9998306036, 0.9999812245
+};
+
+short nelly_delta_table[32] = {
+-11725, -9420, -7910, -6801, -5948, -5233, -4599, -4039, -3507, -3030, -2596,
+-2170, -1774, -1383, -1016, -660, -329, -1, 337, 696, 1085, 1512, 1962, 2433,
+2968, 3569, 4314, 5279, 6622, 8154, 10076, 12975
+};
+
+float nelly_inv_dft_table[129] = {
+0.0000000000, 0.0122715384, 0.0245412290, 0.0368072242, 0.0490676723,
+0.0613207370, 0.0735645667, 0.0857973099, 0.0980171412, 0.1102222130,
+0.1224106774, 0.1345807165, 0.1467304677, 0.1588581353, 0.1709618866,
+0.1830398887, 0.1950903237, 0.2071113735, 0.2191012353, 0.2310581058,
+0.2429801822, 0.2548656464, 0.2667127550, 0.2785196900, 0.2902846932,
+0.3020059466, 0.3136817515, 0.3253102899, 0.3368898630, 0.3484186828,
+0.3598950505, 0.3713171780, 0.3826834261, 0.3939920366, 0.4052413106,
+0.4164295495, 0.4275550842, 0.4386162460, 0.4496113360, 0.4605387151,
+0.4713967443, 0.4821837842, 0.4928981960, 0.5035383701, 0.5141027570,
+0.5245896578, 0.5349976420, 0.5453249812, 0.5555702448, 0.5657318234,
+0.5758081675, 0.5857978463, 0.5956993103, 0.6055110693, 0.6152315736,
+0.6248595119, 0.6343932748, 0.6438315511, 0.6531728506, 0.6624158025,
+0.6715589762, 0.6806010008, 0.6895405650, 0.6983762383, 0.7071067691,
+0.7157308459, 0.7242470980, 0.7326542735, 0.7409511209, 0.7491363883,
+0.7572088242, 0.7651672959, 0.7730104327, 0.7807372212, 0.7883464098,
+0.7958369255, 0.8032075167, 0.8104572296, 0.8175848126, 0.8245893121,
+0.8314695954, 0.8382247090, 0.8448535800, 0.8513551950, 0.8577286005,
+0.8639728427, 0.8700869679, 0.8760700822, 0.8819212317, 0.8876396418,
+0.8932242990, 0.8986744881, 0.9039893150, 0.9091680050, 0.9142097831,
+0.9191138744, 0.9238795042, 0.9285060763, 0.9329928160, 0.9373390079,
+0.9415440559, 0.9456073046, 0.9495281577, 0.9533060193, 0.9569403529,
+0.9604305029, 0.9637760520, 0.9669764638, 0.9700312614, 0.9729399681,
+0.9757021070, 0.9783173800, 0.9807852507, 0.9831054807, 0.9852776527,
+0.9873014092, 0.9891765118, 0.9909026623, 0.9924795032, 0.9939069748,
+0.9951847196, 0.9963126183, 0.9972904325, 0.9981181026, 0.9987954497,
+0.9993223548, 0.9996988177, 0.9999247193, 1.0000000000
+};
+
+unsigned char nelly_center_table[64] = {
+0, 64, 32, 96, 16, 80, 48, 112, 8, 72, 40, 104, 24, 88, 56, 120,
+4, 68, 36, 100, 20, 84, 52, 116, 12, 76, 44, 108, 28, 92, 60, 124,
+2, 66, 34, 98, 18, 82, 50, 114, 10, 74, 42, 106, 26, 90, 58, 122,
+6, 70, 38, 102, 22, 86, 54, 118, 14, 78, 46, 110, 30, 94, 62, 126
+};
+
+static void center(float *audio)
+{
+       int i, j;
+       float ftmp;
+
+       for (i = 0; i < NELLY_BUF_LEN; i+=2) {
+               j = nelly_center_table[i/2];
+               if (j > i) {
+                       ftmp = audio[j];
+                       audio[j] = audio[i];
+                       audio[i] = ftmp;
+                       ftmp = audio[j+1];
+                       audio[j+1] = audio[i+1];
+                       audio[i+1] = ftmp;
+               }
+       }
+}
+
+static void inverse_dft(float *audio)
+{
+       int i, j, k, advance;
+       float *aptr, a, b, c, d, e, f;
+
+       aptr = audio;
+       for (i = 0; i < NELLY_BUF_LEN/4; i++) {
+               a = *aptr;
+               b = *(aptr+2);
+               c = *(aptr+1);
+               d = *(aptr+3);
+
+               *(aptr+2) = a-b;
+               *aptr = a+b;
+               *(aptr+3) = c-d;
+               *(aptr+1) = c+d;
+
+               aptr += 4;
+       }
+
+       aptr = audio;
+       for (i = 0; i < NELLY_BUF_LEN/8; i++) {
+               a = *aptr;
+               b = *(aptr+4);
+               c = *(aptr+1);
+               d = *(aptr+5);
+
+               *(aptr+4) = a-b;
+               *(aptr+5) = c-d;
+               *aptr = a+b;
+               *(aptr+1) = c+d;
+
+               aptr += 2;
+
+               a = *aptr;
+               b = *(aptr+5);
+               c = *(aptr+1);
+               d = *(aptr+4);
+
+               *(aptr+4) = a-b;
+               *aptr = a+b;
+               *(aptr+5) = c+d;
+               *(aptr+1) = c-d;
+
+               aptr += 6;
+       }
+
+       i = 0;
+       for (advance = 8; advance < NELLY_BUF_LEN; advance *= 2) {
+               aptr = audio;
+
+               for (k = 0; k < NELLY_BUF_LEN/(2*advance); k++) {
+                       for (j = 0; j < advance/4; j++) {
+                               a = nelly_inv_dft_table[128-i];
+                               b = *(aptr+advance);
+                               c = nelly_inv_dft_table[i];
+                               d = *(aptr+advance+1);
+                               e = *aptr;
+                               f = *(aptr+1);
+
+                               *(aptr+advance) = e-(a*b+c*d);
+                               *aptr = e+(a*b+c*d);
+                               *(aptr+advance+1) = f+(b*c-a*d);
+                               *(aptr+1) = f-(b*c-a*d);
+
+                               i += 512/advance;
+                               aptr += 2;
+                       }
+
+                       for (j = 0; j < advance/4; j++) {
+                               a = nelly_inv_dft_table[128-i];
+                               b = *(aptr+advance);
+                               c = nelly_inv_dft_table[i];
+                               d = *(aptr+advance+1);
+                               e = *aptr;
+                               f = *(aptr+1);
+
+                               *(aptr+advance) = e+(a*b-c*d);
+                               *aptr = e-(a*b-c*d);
+                               *(aptr+advance+1) = f+(a*d+b*c);
+                               *(aptr+1) = f-(a*d+b*c);
+
+                               i -= 512/advance;
+                               aptr += 2;
+                       }
+
+                       aptr += advance;
+               }
+       }
+}
+
+static void unpack_coeffs(float *buf, float *audio)
+{
+       int i, end, mid_hi, mid_lo;
+       float a, b, c, d, e, f;
+
+       end = NELLY_BUF_LEN-1;
+       mid_hi = NELLY_BUF_LEN/2;
+       mid_lo = mid_hi-1;
+
+       for (i = 0; i < NELLY_BUF_LEN/4; i++) {
+               a = buf[end-(2*i)];
+               b = buf[2*i];
+               c = buf[(2*i)+1];
+               d = buf[end-(2*i)-1];
+               e = nelly_pos_unpack_table[i];
+               f = nelly_neg_unpack_table[i];
+
+               audio[2*i] = b*e-a*f;
+               audio[(2*i)+1] = a*e+b*f;
+
+               a = nelly_neg_unpack_table[mid_lo-i];
+               b = nelly_pos_unpack_table[mid_lo-i];
+
+               audio[end-(2*i)-1] = b*d-a*c;
+               audio[end-(2*i)] = b*c+a*d;
+       }
+}
+
+static void complex2signal(float *audio)
+{
+       int i, end, mid_hi, mid_lo;
+       float *aptr, *sigptr, a, b, c, d, e, f, g;
+
+       end = NELLY_BUF_LEN-1;
+       mid_hi = NELLY_BUF_LEN/2;
+       mid_lo = mid_hi-1;
+
+       a = audio[end];
+       b = audio[end-1];
+       c = audio[1];
+       d = nelly_signal_table[0];
+       e = audio[0];
+       f = nelly_signal_table[mid_lo];
+       g = nelly_signal_table[1];
+
+       audio[0] = d*e;
+       audio[1] = b*g-a*f;
+       audio[end-1] = a*g+b*f;
+       audio[end] = c*(-d);
+
+       aptr = audio+end-2;
+       sigptr = nelly_signal_table+mid_hi-1;
+
+       for (i = 3; i < NELLY_BUF_LEN/2; i += 2) {
+               a = audio[i-1];
+               b = audio[i];
+               c = nelly_signal_table[i/2];
+               d = *sigptr;
+               e = *(aptr-1);
+               f = *aptr;
+
+               audio[i-1] = a*c+b*d;
+               *aptr = a*d-b*c;
+
+               a = nelly_signal_table[(i/2)+1];
+               b = *(sigptr-1);
+
+               *(aptr-1) = b*e+a*f;
+               audio[i] = a*e-b*f;
+
+               sigptr--;
+               aptr -= 2;
+       }
+}
+
+static void apply_state(float *state, float *audio)
+{
+       int bot, mid_up, mid_down, top;
+       float s_bot, s_top;
+       float *t = nelly_state_table;
+
+       bot = 0;
+       top = NELLY_BUF_LEN-1;
+       mid_up = NELLY_BUF_LEN/2;
+       mid_down = (NELLY_BUF_LEN/2)-1;
+
+       while (bot < NELLY_BUF_LEN/4) {
+               s_bot = audio[bot];
+               s_top = audio[top];
+
+               audio[bot] = audio[mid_up]*t[bot]+state[bot]*t[top];
+               audio[top] = state[bot]*t[bot]-audio[mid_up]*t[top];
+               state[bot] = -audio[mid_down];
+
+               audio[mid_down] = s_top*t[mid_down]+state[mid_down]*t[mid_up];
+               audio[mid_up] = state[mid_down]*t[mid_down]-s_top*t[mid_up];
+               state[mid_down] = -s_bot;
+
+               bot++;
+               mid_up++;
+               mid_down--;
+               top--;
+       }
+}
+
+static int sum_bits(short *buf, short shift, short off)
+{
+       int b, i = 0, ret = 0;
+
+       for (i = 0; i < NELLY_FILL_LEN; i++) {
+               b = buf[i] - off;
+               if (b < 0)
+                       b = 0;
+               b = ((b>>(shift-1))+1)>>1;
+               if (b > NELLY_BIT_CAP)
+                       ret += NELLY_BIT_CAP;
+               else
+                       ret += b;
+       }
+
+       return ret;
+}
+
+static int headroom(int *la, short *sa)
+{
+       if (*la == 0)
+               *sa += 31;
+       else if (*la < 0) {
+               while (*la > -1<<30) {
+                       *la <<= 1;
+                       (*sa)++;
+               }
+       } else {
+               while (*la < 1<<30) {
+                       *la <<= 1;
+                       (*sa)++;
+               }
+       }
+
+       return *la;
+}
+
+static void get_sample_bits(float *buf, int *bits)
+{
+       int i, j;
+       short sbuf[128];
+       int bitsum = 0, last_bitsum, small_bitsum, big_bitsum;
+       short shift, shift_saved;
+       int tmp;
+       int big_off;
+       int off, diff;
+
+       tmp = 0;
+       for (i = 0; i < NELLY_FILL_LEN; i++) {
+               if (buf[i] > tmp)
+                       tmp = buf[i];
+       }
+       shift = -16;
+       headroom(&tmp, &shift);
+
+       if (shift < 0)
+               for (i = 0; i < NELLY_FILL_LEN; i++)
+                       sbuf[i] = ((int)buf[i]) >> -shift;
+       else
+               for (i = 0; i < NELLY_FILL_LEN; i++)
+                       sbuf[i] = ((int)buf[i]) << shift;
+
+       for (i = 0; i < NELLY_FILL_LEN; i++)
+               sbuf[i] = (3*sbuf[i])>>2;
+
+       tmp = 0;
+       for (i = 0; i < NELLY_FILL_LEN; i++)
+               tmp += sbuf[i];
+
+       shift += 11;
+       shift_saved = shift;
+       tmp -= NELLY_DETAIL_BITS << shift;
+       headroom(&tmp, &shift);
+       off = (NELLY_BASE_OFF * (tmp>>16)) >> 15;
+       shift = shift_saved - (NELLY_BASE_SHIFT+shift-31);
+
+       if (shift < 0)
+               off >>= -shift;
+       else
+               off <<= shift;
+
+       bitsum = sum_bits(sbuf, shift_saved, off);
+
+       if (bitsum != NELLY_DETAIL_BITS) {
+               shift = 0;
+               diff = bitsum - NELLY_DETAIL_BITS;
+
+               if (diff > 0) {
+                       while (diff <= 16383) {
+                               shift++;
+                               diff *= 2;
+                       }
+               } else {
+                       while (diff >= -16383) {
+                               shift++;
+                               diff *= 2;
+                       }
+               }
+
+               diff = (diff * NELLY_BASE_OFF) >> 15;
+               shift = shift_saved-(NELLY_BASE_SHIFT+shift-15);
+
+               if (shift > 0) {
+                       diff <<= shift;
+               } else {
+                       diff >>= -shift;
+               }
+
+               for (j = 1; j < 20; j++) {
+                       tmp = off;
+                       off += diff;
+                       last_bitsum = bitsum;
+
+                       bitsum = sum_bits(sbuf, shift_saved, off);
+
+                       if ((bitsum-NELLY_DETAIL_BITS) * 
(last_bitsum-NELLY_DETAIL_BITS) <= 0)
+                               break;
+               }
+
+               if (bitsum != NELLY_DETAIL_BITS) {
+                       if (bitsum > NELLY_DETAIL_BITS) {
+                               big_off = off;
+                               off = tmp;
+                               big_bitsum=bitsum;
+                               small_bitsum=last_bitsum;
+                       } else {
+                               big_off = tmp;
+                               big_bitsum=last_bitsum;
+                               small_bitsum=bitsum;
+                       }
+
+                       while (bitsum != NELLY_DETAIL_BITS && j <= 19) {
+                               diff = (big_off+off)>>1;
+                               bitsum = sum_bits(sbuf, shift_saved, diff);
+                               if (bitsum > NELLY_DETAIL_BITS) {
+                                       big_off=diff;
+                                       big_bitsum=bitsum;
+                               } else {
+                                       off = diff;
+                                       small_bitsum=bitsum;
+                               }
+                               j++;
+                       }
+
+                       if (abs(big_bitsum-NELLY_DETAIL_BITS) >=
+                           abs(small_bitsum-NELLY_DETAIL_BITS)) {
+                               bitsum = small_bitsum;
+                       } else {
+                               off = big_off;
+                               bitsum = big_bitsum;
+                       }
+
+               }
+       }
+
+       for (i = 0; i < NELLY_FILL_LEN; i++) {
+               tmp = sbuf[i]-off;
+               if (tmp < 0)
+                       tmp = 0;
+               else
+                       tmp = ((tmp>>(shift_saved-1))+1)>>1;
+
+               if (tmp > NELLY_BIT_CAP)
+                       tmp = NELLY_BIT_CAP;
+               bits[i] = tmp;
+       }
+
+       if (bitsum > NELLY_DETAIL_BITS) {
+               tmp = i = 0;
+               while (tmp < NELLY_DETAIL_BITS) {
+                       tmp += bits[i];
+                       i++;
+               }
+
+               tmp -= bits[i-1];
+               bits[i-1] = NELLY_DETAIL_BITS-tmp;
+               bitsum = NELLY_DETAIL_BITS;
+               while (i < NELLY_FILL_LEN) {
+                       bits[i] = 0;
+                       i++;
+               }
+       }
+}
+
+static unsigned char get_bits(unsigned char block[NELLY_BLOCK_LEN], int *off, 
int n)
+{
+       char ret;
+       int boff = *off/8, bitpos = *off%8, mask = (1<<n)-1;
+
+       if (bitpos+n > 8) {
+               ret = block[boff%NELLY_BLOCK_LEN] >> bitpos;
+               mask >>= 8-bitpos;
+               ret |= (block[(boff+1)%NELLY_BLOCK_LEN] & mask) << (8-bitpos);
+       } else {
+               ret = (block[boff%NELLY_BLOCK_LEN] >> bitpos) & mask;
+       }
+       
+       *off += n;
+       return ret;
+}
+
+static void nelly_decode_block(nelly_handle* nh, unsigned char 
block[NELLY_BLOCK_LEN], float audio[256])
+{
+       int i,j;
+       float buf[NELLY_BUF_LEN], pows[NELLY_BUF_LEN];
+       float *aptr, *bptr, *pptr, val, pval;
+       int bits[NELLY_BUF_LEN];
+       unsigned char v;
+       int bit_offset = 0;
+
+       bptr = buf;
+       pptr = pows;
+       val = nelly_init_table[get_bits(block, &bit_offset, 6)];
+       for (i = 0; i < 23; i++) {
+               if (i > 0)
+                       val += nelly_delta_table[get_bits(block, &bit_offset, 
5)];
+               pval = pow(2, val/2048);
+               for (j = 0; j < nelly_copy_count[i]; j++) {
+                       *bptr = val;
+                       *pptr = pval;
+                       bptr++;
+                       pptr++;
+               }
+
+       }
+
+       for (i = NELLY_FILL_LEN; i < NELLY_BUF_LEN; i++)
+               buf[i] = pows[i] = 0.0;
+
+       get_sample_bits(buf, bits);
+
+       for (i = 0; i < 2; i++) {
+               aptr = audio+i*128;
+               bit_offset = NELLY_HEADER_BITS + i*NELLY_DETAIL_BITS;
+
+               for (j = 0; j < NELLY_FILL_LEN; j++) {
+                       if (bits[j] <= 0) {
+                               buf[j] = M_SQRT1_2*pows[j];
+                               if (random() % 2)
+                                       buf[j] *= -1.0;
+                       } else {
+                               v = get_bits(block, &bit_offset, bits[j]);
+                               buf[j] = 
nelly_huff_table[(1<<bits[j])-1+v]*pows[j];
+                       }
+               }
+
+               unpack_coeffs(buf, aptr);
+               center(aptr);
+               inverse_dft(aptr);
+               complex2signal(aptr);
+               apply_state(nh->state, aptr);
+       }
+}
+
+static void nelly_util_floats2shorts(float audio[256], short shorts[256])
+{
+       int i;
+
+       for (i = 0; i < 256; i++) {
+               if (audio[i] >= 32767.0)
+                       shorts[i] = 32767;
+               else if (audio[i] <= -32768.0)
+                       shorts[i] = -32768;
+               else
+                       shorts[i] = (short)audio[i];
+       }
+}
+
+static nelly_handle *nelly_get_handle()
+{
+       static int first = 1;
+       int i;
+       nelly_handle *nh;
+
+       if (first) {
+               srandom(time(NULL));
+               first = 0;
+       }
+
+       nh = new nelly_handle;
+
+       if (nh != NULL)
+               for (i = 0; i < 64; i++)
+                       nh->state[i] = 0.0;
+
+       return nh;
+}
+
+static void nelly_free_handle(nelly_handle *nh)
+{
+       delete nh;
+}
+       
+AudioDecoderNellymoser::AudioDecoderNellymoser ()
+       :
+       _sampleRate(0),
+       _stereo(false)
+{
+       _nh = nelly_get_handle();
+}
+
+AudioDecoderNellymoser::~AudioDecoderNellymoser()
+{
+       nelly_free_handle(_nh);
+}
+
+bool AudioDecoderNellymoser::setup(SoundInfo* info)
+{
+       if (info->getFormat() == AUDIO_CODEC_NELLYMOSER || info->getFormat() == 
AUDIO_CODEC_NELLYMOSER_8HZ_MONO) {
+               _sampleRate = info->getSampleRate();
+               _stereo = info->isStereo();
+               return true;
+       } else {
+               return false;
+       }
+}
+
+bool AudioDecoderNellymoser::setup(AudioInfo* info)
+{
+       if (info->type == FLASH && (info->codec == AUDIO_CODEC_NELLYMOSER || 
info->codec == AUDIO_CODEC_NELLYMOSER_8HZ_MONO)) {
+               _sampleRate = info->sampleRate;
+               _stereo = info->stereo;
+               return true;
+       } else {
+               return false;
+       }
+}
+
+
+uint8_t* AudioDecoderNellymoser::decode(uint8_t* input, uint32_t inputSize, 
uint32_t& outputSize, uint32_t& decodedBytes, bool /*parse*/)
+{
+
+       float float_buf[256];
+       uint32_t out_buf_size = (inputSize / 64) * 256;
+       int16_t* out_buf = new int16_t[out_buf_size];
+       int16_t* out_buf_start = out_buf;
+
+       while (inputSize > 0) {
+               nelly_decode_block(_nh, input, float_buf);
+               nelly_util_floats2shorts(float_buf, out_buf);
+               out_buf += 256;
+               input += 64;
+               inputSize -= 64;
+       }
+                       
+       uint8_t* tmp_raw_buffer = reinterpret_cast<uint8_t*>(out_buf_start);
+       uint32_t tmp_raw_buffer_size = out_buf_size * 2;
+
+       // If we need to convert samplerate or/and from mono to stereo...
+       if (out_buf_size > 0 && (_sampleRate != 44100 || !_stereo)) {
+
+               int16_t* adjusted_data = 0;
+               int     adjusted_size = 0;
+               int sample_count = out_buf_size / (_stereo ? 2 : 1);
+
+               // Convert to needed samplerate - this converter only support 
standard flash samplerates
+               convert_raw_data(&adjusted_data, &adjusted_size, 
tmp_raw_buffer, sample_count, 0, 
+                               _sampleRate, _stereo,
+                               44100,  true /* stereo */);
+
+               // Hopefully this wont happen
+               if (!adjusted_data) {
+                       log_error(_("Error in sound sample conversion"));
+                       delete[] tmp_raw_buffer;
+                       outputSize = 0;
+                       decodedBytes = 0;
+                       return NULL;
+               }
+
+               // Move the new data to the sound-struct
+               delete[] tmp_raw_buffer;
+               tmp_raw_buffer = reinterpret_cast<uint8_t*>(adjusted_data);
+               tmp_raw_buffer_size = adjusted_size;
+
+       } else {
+               tmp_raw_buffer_size = out_buf_size;
+       }
+
+       outputSize = tmp_raw_buffer_size;
+       decodedBytes = inputSize;
+       return tmp_raw_buffer;
+}
+
+} // namespace gnash
+

Index: libmedia/AudioDecoderNellymoser.h
===================================================================
RCS file: libmedia/AudioDecoderNellymoser.h
diff -N libmedia/AudioDecoderNellymoser.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/AudioDecoderNellymoser.h   27 Sep 2007 23:59:52 -0000      1.1
@@ -0,0 +1,96 @@
+// AudioDecoderNellymoser.h: Nellymoser decoding
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+//  $Id:
+
+// Original copyright notice:
+
+/*
+ * Copyright (c) 2007 a840bda5870ba11f19698ff6eb9581dfb0f95fa5,
+ *                    539459aeb7d425140b62a3ec7dbf6dc8e408a306, and
+ *                    520e17cd55896441042b14df2566a6eb610ed444
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __AUDIODECODERNELLYMOSER_H__
+#define __AUDIODECODERNELLYMOSER_H__
+
+#include "log.h"
+#include "AudioDecoder.h"
+
+#define NELLY_BLOCK_LEN 64
+#define NELLY_HEADER_BITS 116
+#define NELLY_DETAIL_BITS 198
+#define NELLY_BUF_LEN 128
+#define NELLY_FILL_LEN 124
+#define NELLY_BIT_CAP 6
+#define NELLY_BASE_OFF 4228
+#define NELLY_BASE_SHIFT 19
+
+
+
+typedef struct nelly_handle_struct {
+       float state[64];
+} nelly_handle;
+
+namespace gnash {
+
+class AudioDecoderNellymoser : public AudioDecoder {
+
+public:
+       AudioDecoderNellymoser();
+       ~AudioDecoderNellymoser();
+
+       bool setup(AudioInfo* info);
+       bool setup(SoundInfo* info);
+
+       uint8_t* decode(uint8_t* input, uint32_t inputSize, uint32_t& 
outputSize, uint32_t& decodedBytes, bool parse);
+
+private:
+
+       // The handle used by the decoder
+       nelly_handle* _nh;
+
+       // samplerate
+       uint16_t _sampleRate;
+
+       // stereo
+       bool _stereo;
+};
+       
+} // gnash namespace
+
+#endif // __AUDIODECODERNELLYMOSER_H__
+       

Index: libmedia/AudioDecoderSimple.cpp
===================================================================
RCS file: libmedia/AudioDecoderSimple.cpp
diff -N libmedia/AudioDecoderSimple.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/AudioDecoderSimple.cpp     27 Sep 2007 23:59:53 -0000      1.1
@@ -0,0 +1,541 @@
+// AudioDecoderSimple.cpp: Audio decoding using "simple" internal decoders.
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include <boost/scoped_array.hpp>
+
+#include "AudioDecoderSimple.h"
+#include "utility.h"
+
+namespace gnash {
+
+class BitReader 
+{
+public:
+       typedef unsigned char byte;
+
+       /// Ownership of buffer left to caller
+       BitReader(byte* input, size_t len)
+               :
+               start(input),
+               ptr(input),
+               end(ptr+len),
+               usedBits(0)
+       {
+       }
+
+       ~BitReader() {}
+
+       /// Set a new buffer to work with
+       void setBuffer(byte* input, size_t len)
+       {
+               start = ptr = input;
+               end = start+len;
+               usedBits = 0;
+       }
+
+       bool read_bit()
+       {
+               bool ret = (*ptr&(128>>usedBits));
+               if ( ++usedBits == 8 ) advanceToNextByte();
+               return ret;
+       }
+
+       unsigned int read_uint(unsigned short bitcount)
+       {
+               assert(bitcount <= 32);
+
+               uint32_t value = 0;
+
+               unsigned short bits_needed = bitcount;
+               do
+               {
+                       int unusedMask = 0xFF >> usedBits;
+                       int unusedBits = 8-usedBits;
+
+                       if (bits_needed == unusedBits)
+                       {
+                               // Consume all the unused bits.
+                               value |= (*ptr&unusedMask);
+                               advanceToNextByte();
+                               break;
+
+                       }
+                       else if (bits_needed > unusedBits)
+                       {
+                               // Consume all the unused bits.
+
+                               bits_needed -= unusedBits; // 
assert(bits_needed>0)
+
+                               value |= ((*ptr&unusedMask) << bits_needed);
+                               advanceToNextByte();
+                       }
+                       else
+                       {
+                               assert(bits_needed <= unusedBits);
+
+                               // Consume some of the unused bits.
+
+                               unusedBits -= bits_needed;
+
+                               value |= ((*ptr&unusedMask) >> unusedBits);
+
+                               usedBits += bits_needed;
+                               if ( usedBits >= 8 ) advanceToNextByte();
+
+                               // We're done.
+                               break;
+                       }
+               }
+               while (bits_needed > 0);
+
+               return value;
+
+       }
+
+
+       int32_t read_sint(unsigned short bitcount)
+       {
+               int32_t value = int32_t(read_uint(bitcount));
+
+               // Sign extend...
+               if (value & (1 << (bitcount - 1))) 
+                       value |= -1 << bitcount;
+
+               return value;
+       }
+
+
+private:
+
+       void advanceToNextByte()
+       {
+               if ( ++ptr == end )
+               {
+                       log_debug("Going round");
+                       ptr=start;
+               }
+               usedBits=0;
+       }
+
+       /// Pointer to first byte
+       byte* start;
+
+       /// Pointer to current byte
+       byte* ptr;
+
+       /// Pointer to one past last byte
+       byte* end;
+
+       /// Number of used bits in current byte
+       unsigned usedBits;
+
+};
+
+// ----------------------------------------------------------------------------
+// ADPCMDecoder class
+// ----------------------------------------------------------------------------
+
+/// ADPCM decoder utilities
+//
+/// Algo from 
http://www.circuitcellar.com/pastissues/articles/richey110/text.htm
+/// And also Jansen.
+/// Here's another reference: 
http://www.geocities.com/SiliconValley/8682/aud3.txt
+/// Original IMA spec doesn't seem to be on the web :(
+///
+/// TODO: move in it's own file
+///
+class ADPCMDecoder {
+
+private:
+
+       // Data from Alexis' SWF reference
+       static int _index_update_table_2bits[2];
+       static int _index_update_table_3bits[4];
+       static int _index_update_table_4bits[8];
+       static int _index_update_table_5bits[16];
+
+       static int* s_index_update_tables[4];
+
+       // Data from Jansen.  http://homepages.cwi.nl/~jack/
+       // Check out his Dutch retro punk songs, heh heh :)
+       static const int STEPSIZE_CT = 89;
+       static int s_stepsize[STEPSIZE_CT];
+
+
+       static void doSample(int n_bits, int& sample, int& stepsize_index, int 
raw_code)
+       {
+               assert(raw_code >= 0 && raw_code < (1 << n_bits));              
                                                
+                                                                               
                                                
+               static const int        HI_BIT = (1 << (n_bits - 1));           
                                                
+               int*    index_update_table = s_index_update_tables[n_bits - 2]; 
                                                
+                                                                               
                                                
+               /* Core of ADPCM. */                                            
                                                
+                                                                               
                                                
+               int     code_mag = raw_code & (HI_BIT - 1);                     
                                                
+               bool    code_sign_bit = (raw_code & HI_BIT) ? 1 : 0;            
                                                
+               int     mag = (code_mag << 1) + 1;      /* shift in LSB (they 
do this so that pos & neg zero are different)*/   
+                                                                               
                                                
+               int     stepsize = s_stepsize[stepsize_index];                  
                                                
+                                                                               
                                                
+               /* Compute the new sample.  It's the predicted value            
        */                                      
+               /* (i.e. the previous value), plus a delta.  The delta          
        */                                      
+               /* comes from the code times the stepsize.  going for           
        */                                      
+               /* something like: delta = stepsize * (code * 2 + 1) >> 
code_bits       */                                      
+               int     delta = (stepsize * mag) >> (n_bits - 1);               
                                                
+               if (code_sign_bit) delta = -delta;                              
                                                
+                                                                               
                                                
+               sample += delta;                                                
                                                
+               sample = iclamp(sample, -32768, 32767);                         
                                                
+                                                                               
                                                
+               /* Update our stepsize index.  Use a lookup table. */           
                                                
+               stepsize_index += index_update_table[code_mag];                 
                                                
+               stepsize_index = iclamp(stepsize_index, 0, STEPSIZE_CT - 1);    
                                                
+       }
+
+       /* Uncompress 4096 mono samples of ADPCM. */                            
                                        
+       static void doMonoBlock(int16_t** out_data, int n_bits, int 
sample_count, BitReader* in, int sample, int stepsize_index)
+       {
+               /* First sample doesn't need to be decompressed. */             
                                                
+               sample_count--;                                                 
                                                
+               *(*out_data)++ = (int16_t) sample;                              
                                                
+                                                                               
                                                
+               while (sample_count--)                                          
                                                
+               {                                                               
                                                
+                       int     raw_code = in->read_uint(n_bits);               
                                                
+                       doSample(n_bits, sample, stepsize_index, raw_code);     
/* sample & stepsize_index are in/out params */ 
+                       *(*out_data)++ = (int16_t) sample;                      
                                                
+               }                                                               
                                                
+       }
+
+
+       /* Uncompress 4096 stereo sample pairs of ADPCM. */                     
                                                
+       static void doStereoBlock(
+                       int16_t** out_data,     // in/out param
+                       int n_bits,
+                       int sample_count,
+                       BitReader* in,
+                       int left_sample,
+                       int left_stepsize_index,
+                       int right_sample,
+                       int right_stepsize_index
+                       )
+       {
+               /* First samples don't need to be decompressed. */              
                                                
+               sample_count--;                                                 
                                                
+               *(*out_data)++ = (int16_t) left_sample;                         
                                                
+               *(*out_data)++ = (int16_t) right_sample;                        
                                                        
+                                                                               
                                                
+               while (sample_count--)                                          
                                                
+               {                                                               
                                                
+                       int     left_raw_code = in->read_uint(n_bits);          
                                                
+                       doSample(n_bits, left_sample, left_stepsize_index, 
left_raw_code);                                      
+                       *(*out_data)++ = (int16_t) left_sample;                 
                                                
+                                                                               
                                                
+                       int     right_raw_code = in->read_uint(n_bits);         
                                                
+                       doSample(n_bits, right_sample, right_stepsize_index, 
right_raw_code);                                   
+                       *(*out_data)++ = (int16_t) right_sample;                
                                                        
+               }                                                               
                                                
+       }
+
+public:
+
+       // Utility function: uncompress ADPCM data from in BitReader to
+       // out_data[].  The output buffer must have (sample_count*2)
+       // bytes for mono, or (sample_count*4) bytes for stereo.
+       static void adpcm_expand(
+               unsigned char* &data,
+               BitReader* in,
+               unsigned int sample_count,      // in stereo, this is number of 
*pairs* of samples
+               bool stereo)
+       {
+               int16_t* out_data = new int16_t[stereo ? sample_count*2 : 
sample_count];
+               data = reinterpret_cast<unsigned char *>(out_data);
+
+               // Read header.
+               //in->ensureBytes(1); // nbits
+               unsigned int n_bits = in->read_uint(2) + 2;     // 2 to 5 bits 
(TODO: use unsigned...)
+
+               while (sample_count)
+               {
+                       // Read initial sample & index values.
+
+                       int     sample = in->read_sint(16);
+
+                       int     stepsize_index = in->read_uint(6);
+                       assert(STEPSIZE_CT >= (1 << 6));        // ensure we 
don't need to clamp.
+
+                       int     samples_this_block = imin(sample_count, 4096);
+                       sample_count -= samples_this_block;
+
+                       if (stereo == false)
+                       {
+#define DO_MONO(n) doMonoBlock(&out_data, n, samples_this_block, in, sample, 
stepsize_index)
+
+                               switch (n_bits)
+                               {
+                               default: assert(0); break;
+                               case 2: DO_MONO(2); break;
+                               case 3: DO_MONO(3); break;
+                               case 4: DO_MONO(4); break;
+                               case 5: DO_MONO(5); break;
+                               }
+                       }
+                       else
+                       {
+                               // Stereo.
+
+                               // Got values for left channel; now get initial 
sample
+                               // & index for right channel.
+                               int     right_sample = in->read_sint(16);
+
+                               int     right_stepsize_index = in->read_uint(6);
+                               assert(STEPSIZE_CT >= (1 << 6));        // 
ensure we don't need to clamp.
+
+#define DO_STEREO(n)                                   \
+               doStereoBlock(                          \
+                       &out_data, n, samples_this_block,       \
+                       in, sample, stepsize_index,             \
+                       right_sample, right_stepsize_index)
+                               
+                               switch (n_bits)
+                               {
+                               default: assert(0); break;
+                               case 2: DO_STEREO(2); break;
+                               case 3: DO_STEREO(3); break;
+                               case 4: DO_STEREO(4); break;
+                               case 5: DO_STEREO(5); break;
+                               }
+                       }
+               }
+
+       }
+
+};
+
+int ADPCMDecoder::_index_update_table_2bits[2] = { -1,  2 };
+int ADPCMDecoder::_index_update_table_3bits[4] = { -1, -1,  2,  4 };
+int ADPCMDecoder::_index_update_table_4bits[8] = { -1, -1, -1, -1,  2,  4,  6, 
 8 };
+int ADPCMDecoder::_index_update_table_5bits[16] = { -1, -1, -1, -1, -1, -1, 
-1, -1, 1,  2,  4,  6,  8, 10, 13, 16 };
+
+int* ADPCMDecoder::s_index_update_tables[4] = {
+       ADPCMDecoder::_index_update_table_2bits,
+       ADPCMDecoder::_index_update_table_3bits,
+       ADPCMDecoder::_index_update_table_4bits,
+       ADPCMDecoder::_index_update_table_5bits
+};
+
+int ADPCMDecoder::s_stepsize[STEPSIZE_CT] = {
+       7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+       19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+       50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+       130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+       337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+       876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+       2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+       5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+       15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+};
+
+// ----------------------------------------------------------------------------
+// END OF ADPCMDecoder class
+// ----------------------------------------------------------------------------
+
+//
+// Unsigned 8-bit expansion (128 is silence)
+//
+// u8_expand allocates the memory for its "data" pointer.
+//
+
+static void u8_expand(
+       unsigned char * &data,
+       unsigned char* input,
+       uint32_t input_size) // This is also the number of u8bit samples
+{
+       boost::scoped_array<uint8_t> in_data ( new uint8_t[input_size] );
+       int16_t *out_data = new int16_t[input_size];
+
+       memcpy((char *)in_data.get(), input, input_size);
+
+       // Convert 8-bit to 16
+       uint8_t *inp = in_data.get();
+       int16_t *outp = out_data;
+       for (unsigned int i = input_size; i>0; i--) {
+               *outp++ = ((int16_t)(*inp++) - 128) * 256;
+       }
+       
+       data = (unsigned char *)out_data;
+}
+
+
+AudioDecoderSimple::AudioDecoderSimple ()
+       :
+       _sampleRate(0),
+       _sampleCount(0),
+       _stereo(false),
+       _is16bit(true)
+{
+}
+
+AudioDecoderSimple::~AudioDecoderSimple()
+{
+
+}
+
+bool AudioDecoderSimple::setup(SoundInfo* info)
+{
+       if (info->getFormat() == AUDIO_CODEC_ADPCM || info->getFormat() == 
AUDIO_CODEC_RAW || info->getFormat() == AUDIO_CODEC_UNCOMPRESSED) {
+               _codec = info->getFormat();
+               _sampleRate = info->getSampleRate();
+               _sampleCount = info->getSampleCount();
+               _stereo = info->isStereo();
+               _is16bit = info->is16bit();
+               return true;
+       }
+       return false;
+}
+
+bool AudioDecoderSimple::setup(AudioInfo* info)
+{
+       if (info->type == FLASH && (info->codec == AUDIO_CODEC_ADPCM || 
info->codec == AUDIO_CODEC_RAW || info->codec == AUDIO_CODEC_UNCOMPRESSED)) {
+               _codec = static_cast<audioCodecType>(info->codec);
+               _sampleRate = info->sampleRate;
+               _stereo = info->stereo;
+               _is16bit = true; // Fix this?
+               return true;
+       } else {
+               return false;
+       }
+}
+
+uint8_t* AudioDecoderSimple::decode(uint8_t* input, uint32_t inputSize, 
uint32_t& outputSize, uint32_t& decodedBytes, bool /*parse*/)
+{
+
+       unsigned char* decodedData = NULL;
+       int outsize = 0;
+
+    switch (_codec) {
+       case AUDIO_CODEC_ADPCM:
+               {
+               uint32_t sample_count = inputSize * ( _stereo ? 1 : 2 ); 
//(_sampleCount == 0 ? inputSize / ( _stereo ? 4 : 2 ) : _sampleCount);
+               ADPCMDecoder::adpcm_expand(decodedData, new 
BitReader(input,inputSize), sample_count, _stereo);
+               outsize = sample_count * (_stereo ? 4 : 2);
+               }
+               break;
+       case AUDIO_CODEC_RAW:
+               if (_is16bit) {
+                       // FORMAT_RAW 16-bit is exactly what we want!
+                       decodedData = new unsigned char[inputSize];
+                       memcpy(decodedData, input, inputSize);
+                       outsize = inputSize;
+               } else {
+                       // Convert 8-bit signed to 16-bit range
+                       // Allocate as many shorts as there are samples
+                       u8_expand(decodedData, input, inputSize);
+                       outsize = inputSize * (_stereo ? 4 : 2);
+               }
+               break;
+       case AUDIO_CODEC_UNCOMPRESSED:
+               // 8- or 16-bit mono or stereo little-endian audio
+               // Convert to 16-bit host-endian.
+               if (!_is16bit)
+               {
+                       // Convert 8-bit signed to 16-bit range
+                       // Allocate as many shorts as there are 8-bit samples
+                       u8_expand(decodedData, input, inputSize);
+                       outsize = inputSize * (_stereo ? 4 : 2);
+
+               } else {
+                       // Read 16-bit data into buffer
+                       decodedData = new unsigned char[inputSize];
+                       memcpy((char *)decodedData, input, inputSize);
+
+                       // Convert 16-bit little-endian data to host-endian.
+
+                       // Runtime detection of host endianness costs almost
+                       // nothing and is less of a continual maintenance 
headache
+                       // than compile-time detection.
+                       union u {
+                               uint16_t s;
+                               struct {
+                                       uint8_t c0;
+                                       uint8_t c1;
+                               } c;
+                       } u = { 0x0001 };
+
+                       switch (u.c.c0) {
+                               case 0x01:      // Little-endian host: sample 
is already native.
+                                       break;
+                               case 0x00:  // Big-endian host
+                                       // Swap sample bytes to get big-endian 
format.
+                                       assert(inputSize & 1 == 0);
+                                       for (unsigned i = 0; i < inputSize; 
i+=2)
+                                       {
+                                               swap(&decodedData[i], 
&decodedData[i+1]);
+                                       }
+                                       break;
+                       default:        // Impossible
+                                       log_error(_("Host endianness not 
detected in AudioDecoderSimple"));
+                                       // Just carry on anyway...
+                       }
+               }
+               break;
+               default:
+               break;
+               // ???, this should only decode ADPCM, RAW and UNCOMPRESSED
+       }
+
+       uint8_t* tmp_raw_buffer = decodedData;
+       uint32_t tmp_raw_buffer_size = 0;
+
+       // If we need to convert samplerate or/and from mono to stereo...
+       if (outsize > 0 && (_sampleRate != 44100 || !_stereo)) {
+
+               int16_t* adjusted_data = 0;
+               int     adjusted_size = 0;
+               int sample_count = outsize / 2;// samples are of size 2
+
+               // Convert to needed samplerate - this converter only support 
standard flash samplerates
+               convert_raw_data(&adjusted_data, &adjusted_size, 
tmp_raw_buffer, sample_count, 0, 
+                               _sampleRate, _stereo,
+                               44100,  true /* stereo */);
+
+               // Hopefully this wont happen
+               if (!adjusted_data) {
+                       log_error(_("Error in sound sample conversion"));
+                       delete[] tmp_raw_buffer;
+                       outputSize = 0;
+                       decodedBytes = 0;
+                       return NULL;
+               }
+
+               // Move the new data to the sound-struct
+               delete[] tmp_raw_buffer;
+               tmp_raw_buffer = reinterpret_cast<uint8_t*>(adjusted_data);
+               tmp_raw_buffer_size = adjusted_size;
+
+       } else {
+               tmp_raw_buffer_size = outsize;
+       }
+
+       outputSize = tmp_raw_buffer_size;
+       decodedBytes = inputSize;
+       return tmp_raw_buffer;
+}
+
+} // gnash namespace

Index: libmedia/AudioDecoderSimple.h
===================================================================
RCS file: libmedia/AudioDecoderSimple.h
diff -N libmedia/AudioDecoderSimple.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/AudioDecoderSimple.h       27 Sep 2007 23:59:53 -0000      1.1
@@ -0,0 +1,69 @@
+// AudioDecoderSimple.h: Audio decoding using "simple" internal decoders.
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+//  $Id:
+
+#ifndef __AUDIODECODERSIMPLE_H__
+#define __AUDIODECODERSIMPLE_H__
+
+#include "log.h"
+#include "AudioDecoder.h"
+
+namespace gnash {
+       class SoundInfo;
+}
+
+namespace gnash {
+
+class AudioDecoderSimple : public AudioDecoder {
+
+public:
+       AudioDecoderSimple();
+       ~AudioDecoderSimple();
+
+       bool setup(AudioInfo* info);
+
+       bool setup(SoundInfo* info);
+
+       uint8_t* decode(uint8_t* input, uint32_t inputSize, uint32_t& 
outputSize, uint32_t& decodedBytes, bool parse);
+
+private:
+
+       // codec
+       audioCodecType _codec;
+
+       // samplerate
+       uint16_t _sampleRate;
+
+       // sampleCount
+       uint32_t _sampleCount;
+
+       // stereo
+       bool _stereo;
+
+       // samplesize: 8 or 16 bit
+       bool _is16bit;
+
+
+       // 
+};
+       
+} // gnash namespace
+
+#endif // __AUDIODECODERSIMPLE_H__
+

Index: libmedia/FLVParser.cpp
===================================================================
RCS file: libmedia/FLVParser.cpp
diff -N libmedia/FLVParser.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/FLVParser.cpp      27 Sep 2007 23:59:53 -0000      1.1
@@ -0,0 +1,702 @@
+// FLVParser.cpp:  Flash Video file parser, for Gnash.
+//
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+// $Id: FLVParser.cpp,v 1.1 2007/09/27 23:59:53 tgc Exp $
+
+#include "FLVParser.h"
+#include "amf.h"
+#include "log.h"
+
+#define PADDING_BYTES 8
+
+// Define the following macro the have seek() operations printed
+//#define GNASH_DEBUG_SEEK 1
+
+namespace gnash {
+
+FLVParser::FLVParser(tu_file* stream)
+       :
+       MediaParser(stream),
+       _lastParsedPosition(0),
+       _parsingComplete(false),
+       _videoInfo(NULL),
+       _audioInfo(NULL),
+       _nextAudioFrame(0),
+       _nextVideoFrame(0),
+       _audio(false),
+       _video(false)
+{
+}
+
+FLVParser::~FLVParser()
+{
+       _videoFrames.clear();
+
+       _audioFrames.clear();
+}
+
+
+uint32_t FLVParser::getBufferLength()
+{
+       boost::mutex::scoped_lock lock(_mutex);
+
+       if (_video) {
+               size_t size = _videoFrames.size();
+               if (size > 1 && size > _nextVideoFrame) {
+                       return _videoFrames.back()->timestamp - 
_videoFrames[_nextVideoFrame]->timestamp;
+               }
+       }
+       if (_audio) {
+               size_t size = _audioFrames.size();
+               if (size > 1 && size > _nextAudioFrame) {
+                       return _audioFrames.back()->timestamp - 
_audioFrames[_nextAudioFrame]->timestamp;
+               }
+       }
+       return 0;
+}
+uint16_t FLVParser::videoFrameRate()
+{
+       boost::mutex::scoped_lock lock(_mutex);
+
+       // Make sure that there are parsed some frames
+       while(_videoFrames.size() < 2 && !_parsingComplete) {
+               parseNextFrame();
+       }
+
+       if (_videoFrames.size() < 2) return 0;
+
+       uint32_t framedelay = _videoFrames[1]->timestamp - 
_videoFrames[0]->timestamp;
+
+       return static_cast<int16_t>(1000 / framedelay);
+}
+
+
+uint32_t FLVParser::videoFrameDelay()
+{
+       boost::mutex::scoped_lock lock(_mutex);
+
+       // If there are no video in this FLV return 0
+       if (!_video && _lastParsedPosition > 0) return 0;
+
+       // Make sure that there are parsed some frames
+       while(_videoFrames.size() < 2 && !_parsingComplete) {
+               parseNextFrame();
+       }
+
+       // If there is no video data return 0
+       if (_videoFrames.size() == 0 || !_video || _nextVideoFrame < 2) return 
0;
+
+       return _videoFrames[_nextVideoFrame-1]->timestamp - 
_videoFrames[_nextVideoFrame-2]->timestamp;
+}
+
+uint32_t FLVParser::audioFrameDelay()
+{
+       boost::mutex::scoped_lock lock(_mutex);
+
+       // If there are no audio in this FLV return 0
+       if (!_audio && _lastParsedPosition > 0) return 0;
+
+       // Make sure that there are parsed some frames
+       while(_audioFrames.size() < 2 && !_parsingComplete) {
+               parseNextFrame();
+       }
+
+       // If there is no video data return 0
+       if (_audioFrames.size() == 0 || !_audio || _nextAudioFrame < 2) return 
0;
+
+       return _audioFrames[_nextAudioFrame-1]->timestamp - 
_audioFrames[_nextAudioFrame-2]->timestamp;
+}
+
+MediaFrame* FLVParser::parseMediaFrame()
+{
+       boost::mutex::scoped_lock lock(_mutex);
+
+       uint32_t video_size = _videoFrames.size();
+       uint32_t audio_size = _audioFrames.size();
+
+       if (_audio && audio_size <= _nextAudioFrame)
+       {
+               // Parse a media frame if any left or if needed
+               while(_audioFrames.size() <= _nextAudioFrame && 
!_parsingComplete) {
+                       if (!parseNextFrame()) break;
+               }
+       }
+
+       if (_video && video_size <= _nextVideoFrame)
+       {
+               // Parse a media frame if any left or if needed
+               while(_videoFrames.size() <= _nextVideoFrame && 
!_parsingComplete) {
+                       if (!parseNextFrame()) break;
+               }
+       }
+
+       // Find the next frame in the file
+       bool audioReady = _audioFrames.size() > _nextAudioFrame;
+       bool videoReady = _videoFrames.size() > _nextVideoFrame;
+       bool useAudio = false;
+
+       if (audioReady && videoReady) {
+               useAudio = _audioFrames[_nextAudioFrame]->dataPosition < 
_videoFrames[_nextVideoFrame]->dataPosition;
+       } else if (!audioReady && videoReady) {
+               useAudio = false;
+       } else if (audioReady && !videoReady) {
+               useAudio = true;
+       } else {
+               // If no frames are next we have reached EOF
+               return NULL;
+       }
+
+       // Find the next frame in the file a return it
+
+       if (useAudio) {
+
+               MediaFrame* frame = new MediaFrame;
+               frame->dataSize = _audioFrames[_nextAudioFrame]->dataSize;
+               frame->timestamp = _audioFrames[_nextAudioFrame]->timestamp;
+
+               
_stream->set_position(_audioFrames[_nextAudioFrame]->dataPosition); 
//_lt.seek(_audioFrames[_nextAudioFrame]->dataPosition);
+               frame->data = new uint8_t[frame->dataSize + PADDING_BYTES];
+               size_t bytesread = _stream->read_bytes(frame->data, 
frame->dataSize); //_lt.read(frame->data, frame->dataSize);
+               memset(frame->data + bytesread, 0, PADDING_BYTES);
+
+               frame->tag = 8;
+               _nextAudioFrame++;
+
+               return frame;
+
+       } else {
+               MediaFrame* frame = new MediaFrame;
+               frame->dataSize = _videoFrames[_nextVideoFrame]->dataSize;
+               frame->timestamp = _videoFrames[_nextVideoFrame]->timestamp;
+
+               
_stream->set_position(_videoFrames[_nextVideoFrame]->dataPosition); 
//_lt.seek(_videoFrames[_nextVideoFrame]->dataPosition);
+               frame->data = new uint8_t[frame->dataSize + PADDING_BYTES];
+               size_t bytesread  = _stream->read_bytes(frame->data, 
frame->dataSize); //_lt.read(frame->data, frame->dataSize);
+               memset(frame->data + bytesread, 0, PADDING_BYTES);
+
+               frame->tag = 9;
+               _nextVideoFrame++;
+
+               return frame;
+       }
+}
+
+MediaFrame* FLVParser::nextAudioFrame()
+{
+       boost::mutex::scoped_lock lock(_mutex);
+
+       // If there are no audio in this FLV return NULL
+       if (!_audio && _lastParsedPosition > 0) return NULL;
+
+       // Make sure that there are parsed enough frames to return the need 
frame
+       while(_audioFrames.size() <= _nextAudioFrame && !_parsingComplete) {
+               if (!parseNextFrame()) break;
+       }
+
+       // If the needed frame can't be parsed (EOF reached) return NULL
+       if (_audioFrames.size() <= _nextAudioFrame || _audioFrames.size() == 0) 
return NULL;
+
+       MediaFrame* frame = new MediaFrame;
+       frame->dataSize = _audioFrames[_nextAudioFrame]->dataSize;
+       frame->timestamp = _audioFrames[_nextAudioFrame]->timestamp;
+       frame->tag = 8;
+
+       _stream->set_position(_audioFrames[_nextAudioFrame]->dataPosition); 
//_lt.seek(_audioFrames[_nextAudioFrame]->dataPosition);
+       frame->data = new uint8_t[_audioFrames[_nextAudioFrame]->dataSize +
+                                 PADDING_BYTES];
+       size_t bytesread = _stream->read_bytes(frame->data, 
_audioFrames[_nextAudioFrame]->dataSize); //_lt.read(frame->data, 
_audioFrames[_nextAudioFrame]->dataSize);
+       memset(frame->data + bytesread, 0, PADDING_BYTES);
+
+       _nextAudioFrame++;
+       return frame;
+
+}
+
+MediaFrame* FLVParser::nextVideoFrame()
+{
+       boost::mutex::scoped_lock lock(_mutex);
+
+       // If there are no video in this FLV return NULL
+       if (!_video && _lastParsedPosition > 0)
+       {
+               //gnash::log_debug("no video, or lastParserPosition > 0");
+               return NULL;
+       }
+
+       // Make sure that there are parsed enough frames to return the need 
frame
+       while(_videoFrames.size() <= static_cast<uint32_t>(_nextVideoFrame) && 
!_parsingComplete)
+       {
+               if (!parseNextFrame()) break;
+       }
+
+       // If the needed frame can't be parsed (EOF reached) return NULL
+       if (_videoFrames.size() <= _nextVideoFrame || _videoFrames.size() == 0)
+       {
+               //gnash::log_debug("The needed frame (%d) can't be parsed (EOF 
reached)", _lastVideoFrame);
+               return NULL;
+       }
+
+
+       MediaFrame* frame = new MediaFrame;
+       frame->dataSize = _videoFrames[_nextVideoFrame]->dataSize;
+       frame->timestamp = _videoFrames[_nextVideoFrame]->timestamp;
+       frame->tag = 9;
+
+       _stream->set_position(_videoFrames[_nextVideoFrame]->dataPosition); 
//_lt.seek(_videoFrames[_nextVideoFrame]->dataPosition);
+       frame->data = new uint8_t[_videoFrames[_nextVideoFrame]->dataSize + 
+                                 PADDING_BYTES];
+       size_t bytesread = _stream->read_bytes(frame->data, 
_videoFrames[_nextVideoFrame]->dataSize); //_lt.read(frame->data, 
_videoFrames[_nextVideoFrame]->dataSize);
+       memset(frame->data + bytesread, 0, PADDING_BYTES);
+
+       _nextVideoFrame++;
+       return frame;
+}
+
+
+uint32_t FLVParser::seekAudio(uint32_t time)
+{
+
+       // Make sure that there are parsed some frames
+       while(_audioFrames.size() < 1 && !_parsingComplete) {
+               parseNextFrame();
+       }
+
+       // If there is no audio data return NULL
+       if (_audioFrames.size() == 0) return 0;
+
+       // Make sure that there are parsed some enough frames
+       // to get the right frame.
+       while(_audioFrames.back()->timestamp < time && !_parsingComplete) {
+               parseNextFrame();
+       }
+
+       // If there are no audio greater than the given time
+       // the last audioframe is returned
+       FLVAudioFrame* lastFrame = _audioFrames.back();
+       if (lastFrame->timestamp < time) {
+               _nextAudioFrame = _audioFrames.size() - 1;
+               return lastFrame->timestamp;
+       }
+
+       // We try to guess where in the vector the audioframe
+       // with the correct timestamp is
+       size_t numFrames = _audioFrames.size();
+       double tpf = lastFrame->timestamp / numFrames; // time per frame
+       size_t guess = size_t(time / tpf);
+
+       // Here we test if the guess was ok, and adjust if needed.
+       size_t bestFrame = iclamp(guess, 0, _audioFrames.size()-1);
+
+       // Here we test if the guess was ok, and adjust if needed.
+       long diff = _audioFrames[bestFrame]->timestamp - time;
+       if ( diff > 0 ) // our guess was too long
+       {
+               while ( bestFrame > 0 && _audioFrames[bestFrame-1]->timestamp > 
time ) --bestFrame;
+       }
+       else // our guess was too short
+       {
+               while ( bestFrame < _audioFrames.size()-1 && 
_audioFrames[bestFrame+1]->timestamp < time ) ++bestFrame;
+       }
+
+#ifdef GNASH_DEBUG_SEEK
+       gnash::log_debug("Seek (audio): " SIZET_FMT "/" SIZET_FMT " (%u/%u)", 
bestFrame, numFrames, _audioFrames[bestFrame]->timestamp, time);
+#endif
+       _nextAudioFrame = bestFrame;
+       return _audioFrames[bestFrame]->timestamp;
+
+}
+
+
+uint32_t FLVParser::seekVideo(uint32_t time)
+{
+       // Make sure that there are parsed some frames
+       while(_videoFrames.size() < 1 && !_parsingComplete) {
+               parseNextFrame();
+       }
+
+       // If there is no video data return NULL
+       if (_videoFrames.size() == 0) return 0;
+
+       // Make sure that there are parsed some enough frames
+       // to get the right frame.
+       while(_videoFrames.back()->timestamp < time && !_parsingComplete) {
+               parseNextFrame();
+       }
+
+       // If there are no videoframe greater than the given time
+       // the last key videoframe is returned
+       FLVVideoFrame* lastFrame = _videoFrames.back();
+       size_t numFrames = _videoFrames.size();
+       if (lastFrame->timestamp < time)
+       {
+               size_t lastFrameNum = numFrames -1;
+               while (! lastFrame->isKeyFrame() )
+               {
+                       lastFrameNum--;
+                       lastFrame = _videoFrames[lastFrameNum];
+               }
+
+               _nextVideoFrame = lastFrameNum;
+               return lastFrame->timestamp;
+
+       }
+
+       // We try to guess where in the vector the videoframe
+       // with the correct timestamp is
+       double tpf = lastFrame->timestamp / numFrames; // time per frame
+       size_t guess = size_t(time / tpf);
+
+       size_t bestFrame = iclamp(guess, 0, _videoFrames.size()-1);
+
+       // Here we test if the guess was ok, and adjust if needed.
+       long diff = _videoFrames[bestFrame]->timestamp - time;
+       if ( diff > 0 ) // our guess was too long
+       {
+               while ( bestFrame > 0 && _videoFrames[bestFrame-1]->timestamp > 
time ) --bestFrame;
+       }
+       else // our guess was too short
+       {
+               while ( bestFrame < _videoFrames.size()-1 && 
_videoFrames[bestFrame+1]->timestamp < time ) ++bestFrame;
+       }
+
+#if 0
+       uint32_t diff = abs(_videoFrames[bestFrame]->timestamp - time);
+       while (true)
+       {
+               if (bestFrame+1 < numFrames && 
static_cast<uint32_t>(abs(_videoFrames[bestFrame+1]->timestamp - time)) < diff) 
{
+                       diff = abs(_videoFrames[bestFrame+1]->timestamp - time);
+                       bestFrame = bestFrame + 1;
+               } else if (bestFrame > 0 && 
static_cast<uint32_t>(abs(_videoFrames[bestFrame-1]->timestamp - time)) < diff) 
{
+                       diff = abs(_videoFrames[bestFrame-1]->timestamp - time);
+                       bestFrame = bestFrame - 1;
+               } else {
+                       break;
+               }
+       }
+#endif
+
+
+       // Find closest backward keyframe  
+       size_t rewindKeyframe = bestFrame;
+       while ( rewindKeyframe && ! _videoFrames[rewindKeyframe]->isKeyFrame() )
+       {
+               rewindKeyframe--;
+       }
+
+       // Find closest forward keyframe 
+       size_t forwardKeyframe = bestFrame;
+       size_t size = _videoFrames.size();
+       while (size > forwardKeyframe+1 && ! 
_videoFrames[forwardKeyframe]->isKeyFrame() )
+       {
+               forwardKeyframe++;
+       }
+
+       // We can't ensure we were able to find a key frame *after* the best 
position
+       // in that case we just use any previous keyframe instead..
+       if ( ! _videoFrames[forwardKeyframe]->isKeyFrame() )
+       {
+               bestFrame = rewindKeyframe;
+       }
+       else
+       {
+               int32_t forwardDiff = _videoFrames[forwardKeyframe]->timestamp 
- time;
+               int32_t rewindDiff = time - 
_videoFrames[rewindKeyframe]->timestamp;
+
+               if (forwardDiff < rewindDiff) bestFrame = forwardKeyframe;
+               else bestFrame = rewindKeyframe;
+       }
+
+#ifdef GNASH_DEBUG_SEEK
+       gnash::log_debug("Seek (video): " SIZET_FMT "/" SIZET_FMT " (%u/%u)", 
bestFrame, numFrames, _videoFrames[bestFrame]->timestamp, time);
+#endif
+
+       _nextVideoFrame = bestFrame;
+       assert( _videoFrames[bestFrame]->isKeyFrame() );
+       return _videoFrames[bestFrame]->timestamp;
+}
+
+
+
+std::auto_ptr<VideoInfo> FLVParser::getVideoInfo()
+{
+       boost::mutex::scoped_lock lock(_mutex);
+
+       // If there are no video in this FLV return NULL
+       if (!_video && _lastParsedPosition > 0) return 
std::auto_ptr<VideoInfo>(NULL);
+
+       // Make sure that there are parsed some video frames
+       while(_videoInfo.get() == NULL && !_parsingComplete && !(!_video && 
_lastParsedPosition > 0)) {
+               if (parseNextFrame() == false) break;
+       }
+
+       // If there are no video data return NULL
+       if (_videoInfo.get() == NULL) {
+               log_debug("No audio data");
+               return std::auto_ptr<VideoInfo>(NULL);
+       }
+
+       std::auto_ptr<VideoInfo> info(new VideoInfo(_videoInfo->codec, 
_videoInfo->width, _videoInfo->height, _videoInfo->frameRate, 
_videoInfo->duration, FLASH));
+       return info;
+
+}
+
+std::auto_ptr<AudioInfo> FLVParser::getAudioInfo()
+{
+
+       boost::mutex::scoped_lock lock(_mutex);
+
+       // If there are no audio in this FLV return NULL
+       if (!_audio && _lastParsedPosition > 0) return 
std::auto_ptr<AudioInfo>(NULL);
+
+       // Make sure that there are parsed some audio frames
+       while(_audioInfo.get() == NULL && !_parsingComplete && !(!_video && 
_lastParsedPosition > 0)) {
+               if (parseNextFrame() == false) break;
+       }
+
+       // If there are no audio data return NULL
+       if (_audioInfo.get() == NULL) return std::auto_ptr<AudioInfo>(NULL);
+
+       if (_audioInfo->codec == AUDIO_CODEC_MP3) _isAudioMp3 = true;
+       else if (_audioInfo->codec == AUDIO_CODEC_NELLYMOSER || 
_audioInfo->codec == AUDIO_CODEC_NELLYMOSER_8HZ_MONO) _isAudioNellymoser = true;
+
+       std::auto_ptr<AudioInfo> info(new AudioInfo(_audioInfo->codec, 
_audioInfo->sampleRate, _audioInfo->sampleSize, _audioInfo->stereo, 
_audioInfo->duration, FLASH));
+       return info;
+
+}
+
+bool FLVParser::isTimeLoaded(uint32_t time)
+{
+       boost::mutex::scoped_lock lock(_mutex);
+
+       // Parse frames until the need time is found, or EOF
+       while (!_parsingComplete) {
+               if (!parseNextFrame()) break;
+               if ((_videoFrames.size() > 0 && _videoFrames.back()->timestamp 
>= time)
+                       || (_audioFrames.size() > 0 && 
_audioFrames.back()->timestamp >= time)) {
+                       return true;
+               }
+       }
+
+       if (_videoFrames.size() > 0 && _videoFrames.back()->timestamp >= time) {
+               return true;
+       }
+
+       if (_audioFrames.size() > 0 && _audioFrames.back()->timestamp >= time) {
+               return true;
+       }
+
+       return false;
+
+}
+
+uint32_t FLVParser::seek(uint32_t time)
+{
+       boost::mutex::scoped_lock lock(_mutex);
+
+       if (time == 0) {
+               if (_video) _nextVideoFrame = 0;
+               if (_audio) _nextAudioFrame = 0;
+       }
+
+       if (_video)     time = seekVideo(time);
+       if (_audio)     time = seekAudio(time);
+       return time;
+}
+
+bool FLVParser::parseNextFrame()
+{
+       // Parse the header if not done already. If unsuccesfull return false.
+       if (_lastParsedPosition == 0 && !parseHeader()) return false;
+
+       // Check if there is enough data to parse the header of the frame
+       //if (!_lt.isPositionConfirmed(_lastParsedPosition+14)) return false;
+
+       // Seek to next frame and skip the size of the last tag,
+       // return false on error
+       if (_stream->set_position(_lastParsedPosition+4) != 0) return false;
+       //_lt.seek(_lastParsedPosition+4);
+
+       // Read the tag info
+       uint8_t tag[12];
+       _stream->read_bytes(tag, 12);
+       //_lt.read(tag, 12);
+
+       // Extract length and timestamp
+       uint32_t bodyLength = getUInt24(&tag[1]);
+       uint32_t timestamp = getUInt24(&tag[4]);
+
+       // Check if there is enough data to parse the body of the frame
+       //if (!_lt.isPositionConfirmed(_lastParsedPosition+15+bodyLength)) 
return false;
+       /*if (_stream->set_position(_lastParsedPosition+15+bodyLength) != 0) 
return false;*/
+       //_stream->set_position(_lastParsedPosition + HEADER_SKIP + bodyLength);
+
+       // check for empty tag
+       if (bodyLength == 0) {
+               _lastParsedPosition += HEADER_SKIP + bodyLength;
+               return true;
+       }
+
+       if (tag[0] == AUDIO_TAG) {
+               FLVAudioFrame* frame = new FLVAudioFrame;
+               frame->dataSize = bodyLength - 1;
+               frame->timestamp = timestamp;
+               frame->dataPosition = _lastParsedPosition + HEADER_SKIP + 1; // 
_stream->get_position(); //_lt.tell(); 
+               _audioFrames.push_back(frame);
+//log_debug("audio tag, timestamp: %d", timestamp);
+
+               // If this is the first audioframe no info about the
+               // audio format has been noted, so we do that now
+               if (_audioInfo.get() == NULL) {
+                       int samplerate = (tag[11] & 0x0C) >> 2;
+                       if (samplerate == 0) samplerate = 5500;
+                       else if (samplerate == 1) samplerate = 11000;
+                       else if (samplerate == 2) samplerate = 22050;
+                       else if (samplerate == 3) samplerate = 44100;
+
+                       int samplesize = (tag[11] & 0x02) >> 1;
+                       if (samplesize == 0) samplesize = 1;
+                       else samplesize = 2;
+
+                       _audioInfo.reset(new 
AudioInfo(static_cast<audioCodecType>((tag[11] & 0xf0) >> 4), samplerate, 
samplesize, (tag[11] & 0x01) >> 0, 0, FLASH));
+               }
+               _lastParsedPosition += HEADER_SKIP + bodyLength;
+
+       } else if (tag[0] == VIDEO_TAG) {
+               FLVVideoFrame* frame = new FLVVideoFrame;
+               frame->dataSize = bodyLength - 1;
+               frame->timestamp = timestamp;
+               frame->dataPosition = _lastParsedPosition + HEADER_SKIP + 1; 
//_stream->get_position(); //_lt.tell();
+               frame->frameType = (tag[11] & 0xf0) >> 4;
+               _videoFrames.push_back(frame);
+
+//log_debug("video tag, timestamp: %d", timestamp);
+
+               // If this is the first videoframe no info about the
+               // video format has been noted, so we do that now
+               if (_videoInfo.get() == NULL) {
+                       videoCodecType codec = 
static_cast<videoCodecType>((tag[11] & 0x0f) >> 0);
+                       // Set standard guessed size...
+                       uint16_t width = 320;
+                       uint16_t height = 240;
+
+                       // Extract the video size from the videodata header
+                       if (codec == VIDEO_CODEC_H263) {
+                               _stream->set_position(frame->dataPosition); 
//_lt.seek(frame->dataPosition);
+                               uint8_t videohead[12];
+                               _stream->read_bytes(videohead, 12); 
//_lt.read(videohead, 12);
+
+                               bool sizebit1 = (videohead[3] & 0x02);
+                               bool sizebit2 = (videohead[3] & 0x01);
+                               bool sizebit3 = (videohead[4] & 0x80);
+
+                               // First some predefined sizes
+                               if (!sizebit1 && sizebit2 && !sizebit3 ) {
+                                       width = 352;
+                                       height = 288;
+                               } else if (!sizebit1 && sizebit2 && sizebit3 ) {
+                                       width = 176;
+                                       height = 144;
+                               } else if (sizebit1 && !sizebit2 && !sizebit3 ) 
{
+                                       width = 128;
+                                       height = 96;
+                               } else if (sizebit1 && !sizebit2 && sizebit3 ) {
+                                       width = 320;
+                                       height = 240;
+                               } else if (sizebit1 && sizebit2 && !sizebit3 ) {
+                                       width = 160;
+                                       height = 120;
+
+                               // Then the custom sizes (1 byte - untested and 
ugly)
+                               } else if (!sizebit1 && !sizebit2 && !sizebit3 
) {
+                                       width = (videohead[4] & 0x40) | 
(videohead[4] & 0x20) | (videohead[4] & 0x20) | (videohead[4] & 0x08) | 
(videohead[4] & 0x04) | (videohead[4] & 0x02) | (videohead[4] & 0x01) | 
(videohead[5] & 0x80);
+
+                                       height = (videohead[5] & 0x40) | 
(videohead[5] & 0x20) | (videohead[5] & 0x20) | (videohead[5] & 0x08) | 
(videohead[5] & 0x04) | (videohead[5] & 0x02) | (videohead[5] & 0x01) | 
(videohead[6] & 0x80);
+
+                               // Then the custom sizes (2 byte - untested and 
ugly)
+                               } else if (!sizebit1 && !sizebit2 && sizebit3 ) 
{
+                                       width = (videohead[4] & 0x40) | 
(videohead[4] & 0x20) | (videohead[4] & 0x20) | (videohead[4] & 0x08) | 
(videohead[4] & 0x04) | (videohead[4] & 0x02) | (videohead[4] & 0x01) | 
(videohead[5] & 0x80) | (videohead[5] & 0x40) | (videohead[5] & 0x20) | 
(videohead[5] & 0x20) | (videohead[5] & 0x08) | (videohead[5] & 0x04) | 
(videohead[5] & 0x02) | (videohead[5] & 0x01) | (videohead[6] & 0x80);
+
+                                       height = (videohead[6] & 0x40) | 
(videohead[6] & 0x20) | (videohead[6] & 0x20) | (videohead[6] & 0x08) | 
(videohead[6] & 0x04) | (videohead[6] & 0x02) | (videohead[6] & 0x01) | 
(videohead[7] & 0x80) | (videohead[7] & 0x40) | (videohead[7] & 0x20) | 
(videohead[7] & 0x20) | (videohead[7] & 0x08) | (videohead[7] & 0x04) | 
(videohead[7] & 0x02) | (videohead[7] & 0x01) | (videohead[8] & 0x80);
+                               }
+                       }
+
+                       // Create the videoinfo
+                       _videoInfo.reset(new VideoInfo(codec, width, height, 0 
/*frameRate*/, 0 /*duration*/, FLASH));
+               }
+               _lastParsedPosition += HEADER_SKIP + bodyLength;
+
+       } else if (tag[0] == META_TAG) {
+//log_debug("meta tag");
+               // Extract information from the meta tag
+               /*_lt.seek(_lastParsedPosition+16);
+               char* metaTag = new char[bodyLength];
+               _lt.read(metaTag, bodyLength);
+               amf::AMF* amfParser = new amf::AMF();
+               amfParser->parseAMF(metaTag);*/
+               _lastParsedPosition += HEADER_SKIP + bodyLength;
+
+       } else {
+log_debug("no tag - the end?");
+               // We can't be sure that the parsing is really complete,
+               // maybe it's a corrupt FLV.
+               _parsingComplete = true;
+               return false;
+       }
+
+       return true;
+}
+
+bool FLVParser::parseHeader()
+{
+       // seek to the begining of the file
+       _stream->set_position(0); //_lt.seek(0);
+
+       // Read the header
+       uint8_t header[9];
+       _stream->read_bytes(header, 9); //_lt.read(header, 9);
+
+       // Check if this is really a FLV file
+       if (header[0] != 'F' || header[1] != 'L' || header[2] != 'V') return 
false;
+
+       _audio = false;
+       _video = false;
+
+       // Parse the audio+video bitmask
+       if (header[4] & CONTAINS_AUDIO) {
+               _audio = true;
+       } 
+       if (header[4] & CONTAINS_VIDEO) {
+               _video = true;
+       } 
+
+       gnash::log_debug("FLV bit mask: %#x", header[4]);
+
+       _lastParsedPosition = 9;
+       return true;
+}
+
+inline uint32_t FLVParser::getUInt24(uint8_t* in)
+{
+       // The bits are in big endian order
+       return (in[0] << 16) | (in[1] << 8) | in[2];
+}
+
+} // end of gnash namespace
+
+#undef PADDING_BYTES

Index: libmedia/FLVParser.h
===================================================================
RCS file: libmedia/FLVParser.h
diff -N libmedia/FLVParser.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/FLVParser.h        27 Sep 2007 23:59:53 -0000      1.1
@@ -0,0 +1,277 @@
+// FLVParser.h:  Flash Video file format parser, for Gnash.
+//
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+// $Id: FLVParser.h,v 1.1 2007/09/27 23:59:53 tgc Exp $
+
+// Information about the FLV format can be found at http://osflash.org/flv
+
+#ifndef __FLVPARSER_H__
+#define __FLVPARSER_H__
+
+#include <tu_file.h>
+#include <vector>
+#include <boost/thread/mutex.hpp>
+#include "MediaParser.h"
+
+#define HEADER_SKIP 15
+
+namespace gnash {
+
+enum videoFrameType
+{
+       KEY_FRAME = 1,
+       INTER_FRAME = 2,
+       DIS_INTER_FRAME = 3
+};
+
+enum {
+       CONTAINS_VIDEO = 1,
+       CONTAINS_AUDIO = 4,
+};
+
+class FLVVideoFrame
+{
+public:
+       uint16_t frameType;
+       uint32_t dataSize;
+       uint64_t dataPosition;
+
+       /// in milliseconds 
+       uint32_t timestamp;
+
+       /// Return true if this video frame is a key frame
+       bool isKeyFrame() const
+       {
+               return frameType == KEY_FRAME;
+       }
+
+};
+
+class FLVAudioFrame
+{
+public:
+       uint32_t dataSize;
+       uint64_t dataPosition;
+
+       /// in milliseconds 
+       uint32_t timestamp;
+
+};
+
+/// \brief
+/// The FLVParser class parses an FLV stream, buffers information about 
+/// audio/video frames and provides cursor-based access to them.
+//
+/// Cursor-based access allow seeking as close as possible to a specified time
+/// and fetching frames from there on, sequentially.
+/// See seek(), nextVideoFrame(), nextAudioFrame() and nextMediaFrame().
+///
+/// Input is received from a tu_file object.
+///
+class DSOEXPORT FLVParser : public MediaParser
+{
+
+public:
+
+       /// \brief
+       /// Create an FLV parser reading input from
+       /// the given tu_file
+       //
+       /// @param stream
+       ///     tu_file to use for input.
+       ///     Ownership left to the caller.
+       ///
+       FLVParser(tu_file* stream);
+
+       /// Kills the parser...
+       ~FLVParser();
+
+       /// Return next media frame
+       //
+       /// Locks the _mutex
+       ///
+       MediaFrame* parseMediaFrame();
+
+       /// \brief
+       /// Returns the next audio frame in the parsed buffer.
+       //
+       /// If no frame has been played before the first frame is returned.
+       /// If there is no more frames in the parsed buffer NULL is returned,
+       /// you can check with parsingCompleted() to know wheter this is due to 
+       /// EOF reached.
+       ///
+       /// Locks the _mutex
+       ///
+       MediaFrame* nextAudioFrame();
+
+       /// \brief
+       /// Returns the next video frame in the parsed buffer.
+       //
+       /// If no frame has been played before the first frame is returned.
+       /// If there is no more frames in the parsed buffer NULL is returned.
+       /// you can check with parsingCompleted() to know wheter this is due to 
+       /// EOF reached.
+       ///
+       /// Locks the _mutex
+       ///
+       MediaFrame* nextVideoFrame();
+
+       /// Return true of parsing is completed
+       //
+       /// If this function returns true, any call to nextVideoFrame() or 
nextAudioFrame
+       /// will always return NULL
+       ///
+       bool parsingCompleted() const { return _parsingComplete; }
+
+       /// Returns a VideoInfo class about the videostream
+       //
+       /// Locks the _mutex
+       ///
+       std::auto_ptr<VideoInfo> getVideoInfo();
+
+       /// Returns a AudioInfo class about the audiostream
+       //
+       /// Locks the _mutex
+       ///
+       std::auto_ptr<AudioInfo> getAudioInfo();
+
+       /// \brief
+       /// Asks if a frame with with a timestamp larger than
+       /// the given time is available.
+       //
+       /// If such a frame is not
+       /// available in list of already the parsed frames, we
+       /// parse some more. This is used to check how much is buffered.
+       ///
+       /// Locks the _mutex
+       ///
+       /// @param time
+       ///     Timestamp, in milliseconds.
+       ///
+       bool isTimeLoaded(uint32_t time);
+
+       /// \brief
+       /// Seeks to the closest possible position the given position,
+       /// and returns the new position.
+       //
+       /// Locks the _mutex
+       ///
+       uint32_t seek(uint32_t);
+
+       /// Returns the framedelay from the last to the current
+       /// audioframe in milliseconds. This is used for framerate.
+       //
+       /// Locks the _mutex
+       ///
+       uint32_t audioFrameDelay();
+
+       /// \brief
+       /// Returns the framedelay from the last to the current
+       /// videoframe in milliseconds. 
+       //
+       /// Locks the _mutex
+       ///
+       uint32_t videoFrameDelay();
+
+       /// Returns the framerate of the video
+       //
+       /// Locks the _mutex
+       ///
+       uint16_t videoFrameRate();
+
+       /// Returns the "bufferlength", meaning the differens between the
+       /// current frames timestamp and the timestamp of the last parseable
+       /// frame. Returns the difference in milliseconds.
+       //
+       /// Locks the _mutex
+       ///
+       uint32_t getBufferLength();
+
+       /// Setup the parser
+       //
+       /// @return whether we'll be able to parse the file.
+       bool setupParser() { return true; }
+
+       uint32_t getLastParsedPos() { return _lastParsedPosition; }
+
+private:
+
+       /// seeks to the closest possible position the given position,
+       /// and returns the new position.
+       uint32_t seekAudio(uint32_t time);
+
+       /// seeks to the closest possible position the given position,
+       /// and returns the new position.
+       uint32_t seekVideo(uint32_t time);
+
+
+       /// Parses next frame from the file, returns true if a frame
+       /// was succesfully parsed, or false if not enough data was present.
+       bool parseNextFrame();
+
+       /// Parses the header of the file
+       bool parseHeader();
+
+       // Functions used to extract numbers from the file
+       inline uint32_t getUInt24(uint8_t* in);
+
+       /// The interface to the file, externally owned
+//     tu_file* _stream;
+
+       typedef std::vector<FLVVideoFrame*> VideoFrames;
+
+       /// list of videoframes, does no contain the frame data.
+       VideoFrames _videoFrames;
+
+       typedef std::vector<FLVAudioFrame*> AudioFrames;
+
+       /// list of audioframes, does no contain the frame data.
+       AudioFrames _audioFrames;
+
+       /// The position where the parsing should continue from.
+       uint32_t _lastParsedPosition;
+
+       /// Whether the parsing is complete or not
+       bool _parsingComplete;
+
+       /// Info about the video stream
+       std::auto_ptr<VideoInfo> _videoInfo;
+
+       /// Info about the audio stream
+       std::auto_ptr<AudioInfo> _audioInfo;
+
+       /// Last audio frame returned
+       size_t _nextAudioFrame;
+
+       /// Last video frame returned
+       size_t _nextVideoFrame;
+
+       /// Audio stream is present
+       bool _audio;
+
+       /// Audio stream is present
+       bool _video;
+
+       /// Mutex to avoid problems with threads using the parser
+       boost::mutex _mutex;
+};
+
+} // end of gnash namespace
+
+#endif // __FLVPARSER_H__

Index: libmedia/Makefile.am
===================================================================
RCS file: libmedia/Makefile.am
diff -N libmedia/Makefile.am
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/Makefile.am        27 Sep 2007 23:59:53 -0000      1.1
@@ -0,0 +1,130 @@
+# 
+#   Copyright (C) 2007 Free Software Foundation, Inc.
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program 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 General Public License for more details.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+AUTOMAKE_OPTIONS = no-dependencies foreign
+
+EXTRA_DIST = 
+
+# this is where Gnash plugins get installed
+pluginsdir = $(prefix)/lib/gnash/plugins
+
+if INSTALL_LTDL
+include_HEADERS =  $(top_srcdir)/libltdl/ltdl.h
+LIBLTDLLIB = libltdl.la
+LIBLTDLHEAD =  $(top_srcdir)/libltdl/ltdl.h
+endif
+
+# If we are using an installable libltdl, then it needs to be built
+# before libgnash, as libgnash depends on it for extensions.
+pkglib_LTLIBRARIES =  $(LIBLTDLLIB) libgnashmedia.la
+
+libgnashmedia_la_CPPFLAGS = \
+       -I.. -I$(srcdir) \
+       -I$(top_srcdir) \
+       -I$(top_srcdir)/libamf  \
+       -I$(top_srcdir)/backend \
+       -I$(top_srcdir)/libbase \
+       -I$(top_srcdir)/server  \
+       $(PTHREAD_CFLAGS) \
+       $(OPENGL_CFLAGS) \
+       $(LIBXML_CFLAGS) \
+       $(PNG_CFLAGS) \
+       $(SDL_CFLAGS) \
+       $(GLIB_CFLAGS) \
+       $(GSTREAMER_CFLAGS) \
+       $(CURL_CFLAGS) \
+       $(Z_CFLAGS) \
+       $(JPEG_CFLAGS) \
+       $(BOOST_CFLAGS) \
+       $(INCLTDL) \
+       $(NULL)
+
+# These headers get installed
+# include_HEADERS = log.h err.h proc.h serial.h xantrex.h outback.h
+
+# Don't build Dmalloc support if it's not configured in
+if HAVE_DMALLOC
+DMALLOC_FILE = dlmalloc.c
+endif
+
+libgnashmedia_la_LIBADD = \
+       $(JPEG_LIBS) \
+       $(Z_LIBS) \
+       $(CURL_LIBS) \
+       $(OPENGL_LIBS) \
+       $(LIBINTL) \
+       $(LIBLTDL) \
+       $(BOOST_LIBS) \
+       $(PTHREAD_LIBS) \
+       $(SDL_LIBS) \
+       $(NULL)
+
+libgnashmedia_la_SOURCES = \
+       AudioDecoderNellymoser.cpp \
+       AudioDecoderSimple.cpp \
+       $(NULL)
+
+noinst_HEADERS = \
+       MediaBuffer.h \
+       MediaDecoder.h \
+       AudioDecoder.h \
+       VideoDecoder.h \
+       MediaParser.h \
+       AudioDecoderNellymoser.h \
+       AudioDecoderSimple.h \
+       sound_handler.h \
+       SoundInfo.h \
+       $(NULL)
+
+
+if USE_SOUND_GST
+#libgnashmedia_la_SOURCES += gst/gstgnashsrc.c gst/VideoDecoderGst.cpp 
gst/gstappbuffer.c gst/gstappsink.c gst/gstappsrc.c gst/sound_handler_gst.cpp
+libgnashmedia_la_SOURCES += gst/VideoDecoderGst.cpp gst/sound_handler_gst.cpp
+#noinst_HEADERS += gst/gstgnashsrc.h gst/gstappbuffer.h gst/VideoDecoderGst.h 
gst/gstappsink.h gst/gstappsrc.h gst/sound_handler_gst.h
+noinst_HEADERS += gst/VideoDecoderGst.h gst/sound_handler_gst.h
+libgnashmedia_la_CPPFLAGS += $(GSTREAMER_CFLAGS)
+libgnashmedia_la_LIBADD += $(GSTREAMER_LIBS) -lgstbase-0.10
+endif
+
+if USE_FFMPEG_ENGINE
+#libgnashmedia_la_SOURCES += sdl/MediaDecoderSdl.cpp 
sdl/AudioDecoderFfmpeg.cpp sdl/VideoDecoderFfmpeg.cpp sdl/MediaParserFfmpeg.cpp 
sdl/sound_handler_sdl.cpp
+libgnashmedia_la_SOURCES += sdl/VideoDecoderFfmpeg.cpp 
sdl/AudioDecoderFfmpeg.cpp sdl/sound_handler_sdl.cpp
+#noinst_HEADERS += sdl/MediaDecoderSdl.h sdl/AudioDecoderFfmpeg.h 
sdl/VideoDecoderFfmpeg.h sdl/MediaParserFfmpeg.h sdl/sound_handler_sdl.h
+noinst_HEADERS += sdl/AudioDecoderFfmpeg.h sdl/VideoDecoderFfmpeg.h 
sdl/sound_handler_sdl.h
+libgnashmedia_la_LIBADD += $(FFMPEG_LIBS)
+libgnashmedia_la_CPPFLAGS += $(FFMPEG_CFLAGS)
+endif
+
+if USE_MAD_ENGINE
+#libgnashmedia_la_SOURCES += sdl/MediaDecoderSdl.cpp sdl/AudioDecoderMad.cpp 
sdl/sound_handler_sdl.cpp
+libgnashmedia_la_SOURCES += sdl/AudioDecoderMad.cpp sdl/sound_handler_sdl.cpp
+#noinst_HEADERS += sdl/MediaDecoderSdl.h sdl/AudioDecoderMad.h 
sdl/sound_handler_sdl.h
+noinst_HEADERS += sdl/AudioDecoderMad.h sdl/sound_handler_sdl.h
+libgnashmedia_la_LIBADD += $(MAD_LIBS)
+libgnashmedia_la_CPPFLAGS += $(MAD_CFLAGS)
+endif
+
+libgnashmedia_la_LDFLAGS = -release $(VERSION)
+
+
+# Rebuild with GCC 4.x Mudflap support
+mudflap:
+       @echo "Rebuilding with GCC Mudflap support"
+       $(MAKE) CXXFLAGS="$(CXXFLAGS) -fmudflap" LDFLAGS="$(LDFLAGS) -lmudflap"
+
+clean-hook:
+       -rm -f core.* *.obj
+

Index: libmedia/Makefile.in
===================================================================
RCS file: libmedia/Makefile.in
diff -N libmedia/Makefile.in
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/Makefile.in        27 Sep 2007 23:59:53 -0000      1.1
@@ -0,0 +1,777 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
address@hidden@
+
+# 
+#   Copyright (C) 2007 Free Software Foundation, Inc.
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program 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 General Public License for more details.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+
+#libgnashmedia_la_SOURCES += gst/gstgnashsrc.c gst/VideoDecoderGst.cpp 
gst/gstappbuffer.c gst/gstappsink.c gst/gstappsrc.c gst/sound_handler_gst.cpp
address@hidden@am__append_1 = gst/VideoDecoderGst.cpp gst/sound_handler_gst.cpp
+#noinst_HEADERS += gst/gstgnashsrc.h gst/gstappbuffer.h gst/VideoDecoderGst.h 
gst/gstappsink.h gst/gstappsrc.h gst/sound_handler_gst.h
address@hidden@am__append_2 = gst/VideoDecoderGst.h gst/sound_handler_gst.h
address@hidden@am__append_3 = $(GSTREAMER_CFLAGS)
address@hidden@am__append_4 = $(GSTREAMER_LIBS) -lgstbase-0.10
+
+#libgnashmedia_la_SOURCES += sdl/MediaDecoderSdl.cpp 
sdl/AudioDecoderFfmpeg.cpp sdl/VideoDecoderFfmpeg.cpp sdl/MediaParserFfmpeg.cpp 
sdl/sound_handler_sdl.cpp
address@hidden@am__append_5 = sdl/VideoDecoderFfmpeg.cpp 
sdl/AudioDecoderFfmpeg.cpp sdl/sound_handler_sdl.cpp
+#noinst_HEADERS += sdl/MediaDecoderSdl.h sdl/AudioDecoderFfmpeg.h 
sdl/VideoDecoderFfmpeg.h sdl/MediaParserFfmpeg.h sdl/sound_handler_sdl.h
address@hidden@am__append_6 = sdl/AudioDecoderFfmpeg.h sdl/VideoDecoderFfmpeg.h 
sdl/sound_handler_sdl.h
address@hidden@am__append_7 = $(FFMPEG_LIBS)
address@hidden@am__append_8 = $(FFMPEG_CFLAGS)
+
+#libgnashmedia_la_SOURCES += sdl/MediaDecoderSdl.cpp sdl/AudioDecoderMad.cpp 
sdl/sound_handler_sdl.cpp
address@hidden@am__append_9 = sdl/AudioDecoderMad.cpp sdl/sound_handler_sdl.cpp
+#noinst_HEADERS += sdl/MediaDecoderSdl.h sdl/AudioDecoderMad.h 
sdl/sound_handler_sdl.h
address@hidden@am__append_10 = sdl/AudioDecoderMad.h sdl/sound_handler_sdl.h
address@hidden@am__append_11 = $(MAD_LIBS)
address@hidden@am__append_12 = $(MAD_CFLAGS)
+subdir = libmedia
+DIST_COMMON = $(am__include_HEADERS_DIST) $(am__noinst_HEADERS_DIST) \
+       $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/macros/agg.m4 \
+       $(top_srcdir)/macros/archflag.m4 $(top_srcdir)/macros/boost.m4 \
+       $(top_srcdir)/macros/curl.m4 $(top_srcdir)/macros/dbus.m4 \
+       $(top_srcdir)/macros/docbook.m4 $(top_srcdir)/macros/ffmpeg.m4 \
+       $(top_srcdir)/macros/firefox.m4 \
+       $(top_srcdir)/macros/freetype.m4 \
+       $(top_srcdir)/macros/gettext.m4 $(top_srcdir)/macros/glib.m4 \
+       $(top_srcdir)/macros/gnashpkgtool.m4 \
+       $(top_srcdir)/macros/gtk2.m4 $(top_srcdir)/macros/gtkglext.m4 \
+       $(top_srcdir)/macros/iconv.m4 $(top_srcdir)/macros/kde.m4 \
+       $(top_srcdir)/macros/lib-link.m4 \
+       $(top_srcdir)/macros/lib-prefix.m4 \
+       $(top_srcdir)/macros/libXML.m4 $(top_srcdir)/macros/libexe.m4 \
+       $(top_srcdir)/macros/libltdl.m4 $(top_srcdir)/macros/ming.m4 \
+       $(top_srcdir)/macros/mtasc.m4 $(top_srcdir)/macros/mysql.m4 \
+       $(top_srcdir)/macros/nls.m4 $(top_srcdir)/macros/opengl.m4 \
+       $(top_srcdir)/macros/pango.m4 $(top_srcdir)/macros/pkg.m4 \
+       $(top_srcdir)/macros/po.m4 $(top_srcdir)/macros/progtest.m4 \
+       $(top_srcdir)/macros/pthreads.m4 $(top_srcdir)/macros/sdl.m4 \
+       $(top_srcdir)/macros/x11.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(pkglibdir)" "$(DESTDIR)$(includedir)"
+pkglibLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
address@hidden@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
address@hidden@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1)
address@hidden@am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1)
+libgnashmedia_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+       $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+       $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+       $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+       $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+       $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3) \
+       $(am__DEPENDENCIES_4)
+am__libgnashmedia_la_SOURCES_DIST = AudioDecoderNellymoser.cpp \
+       AudioDecoderSimple.cpp gst/VideoDecoderGst.cpp \
+       gst/sound_handler_gst.cpp sdl/VideoDecoderFfmpeg.cpp \
+       sdl/AudioDecoderFfmpeg.cpp sdl/sound_handler_sdl.cpp \
+       sdl/AudioDecoderMad.cpp
address@hidden@am__objects_1 =  \
address@hidden@ libgnashmedia_la-VideoDecoderGst.lo \
address@hidden@ libgnashmedia_la-sound_handler_gst.lo
address@hidden@am__objects_2 = libgnashmedia_la-VideoDecoderFfmpeg.lo \
address@hidden@ libgnashmedia_la-AudioDecoderFfmpeg.lo \
address@hidden@ libgnashmedia_la-sound_handler_sdl.lo
address@hidden@am__objects_3 =  \
address@hidden@ libgnashmedia_la-AudioDecoderMad.lo \
address@hidden@ libgnashmedia_la-sound_handler_sdl.lo
+am_libgnashmedia_la_OBJECTS =  \
+       libgnashmedia_la-AudioDecoderNellymoser.lo \
+       libgnashmedia_la-AudioDecoderSimple.lo $(am__objects_1) \
+       $(am__objects_2) $(am__objects_3)
+libgnashmedia_la_OBJECTS = $(am_libgnashmedia_la_OBJECTS)
+libgnashmedia_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+       $(CXXFLAGS) $(libgnashmedia_la_LDFLAGS) $(LDFLAGS) -o $@
+libltdl_la_LIBADD =
+libltdl_la_SOURCES = libltdl.c
+libltdl_la_OBJECTS = libltdl.lo
address@hidden@am_libltdl_la_rpath = -rpath $(pkglibdir)
+DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
+depcomp =
+am__depfiles_maybe =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+       $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+       $(LDFLAGS) -o $@
+SOURCES = $(libgnashmedia_la_SOURCES) libltdl.c
+DIST_SOURCES = $(am__libgnashmedia_la_SOURCES_DIST) libltdl.c
+am__include_HEADERS_DIST = $(top_srcdir)/libltdl/ltdl.h
+includeHEADERS_INSTALL = $(INSTALL_HEADER)
+am__noinst_HEADERS_DIST = MediaBuffer.h MediaDecoder.h AudioDecoder.h \
+       VideoDecoder.h MediaParser.h AudioDecoderNellymoser.h \
+       AudioDecoderSimple.h sound_handler.h SoundInfo.h \
+       gst/VideoDecoderGst.h gst/sound_handler_gst.h \
+       sdl/AudioDecoderFfmpeg.h sdl/VideoDecoderFfmpeg.h \
+       sdl/sound_handler_sdl.h sdl/AudioDecoderMad.h
+HEADERS = $(include_HEADERS) $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AGG_CFLAGS = @AGG_CFLAGS@
+AGG_LIBS = @AGG_LIBS@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+ATK_CFLAGS = @ATK_CFLAGS@
+ATK_LIBS = @ATK_LIBS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AUTOTRACE = @AUTOTRACE@
+AWK = @AWK@
+BOOST_CFLAGS = @BOOST_CFLAGS@
+BOOST_LIBS = @BOOST_LIBS@
+CAIRO_CFLAGS = @CAIRO_CFLAGS@
+CAIRO_LIBS = @CAIRO_LIBS@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DB2X_MANXML = @DB2X_MANXML@
+DB2X_TEXIXML = @DB2X_TEXIXML@
+DB2X_VERSION = @DB2X_VERSION@
+DB2X_XSLTPROC = @DB2X_XSLTPROC@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DEFS = @DEFS@
+DEJAGNU_CFLAGS = @DEJAGNU_CFLAGS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DLOPEN = @DLOPEN@
+DLPREOPEN = @DLPREOPEN@
+DOXYGEN = @DOXYGEN@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXPAT_CFLAGS = @EXPAT_CFLAGS@
+EXPAT_LIBS = @EXPAT_LIBS@
+EXTENSIONS_LIST = @EXTENSIONS_LIST@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FFMPEG_CFLAGS = @FFMPEG_CFLAGS@
+FFMPEG_LIBS = @FFMPEG_LIBS@
+FIREFOX_PLUGINS = @FIREFOX_PLUGINS@
+FLTK2_CFLAGS = @FLTK2_CFLAGS@
+FLTK2_LIBS = @FLTK2_LIBS@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+FOP = @FOP@
+FREETYPE2_CFLAGS = @FREETYPE2_CFLAGS@
+FREETYPE2_LIBS = @FREETYPE2_LIBS@
+GLEXT_CFLAGS = @GLEXT_CFLAGS@
+GLEXT_LIBS = @GLEXT_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@
+GSTREAMER_LIBS = @GSTREAMER_LIBS@
+GTK2_CFLAGS = @GTK2_CFLAGS@
+GTK2_LIBS = @GTK2_LIBS@
+INCLTDL = @INCLTDL@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+JAVA = @JAVA@
+JPEG_CFLAGS = @JPEG_CFLAGS@
+JPEG_LIBS = @JPEG_LIBS@
+KDE_CFLAGS = @KDE_CFLAGS@
+KDE_CONFIG = @KDE_CONFIG@
+KDE_LIBS = @KDE_LIBS@
+KLASH_PLUGIN = @KLASH_PLUGIN@
+LDFLAGS = @LDFLAGS@
+LIBADD_DL = @LIBADD_DL@
+LIBEXT = @LIBEXT@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBLTDL = @LIBLTDL@
+LIBOBJS = @LIBOBJS@
+LIBPRE = @LIBPRE@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LIBXML_CFLAGS = @LIBXML_CFLAGS@
+LIBXML_LIBS = @LIBXML_LIBS@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAD_CFLAGS = @MAD_CFLAGS@
+MAD_LIBS = @MAD_LIBS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAKESWF = @MAKESWF@
+MEDIA_CONFIG = @MEDIA_CONFIG@
+MING_CFLAGS = @MING_CFLAGS@
+MING_CONFIG = @MING_CONFIG@
+MING_LIBS = @MING_LIBS@
+MING_VERSION = @MING_VERSION@
+MING_VERSION_CODE = @MING_VERSION_CODE@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MOC = @MOC@
+MSGFMT = @MSGFMT@
+MSGMERGE = @MSGMERGE@
+MTASC = @MTASC@
+MTASC_CLASSPATH = @MTASC_CLASSPATH@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_LIBS = @MYSQL_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENGL_CFLAGS = @OPENGL_CFLAGS@
+OPENGL_LIBS = @OPENGL_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PANGO_CFLAGS = @PANGO_CFLAGS@
+PANGO_LIBS = @PANGO_LIBS@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PDFXMLTEX = @PDFXMLTEX@
+PKG_CONFIG = @PKG_CONFIG@
+POSUB = @POSUB@
+PRTDIAG = @PRTDIAG@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_CXX = @PTHREAD_CXX@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+QT_CFLAGS = @QT_CFLAGS@
+QT_LIBS = @QT_LIBS@
+RANLIB = @RANLIB@
+RENDERER_CONFIG = @RENDERER_CONFIG@
+RENDERER_LIBS = @RENDERER_LIBS@
+SCROLLINSTALL = @SCROLLINSTALL@
+SCROLLKEEPER = @SCROLLKEEPER@
+SCROLLUPDATE = @SCROLLUPDATE@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_CONFIG = @SDL_CONFIG@
+SDL_LIBS = @SDL_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SUPPORTED_GUIS = @SUPPORTED_GUIS@
+SWFC = @SWFC@
+SWFDEC_TESTSUITE = @SWFDEC_TESTSUITE@
+SWFMILL = @SWFMILL@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+X11_CFLAGS = @X11_CFLAGS@
+X11_LIBS = @X11_LIBS@
+XFT_CFLAGS = @XFT_CFLAGS@
+XFT_LIBS = @XFT_LIBS@
+XGETTEXT = @XGETTEXT@
+XML2_CONFIG = @XML2_CONFIG@
+XSLTPROC = @XSLTPROC@
+Z_CFLAGS = @Z_CFLAGS@
+Z_LIBS = @Z_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+curlconfig = @curlconfig@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docbook_styles = @docbook_styles@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mconfig = @mconfig@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pth_config = @pth_config@
+pthread_config = @pthread_config@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AUTOMAKE_OPTIONS = no-dependencies foreign
+EXTRA_DIST = 
+
+# this is where Gnash plugins get installed
+pluginsdir = $(prefix)/lib/gnash/plugins
address@hidden@include_HEADERS = $(top_srcdir)/libltdl/ltdl.h
address@hidden@LIBLTDLLIB = libltdl.la
address@hidden@LIBLTDLHEAD = $(top_srcdir)/libltdl/ltdl.h
+
+# If we are using an installable libltdl, then it needs to be built
+# before libgnash, as libgnash depends on it for extensions.
+pkglib_LTLIBRARIES = $(LIBLTDLLIB) libgnashmedia.la
+libgnashmedia_la_CPPFLAGS = -I.. -I$(srcdir) -I$(top_srcdir) \
+       -I$(top_srcdir)/libamf -I$(top_srcdir)/backend \
+       -I$(top_srcdir)/libbase -I$(top_srcdir)/server \
+       $(PTHREAD_CFLAGS) $(OPENGL_CFLAGS) $(LIBXML_CFLAGS) \
+       $(PNG_CFLAGS) $(SDL_CFLAGS) $(GLIB_CFLAGS) $(GSTREAMER_CFLAGS) \
+       $(CURL_CFLAGS) $(Z_CFLAGS) $(JPEG_CFLAGS) $(BOOST_CFLAGS) \
+       $(INCLTDL) $(NULL) $(am__append_3) $(am__append_8) \
+       $(am__append_12)
+
+# These headers get installed
+# include_HEADERS = log.h err.h proc.h serial.h xantrex.h outback.h
+
+# Don't build Dmalloc support if it's not configured in
address@hidden@DMALLOC_FILE = dlmalloc.c
+libgnashmedia_la_LIBADD = $(JPEG_LIBS) $(Z_LIBS) $(CURL_LIBS) \
+       $(OPENGL_LIBS) $(LIBINTL) $(LIBLTDL) $(BOOST_LIBS) \
+       $(PTHREAD_LIBS) $(SDL_LIBS) $(NULL) $(am__append_4) \
+       $(am__append_7) $(am__append_11)
+libgnashmedia_la_SOURCES = AudioDecoderNellymoser.cpp \
+       AudioDecoderSimple.cpp $(NULL) $(am__append_1) $(am__append_5) \
+       $(am__append_9)
+noinst_HEADERS = MediaBuffer.h MediaDecoder.h AudioDecoder.h \
+       VideoDecoder.h MediaParser.h AudioDecoderNellymoser.h \
+       AudioDecoderSimple.h sound_handler.h SoundInfo.h $(NULL) \
+       $(am__append_2) $(am__append_6) $(am__append_10)
+libgnashmedia_la_LDFLAGS = -release $(VERSION)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  
$(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  libmedia/Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  libmedia/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ 
$(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ 
$(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure 
$(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES)
+       @$(NORMAL_INSTALL)
+       test -z "$(pkglibdir)" || $(MKDIR_P) "$(DESTDIR)$(pkglibdir)"
+       @list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \
+         if test -f $$p; then \
+           f=$(am__strip_dir) \
+           echo " $(LIBTOOL) --mode=install $(pkglibLTLIBRARIES_INSTALL) 
$(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(pkglibdir)/$$f'"; \
+           $(LIBTOOL) --mode=install $(pkglibLTLIBRARIES_INSTALL) 
$(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(pkglibdir)/$$f"; \
+         else :; fi; \
+       done
+
+uninstall-pkglibLTLIBRARIES:
+       @$(NORMAL_UNINSTALL)
+       @list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \
+         p=$(am__strip_dir) \
+         echo " $(LIBTOOL) --mode=uninstall rm -f 
'$(DESTDIR)$(pkglibdir)/$$p'"; \
+         $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$p"; \
+       done
+
+clean-pkglibLTLIBRARIES:
+       -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES)
+       @list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \
+         dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+         test "$$dir" != "$$p" || dir=.; \
+         echo "rm -f \"$${dir}/so_locations\""; \
+         rm -f "$${dir}/so_locations"; \
+       done
+libgnashmedia.la: $(libgnashmedia_la_OBJECTS) $(libgnashmedia_la_DEPENDENCIES) 
+       $(libgnashmedia_la_LINK) -rpath $(pkglibdir) 
$(libgnashmedia_la_OBJECTS) $(libgnashmedia_la_LIBADD) $(LIBS)
+libltdl.la: $(libltdl_la_OBJECTS) $(libltdl_la_DEPENDENCIES) 
+       $(LINK) $(am_libltdl_la_rpath) $(libltdl_la_OBJECTS) 
$(libltdl_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+.c.o:
+       $(COMPILE) -c $<
+
+.c.obj:
+       $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+       $(LTCOMPILE) -c -o $@ $<
+
+.cpp.o:
+       $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+       $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+       $(LTCXXCOMPILE) -c -o $@ $<
+
+libgnashmedia_la-AudioDecoderNellymoser.lo: AudioDecoderNellymoser.cpp
+       $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile 
$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnashmedia_la_CPPFLAGS) 
$(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o 
libgnashmedia_la-AudioDecoderNellymoser.lo `test -f 
'AudioDecoderNellymoser.cpp' || echo '$(srcdir)/'`AudioDecoderNellymoser.cpp
+
+libgnashmedia_la-AudioDecoderSimple.lo: AudioDecoderSimple.cpp
+       $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile 
$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnashmedia_la_CPPFLAGS) 
$(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o 
libgnashmedia_la-AudioDecoderSimple.lo `test -f 'AudioDecoderSimple.cpp' || 
echo '$(srcdir)/'`AudioDecoderSimple.cpp
+
+libgnashmedia_la-VideoDecoderGst.lo: gst/VideoDecoderGst.cpp
+       $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile 
$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnashmedia_la_CPPFLAGS) 
$(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o 
libgnashmedia_la-VideoDecoderGst.lo `test -f 'gst/VideoDecoderGst.cpp' || echo 
'$(srcdir)/'`gst/VideoDecoderGst.cpp
+
+libgnashmedia_la-sound_handler_gst.lo: gst/sound_handler_gst.cpp
+       $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile 
$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnashmedia_la_CPPFLAGS) 
$(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o 
libgnashmedia_la-sound_handler_gst.lo `test -f 'gst/sound_handler_gst.cpp' || 
echo '$(srcdir)/'`gst/sound_handler_gst.cpp
+
+libgnashmedia_la-VideoDecoderFfmpeg.lo: sdl/VideoDecoderFfmpeg.cpp
+       $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile 
$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnashmedia_la_CPPFLAGS) 
$(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o 
libgnashmedia_la-VideoDecoderFfmpeg.lo `test -f 'sdl/VideoDecoderFfmpeg.cpp' || 
echo '$(srcdir)/'`sdl/VideoDecoderFfmpeg.cpp
+
+libgnashmedia_la-AudioDecoderFfmpeg.lo: sdl/AudioDecoderFfmpeg.cpp
+       $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile 
$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnashmedia_la_CPPFLAGS) 
$(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o 
libgnashmedia_la-AudioDecoderFfmpeg.lo `test -f 'sdl/AudioDecoderFfmpeg.cpp' || 
echo '$(srcdir)/'`sdl/AudioDecoderFfmpeg.cpp
+
+libgnashmedia_la-sound_handler_sdl.lo: sdl/sound_handler_sdl.cpp
+       $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile 
$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnashmedia_la_CPPFLAGS) 
$(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o 
libgnashmedia_la-sound_handler_sdl.lo `test -f 'sdl/sound_handler_sdl.cpp' || 
echo '$(srcdir)/'`sdl/sound_handler_sdl.cpp
+
+libgnashmedia_la-AudioDecoderMad.lo: sdl/AudioDecoderMad.cpp
+       $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile 
$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnashmedia_la_CPPFLAGS) 
$(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o 
libgnashmedia_la-AudioDecoderMad.lo `test -f 'sdl/AudioDecoderMad.cpp' || echo 
'$(srcdir)/'`sdl/AudioDecoderMad.cpp
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+install-includeHEADERS: $(include_HEADERS)
+       @$(NORMAL_INSTALL)
+       test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
+       @list='$(include_HEADERS)'; for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         f=$(am__strip_dir) \
+         echo " $(includeHEADERS_INSTALL) '$$d$$p' 
'$(DESTDIR)$(includedir)/$$f'"; \
+         $(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \
+       done
+
+uninstall-includeHEADERS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(include_HEADERS)'; for p in $$list; do \
+         f=$(am__strip_dir) \
+         echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \
+         rm -f "$(DESTDIR)$(includedir)/$$f"; \
+       done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+           $$tags $$unique; \
+       fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(CTAGS_ARGS)$$tags$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$tags $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+       for dir in "$(DESTDIR)$(pkglibdir)" "$(DESTDIR)$(includedir)"; do \
+         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+       done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+       mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-includeHEADERS
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-pkglibLTLIBRARIES
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-includeHEADERS uninstall-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+       clean-libtool clean-pkglibLTLIBRARIES ctags distclean \
+       distclean-compile distclean-generic distclean-libtool \
+       distclean-tags distdir dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-includeHEADERS install-info \
+       install-info-am install-man install-pdf install-pdf-am \
+       install-pkglibLTLIBRARIES install-ps install-ps-am \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+       pdf pdf-am ps ps-am tags uninstall uninstall-am \
+       uninstall-includeHEADERS uninstall-pkglibLTLIBRARIES
+
+
+# Rebuild with GCC 4.x Mudflap support
+mudflap:
+       @echo "Rebuilding with GCC Mudflap support"
+       $(MAKE) CXXFLAGS="$(CXXFLAGS) -fmudflap" LDFLAGS="$(LDFLAGS) -lmudflap"
+
+clean-hook:
+       -rm -f core.* *.obj
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:

Index: libmedia/MediaBuffer.h
===================================================================
RCS file: libmedia/MediaBuffer.h
diff -N libmedia/MediaBuffer.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/MediaBuffer.h      27 Sep 2007 23:59:53 -0000      1.1
@@ -0,0 +1,247 @@
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+//  $Id:
+
+#ifndef __MEDIABUFFER_H__
+#define __MEDIABUFFER_H__
+
+#include <boost/thread/mutex.hpp>
+#include <queue>
+
+namespace gnash {
+  
+class raw_mediadata_t
+{
+public:
+       raw_mediadata_t():
+       m_stream_index(-1),
+       m_size(0),
+       m_data(NULL),
+       m_ptr(NULL),
+       m_pts(0)
+       {
+       }
+
+       ~raw_mediadata_t()
+       {
+               if (m_data) delete [] m_data;
+       }
+
+       int m_stream_index;
+       uint32_t m_size;
+       uint8_t* m_data;
+       uint8_t* m_ptr;
+       uint32_t m_pts; // presentation timestamp in millisec
+};
+
+/// Threadsafe elements-owning queue
+//
+/// This class is a threadsafe queue, using std:queue and locking.
+/// It is used to store decoded audio and video data which are waiting to be 
"played"
+/// Elements of the queue are owned by instances of this class.
+///
+class MediaBuffer
+{
+public:
+       MediaBuffer()
+                       :
+       _bufferTime(100) // Deafault value is 100 milliseconds
+       {
+       }
+
+       ~MediaBuffer()
+       {
+               flush();
+       }
+
+       /// Returns the size if the audio queue. Locks.
+       //
+       /// @return the size of the audio queue
+       ///
+       size_t audioSize() {
+               boost::mutex::scoped_lock lock(_mutex);
+               return audioQueue.size();
+       }
+
+       /// Returns the size if the video queue. Locks.
+       //
+       /// @return the size of the video queue
+       ///
+       size_t videoSize() {
+               boost::mutex::scoped_lock lock(_mutex);
+               return videoQueue.size();
+       }
+
+       /// Pushes an element to the audio queue. Locks.
+       //
+       /// @param member
+       /// The element to be pushed unto the audio queue.
+       ///
+       void pushAudio(raw_mediadata_t* member) {
+               boost::mutex::scoped_lock lock(_mutex);
+               audioQueue.push(member);
+       }
+
+       /// Pushes an element to the video queue. Locks.
+       //
+       /// @param member
+       /// The element to be pushed unto the video queue.
+       ///
+       void pushVideo(raw_mediadata_t* member) {
+               boost::mutex::scoped_lock lock(_mutex);
+               videoQueue.push(member);
+       }
+
+       /// Returns a pointer to the first element on the audio queue. Locks.
+       //
+       /// If no elements are available this function returns NULL.
+       ///
+       /// @return a pointer to the first element on the audio queue, NULL if 
queue is empty.
+       ///
+       raw_mediadata_t* audioFront() {
+               boost::mutex::scoped_lock lock(_mutex);
+               if (audioQueue.empty()) return NULL;
+               return audioQueue.front();
+       }
+
+       /// Returns a pointer to the first element on the video queue. Locks.
+       //
+       /// If no elements are available this function returns NULL.
+       ///
+       /// @return a pointer to the first element on the video queue, NULL if 
queue is empty.
+       ///
+       raw_mediadata_t* videoFront() {
+               boost::mutex::scoped_lock lock(_mutex);
+               if (videoQueue.empty()) return NULL;
+               return videoQueue.front();
+       }
+
+       /// Pops the first element from the audio queue. Locks.
+       //
+       /// If no elements are available this function is a noop. 
+       ///
+       void audioPop() {
+               boost::mutex::scoped_lock lock(_mutex);
+               if (!audioQueue.empty()) audioQueue.pop();
+       }
+
+       /// Pops the first element from the video queue. Locks.
+       //
+       /// If no elements are available this function is a noop. 
+       ///
+       void videoPop() {
+               boost::mutex::scoped_lock lock(_mutex);
+               if (!videoQueue.empty()) videoQueue.pop();
+       }
+
+       /// Fluses the buffer/queues
+       void flush() {
+               boost::mutex::scoped_lock lock(_mutex);
+               while (!videoQueue.empty() > 0)
+               {
+                       delete videoQueue.front();
+                       videoQueue.pop();
+               }
+
+               while (!audioQueue.empty() > 0)
+               {
+                       delete audioQueue.front();
+                       audioQueue.pop();
+               }
+       }
+       
+       /// Sets the size of the buffer in milliseconds. Locks.
+       //
+       /// @param size
+       /// The size of the buffer.
+       ///
+       void setBufferTime(uint32_t size) {
+               boost::mutex::scoped_lock lock(_mutex);
+               _bufferTime = size;
+       }
+
+       /// Gets the requested size of the buffer in milliseconds. Locks.
+       //
+       /// @return the requested size of the buffer.
+       ///
+       uint32_t getReqBufferTime() {
+               boost::mutex::scoped_lock lock(_mutex);
+               return _bufferTime;
+       }
+
+       /// Gets the real size of the buffer in milliseconds. The size of
+       /// the audio and video buffer is compared and the biggest is returned. 
Locks.
+       //
+       /// @return the real size of the buffer in milliseconds.
+       ///
+       uint32_t getBufferTime() {
+               boost::mutex::scoped_lock lock(_mutex);
+               bool ret = calcBufferTime();
+               return ret;
+       }
+
+       /// Checks if the contents of the buffer span a timeframe larger than
+       /// than the requested size. Locks.
+       //
+       /// @return the real size of the buffer in milliseconds.
+       ///
+       bool isFull() {
+               boost::mutex::scoped_lock lock(_mutex);
+               bool ret = (calcBufferTime() >= _bufferTime);
+               return ret;
+       }
+
+private:
+
+       /// Calculates the real size of the buffer in milliseconds. The size of
+       /// the audio and video buffer is compared and the biggest is returned.
+       //
+       /// @return the real size of the buffer in milliseconds.
+       ///
+       uint32_t calcBufferTime() {
+               uint32_t size = 0;
+
+               // Get the size of audio buffer
+               if (!audioQueue.empty()) {
+                       size = audioQueue.back()->m_pts - 
audioQueue.front()->m_pts;
+               }
+
+               // Get the size of video buffer, and use that if it is bigger 
than
+               // the vaule from the audio buffer.
+               if (!videoQueue.empty()) {
+                       uint32_t vSize = videoQueue.back()->m_pts - 
videoQueue.front()->m_pts;
+                       if (vSize > size) size = vSize;
+               }
+               return size;
+       }
+
+
+       /// Mutex used for locking
+       boost::mutex _mutex;
+
+       /// The queues of audio and video data.
+       std::queue <raw_mediadata_t*> audioQueue;
+       std::queue <raw_mediadata_t*> videoQueue;
+
+       /// The requested size of the buffer in milliseconds
+       uint32_t _bufferTime;
+};
+
+} // gnash namespace
+
+#endif // __MEDIABUFFER_H__

Index: libmedia/MediaDecoder.h
===================================================================
RCS file: libmedia/MediaDecoder.h
diff -N libmedia/MediaDecoder.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/MediaDecoder.h     27 Sep 2007 23:59:53 -0000      1.1
@@ -0,0 +1,237 @@
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+//  $Id:
+
+#ifndef __MEDIADECODER_H__
+#define __MEDIADECODER_H__
+
+#include <boost/thread/thread.hpp>
+#include <boost/bind.hpp> 
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition.hpp>
+#include <vector> 
+
+#include "MediaBuffer.h"
+#include "MediaParser.h"
+#include "FLVParser.h"
+#include "log.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+namespace gnash {
+
+
+/// \brief
+/// The MediaDecoder class decodes media data and puts it on a given buffer.
+///
+/// We need to be able to handle event stuff, so we store the events that
+/// need to be handled, and then NetStream can ask for it on ::advance()
+/// or whenever it is appropriate. Eventhandling is different from AS2 to AS3,
+/// but in this first draft only AS2 will be supported.
+///
+class MediaDecoder
+{
+
+public:
+       /// Status codes used for NetStream onStatus notifications
+       // Copied from NetSteam.h, so it should be updated it the orginal
+       // is changed.
+       enum StatusCode {
+       
+               // Internal status, not a valid ActionScript value
+               invalidStatus,
+
+               /// NetStream.Buffer.Empty (level: status)
+               bufferEmpty,
+
+               /// NetStream.Buffer.Full (level: status)
+               bufferFull,
+
+               /// NetStream.Buffer.Flush (level: status)
+               bufferFlush,
+
+               /// NetStream.Play.Start (level: status)
+               playStart,
+
+               /// NetStream.Play.Stop  (level: status)
+               playStop,
+
+               /// NetStream.Seek.Notify  (level: status)
+               seekNotify,
+
+               /// NetStream.Play.StreamNotFound (level: error)
+               streamNotFound,
+
+               /// NetStream.Seek.InvalidTime (level: error)
+               invalidTime
+       };
+
+       /// This is copied from the render and should be changed if the 
original is.
+       enum videoOutputFormat
+       {
+               NONE,
+               YUV,
+               RGB
+       };
+
+       /// Internal error codes
+       enum MediaDecoderErrorCode {
+       
+               /// All is fine
+               noError,
+
+               /// Stream/connection error
+               streamError,
+
+               /// Error while decoding
+               decodingError,
+
+               /// Error while parsing
+               parsingError
+       };
+
+       /// \brief
+       /// Create a MediaDecoder reading input from
+       /// the given tu_file
+       //
+       /// @param stream
+       ///     tu_file to use for input.
+       ///     Ownership left to the caller.
+       ///
+       /// @param buffer
+       ///     The buffer we will use.
+       ///     Ownership left to the caller.
+       ///
+       MediaDecoder(tu_file* stream, MediaBuffer* buffer, uint16_t swfVersion, 
int format)
+               :
+       _buffer(buffer),
+       _stream(stream),
+       _swfVersion(swfVersion),
+       _videoFrameFormat(format),
+       _parser(NULL),
+       _lastConfirmedPosition(0),
+       _streamSize(0),
+       _error(noError),
+       _isFLV(true),
+       _inputPos(0),
+       _audio(true),
+       _video(true)
+       {
+       }
+
+       /// Destroys the Decoder
+       ~MediaDecoder() {}
+
+       /// Pause decoding (needed ?)
+       virtual void pause() {}
+
+       /// Resume/start decoding (needed ?)
+       virtual void decode() {}
+
+       /// Seeks to pos, returns the new position
+       virtual uint32_t seek(uint32_t /*pos*/) { return 0;}
+
+       virtual std::pair<uint32_t, uint32_t> getWidthAndHeight() { return 
std::pair<uint32_t, uint32_t>(0,0); }
+
+       /// Returns the size of the file being loaded, in bytes
+       uint32_t getBytesTotal()
+       {
+               return _streamSize;
+       }
+
+       /// Returns the amount of bytes of the current file that has been 
loaded.
+       uint32_t getBytesLoaded() {
+               return _lastConfirmedPosition;
+       }
+
+       /// Returns a vector with the waiting onStatus events (AS2)
+       std::vector<StatusCode> getOnStatusEvents() {
+               boost::mutex::scoped_lock lock(_onStatusMutex);
+
+               const std::vector<StatusCode> statusQueue(_onStatusQueue);
+               _onStatusQueue.clear();
+               return statusQueue;
+       }
+
+       /// Returns whether we got audio
+       bool gotAudio() {
+               return _audio;
+       }
+
+       /// Returns whether we got video
+       bool gotVideo() {
+               return _video;
+       }
+
+protected:
+       /// Push an event to the onStatus event queue (AS2)
+       void pushOnStatus(StatusCode code) {
+               boost::mutex::scoped_lock lock(_onStatusMutex);
+               _onStatusQueue.push_back(code); 
+       }
+
+       /// The media buffer
+       MediaBuffer* _buffer;
+
+       /// The stream we decode
+       tu_file* _stream;
+
+       /// Version of the SWF playing
+       uint16_t _swfVersion;
+       
+       /// The output format
+       int _videoFrameFormat;
+
+       /// The parser used
+       std::auto_ptr<MediaParser> _parser;
+
+       /// The last confirmed size of the downloaded file
+       uint32_t _lastConfirmedPosition;
+
+       /// total size of the file being downloaded
+       uint32_t _streamSize;
+
+       /// Is everything ok?
+       MediaDecoderErrorCode _error;
+
+       /// Waiting NetStream onStatus events (AS2)
+       std::vector<StatusCode> _onStatusQueue;
+
+       /// Mutex protecting _onStatusQueue
+       boost::mutex _onStatusMutex;
+
+       /// Are we decoding a FLV?
+       bool _isFLV;
+
+       /// The position in the inputfile, only used when not playing a FLV
+       long _inputPos;
+
+       /// Do we have audio ?
+       bool _audio;
+
+       /// Do we have video ?
+       bool _video;
+
+};
+
+
+} // namespace gnash
+
+#endif // __MEDIADECODER_H__

Index: libmedia/MediaParser.h
===================================================================
RCS file: libmedia/MediaParser.h
diff -N libmedia/MediaParser.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/MediaParser.h      27 Sep 2007 23:59:53 -0000      1.1
@@ -0,0 +1,220 @@
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+//  $Id:
+
+#ifndef __MEDIAPARSER_H__
+#define __MEDIAPARSER_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tu_file.h"
+
+#ifdef USE_FFMPEG
+#include <ffmpeg/avcodec.h>
+#endif
+namespace gnash {
+
+enum codecType
+{
+       FLASH,
+       FFMPEG
+};
+
+enum videoCodecType
+{
+       VIDEO_CODEC_H263 = 2,   // H263/SVQ3 video codec
+       VIDEO_CODEC_SCREENVIDEO = 3,    // Screenvideo codec
+       VIDEO_CODEC_VP6 = 4,            // On2 VP6 video codec
+       VIDEO_CODEC_VP6A = 5,           // On2 VP6 Alpha video codec
+       VIDEO_CODEC_SCREENVIDEO2 = 6    // Screenvideo2 codec
+};
+
+enum audioCodecType
+{
+       AUDIO_CODEC_RAW = 0,            // unspecified format.  Useful for 
8-bit sounds???
+       AUDIO_CODEC_ADPCM = 1,  // gnash doesn't pass this through; it 
uncompresses and sends FORMAT_NATIVE16
+       AUDIO_CODEC_MP3 = 2,
+       AUDIO_CODEC_UNCOMPRESSED = 3,   // 16 bits/sample, little-endian
+       AUDIO_CODEC_NELLYMOSER_8HZ_MONO = 5,    // According to ffmpeg
+       AUDIO_CODEC_NELLYMOSER = 6      // Mystery proprietary format; see 
nellymoser.com
+};
+
+enum tagType
+{
+       AUDIO_TAG = 0x08,
+       VIDEO_TAG = 0x09,
+       META_TAG = 0x12
+};
+
+/// \brief
+/// The AudioInfo class contains information about the audiostream
+/// in the file being parsed. The information stored is codec-id,
+/// samplerate, samplesize, stereo, duration and codec-type.
+/// timestamp,
+class AudioInfo
+{
+public:
+       AudioInfo(int codeci, uint16_t sampleRatei, uint16_t sampleSizei, bool 
stereoi, uint64_t durationi, codecType typei)
+               : codec(codeci),
+               sampleRate(sampleRatei),
+               sampleSize(sampleSizei),
+               stereo(stereoi),
+               duration(durationi),
+               type(typei)
+               {
+               }
+
+       int codec;
+       uint16_t sampleRate;
+       uint16_t sampleSize;
+       bool stereo;
+       uint64_t duration;
+       codecType type;
+};
+
+/// \brief
+/// The VideoInfo class contains information about the videostream
+/// in the file being parsed. The information stored is codec-id,
+/// width, height, framerate, duration and codec-type.
+/// timestamp,
+class VideoInfo
+{
+public:
+       VideoInfo(int codeci, uint16_t widthi, uint16_t heighti, uint16_t 
frameRatei, uint64_t durationi, codecType typei)
+               : codec(codeci),
+               width(widthi),
+               height(heighti),
+               frameRate(frameRatei),
+               duration(durationi),
+#ifdef USE_FFMPEG
+               videoCodecCtx(NULL),
+#endif
+               type(typei)
+               {
+               }
+
+       int codec;
+       uint16_t width;
+       uint16_t height;
+       uint16_t frameRate;
+       uint64_t duration;
+#ifdef USE_FFMPEG
+       AVCodecContext* videoCodecCtx; // UGLY!!
+#endif
+       codecType type;
+};
+
+/// \brief
+/// The MediaFrame class contains a video or audio frame, its size, its
+/// timestamp. Ownership of the data is in the parser.
+class MediaFrame
+{
+public:
+       uint32_t dataSize;
+       uint8_t* data;
+       uint64_t timestamp;
+       uint8_t tag;
+};
+
+/// \brief
+/// The MediaParser class detects the format of the input file, and parses it 
on demand.
+///
+class MediaParser
+{
+public:
+       MediaParser(tu_file* stream)
+       :
+       _isAudioMp3(false),
+       _isAudioNellymoser(false),
+       _stream(stream)
+       {}
+
+       /// Used to parse the next media frame in the stream and return it
+       //
+       /// @return a pointer to a MediaFrame in which the undecoded frame data 
is.
+       virtual MediaFrame* parseMediaFrame() { return NULL; }
+
+       /// Is the input MP3?
+       //
+       /// @return if the input audio is MP3
+       bool isAudioMp3() { return _isAudioMp3; }
+
+       /// Is the input Nellymoser?
+       //
+       /// @return if the input audio is Nellymoser
+       bool isAudioNellymoser() { return _isAudioNellymoser; }
+
+       /// Setup the parser
+       //
+       /// @return whether we'll be able to parse the file.
+       virtual bool setupParser() { return false; }
+
+       /// Returns a VideoInfo class about the videostream
+       //
+       /// @return a VideoInfo class about the videostream
+       virtual std::auto_ptr<VideoInfo> getVideoInfo() { return 
std::auto_ptr<VideoInfo>(NULL); }
+
+       /// Returns a AudioInfo class about the audiostream
+       //
+       /// @return a AudioInfo class about the audiostream
+       virtual std::auto_ptr<AudioInfo> getAudioInfo() { return 
std::auto_ptr<AudioInfo>(NULL); }
+
+       /// Seeks to the closest possible position the given position,
+       /// and returns the new position.
+       //
+       /// @return the position the seek reached
+       virtual uint32_t seek(uint32_t) { return 0; }
+
+       /// Returns the framedelay from the last to the current
+       /// audioframe in milliseconds. This is used for framerate.
+       //
+       /// @return the diff between the current and last frame
+       virtual uint32_t audioFrameDelay() { return 0; }
+
+       /// Returns the framedelay from the last to the current
+       /// videoframe in milliseconds. 
+       //
+       /// @return the diff between the current and last frame
+       virtual uint32_t videoFrameDelay() { return 0; }
+
+       /// Returns the framerate of the video
+       //
+       /// @return the framerate of the video
+       virtual uint16_t videoFrameRate() { return 0; }
+
+       /// Returns the last parsed position in the file in bytes
+       virtual uint32_t getLastParsedPos() { return 0; }
+
+protected:
+
+       /// Is the input audio MP3?
+       bool _isAudioMp3;
+
+       /// Is the input audio Nellymoser?
+       bool _isAudioNellymoser;
+
+       /// The stream used to access the file
+       tu_file* _stream;
+};
+
+
+} // namespace gnash
+
+#endif // __MEDIAPARSER_H__

Index: libmedia/SoundInfo.h
===================================================================
RCS file: libmedia/SoundInfo.h
diff -N libmedia/SoundInfo.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/SoundInfo.h        27 Sep 2007 23:59:53 -0000      1.1
@@ -0,0 +1,114 @@
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+// 
+//
+
+// $Id:
+
+#ifndef __SOUNDINFO_H__
+#define __SOUNDINFO_H__
+
+#include "MediaParser.h"
+
+namespace gnash {
+
+///
+/// Class containing information about a sound. Is created by the parser while
+/// parsing, and ownership is then transfered to sound_data. When the parser is
+/// parsing streams, it will ask the soundhandler for this to know what 
properties
+/// the stream has.
+///
+class SoundInfo {
+public:
+       /// Constructor
+       //
+       /// @param format
+       /// The format of the sound. Can be MP3, ADPCM, uncompressed or 
Nellymoser
+       ///
+       /// @param stero
+       /// Defines whether the sound is in stereo.
+       ///
+       /// @param sampleRate
+       /// The sample rate of the sound.
+       ///
+       /// @param sampleCount
+       /// The sample count in the sound. In soundstreams this is an average 
for each frame.
+       ///
+       /// @param is16bit
+       /// Defines whether the sound is in stereo.
+       /// Defines whether the sound is in 16bit format (samplesize == 2)? 
else it 
+       /// is 8bit (samplesize == 1). Used for streams when decoding adpcm.
+       ///
+       SoundInfo(audioCodecType format, bool stereo, uint32_t sampleRate, 
uint32_t sampleCount, bool is16bit)
+       :       _format(format),
+               _stereo(stereo),
+               _sampleRate(sampleRate),
+               _sampleCount(sampleCount),
+               _is16bit(is16bit)
+       {
+       }
+
+       /// Returns the current format of the sound
+       ///
+       /// @return the current format of the sound
+       audioCodecType getFormat() { return _format; }
+
+       /// Returns the stereo status of the sound
+       ///
+       /// @return the stereo status of the sound
+       bool isStereo() { return _stereo; }
+
+       /// Returns the samplerate of the sound
+       ///
+       /// @return the samplerate of the sound
+       unsigned long getSampleRate() { return _sampleRate; }
+
+       /// Returns the samplecount of the sound
+       ///
+       /// @return the samplecount of the sound
+       unsigned long getSampleCount() { return _sampleCount; }
+
+       /// Returns the 16bit status of the sound
+       ///
+       /// @return the 16bit status of the sound
+       bool is16bit() { return _is16bit; }
+
+private:
+       /// Current format of the sound (MP3, raw, etc).
+       audioCodecType _format;
+
+       /// The size of the undecoded data
+       unsigned long _dataSize;
+
+       /// Stereo or not
+       bool _stereo;
+
+       /// Sample rate, one of 5512, 11025, 22050, 44100
+       uint32_t _sampleRate;
+
+       /// Number of samples
+       uint32_t _sampleCount;
+
+       /// Is the audio in 16bit format (samplesize == 2)? else it 
+       /// is 8bit (samplesize == 1). Used for streams when decoding adpcm.
+       bool _is16bit;
+};
+
+} // namespace gnash
+
+#endif // __SOUNDINFO_H__

Index: libmedia/VideoDecoder.h
===================================================================
RCS file: libmedia/VideoDecoder.h
diff -N libmedia/VideoDecoder.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/VideoDecoder.h     27 Sep 2007 23:59:53 -0000      1.1
@@ -0,0 +1,107 @@
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+//  $Id:
+
+#ifndef __VIDEODECODER_H__
+#define __VIDEODECODER_H__
+
+#include "MediaParser.h"
+#include "image.h"
+
+namespace gnash {
+
+class VideoDecoder {
+       
+public:
+       VideoDecoder() {}
+       ~VideoDecoder() {}
+
+       /// Sets up the decoder.
+       //
+       /// @param info
+       ///     VideoInfo class with all the info needed to decode
+       ///     the video correctly.
+       ///
+       /// @return true if succesfull else false
+       ///
+       virtual bool setup(VideoInfo* /*info*/) { return false; }
+
+       /// Sets up the decoder.
+       //
+       /// @param width
+       ///     The width of the video
+       ///
+       /// @param height
+       ///     The height of the video
+       ///
+       /// @param deblocking
+       ///     Should a deblocking filter be used? 1 = off, 2 = on
+       ///
+       /// @param smoothing
+       ///     Should the video be smoothed?
+       ///
+       /// @param format
+       ///     The codec of the video, see codecType
+       ///
+       /// @param outputFormat
+       ///     The outputFormat of the video, see videoOutputFormat
+       ///
+       /// @return true if succesfull else false
+       ///
+       virtual bool setup(
+               int /*width*/,
+               int /*height*/,
+               int /*deblocking*/,
+               bool /*smoothing*/,
+               videoCodecType /*format*/,
+               int /*outputFormat*/) /* should this argument be of 
VideoOutputFormat type ?*/ { return false; }
+
+       /// Decodes a frame and returns a pointer to the data
+       //
+       /// @param input
+       ///     The video data
+       ///
+       /// @param inputSize
+       ///     The size of the video data
+       ///
+       /// @param outputSize
+       ///     The output size of the video data, is passed by reference.
+       ///
+       /// @return a pointer to the decoded data, or NULL if decoding fails.
+       ///     The caller owns the decoded data.
+       ///     
+       virtual uint8_t* decode(uint8_t* /*input*/, uint32_t /*inputSize*/, 
uint32_t& /*outputSize*/) { return NULL; }
+
+       /// Decodes a frame and returns an image::base containing it
+       //
+       /// @param input
+       ///     The video data
+       ///
+       /// @param inputSize
+       ///     The size of the video data
+       ///
+       /// @return a pointer to the image with the decoded data, or NULL if 
decoding fails.
+       ///     The caller owns the decoded data.
+       ///
+       virtual std::auto_ptr<image::image_base> decodeToImage(uint8_t* 
/*input*/, uint32_t /*inputSize*/) { return 
std::auto_ptr<image::image_base>(NULL); }
+
+};
+       
+} // gnash namespace
+
+#endif // __VIDEODECODER_H__

Index: libmedia/sound_handler.h
===================================================================
RCS file: libmedia/sound_handler.h
diff -N libmedia/sound_handler.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/sound_handler.h    27 Sep 2007 23:59:53 -0000      1.1
@@ -0,0 +1,532 @@
+// 
+//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+// 
+//
+
+/* $Id: sound_handler.h,v 1.1 2007/09/27 23:59:53 tgc Exp $ */
+
+/// \page sound_handler_intro Sound handler introduction
+///
+/// This page must be written, volunteers ? :)
+///
+
+#ifndef SOUND_HANDLER_H
+#define SOUND_HANDLER_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tu_config.h" // for DSOEXPORT
+#include "tu_types.h"
+#include "SoundInfo.h"
+
+#include <vector>
+#include <memory>
+#include <cassert>
+
+namespace gnash {
+       class stream;
+//     class SoundInfo;
+}
+
+namespace gnash {
+
+/// A buffer of bytes
+class Buffer {
+public:
+       Buffer()
+               :
+               _capacity(0),
+               _data(0),
+               _size(0)
+       {}
+
+       /// Create a Buffer with the given initial content
+       //
+       /// @param newData data to assign to this buffer.
+       ///     Allocated with new[]. Ownership transferred.
+       ///
+       /// @param size number of bytes in the new data
+       ///
+       Buffer(uint8_t* newData, size_t size)
+               :
+               _capacity(size),
+               _data(newData),
+               _size(size)
+       {}
+
+       /// Append data to this buffer
+       //
+       /// @param newData data to append to this buffer.
+       ///     Allocated with new[]. Ownership transferred.
+       ///
+       /// @param size number of bytes in the new data
+       ///
+       void append(uint8_t* newData, size_t size)
+       {
+               if ( ! _capacity )
+               {
+                       _data = newData;
+                       _size = size;
+                       _capacity = _size;
+                       return;
+               }
+
+               reserve(_size+size);
+
+               assert(_capacity >= _size+size);
+               memcpy(_data+_size, newData, size);
+               _size += size;
+               delete [] newData;
+       }
+
+       /// Assign data to this buffer
+       //
+       /// @param newData data to assign to this buffer.
+       ///     Allocated with new[]. Ownership transferred.
+       ///
+       /// @param size number of bytes in the new data
+       ///
+       void assign(uint8_t* newData, size_t size)
+       {
+               if ( ! _capacity )
+               {
+                       _data = newData;
+                       _size = size;
+                       _capacity = _size;
+                       return;
+               }
+
+               _size=0; // so reserve won't memcpy...
+               reserve(size);
+
+               assert(_capacity >= size);
+
+               memcpy(_data, newData, size);
+               _size = size;
+
+               delete [] newData;
+       }
+
+       const uint8_t* data() const
+       {
+               return _data;
+       }
+
+       uint8_t* data() 
+       {
+               return _data;
+       }
+
+       const uint8_t* data(size_t pos) const
+       {
+               assert(pos < _capacity);
+               return _data+pos;
+       }
+
+       uint8_t* data(size_t pos) 
+       {
+               assert(pos < _capacity);
+               return _data+pos;
+       }
+
+       void resize(size_t newSize)
+       {
+               // we won't change capacity here
+               // (should we?)
+               _size = newSize;
+       }
+
+       void reserve(size_t newCapacity)
+       {
+               if ( _capacity > newCapacity ) return;
+
+               // TODO: use smalles power of 2 bigger then newCapacity
+               _capacity = std::max(newCapacity, _capacity*2);
+
+               uint8_t* tmp = _data;
+               _data = new uint8_t[_capacity];
+               if ( tmp )
+               {
+                       if ( _size ) memcpy(_data, tmp, _size);
+                       delete [] tmp;
+               }
+       }
+
+       size_t size() const
+       {
+               return _size;
+       }
+
+       ~Buffer()
+       {
+               delete [] _data;
+       }
+
+private:
+
+       size_t _capacity;
+
+       uint8_t* _data;
+
+       size_t _size;
+
+};
+
+
+/// Sound handler.
+//
+/// Stores the audio found by the parser and plays on demand.
+/// Can also play sound from AS classes NetStream and Sound using callbacks
+/// (see attach_aux_streamer and dettach_aux_streamer).
+///
+/// You may define a subclass of this, and pass an instance to
+/// set_sound_handler().
+///
+class DSOEXPORT sound_handler
+{
+public:
+
+       // See attach_aux_streamer
+       // TODO: change third parameter type to unsigned
+       typedef bool (*aux_streamer_ptr)(void *udata, uint8_t *stream, int len);
+
+       /// Used to control volume for event sounds. It basically tells that 
from
+       /// sample X the volume for left out is Y and for right out is Z. 
Several
+       /// envelopes can be assigned to a sound to make a fade out or similar 
stuff.
+       struct sound_envelope
+       {
+               uint32_t m_mark44;
+               uint16_t m_level0;
+               uint16_t m_level1;
+       };
+
+       // If stereo is true, samples are interleaved w/ left sample first.
+       
+       /// gnash's parser calls this to create sounds to be played later.
+       //
+       /// @param data
+       ///     The data to be stored. For soundstream this is NULL.
+       ///     If not NULL, ownership of the data is transferred.
+       ///     The data is assumed to have been allocated using new[].
+       ///
+       /// @param data_bytes
+       ///     The size of the data to be stored. For soundstream this is 0.
+       ///
+       /// @param sinfo
+       ///     A SoundInfo object contained in an auto_ptr, which contains 
info about samplerate,
+       ///     samplecount, stereo and more. The SoundObject must be not-NULL!
+       ///
+       /// @return the id given by the soundhandler for later identification.
+       ///
+       virtual int     create_sound(
+               void*           data,
+               unsigned int    data_bytes,
+               std::auto_ptr<SoundInfo> sinfo
+               ) = 0;
+
+       /// gnash's parser calls this to fill up soundstreams data
+       //
+       /// @param data
+       ///     The sound data to be saved, allocated by new[]. Ownership is 
transferred.
+       ///     TODO: define a class for containing both data and data_bytes ? 
or use vector ?
+       ///
+       /// @param data_bytes
+       ///     Size of the data in bytes
+       ///
+       /// @param sample_count
+       ///     Number of samples in the data
+       ///
+       /// @param handle_id
+       ///     The soundhandlers id of the sound we want some info about.
+       ///
+       /// @return size of the data buffer before the new data is appended
+       ///
+       virtual long    fill_stream_data(unsigned char* data, unsigned int 
data_bytes, unsigned int sample_count, int handle_id) = 0;
+
+       /// Returns a pointer to the SoundInfo object for the sound with the 
given id.
+       /// The SoundInfo object is still owned by the soundhandler.
+       //
+       /// @param soundhandle
+       /// The soundhandlers id of the sound we want some info about.
+       ///
+       /// @return a pointer to the SoundInfo object for the sound with the 
given id.
+       ///
+       virtual SoundInfo* get_sound_info(int sound_handle) = 0;
+
+       /// gnash calls this when it wants you to play the defined sound.
+       //
+       /// @param sound_handle
+       ///     The sound_handlers id for the sound to start playing
+       ///
+       /// @param loop_count
+       /// loop_count == 0 means play the sound once (1 means play it twice, 
etc)
+       ///
+       /// @param secondOffset
+       /// When starting soundstreams there sometimes is a offset to make the 
sound
+       /// start at the exact right moment.
+       ///
+       /// @param start
+       /// When starting a soundstream from a random frame, this tells where 
in the
+       /// data the decoding should start.
+       ///
+       /// @param envelopes
+       /// Some eventsounds have some volume control mechanism called 
envelopes.
+       /// They basically tells that from sample X the volume should be Y.
+       ///
+       virtual void    play_sound(int sound_handle, int loop_count, int 
secondOffset, long start, const std::vector<sound_envelope>* envelopes) = 0;
+
+       /// stops all sounds currently playing in a SWF file without stopping 
the playhead.
+       /// Sounds set to stream will resume playing as the playhead moves over 
the frames they are in.
+       virtual void    stop_all_sounds() = 0;
+
+       /// Gets the volume for a given sound. Only used by the AS Sound class
+       //
+       /// @param sound_handle
+       ///     The sound_handlers id for the sound to be deleted
+       ///
+       /// @return the sound volume level as an integer from 0 to 100,
+       /// where 0 is off and 100 is full volume. The default setting is 100.
+       virtual int     get_volume(int sound_handle) = 0;
+       
+       /// Sets the volume for a given sound. Only used by the AS Sound class
+       //
+       /// @param sound_handle
+       ///     The sound_handlers id for the sound to be deleted
+       ///
+       /// @param volume
+       /// A number from 0 to 100 representing a volume level. 
+       /// 100 is full volume and 0 is no volume. The default setting is 100.
+       ///
+       virtual void    set_volume(int sound_handle, int volume) = 0;
+               
+       /// Stop the specified sound if it's playing.
+       /// (Normally a full-featured sound API would take a
+       /// handle specifying the *instance* of a playing
+       /// sample, but SWF is not expressive that way.)
+       //
+       /// @param sound_handle
+       ///     The sound_handlers id for the sound to be deleted
+       ///
+       virtual void    stop_sound(int sound_handle) = 0;
+               
+       /// gnash calls this when it's done with a particular sound.
+       //
+       /// @param sound_handle
+       ///     The sound_handlers id for the sound to be deleted
+       ///
+       virtual void    delete_sound(int sound_handle) = 0;
+               
+       /// gnash calls this to mute audio
+       virtual void    mute() = 0;
+
+       /// gnash calls this to unmute audio
+       virtual void    unmute() = 0;
+
+       /// Returns whether or not sound is muted.
+       //
+       /// @return true if muted, false if not
+       ///
+       virtual bool    is_muted() = 0;
+
+       /// This is called by AS classes NetStream or Sound to attach callback, 
so
+       /// that audio from the classes will be played through the soundhandler.
+       //
+       /// This is actually only used by the SDL sound_handler. It uses these 
"auxiliary"
+       /// streamers to fetch decoded audio data to mix and send to the output 
channel.
+       ///
+       /// The "aux streamer" will be called with the 'udata' pointer as first 
argument,
+       /// then will be passed a buffer pointer as second argument and it's 
length
+       /// as third. The callbacks should fill the given buffer if possible.
+       /// The callback should return true if wants to remain attached, false 
if wants
+       /// to be detached. 
+       ///
+       /// @param ptr
+       ///     The pointer to the callback function
+       ///
+       /// @param udata
+       ///     User data pointer, passed as first argument to the registered 
callback.
+       ///     WARNING: this is currently also used to *identify* the callback 
for later
+       ///     removal, see detach_aux_streamer. TODO: stop using the data 
pointer for 
+       ///     identification purposes and use the callback pointer directly 
instead.
+       ///
+       virtual void    attach_aux_streamer(aux_streamer_ptr ptr, void* owner) 
= 0;
+
+       /// This is called by AS classes NetStream or Sound to dettach 
callback, so
+       /// that audio from the classes no longer will be played through the 
+       /// soundhandler.
+       //
+       /// @param udata
+       ///     The key identifying the auxiliary streamer.
+       ///     WARNING: this need currently be the 'udata' pointer passed to 
attach_aux_streamer.
+       ///     TODO: get the aux_streamer_ptr as key !!
+       ///
+       virtual void    detach_aux_streamer(void* udata) = 0;
+
+       sound_handler()
+               :
+               _soundsStarted(0),
+               _soundsStopped(0)
+       {}
+
+       virtual ~sound_handler() {};
+       
+       /// \brief
+       /// Gets the duration in milliseconds of an event sound connected
+       /// to an AS Sound obejct.
+       //
+       /// @param sound_handle
+       /// The id of the event sound
+       ///
+       /// @return the duration of the sound in milliseconds
+       virtual unsigned int get_duration(int sound_handle) = 0;
+
+       /// \brief
+       /// Gets the playhead position in milliseconds of an event sound 
connected
+       /// to an AS Sound obejct.
+       //
+       /// @param sound_handle
+       /// The id of the event sound
+       ///
+       /// @return the duration of the sound in milliseconds
+       virtual unsigned int get_position(int sound_handle) = 0;
+
+       /// Special test-fuction. Reports how many times a sound has been 
started
+       size_t numSoundsStarted() const { return _soundsStarted; }
+
+       /// Special test-fuction. Reports how many times a sound has been 
stopped
+       size_t numSoundsStopped() const { return _soundsStopped; }
+
+protected:
+
+       /// Special test-member. Stores count of started sounds.
+       size_t _soundsStarted;
+
+       /// Special test-member. Stores count of stopped sounds.
+       size_t _soundsStopped;
+};
+
+/*
+///
+/// Class containing information about a sound. Is created by the parser while
+/// parsing, and ownership is then transfered to sound_data. When the parser is
+/// parsing streams, it will ask the soundhandler for this to know what 
properties
+/// the stream has.
+///
+class SoundInfo {
+public:
+       /// Constructor
+       //
+       /// @param format
+       /// The format of the sound. Can be MP3, ADPCM, uncompressed or 
Nellymoser
+       ///
+       /// @param stero
+       /// Defines whether the sound is in stereo.
+       ///
+       /// @param sampleRate
+       /// The sample rate of the sound.
+       ///
+       /// @param sampleCount
+       /// The sample count in the sound. In soundstreams this is an average 
for each frame.
+       ///
+       /// @param is16bit
+       /// Defines whether the sound is in stereo.
+       /// Defines whether the sound is in 16bit format (samplesize == 2)? 
else it 
+       /// is 8bit (samplesize == 1). Used for streams when decoding adpcm.
+       ///
+       SoundInfo(sound_handler::format_type format, sound_handler::format_type 
orgFormat, bool stereo, uint32_t sampleRate, uint32_t sampleCount, bool is16bit)
+       :       _format(format),
+               _orgFormat(orgFormat),
+               _stereo(stereo),
+               _sampleRate(sampleRate),
+               _sampleCount(sampleCount),
+               _is16bit(is16bit)
+       {
+       }
+
+       /// Returns the current format of the sound
+       ///
+       /// @return the current format of the sound
+       sound_handler::format_type getFormat() { return _format; }
+
+       /// Returns the original format of the sound
+       ///
+       /// @return the original format of the sound
+       sound_handler::format_type getOrgFormat() { return _orgFormat; }
+
+       /// Returns the stereo status of the sound
+       ///
+       /// @return the stereo status of the sound
+       bool isStereo() { return _stereo; }
+
+       /// Returns the samplerate of the sound
+       ///
+       /// @return the samplerate of the sound
+       unsigned long getSampleRate() { return _sampleRate; }
+
+       /// Returns the samplecount of the sound
+       ///
+       /// @return the samplecount of the sound
+       unsigned long getSampleCount() { return _sampleCount; }
+
+       /// Returns the 16bit status of the sound
+       ///
+       /// @return the 16bit status of the sound
+       bool is16bit() { return _is16bit; }
+
+private:
+       /// Current format of the sound (MP3, raw, etc).
+       sound_handler::format_type _format;
+
+       /// Original format of the sound (ADPCM, etc).
+       sound_handler::format_type _orgFormat;
+
+       /// The size of the undecoded data
+       unsigned long _dataSize;
+
+       /// Stereo or not
+       bool _stereo;
+
+       /// Sample rate, one of 5512, 11025, 22050, 44100
+       uint32_t _sampleRate;
+
+       /// Number of samples
+       uint32_t _sampleCount;
+
+       /// Is the audio in 16bit format (samplesize == 2)? else it 
+       /// is 8bit (samplesize == 1). Used for streams when decoding adpcm.
+       bool _is16bit;
+};*/
+
+// TODO: move to appropriate specific sound handlers
+DSOEXPORT sound_handler*       create_sound_handler_sdl();
+DSOEXPORT sound_handler*       create_sound_handler_gst();
+DSOEXPORT sound_handler*       create_sound_handler_test();
+
+       
+
+}      // namespace gnash
+
+#endif // SOUND_HANDLER_H
+
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:

Index: libmedia/gst/VideoDecoderGst.cpp
===================================================================
RCS file: libmedia/gst/VideoDecoderGst.cpp
diff -N libmedia/gst/VideoDecoderGst.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/VideoDecoderGst.cpp    27 Sep 2007 23:59:54 -0000      1.1
@@ -0,0 +1,266 @@
+// 
+//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+// $Id: VideoDecoderGst.cpp,v 1.1 2007/09/27 23:59:54 tgc Exp $
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef SOUND_GST
+
+#include "VideoDecoderGst.h"
+
+namespace gnash {
+
+VideoDecoderGst::VideoDecoderGst() :
+       pipeline(NULL),
+       input(NULL),
+       inputcaps(NULL),
+       videocaps(NULL),
+       output(NULL),
+       decoder(NULL),
+       colorspace(NULL),
+       decodedFrame(NULL),
+       stop(false)
+
+{
+}
+
+VideoDecoderGst::~VideoDecoderGst()
+{
+
+       if (pipeline) {
+               stop = true;
+               delete input_lock;
+               gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
+               gst_object_unref (GST_OBJECT (pipeline));
+       }
+}
+
+bool
+VideoDecoderGst::setup(int widthi, int heighti, int deblockingi, bool 
smoothingi, videoCodecType formati, int outputFormati)
+{
+       // Save video attributes
+       width = widthi;
+       height = heighti;
+       deblocking = deblockingi;
+       smoothing = smoothingi;
+       format = formati;
+       outputFormat = outputFormati;
+
+       // For now only H263/SVQ3, VP6 and screenvideo1 is supported
+       if (format != VIDEO_CODEC_H263 && format != VIDEO_CODEC_VP6 && format 
!= VIDEO_CODEC_SCREENVIDEO) return false;
+
+       // init GStreamer
+       gst_init (NULL, NULL);
+
+       // setup the pipeline
+       pipeline = gst_pipeline_new (NULL);
+
+       // Setup the pipeline elements
+
+       // setup fake source
+       input = gst_element_factory_make ("fakesrc", NULL);
+       g_object_set (G_OBJECT (input), "sizetype", 3, /*"can-activate-pull", 
FALSE,*/ "signal-handoffs", TRUE, NULL);
+       // Setup the callback
+       g_signal_connect (input, "handoff", G_CALLBACK 
(VideoDecoderGst::callback_handoff), this);
+
+       // Setup the input capsfilter
+       inputcaps = gst_element_factory_make ("capsfilter", NULL);
+       GstCaps* caps = NULL;
+       if (format == VIDEO_CODEC_H263) {
+               caps = gst_caps_new_simple ("video/x-flash-video",
+                       "width", G_TYPE_INT, width,
+                       "height", G_TYPE_INT, height,
+                       "framerate", GST_TYPE_FRACTION, 25, 1,
+                       "flvversion", G_TYPE_INT, 1,
+                       NULL);
+       } else if (format == VIDEO_CODEC_VP6) {
+               caps = gst_caps_new_simple ("video/x-vp6-flash",
+                       "width", G_TYPE_INT, width,
+                       "height", G_TYPE_INT, height,
+                       "framerate", GST_TYPE_FRACTION, 25, 1,
+                       NULL);
+       } else if (format == VIDEO_CODEC_SCREENVIDEO) {
+               caps = gst_caps_new_simple ("video/x-flash-screen",
+                       "width", G_TYPE_INT, width,
+                       "height", G_TYPE_INT, height,
+                       "framerate", GST_TYPE_FRACTION, 25, 1,
+                       NULL);
+       }
+
+       if ( caps ) 
+       {
+               g_object_set (G_OBJECT (inputcaps), "caps", caps, NULL);
+               gst_caps_unref (caps);
+#ifndef NDEBUG
+               caps = NULL; // to check it is not null on next use ...
+#endif
+       }
+       else
+       {
+               log_error("Unknown codec format %d", format);
+       }
+
+       // Setup the capsfilter which demands either YUV or RGB videoframe 
format
+       videocaps = gst_element_factory_make ("capsfilter", NULL);
+       caps = gst_caps_new_simple ("video/x-raw-rgb", NULL);
+
+       assert(caps); // ok, this is a silly assertion *now*, but as long as 
+                     // the code is implemented with such long function bodies
+                     // a day will come in which someone will change something
+                     // a few screefulls above and the assertion would make
+                     // sense (maybe boost compile-time assertions could help
+                     // in this reguard).
+
+       g_object_set (G_OBJECT (videocaps), "caps", caps, NULL);
+       gst_caps_unref (caps);
+
+       // setup the videosink with callback
+       output = gst_element_factory_make ("fakesink", NULL);
+       g_object_set (G_OBJECT (output), "signal-handoffs", TRUE, NULL);
+       g_signal_connect (output, "handoff", G_CALLBACK 
(VideoDecoderGst::callback_output), this);
+
+       // setup the video colorspaceconverter converter
+       colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
+
+       // Find the decoder, use auto plugin loader? use plugin-downloader?
+       if (format == VIDEO_CODEC_H263) {
+               decoder = gst_element_factory_make ("ffdec_flv", NULL);
+       } else if (format == VIDEO_CODEC_VP6) {
+               decoder = gst_element_factory_make ("ffdec_vp6f", NULL);
+       } else if (format == VIDEO_CODEC_SCREENVIDEO) {
+               decoder = gst_element_factory_make ("ffdec_flashsv", NULL);
+       } else {
+               gnash::log_error("Unsupported embedded video format");
+               return false;
+       }
+
+       if (!pipeline || !input || !inputcaps || !videocaps || !output || 
!colorspace) {
+               gnash::log_error("Creation of Gstreamer baisc elements failed, 
is your Gstreamer installation complete?");
+               return false;
+       }
+
+       if (!decoder) {
+               gnash::log_error("Creation of decoder element failed, do you 
have gstreamer-0.10-ffmpeg installed?");
+               return false;
+       }
+
+       // Put the elemets in the pipeline and link them
+       gst_bin_add_many (GST_BIN (pipeline), input, inputcaps, decoder, 
colorspace, videocaps, output, NULL);
+
+       // link the elements
+       gst_element_link_many(input, inputcaps, decoder, colorspace, videocaps, 
output, NULL);
+
+       // This make callback_handoff wait for data
+       input_lock = new boost::mutex::scoped_lock(input_mutex);
+
+       // This make decodeFrame wait for data
+       output_lock = new boost::mutex::scoped_lock(output_mutex);
+
+       // Determine required buffer size and allocate buffer
+       decodedFrame.reset(new image::rgb(width, height));
+
+       // Start "playing"
+       gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
+
+       return true;
+}
+
+
+// gnash calls this when it wants you to decode the given videoframe
+std::auto_ptr<image::image_base>
+VideoDecoderGst::decodeToImage(uint8_t* data, uint32_t size)
+{
+
+       std::auto_ptr<image::image_base> ret_image;
+
+       ret_image.reset(new image::rgb(width, height));
+
+       // If there is nothing to decode in the new frame
+       // we just return the lastest.
+       if (data == NULL || size == 0 || !decoder)
+       {
+               // If we never decoded any frame return a NULL
+               // auto pointer ..
+               if ( ! decodedFrame.get() )
+               {
+                       ret_image.reset(NULL);
+                       return ret_image;
+               }
+
+               // return decodedFrame->clone() ?
+               ret_image->update(*decodedFrame);
+               return ret_image;
+       }
+
+       frame = data;
+       frameSize = size;
+
+       delete input_lock;
+
+       output_lock = new boost::mutex::scoped_lock(output_mutex);
+
+       // If we never decoded any frame return a NULL
+       // auto pointer ..
+       if ( ! decodedFrame.get() )
+       {
+               ret_image.reset(NULL);
+               return ret_image;
+       }
+
+       // return decodedFrame->clone() ?
+       ret_image->update(*decodedFrame);
+       return ret_image;
+}
+
+// The callback function which refills the buffer with data
+void
+VideoDecoderGst::callback_handoff (GstElement * /*c*/, GstBuffer *buffer, 
GstPad* /*pad*/, gpointer user_data)
+{
+       VideoDecoderGst* decoder = static_cast<VideoDecoderGst*>(user_data);
+
+       if (decoder->stop) return;
+
+       decoder->input_lock = new 
boost::mutex::scoped_lock(decoder->input_mutex);
+
+       GST_BUFFER_SIZE(buffer) = decoder->frameSize;
+
+       GST_BUFFER_DATA(buffer) = decoder->frame;
+}
+
+// The callback function which passes the decoded video frame
+void
+VideoDecoderGst::callback_output (GstElement * /*c*/, GstBuffer *buffer, 
GstPad* /*pad*/, gpointer user_data)
+{
+       VideoDecoderGst* decoder = static_cast<VideoDecoderGst*>(user_data);
+
+       if (decoder->stop) return;
+
+       if (decoder->decodedFrame.get())
+       {
+               decoder->decodedFrame->update(GST_BUFFER_DATA(buffer));
+       }
+
+       delete decoder->output_lock;
+
+}
+
+} // end of gnash namespace
+
+#endif // SOUND_GST

Index: libmedia/gst/VideoDecoderGst.h
===================================================================
RCS file: libmedia/gst/VideoDecoderGst.h
diff -N libmedia/gst/VideoDecoderGst.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/VideoDecoderGst.h      27 Sep 2007 23:59:54 -0000      1.1
@@ -0,0 +1,103 @@
+// VideoDecoderGst.h: Video decoding using the FFMPEG library.
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+//  $Id:
+
+#ifndef __VIDEODECODERGST_H__
+#define __VIDEODECODERGST_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "log.h"
+#include "VideoDecoder.h"
+
+#include <gst/gst.h>
+#include "image.h"
+#include <boost/thread/thread.hpp>
+#include <boost/bind.hpp> 
+#include <boost/thread/mutex.hpp>
+
+namespace gnash {
+
+
+class VideoDecoderGst : public VideoDecoder {
+       
+public:
+       VideoDecoderGst();
+       ~VideoDecoderGst();
+
+       bool setup(
+               int /*width*/,
+               int /*height*/,
+               int /*deblocking*/,
+               bool /*smoothing*/,
+               videoCodecType /*format*/, // should this argument be of 
codecType type ?
+               int /*outputFormat*/);
+
+//     uint8_t* decode(uint8_t* input, uint32_t inputSize, uint32_t& 
outputSize);
+
+       std::auto_ptr<image::image_base> decodeToImage(uint8_t* /*input*/, 
uint32_t /*inputSize*/);
+
+       static void callback_handoff (GstElement * /*c*/, GstBuffer *buffer, 
GstPad* /*pad*/, gpointer user_data);
+       static void callback_output (GstElement * /*c*/, GstBuffer *buffer, 
GstPad* /*pad*/, gpointer user_data);
+private:
+
+       // gstreamer pipeline objects
+
+       /// the main bin containing the elements
+       GstElement *pipeline;
+
+       /// Gstreamer objects
+       GstElement *input;
+       GstElement *inputcaps;
+       GstElement *videocaps;
+       GstElement *output;
+       GstElement *decoder;
+       GstElement *colorspace;
+
+       /// mutexes and locks used to handle input and output.
+       boost::mutex input_mutex;
+       boost::mutex output_mutex;
+       boost::mutex::scoped_lock* input_lock;
+       boost::mutex::scoped_lock* output_lock;
+
+       /// Info from the video tag header. Might be usefull...
+       uint32_t width;
+       uint32_t height;
+       int deblocking;
+       bool smoothing;
+       videoCodecType format;
+       int outputFormat;
+
+       /// Input data and size for current frame
+       uint8_t* frame;
+       int frameSize;
+       
+       /// Last decoded frame
+       std::auto_ptr<image::image_base> decodedFrame;
+
+       /// If we should stop this will be true
+       volatile bool stop;
+
+};
+       
+} // gnash namespace
+
+#endif // __VIDEODECODERGST_H__

Index: libmedia/gst/gstappbuffer.c
===================================================================
RCS file: libmedia/gst/gstappbuffer.c
diff -N libmedia/gst/gstappbuffer.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/gstappbuffer.c 27 Sep 2007 23:59:54 -0000      1.1
@@ -0,0 +1,108 @@
+/* GStreamer
+ * Copyright (C) 2007 David Schleef <address@hidden>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/base/gstpushsrc.h>
+
+#include <string.h>
+
+#include "gstappbuffer.h"
+
+static void gst_app_buffer_init (GstAppBuffer * buffer, gpointer g_class);
+static void gst_app_buffer_class_init (gpointer g_class, gpointer class_data);
+static void gst_app_buffer_finalize (GstAppBuffer * buffer);
+
+static GstBufferClass *parent_class;
+
+GType
+gst_app_buffer_get_type (void)
+{
+  static GType _gst_app_buffer_type;
+
+  if (G_UNLIKELY (_gst_app_buffer_type == 0)) {
+    static const GTypeInfo app_buffer_info = {
+      sizeof (GstBufferClass),
+      NULL,
+      NULL,
+      gst_app_buffer_class_init,
+      NULL,
+      NULL,
+      sizeof (GstAppBuffer),
+      0,
+      (GInstanceInitFunc) gst_app_buffer_init,
+      NULL
+    };
+    _gst_app_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
+        "GstAppBuffer", &app_buffer_info, 0);
+  }
+  return _gst_app_buffer_type;
+}
+
+static void
+gst_app_buffer_init (GstAppBuffer * buffer, gpointer g_class)
+{
+  UNUSEDPAR(buffer);
+  UNUSEDPAR(g_class);
+}
+
+static void
+gst_app_buffer_class_init (gpointer g_class, gpointer class_data)
+{
+  UNUSEDPAR(class_data);
+  GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
+
+  mini_object_class->finalize =
+      (GstMiniObjectFinalizeFunction) gst_app_buffer_finalize;
+
+  parent_class = g_type_class_peek_parent (g_class);
+}
+
+static void
+gst_app_buffer_finalize (GstAppBuffer * buffer)
+{
+  g_return_if_fail (buffer != NULL);
+  g_return_if_fail (GST_IS_APP_BUFFER (buffer));
+
+  if (buffer->finalize) {
+    buffer->finalize (buffer->priv);
+  }
+
+  GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (buffer));
+}
+
+GstBuffer *
+gst_app_buffer_new (void *data, int length,
+    GstAppBufferFinalizeFunc finalize, void *priv)
+{
+  GstAppBuffer *buffer;
+
+  buffer = (GstAppBuffer *) gst_mini_object_new (GST_TYPE_APP_BUFFER);
+
+  GST_BUFFER_DATA (buffer) = data;
+  GST_BUFFER_SIZE (buffer) = length;
+
+  buffer->finalize = finalize;
+  buffer->priv = priv;
+
+  return GST_BUFFER (buffer);
+}

Index: libmedia/gst/gstappbuffer.h
===================================================================
RCS file: libmedia/gst/gstappbuffer.h
diff -N libmedia/gst/gstappbuffer.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/gstappbuffer.h 27 Sep 2007 23:59:54 -0000      1.1
@@ -0,0 +1,66 @@
+/* GStreamer
+ * Copyright (C) 2007 David Schleef <address@hidden>
+ *
+ * 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_APP_BUFFER_H_
+#define _GST_APP_BUFFER_H_
+
+#include <gst/gst.h>
+
+#define UNUSEDPAR(x)  { x = x; }
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_APP_BUFFER \
+  (gst_app_buffer_get_type())
+#define GST_APP_BUFFER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_APP_BUFFER,GstAppBuffer))
+#define GST_APP_BUFFER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_APP_BUFFER,GstAppBufferClass))
+#define GST_IS_APP_BUFFER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_APP_BUFFER))
+#define GST_IS_APP_BUFFER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_APP_BUFFER))
+
+typedef struct _GstAppBuffer GstAppBuffer;
+typedef struct _GstAppBufferClass GstAppBufferClass;
+typedef void (*GstAppBufferFinalizeFunc) (void *priv);
+
+struct _GstAppBuffer
+{
+  GstBuffer buffer;
+
+  /*< private >*/
+  GstAppBufferFinalizeFunc finalize;
+  void *priv;
+};
+
+struct _GstAppBufferClass
+{
+  GstBufferClass buffer_class;
+};
+
+GType gst_app_buffer_get_type(void);
+
+GstBuffer *gst_app_buffer_new (void *data, int length,
+    GstAppBufferFinalizeFunc finalize, void *priv);
+
+G_END_DECLS
+
+#endif
+

Index: libmedia/gst/gstappsink.c
===================================================================
RCS file: libmedia/gst/gstappsink.c
diff -N libmedia/gst/gstappsink.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/gstappsink.c   27 Sep 2007 23:59:54 -0000      1.1
@@ -0,0 +1,273 @@
+/* GStreamer
+ * Copyright (C) 2007 David Schleef <address@hidden>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/base/gstbasesink.h>
+
+#include <string.h>
+
+#include "gstappsink.h"
+
+
+GST_DEBUG_CATEGORY (app_sink_debug);
+#define GST_CAT_DEFAULT app_sink_debug
+
+static const GstElementDetails app_sink_details =
+GST_ELEMENT_DETAILS ("AppSink",
+    "FIXME",
+    "FIXME",
+    "autogenerated by makefilter");
+
+enum
+{
+  PROP_0
+};
+
+static GstStaticPadTemplate gst_app_sink_template =
+GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
+
+static void gst_app_sink_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_app_sink_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static void gst_app_sink_dispose (GObject * object);
+static gboolean gst_app_sink_start (GstBaseSink * psink);
+static gboolean gst_app_sink_stop (GstBaseSink * psink);
+static gboolean gst_app_sink_event (GstBaseSink * sink, GstEvent * event);
+static GstFlowReturn gst_app_sink_render (GstBaseSink * psink,
+    GstBuffer * buffer);
+
+GST_BOILERPLATE (GstAppSink, gst_app_sink, GstBaseSink, GST_TYPE_BASE_SINK);
+
+static void
+gst_app_sink_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  //GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
+
+  GST_DEBUG_CATEGORY_INIT (app_sink_debug, "appsink", 0, "appsink element");
+
+  gst_element_class_set_details (element_class, &app_sink_details);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_app_sink_template));
+
+}
+
+static void
+gst_app_sink_class_init (GstAppSinkClass * klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  GstBaseSinkClass *basesink_class = (GstBaseSinkClass *) klass;
+
+  gobject_class->set_property = gst_app_sink_set_property;
+  gobject_class->get_property = gst_app_sink_get_property;
+  gobject_class->dispose = gst_app_sink_dispose;
+
+  basesink_class->start = gst_app_sink_start;
+  basesink_class->stop = gst_app_sink_stop;
+  basesink_class->event = gst_app_sink_event;
+  basesink_class->render = gst_app_sink_render;
+}
+
+static void
+gst_app_sink_dispose (GObject * obj)
+{
+  GstAppSink *appsink = GST_APP_SINK (obj);
+
+  if (appsink->caps) {
+    gst_caps_unref (appsink->caps);
+    appsink->caps = NULL;
+  }
+  if (appsink->mutex) {
+    g_mutex_free (appsink->mutex);
+    appsink->mutex = NULL;
+  }
+  if (appsink->cond) {
+    g_cond_free (appsink->cond);
+    appsink->cond = NULL;
+  }
+  if (appsink->queue) {
+    g_queue_free (appsink->queue);
+    appsink->queue = NULL;
+  }
+
+  G_OBJECT_CLASS (parent_class)->dispose (obj);
+}
+
+static void
+gst_app_sink_init (GstAppSink * appsink, GstAppSinkClass * klass)
+{
+  UNUSEDPAR(klass);
+  appsink->mutex = g_mutex_new ();
+  appsink->cond = g_cond_new ();
+  appsink->queue = g_queue_new ();
+}
+
+static void
+gst_app_sink_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  UNUSEDPAR(value);
+  GstAppSink *appsink = GST_APP_SINK (object);
+
+  GST_OBJECT_LOCK (appsink);
+  switch (prop_id) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+  GST_OBJECT_UNLOCK (appsink);
+}
+
+static void
+gst_app_sink_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  UNUSEDPAR(value);
+  GstAppSink *appsink = GST_APP_SINK (object);
+
+  GST_OBJECT_LOCK (appsink);
+  switch (prop_id) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+  GST_OBJECT_UNLOCK (appsink);
+}
+
+static gboolean
+gst_app_sink_start (GstBaseSink * psink)
+{
+  GstAppSink *appsink = GST_APP_SINK (psink);
+
+  appsink->end_of_stream = FALSE;
+
+  return TRUE;
+}
+
+static gboolean
+gst_app_sink_stop (GstBaseSink * psink)
+{
+  UNUSEDPAR(psink);
+  //GstAppSink *appsink = GST_APP_SINK(psink);
+
+  return TRUE;
+}
+
+static gboolean
+gst_app_sink_event (GstBaseSink * sink, GstEvent * event)
+{
+  GstAppSink *appsink = GST_APP_SINK (sink);
+
+  switch (event->type) {
+    case GST_EVENT_EOS:
+      appsink->end_of_stream = TRUE;
+      break;
+    default:
+      break;
+  }
+
+  gst_object_unref (sink);
+  return FALSE;
+}
+
+static GstFlowReturn
+gst_app_sink_render (GstBaseSink * psink, GstBuffer * buffer)
+{
+  GstAppSink *appsink = GST_APP_SINK (psink);
+
+  g_mutex_lock (appsink->mutex);
+  g_queue_push_tail (appsink->queue, gst_buffer_ref (buffer));
+  g_cond_signal (appsink->cond);
+  g_mutex_unlock (appsink->mutex);
+
+  return GST_FLOW_OK;
+}
+
+
+
+
+/* external API */
+
+/**
+ * gst_app_sink_set_caps:
+ * @appsink:
+ * @caps:
+ *
+ * Set the capabilities on the appsink element.  This function takes
+ * ownership of the caps structure.
+ */
+void
+gst_app_sink_set_caps (GstAppSink * appsink, GstCaps * caps)
+{
+  g_return_if_fail (appsink != NULL);
+  g_return_if_fail (GST_IS_APP_SINK (appsink));
+
+  gst_caps_replace (&appsink->caps, caps);
+}
+
+gboolean
+gst_app_sink_end_of_stream (GstAppSink * appsink)
+{
+  gboolean ret;
+
+  g_return_val_if_fail (appsink != NULL, FALSE);
+  g_return_val_if_fail (GST_IS_APP_SINK (appsink), FALSE);
+
+  g_mutex_lock (appsink->mutex);
+  if (appsink->end_of_stream && g_queue_is_empty (appsink->queue)) {
+    ret = TRUE;
+  } else {
+    ret = FALSE;
+  }
+  g_mutex_unlock (appsink->mutex);
+
+  return ret;
+}
+
+GstBuffer *
+gst_app_sink_pull_buffer (GstAppSink * appsink)
+{
+  GstBuffer *buf = NULL;
+
+  g_return_val_if_fail (appsink != NULL, NULL);
+  g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
+
+  g_mutex_lock (appsink->mutex);
+  while (g_queue_is_empty (appsink->queue)) {
+    if (appsink->end_of_stream)
+      goto out;
+
+    g_cond_wait (appsink->cond, appsink->mutex);
+  }
+  buf = g_queue_pop_head (appsink->queue);
+out:
+  g_mutex_unlock (appsink->mutex);
+
+  return buf;
+}

Index: libmedia/gst/gstappsink.h
===================================================================
RCS file: libmedia/gst/gstappsink.h
diff -N libmedia/gst/gstappsink.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/gstappsink.h   27 Sep 2007 23:59:54 -0000      1.1
@@ -0,0 +1,73 @@
+/* GStreamer
+ * Copyright (C) 2007 David Schleef <address@hidden>
+ *
+ * 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_APP_SINK_H_
+#define _GST_APP_SINK_H_
+
+#define UNUSEDPAR(x)  { x = x; }
+
+#include <gst/gst.h>
+#include <gst/base/gstbasesink.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_APP_SINK \
+  (gst_app_sink_get_type())
+#define GST_APP_SINK(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_APP_SINK,GstAppSink))
+#define GST_APP_SINK_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_APP_SINK,GstAppSinkClass))
+#define GST_IS_APP_SINK(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_APP_SINK))
+#define GST_IS_APP_SINK_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_APP_SINK))
+
+typedef struct _GstAppSink GstAppSink;
+typedef struct _GstAppSinkClass GstAppSinkClass;
+
+struct _GstAppSink
+{
+  GstBaseSink basesink;
+
+  /*< private >*/
+  GstCaps *caps;
+
+  GCond *cond;
+  GMutex *mutex;
+  GQueue *queue;
+  gboolean end_of_stream;
+};
+
+struct _GstAppSinkClass
+{
+  GstBaseSinkClass basesink_class;
+};
+
+GType gst_app_sink_get_type(void);
+
+GST_DEBUG_CATEGORY_EXTERN (app_sink_debug);
+
+void gst_app_sink_set_caps (GstAppSink *appsink, GstCaps *caps);
+gboolean gst_app_sink_end_of_stream (GstAppSink *appsink);
+GstBuffer *gst_app_sink_pull_buffer (GstAppSink *appsink);
+
+G_END_DECLS
+
+#endif
+

Index: libmedia/gst/gstappsrc.c
===================================================================
RCS file: libmedia/gst/gstappsrc.c
diff -N libmedia/gst/gstappsrc.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/gstappsrc.c    27 Sep 2007 23:59:54 -0000      1.1
@@ -0,0 +1,323 @@
+/* GStreamer
+ * Copyright (C) 2007 David Schleef <address@hidden>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/base/gstpushsrc.h>
+
+#include <string.h>
+
+#include "gstappsrc.h"
+
+
+GST_DEBUG_CATEGORY (app_src_debug);
+#define GST_CAT_DEFAULT app_src_debug
+
+static const GstElementDetails app_src_details = GST_ELEMENT_DETAILS ("AppSrc",
+    "FIXME",
+    "FIXME",
+    "autogenerated by makefilter");
+
+enum
+{
+  PROP_0
+};
+
+static GstStaticPadTemplate gst_app_src_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
+
+static void gst_app_src_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_app_src_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static void gst_app_src_dispose (GObject * object);
+static GstFlowReturn gst_app_src_create (GstPushSrc * psrc, GstBuffer ** buf);
+static gboolean gst_app_src_start (GstBaseSrc * psrc);
+static gboolean gst_app_src_stop (GstBaseSrc * psrc);
+static gboolean gst_app_src_unlock (GstBaseSrc * psrc);
+
+GST_BOILERPLATE (GstAppSrc, gst_app_src, GstPushSrc, GST_TYPE_PUSH_SRC);
+
+static void
+gst_app_src_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  //GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
+
+  GST_DEBUG_CATEGORY_INIT (app_src_debug, "appsrc", 0, "appsrc element");
+
+  gst_element_class_set_details (element_class, &app_src_details);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_app_src_template));
+
+}
+
+static void
+gst_app_src_class_init (GstAppSrcClass * klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  GstPushSrcClass *pushsrc_class = (GstPushSrcClass *) klass;
+  GstBaseSrcClass *basesrc_class = (GstBaseSrcClass *) klass;
+
+  gobject_class->set_property = gst_app_src_set_property;
+  gobject_class->get_property = gst_app_src_get_property;
+  gobject_class->dispose = gst_app_src_dispose;
+
+  pushsrc_class->create = gst_app_src_create;
+  basesrc_class->start = gst_app_src_start;
+  basesrc_class->stop = gst_app_src_stop;
+  basesrc_class->unlock = gst_app_src_unlock;
+}
+
+static void
+gst_app_src_dispose (GObject * obj)
+{
+  GstAppSrc *appsrc = GST_APP_SRC (obj);
+
+  if (appsrc->caps) {
+    gst_caps_unref (appsrc->caps);
+    appsrc->caps = NULL;
+  }
+  if (appsrc->mutex) {
+    g_mutex_free (appsrc->mutex);
+    appsrc->mutex = NULL;
+  }
+  if (appsrc->cond) {
+    g_cond_free (appsrc->cond);
+    appsrc->cond = NULL;
+  }
+  if (appsrc->queue) {
+    g_queue_free (appsrc->queue);
+    appsrc->queue = NULL;
+  }
+
+  G_OBJECT_CLASS (parent_class)->dispose (obj);
+}
+
+static void
+gst_app_src_init (GstAppSrc * appsrc, GstAppSrcClass * klass)
+{
+  UNUSEDPAR(klass);
+  appsrc->mutex = g_mutex_new ();
+  appsrc->cond = g_cond_new ();
+  appsrc->queue = g_queue_new ();
+}
+
+static void
+gst_app_src_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  UNUSEDPAR(value);
+  GstAppSrc *appsrc = GST_APP_SRC (object);
+
+  GST_OBJECT_LOCK (appsrc);
+  switch (prop_id) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+  GST_OBJECT_UNLOCK (appsrc);
+}
+
+static void
+gst_app_src_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  UNUSEDPAR(value);
+  GstAppSrc *appsrc = GST_APP_SRC (object);
+
+  GST_OBJECT_LOCK (appsrc);
+  switch (prop_id) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+  GST_OBJECT_UNLOCK (appsrc);
+}
+
+static gboolean
+gst_app_src_start (GstBaseSrc * psrc)
+{
+  GstAppSrc *appsrc = GST_APP_SRC (psrc);
+
+  appsrc->unlock = FALSE;
+
+#if 0
+  /* FIXME: I don't know if this makes sense */
+  appsrc->end_of_stream = FALSE;
+  appsrc->flush = FALSE;
+#endif
+
+  return TRUE;
+}
+
+static gboolean
+gst_app_src_stop (GstBaseSrc * psrc)
+{
+  UNUSEDPAR(psrc);
+  //GstAppSrc *appsrc = GST_APP_SRC(psrc);
+
+  return TRUE;
+}
+
+static gboolean
+gst_app_src_unlock (GstBaseSrc * psrc)
+{
+  GstAppSrc *appsrc = GST_APP_SRC (psrc);
+
+  appsrc->unlock = TRUE;
+  g_cond_signal (appsrc->cond);
+
+  return TRUE;
+}
+
+static GstFlowReturn
+gst_app_src_create (GstPushSrc * psrc, GstBuffer ** buf)
+{
+  GstAppSrc *appsrc = GST_APP_SRC (psrc);
+  int ret = GST_FLOW_ERROR;
+
+  g_mutex_lock (appsrc->mutex);
+
+  while (1) {
+    if (appsrc->unlock) {
+      ret = GST_FLOW_WRONG_STATE;
+      break;
+    }
+    if (!g_queue_is_empty (appsrc->queue)) {
+      *buf = g_queue_pop_head (appsrc->queue);
+
+      gst_buffer_set_caps (*buf, appsrc->caps);
+
+      ret = GST_FLOW_OK;
+      break;
+    }
+    if (appsrc->end_of_stream) {
+      appsrc->end_of_stream = FALSE;
+      ret = GST_FLOW_UNEXPECTED;
+      break;
+    }
+    if (appsrc->flush) {
+      appsrc->flush = FALSE;
+      /* FIXME: I don't really know how to do this */
+      break;
+    }
+    g_cond_wait (appsrc->cond, appsrc->mutex);
+  }
+
+  g_mutex_unlock (appsrc->mutex);
+
+  return ret;
+}
+
+
+/* external API */
+
+/**
+ * gst_app_src_push_buffer:
+ * @appsrc:
+ * @buffer:
+ *
+ * Adds a buffer to the queue of buffers that the appsrc element will
+ * push to its source pad.  This function takes ownership of the buffer.
+ */
+void
+gst_app_src_push_buffer (GstAppSrc * appsrc, GstBuffer * buffer)
+{
+  g_return_if_fail (appsrc);
+  g_return_if_fail (GST_IS_APP_SRC (appsrc));
+
+  g_mutex_lock (appsrc->mutex);
+
+  g_queue_push_tail (appsrc->queue, buffer);
+
+  g_cond_signal (appsrc->cond);
+  g_mutex_unlock (appsrc->mutex);
+}
+
+/**
+ * gst_app_src_set_caps:
+ * @appsrc:
+ * @caps:
+ *
+ * Set the capabilities on the appsrc element.  This function takes
+ * ownership of the caps structure.
+ */
+void
+gst_app_src_set_caps (GstAppSrc * appsrc, GstCaps * caps)
+{
+  g_return_if_fail (appsrc);
+  g_return_if_fail (GST_IS_APP_SRC (appsrc));
+
+  gst_caps_replace (&appsrc->caps, caps);
+}
+
+/**
+ * gst_app_src_flush:
+ * @appsrc:
+ *
+ * Flushes all queued buffers from the appsrc element.
+ */
+void
+gst_app_src_flush (GstAppSrc * appsrc)
+{
+  GstBuffer *buffer;
+
+  g_return_if_fail (appsrc);
+  g_return_if_fail (GST_IS_APP_SRC (appsrc));
+
+  g_mutex_lock (appsrc->mutex);
+
+  while ((buffer = g_queue_pop_head (appsrc->queue))) {
+    gst_buffer_unref (buffer);
+  }
+  appsrc->flush = TRUE;
+
+  g_cond_signal (appsrc->cond);
+  g_mutex_unlock (appsrc->mutex);
+}
+
+/**
+ * gst_app_src_end_of_stream:
+ * @appsrc:
+ *
+ * Indicates to the appsrc element that the last buffer queued in the
+ * element is the last buffer of the stream.
+ */
+void
+gst_app_src_end_of_stream (GstAppSrc * appsrc)
+{
+  g_return_if_fail (appsrc);
+  g_return_if_fail (GST_IS_APP_SRC (appsrc));
+
+  g_mutex_lock (appsrc->mutex);
+
+  appsrc->end_of_stream = TRUE;
+
+  g_cond_signal (appsrc->cond);
+  g_mutex_unlock (appsrc->mutex);
+}

Index: libmedia/gst/gstappsrc.h
===================================================================
RCS file: libmedia/gst/gstappsrc.h
diff -N libmedia/gst/gstappsrc.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/gstappsrc.h    27 Sep 2007 23:59:54 -0000      1.1
@@ -0,0 +1,76 @@
+/* GStreamer
+ * Copyright (C) 2007 David Schleef <address@hidden>
+ *
+ * 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_APP_SRC_H_
+#define _GST_APP_SRC_H_
+
+#define UNUSEDPAR(x)  { x = x; }
+
+#include <gst/gst.h>
+#include <gst/base/gstpushsrc.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_APP_SRC \
+  (gst_app_src_get_type())
+#define GST_APP_SRC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_APP_SRC,GstAppSrc))
+#define GST_APP_SRC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_APP_SRC,GstAppSrcClass))
+#define GST_IS_APP_SRC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_APP_SRC))
+#define GST_IS_APP_SRC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_APP_SRC))
+
+typedef struct _GstAppSrc GstAppSrc;
+typedef struct _GstAppSrcClass GstAppSrcClass;
+
+struct _GstAppSrc
+{
+  GstPushSrc pushsrc;
+
+  /*< private >*/
+  gboolean unlock;
+  GCond *cond;
+  GMutex *mutex;
+  GQueue *queue;
+  GstCaps *caps;
+  gboolean end_of_stream;
+  gboolean flush;
+};
+
+struct _GstAppSrcClass
+{
+  GstPushSrcClass pushsrc_class;
+};
+
+GType gst_app_src_get_type(void);
+
+GST_DEBUG_CATEGORY_EXTERN (app_src_debug);
+
+
+void gst_app_src_push_buffer (GstAppSrc *appsrc, GstBuffer *buffer);
+void gst_app_src_set_caps (GstAppSrc *appsrc, GstCaps *caps);
+void gst_app_src_flush (GstAppSrc *appsrc);
+void gst_app_src_end_of_stream (GstAppSrc *appsrc);
+
+G_END_DECLS
+
+#endif
+

Index: libmedia/gst/gstgnashsrc.c
===================================================================
RCS file: libmedia/gst/gstgnashsrc.c
diff -N libmedia/gst/gstgnashsrc.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/gstgnashsrc.c  27 Sep 2007 23:59:54 -0000      1.1
@@ -0,0 +1,328 @@
+// 
+//   Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+// 
+// Based on the filesrc and fdsrc element in Gstreamer-core.
+//
+
+/* $Id: gstgnashsrc.c,v 1.1 2007/09/27 23:59:54 tgc Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstgnashsrc.h"
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
+
+
+GST_DEBUG_CATEGORY_STATIC (gst_gnash_src_debug);
+#define GST_CAT_DEFAULT gst_gnash_src_debug
+
+static const GstElementDetails gst_gnash_src_details =
+GST_ELEMENT_DETAILS ("Gnash source",
+    "Gnash",
+    "Use callback to read from Gnash",
+    "Gnash team");
+
+/* GnashSrc signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+#define DEFAULT_BLOCKSIZE      4*1024
+#define DEFAULT_DATA           NULL
+#define DEFAULT_CALLBACKS      NULL
+
+enum
+{
+  ARG_0,
+  ARG_DATA,
+  ARG_CALLBACKS
+};
+
+static void gst_gnash_src_finalize (GObject * object);
+
+static void gst_gnash_src_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_gnash_src_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static gboolean gst_gnash_src_start (GstBaseSrc * basesrc);
+static gboolean gst_gnash_src_stop (GstBaseSrc * basesrc);
+
+static gboolean gst_gnash_src_is_seekable (GstBaseSrc * src);
+static gboolean gst_gnash_src_get_size (GstBaseSrc * src, guint64 * size);
+static GstFlowReturn gst_gnash_src_create (GstPushSrc * src, GstBuffer ** 
buffer);
+static gboolean gst_gnash_src_do_seek (GstBaseSrc * src, GstSegment * s);
+
+static void
+_do_init (GType gnashsrc_type)
+{
+       UNUSEDPAR(gnashsrc_type);
+/*  static const GInterfaceInfo urihandler_info = {
+    gst_gnash_src_uri_handler_init,
+    NULL,
+    NULL
+  };*/
+
+  GST_DEBUG_CATEGORY_INIT (gst_gnash_src_debug, "gnashsrc", 0, "gnashsrc 
element");
+}
+
+GST_BOILERPLATE_FULL (GstGnashSrc, gst_gnash_src, GstElement, 
GST_TYPE_PUSH_SRC, _do_init);
+
+static void
+gst_gnash_src_base_init (gpointer g_class)
+{
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&srctemplate));
+
+  gst_element_class_set_details (gstelement_class, &gst_gnash_src_details);
+}
+
+static void
+gst_gnash_src_class_init (GstGnashSrcClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+  GstBaseSrcClass *gstbasesrc_class;
+  GstPushSrcClass *gstpush_src_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gstelement_class = GST_ELEMENT_CLASS (klass);
+  gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
+  gstpush_src_class = GST_PUSH_SRC_CLASS (klass);
+
+  gobject_class->set_property = gst_gnash_src_set_property;
+  gobject_class->get_property = gst_gnash_src_get_property;
+
+  g_object_class_install_property (gobject_class, ARG_DATA,
+      g_param_spec_pointer ("data", NULL, NULL, 
(GParamFlags)G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, ARG_CALLBACKS,
+      g_param_spec_pointer ("callbacks", NULL, NULL, 
(GParamFlags)G_PARAM_READWRITE));
+
+  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_gnash_src_finalize);
+
+  gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gnash_src_start);
+  gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_gnash_src_stop);
+  gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR 
(gst_gnash_src_is_seekable);
+  gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_gnash_src_get_size);
+  gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_gnash_src_do_seek);
+
+  gstpush_src_class->create = GST_DEBUG_FUNCPTR (gst_gnash_src_create);
+}
+
+static void
+gst_gnash_src_init (GstGnashSrc * src, GstGnashSrcClass * g_class)
+{
+  UNUSEDPAR(g_class);
+  src->data = NULL;
+  src->callbacks = NULL;
+  src->read_position = 0;
+}
+
+static void
+gst_gnash_src_finalize (GObject * object)
+{
+  GstGnashSrc *src;
+
+  src = GST_GNASH_SRC (object);
+
+  free (src->callbacks);
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_gnash_src_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstGnashSrc *src;
+
+  g_return_if_fail (GST_IS_GNASH_SRC (object));
+
+  src = GST_GNASH_SRC (object);
+
+  switch (prop_id) {
+    case ARG_DATA:
+      src->data = g_value_get_pointer (value);
+      break;
+    case ARG_CALLBACKS:
+      src->callbacks = g_value_get_pointer (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_gnash_src_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  GstGnashSrc *src;
+  UNUSEDPAR(value);
+  g_return_if_fail (GST_IS_GNASH_SRC (object));
+
+  src = GST_GNASH_SRC (object);
+
+  switch (prop_id) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+//
+// Below is the functions used get make this plugin work.
+//
+
+// Used for seeking
+static gboolean
+gst_gnash_src_do_seek (GstBaseSrc * basesrc, GstSegment * seg)
+{
+
+  GstGnashSrc *src;
+  off_t res;
+  src = GST_GNASH_SRC (basesrc);
+
+  if (seg->format != GST_FORMAT_BYTES) return FALSE;
+
+  struct gnashsrc_callback *gc;
+  gc = src->callbacks;
+  res = gc->seek (src->data, seg->start, SEEK_CUR);
+  return TRUE;
+
+}
+
+// Output the next buffer
+static GstFlowReturn
+gst_gnash_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
+{
+  GstGnashSrc *src;
+  src = GST_GNASH_SRC (psrc);
+  int ret, blocksize;
+  GstBuffer *buf;
+
+  struct gnashsrc_callback *gc;
+  gc = src->callbacks;
+
+  blocksize = GST_BASE_SRC (src)->blocksize;
+  buf = gst_buffer_new_and_alloc (blocksize);
+
+  GST_LOG_OBJECT (src, "Reading %d bytes", blocksize);
+
+  ret = gc->read(src->data, (void*)GST_BUFFER_DATA(buf), blocksize);
+       
+  if (G_UNLIKELY (ret < 0)) goto could_not_read;
+
+  /* other files should eos if they read 0 and more was requested */
+  if (G_UNLIKELY (ret == 0 && blocksize > 0))
+    goto eos;
+
+  blocksize = ret;
+
+  GST_BUFFER_SIZE (buf) = blocksize;
+  GST_BUFFER_OFFSET (buf) = src->read_position;
+  GST_BUFFER_OFFSET_END (buf) = src->read_position + blocksize;
+
+  *outbuf = buf;
+
+  src->read_position += blocksize;
+
+  return GST_FLOW_OK;
+
+  /* ERROR */
+could_not_read:
+  {
+    GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
+    gst_buffer_unref (buf);
+    return GST_FLOW_ERROR;
+  }
+eos:
+  {
+    GST_DEBUG ("non-regular file hits EOS");
+    gst_buffer_unref (buf);
+    return GST_FLOW_UNEXPECTED;
+  }
+}
+
+static gboolean
+gst_gnash_src_is_seekable (GstBaseSrc * basesrc)
+{
+  GstGnashSrc *src = GST_GNASH_SRC (basesrc);
+
+  return src->seekable;
+}
+
+// Get size of the file. Not sure how we shall handles this...
+static gboolean
+gst_gnash_src_get_size (GstBaseSrc * basesrc, guint64 * size)
+{
+  GstGnashSrc *src;
+
+  src = GST_GNASH_SRC (basesrc);
+
+  if (!src->seekable) {
+    /* If it isn't seekable, we won't know the length (but fstat will still
+     * succeed, and wrongly say our length is zero. */
+    return FALSE;
+  }
+  return FALSE;
+
+  // Since it's a streamed video file we probably don't know the length, so we
+  // tell it's 50000. Maybe we should just return FALSE?
+  *size = 500000;
+  return TRUE;
+
+}
+
+/* open the file and mmap it, necessary to go to READY state */
+static gboolean
+gst_gnash_src_start (GstBaseSrc * basesrc)
+{
+  GstGnashSrc *src = GST_GNASH_SRC (basesrc);
+
+  if (src->data == NULL || src->callbacks == NULL) {
+    GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,(("No data or callback struct 
supplied.")), (NULL));
+    return FALSE;
+  }
+
+  src->read_position = 0;
+  GST_INFO_OBJECT (src, "Ready for reading using callbacks");
+
+  // TODO: set seekable to false when real streaming
+  src->seekable = TRUE;
+
+  return TRUE;
+
+}
+
+/* stop and free */
+static gboolean
+gst_gnash_src_stop (GstBaseSrc * basesrc)
+{
+  GstGnashSrc *src = GST_GNASH_SRC (basesrc);
+  UNUSEDPAR(src);
+  return TRUE;
+}
+

Index: libmedia/gst/gstgnashsrc.h
===================================================================
RCS file: libmedia/gst/gstgnashsrc.h
diff -N libmedia/gst/gstgnashsrc.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/gstgnashsrc.h  27 Sep 2007 23:59:54 -0000      1.1
@@ -0,0 +1,81 @@
+// 
+//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+// 
+// Based on the filesrc and fdsrc element in Gstreamer-core
+//
+
+/* $Id: gstgnashsrc.h,v 1.1 2007/09/27 23:59:54 tgc Exp $ */
+
+#ifndef __GST_GNASH_SRC_H__
+#define __GST_GNASH_SRC_H__
+
+#define UNUSEDPAR(x)  { x = x; }
+
+
+#include <gst/gst.h>
+#include <gst/base/gstpushsrc.h>
+
+// Struct to contain the callback functions
+struct gnashsrc_callback {
+       int (*read)(void* data, char* buf, int buf_size);
+       int (*seek)(void* data, int offset, int whence);
+};
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_GNASH_SRC \
+  (gst_gnash_src_get_type())
+#define GST_GNASH_SRC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GNASH_SRC,GstGnashSrc))
+#define GST_GNASH_SRC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GNASH_SRC,GstGnashSrcClass))
+#define GST_IS_GNASH_SRC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GNASH_SRC))
+#define GST_IS_GNASH_SRC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GNASH_SRC))
+
+typedef struct _GstGnashSrc GstGnashSrc;
+typedef struct _GstGnashSrcClass GstGnashSrcClass;
+
+/**
+ * GstGnashSrc:
+ *
+ * Opaque #GstGnashSrc structure.
+ */
+struct _GstGnashSrc {
+  GstPushSrc element;
+
+  /*< private >*/
+
+  guint64 read_position;       // position in the stream
+
+  gpointer data;                // data passes with the callbacks
+  gpointer callbacks;          // struct with the callbacks
+
+  gboolean seekable;           // seekable or not
+
+};
+
+struct _GstGnashSrcClass {
+  GstPushSrcClass parent_class;
+};
+
+GType gst_gnash_src_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_GNASH_SRC_H__ */

Index: libmedia/gst/sound_handler_gst.cpp
===================================================================
RCS file: libmedia/gst/sound_handler_gst.cpp
diff -N libmedia/gst/sound_handler_gst.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/sound_handler_gst.cpp  27 Sep 2007 23:59:54 -0000      1.1
@@ -0,0 +1,712 @@
+// sound_handler_gst.cpp: Audio output via GStreamer, for Gnash.
+//
+//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+// Based on sound_handler_sdl.cpp by Thatcher Ulrich http://tulrich.com 2003
+// which has been donated to the Public Domain.
+
+/* $Id: sound_handler_gst.cpp,v 1.1 2007/09/27 23:59:54 tgc Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "utility.h" // for convert_raw_data
+
+// Assume people running --enable-media=gst know what they are doing
+// (HAVE_GST_GST_H seems broken atm, specifically when an older glib
+//  install is around)
+//
+
+#ifdef SOUND_GST
+
+#include "sound_handler_gst.h"
+#include "gnash.h"
+#include "container.h"
+#include "log.h"
+#include "types.h"     // for IF_VERBOSE_* macros
+#include <cmath>
+#include <vector>
+
+#include <gst/gst.h>
+
+#define BUFFER_SIZE 5000
+
+using namespace boost;
+
+namespace gnash {
+
+GST_sound_handler::GST_sound_handler()
+       : looping(false),
+         muted(false)
+{
+               // init gstreamer
+       gst_init(NULL, NULL);
+}
+
+GST_sound_handler::~GST_sound_handler()
+{
+
+       for (size_t i=0, e=m_sound_data.size(); i < e; ++i)  {
+               stop_sound(i);
+               delete_sound(i);
+       }
+}
+
+
+int    GST_sound_handler::create_sound(
+       void* data_,
+       unsigned int data_bytes,
+       std::auto_ptr<SoundInfo> sinfo)
+// Called to create a sample.  We'll return a sample ID that
+// can be use for playing it.
+{
+
+       try_mutex::scoped_lock lock(_mutex);
+
+       unsigned char* data = static_cast<unsigned char*>(data_);
+
+       assert(sinfo.get());
+       sound_data *sounddata = new sound_data;
+       if (!sounddata) {
+               log_error(_("could not allocate memory for sound data"));
+               return -1;
+       }
+
+       sounddata->volume = 100;
+       sounddata->soundinfo = sinfo;
+
+       switch (sounddata->soundinfo->getFormat())
+       {
+       case AUDIO_CODEC_MP3:
+       case AUDIO_CODEC_RAW:
+       case AUDIO_CODEC_ADPCM:
+       case AUDIO_CODEC_UNCOMPRESSED:
+       case AUDIO_CODEC_NELLYMOSER:
+       case AUDIO_CODEC_NELLYMOSER_8HZ_MONO:
+               if ( data ) sounddata->append(data, data_bytes);
+               break;
+
+
+       default:
+               // Unhandled format.
+               log_error(_("Unknown sound format %d requested; gnash does not 
handle it"), (int)sounddata->soundinfo->getFormat());
+               return -1; // Unhandled format, set to NULL.
+       }
+
+       m_sound_data.push_back(sounddata);
+
+       return m_sound_data.size()-1;
+}
+
+
+// this gets called when a stream gets more data
+long   GST_sound_handler::fill_stream_data(unsigned char* data, unsigned int 
data_bytes, unsigned int /*sample_count*/, int handle_id)
+{
+       try_mutex::scoped_lock lock(_mutex);
+
+       // @@ does a negative handle_id have any meaning ?
+       //    should we change it to unsigned instead ?
+       if (handle_id >= 0 && (unsigned int) handle_id < m_sound_data.size())
+       {
+               sound_data* sounddata = m_sound_data[handle_id];
+
+               long startSize = sounddata->dataSize();
+
+               sounddata->append(data, data_bytes);
+
+               // If playback has already started, we also update the active 
sounds
+               for (size_t i=0, e=sounddata->m_gst_elements.size(); i < e; 
++i) {
+                       gst_elements* sound = sounddata->m_gst_elements[i];
+                       sound->data_size = sounddata->dataSize();
+                       sound->set_data(sounddata->data());
+               }
+
+               return startSize;
+       }
+       else
+       {
+               delete [] data;
+               return 0;
+       }
+}
+
+// This stops sounds when they are done playing
+static gboolean sound_killer (gpointer user_data)
+{
+       gst_elements *gstelements = static_cast<gst_elements*>(user_data);
+       gst_element_set_state (GST_ELEMENT (gstelements->pipeline), 
GST_STATE_NULL);
+       return false;
+}
+
+// The callback function which refills the buffer with data
+void GST_sound_handler::callback_handoff (GstElement * /*c*/, GstBuffer 
*buffer, GstPad* /*pad*/, gpointer user_data)
+{
+       gst_elements *gstelements = static_cast<gst_elements*>(user_data);
+
+       try_mutex::scoped_try_lock lock(gstelements->handler->_mutex);
+
+       // If we couldn't obtain a lock return to avoid a deadlock
+       if (!lock.locked()) {
+
+               // We return nothing in this case to avoid noise being decoded 
and played
+               if (GST_BUFFER_SIZE(buffer) != 0 && GST_BUFFER_DATA(buffer)) {
+                       GST_BUFFER_DATA(buffer) = 0;
+                       GST_BUFFER_SIZE(buffer) = 0;
+               }
+               return;
+       }
+
+       // First callback or after a couldn't-get-lock-return 
+       if (GST_BUFFER_SIZE(buffer) == 0) {
+               if (gstelements->data_size > BUFFER_SIZE) {
+                       GST_BUFFER_SIZE(buffer) = BUFFER_SIZE;
+               } else {
+                       GST_BUFFER_SIZE(buffer) = gstelements->data_size;
+               }
+
+               // Reallocate the required memory.
+               guint8* tmp_buf = new guint8[GST_BUFFER_SIZE(buffer)];
+               memcpy(tmp_buf, GST_BUFFER_DATA(buffer), sizeof(buffer));
+
+               delete [] GST_BUFFER_DATA(buffer);
+               GST_BUFFER_DATA(buffer) = tmp_buf;
+       }
+
+       // All the data has been given to the pipeline, so now we need to stop
+       // the pipeline. g_idle_add() makes sure sound_killer is called soon.
+       if (gstelements->position > gstelements->data_size) {
+               g_idle_add(sound_killer, user_data);
+               GST_BUFFER_SIZE(buffer) = 0;
+               GST_BUFFER_DATA(buffer) = 0;
+               return;
+       }
+
+       const guint8* data_pos = 
gstelements->get_data_ptr(gstelements->position);
+
+       // Last callback - the last re-fill
+       if (gstelements->position+BUFFER_SIZE > gstelements->data_size) {
+       
+               unsigned int chunk_size = 
gstelements->data_size-gstelements->position;
+               // Check if we should loop. If loop_count is 0 we have we just
+               // played the sound for the last (and perhaps first) time.
+               // If loop_count is anything else we continue to loop.
+               if (gstelements->loop_count == 0) {
+                       GST_BUFFER_SIZE(buffer) = chunk_size;
+                       memcpy(GST_BUFFER_DATA(buffer), data_pos, chunk_size);
+                       gstelements->position += BUFFER_SIZE;
+
+                       gst_element_set_state (GST_ELEMENT 
(gstelements->input), GST_STATE_PAUSED);
+
+               } else {
+                       // Copy what's left of the data, and then fill the rest 
with "new" data.
+                       memcpy(GST_BUFFER_DATA(buffer), data_pos,  chunk_size);
+                       memcpy(GST_BUFFER_DATA(buffer) + chunk_size, 
gstelements->get_data_ptr(0), GST_BUFFER_SIZE(buffer)- chunk_size);
+                       gstelements->position = GST_BUFFER_SIZE(buffer) - 
chunk_size;
+                       gstelements->loop_count--;
+
+               }
+
+               return;
+
+       }
+
+       // Standard re-fill
+       memcpy(GST_BUFFER_DATA(buffer), data_pos, BUFFER_SIZE);
+       gstelements->position += BUFFER_SIZE;
+
+}
+
+
+void   GST_sound_handler::play_sound(int sound_handle, int loop_count, int 
/*offset*/, long start_position, const std::vector<sound_envelope>* 
/*envelopes*/)
+// Play the index'd sample.
+{
+       try_mutex::scoped_lock lock(_mutex);
+
+       // Check if the sound exists, or if audio is muted
+       if (sound_handle < 0 || (unsigned int) sound_handle >= 
m_sound_data.size() || muted)
+       {
+               // Invalid handle, or audio is muted.
+               return;
+       }
+
+       sound_data* sounddata = m_sound_data[sound_handle];
+
+       // If this is called from a streamsoundblocktag, we only start if this
+       // sound isn't already playing.
+       if (start_position > 0 && sounddata->m_gst_elements.size() > 0) {
+               return;
+       }
+       // Make sure sound actually got some data
+       if (sounddata->dataSize() < 1) {
+               IF_VERBOSE_MALFORMED_SWF(
+                       log_swferror(_("Trying to play sound with size 0"));
+               );
+               return;
+       }
+
+       // Make a "gst_elements" for this sound which is latter placed on the 
vector of instances of this sound being played
+       gst_elements* gst_element = new gst_elements;
+       if (gst_element == NULL) {
+               log_error (_("Could not allocate memory for gst_element"));
+               return;
+       }
+
+       // Set the handler
+       gst_element->handler = this;
+
+       // Copy data-info to the "gst_elements"
+       gst_element->data_size = sounddata->dataSize();
+       gst_element->set_data(sounddata->data());
+       gst_element->position = start_position;
+
+       // Set number of loop we should do. -1 is infinte loop, 0 plays it 
once, 1 twice etc.
+       gst_element->loop_count = loop_count;
+
+       // create main pipeline
+       gst_element->pipeline = gst_pipeline_new (NULL);
+
+       // create an audio sink - use oss, alsa or...? make a commandline 
option?
+       // we first try atudetect, then alsa, then oss, then esd, then...?
+#if !defined(__NetBSD__)
+       gst_element->audiosink = gst_element_factory_make ("autoaudiosink", 
NULL);
+       if (!gst_element->audiosink) gst_element->audiosink = 
gst_element_factory_make ("alsasink", NULL);
+       if (!gst_element->audiosink) gst_element->audiosink = 
gst_element_factory_make ("osssink", NULL);
+#endif
+       if (!gst_element->audiosink) gst_element->audiosink = 
gst_element_factory_make ("esdsink", NULL);
+
+       // Check if the creation of the gstreamer pipeline, adder and audiosink 
was a succes
+       if (!gst_element->pipeline) {
+               log_error(_("The gstreamer pipeline element could not be 
created"));
+       }
+       if (!gst_element->audiosink) {
+               log_error(_("The gstreamer audiosink element could not be 
created"));
+       }
+
+       // link adder and output to bin
+       gst_bin_add (GST_BIN (gst_element->pipeline), gst_element->audiosink);
+
+       gst_element->bin = gst_bin_new(NULL);
+       gst_element->input = gst_element_factory_make ("fakesrc", NULL);
+       gst_element->capsfilter = gst_element_factory_make ("capsfilter", NULL);
+       gst_element->audioconvert = gst_element_factory_make ("audioconvert", 
NULL);
+       gst_element->audioresample = gst_element_factory_make ("audioresample", 
NULL);
+       gst_element->volume = gst_element_factory_make ("volume", NULL);
+
+       // Put the gstreamer elements in the pipeline
+       gst_bin_add_many (GST_BIN (gst_element->bin), gst_element->input,
+                                       gst_element->capsfilter,
+                                       gst_element->audioconvert,
+                                       gst_element->audioresample, 
+                                       gst_element->volume, NULL);
+
+       // Test if the fakesrc, typefind and audio* elements was correctly 
created
+       if (!gst_element->input
+               || !gst_element->capsfilter
+               || !gst_element->audioconvert
+               || !gst_element->audioresample) {
+
+               log_error(_("Gstreamer element for audio handling could not be 
created"));
+               return;
+       }
+
+       // Create a gstreamer decoder for the chosen sound.
+
+       // Temp variables to make the code simpler and easier to read
+       audioCodecType soundFormat = sounddata->soundinfo->getFormat();
+       bool soundStereo = sounddata->soundinfo->isStereo();
+       uint32_t soundSampleRate = sounddata->soundinfo->getSampleRate();
+
+       if (soundFormat == AUDIO_CODEC_MP3) {
+
+               gst_element->decoder = gst_element_factory_make ("mad", NULL);
+               if (gst_element->decoder == NULL) {
+                       gst_element->decoder = gst_element_factory_make 
("flump3dec", NULL);
+                       if (gst_element->decoder != NULL && 
!gst_default_registry_check_feature_version("flump3dec", 0, 10, 4))
+                       {
+                               static bool warned=false;
+                               if ( ! warned ) 
+                               {
+                                       // I keep getting these messages even 
if I hear sound... too much paranoia ?
+                                       log_debug(_("This version of fluendos 
mp3 plugin does not support flash streaming sounds, please upgrade to version 
0.10.4 or higher"));
+                                       warned=true;
+                               }
+                       }
+               }
+               // Check if the element was correctly created
+               if (!gst_element->decoder) {
+                       log_error(_("A gstreamer mp3-decoder element could not 
be created.  You probably need to install a mp3-decoder plugin like 
gstreamer0.10-mad or gstreamer0.10-fluendo-mp3."));
+                       return;
+               }
+               gst_bin_add (GST_BIN (gst_element->bin), gst_element->decoder);
+
+               // Set the info about the stream so that gstreamer knows what 
it is.
+               GstCaps *caps = gst_caps_new_simple ("audio/mpeg",
+                       "mpegversion", G_TYPE_INT, 1,
+                       "layer", G_TYPE_INT, 3,
+                       "rate", G_TYPE_INT, soundSampleRate,
+                       "channels", G_TYPE_INT, soundStereo ? 2 : 1, NULL);
+               g_object_set (G_OBJECT (gst_element->capsfilter), "caps", caps, 
NULL);
+               gst_caps_unref (caps);
+
+               // setup fake source
+               g_object_set (G_OBJECT (gst_element->input),
+                                       "sizetype", 2, "can-activate-pull", 
FALSE, "signal-handoffs", TRUE,
+                                       "sizemax", BUFFER_SIZE, NULL);
+               // Setup the callback
+               gst_element->handoff_signal_id = g_signal_connect 
(gst_element->input, "handoff", G_CALLBACK (callback_handoff), gst_element);
+
+               // link data, decoder, audio* and adder
+               gst_element_link_many (gst_element->input,
+                                               gst_element->capsfilter,
+                                               gst_element->decoder,
+                                               gst_element->audioconvert,
+                                               gst_element->audioresample, 
+                                               gst_element->volume, NULL);
+
+       } else if (soundFormat == AUDIO_CODEC_ADPCM) {
+               gst_element->decoder = gst_element_factory_make 
("ffdec_adpcm_swf", NULL);
+
+               // Check if the element was correctly created
+               if (!gst_element->decoder) {
+                       log_error(_("A gstreamer adpcm-decoder element could 
not be created.  You probably need to install gst-ffmpeg."));
+                       return;
+               }
+               gst_bin_add (GST_BIN (gst_element->bin), gst_element->decoder);
+
+               // Set the info about the stream so that gstreamer knows what 
it is.
+               GstCaps *caps = gst_caps_new_simple ("audio/x-adpcm",
+                       "rate", G_TYPE_INT, soundSampleRate,
+                       "channels", G_TYPE_INT, soundStereo ? 2 : 1, NULL);
+               g_object_set (G_OBJECT (gst_element->capsfilter), "caps", caps, 
NULL);
+               gst_caps_unref (caps);
+
+               // setup fake source
+               g_object_set (G_OBJECT (gst_element->input),
+                                       "sizetype", 2, "can-activate-pull", 
FALSE, "signal-handoffs", TRUE,
+                                       "sizemax", BUFFER_SIZE, NULL);
+               // Setup the callback
+               gst_element->handoff_signal_id = g_signal_connect 
(gst_element->input, "handoff", G_CALLBACK (callback_handoff), gst_element);
+
+               // link data, decoder, audio* and adder
+               gst_element_link_many (gst_element->input,
+                                               gst_element->capsfilter,
+                                               gst_element->decoder,
+                                               gst_element->audioconvert,
+                                               gst_element->audioresample, 
+                                               gst_element->volume, NULL);
+
+       } else if (soundFormat == AUDIO_CODEC_NELLYMOSER_8HZ_MONO || 
soundFormat == AUDIO_CODEC_NELLYMOSER) {
+               return;
+       } else {
+
+               // Set the info about the stream so that gstreamer knows what 
it is.
+               GstCaps *caps = gst_caps_new_simple ("audio/x-raw-int",
+                       "rate", G_TYPE_INT, soundSampleRate,
+                       "channels", G_TYPE_INT, soundStereo ? 2 : 1,
+                       "endianness", G_TYPE_INT, G_BIG_ENDIAN,
+                       "width", G_TYPE_INT, (sounddata->soundinfo->is16bit() ? 
16 : 8),
+                       "depth", G_TYPE_INT, 16,
+                       //"signed", G_TYPE_INT, 1,
+                        NULL);
+               g_object_set (G_OBJECT (gst_element->capsfilter), "caps", caps, 
NULL);
+               gst_caps_unref (caps);
+
+               // setup fake source
+               g_object_set (G_OBJECT (gst_element->input),
+                                       "sizetype", 2, "can-activate-pull", 
FALSE, "signal-handoffs", TRUE,
+                                       "sizemax", BUFFER_SIZE, NULL);
+               // Setup the callback
+               gst_element->handoff_signal_id = g_signal_connect 
(gst_element->input, "handoff", G_CALLBACK (callback_handoff), gst_element);
+
+               // Raw native sound-data, output directly
+               gst_element_link_many (gst_element->input, 
+                                       gst_element->capsfilter, 
+                                       gst_element->audioconvert,
+                                       gst_element->audioresample,
+                                       gst_element->volume, NULL);
+       }
+       // Add ghostpad
+       GstPad *pad = gst_element_get_pad (gst_element->volume, "src");
+       gst_element_add_pad (gst_element->bin, gst_ghost_pad_new ("src", pad));
+       gst_object_unref (GST_OBJECT (pad));
+       
+       // Add the bin to the main pipeline
+       gst_bin_add(GST_BIN (gst_element->pipeline), gst_element->bin);
+       // Link to the adder sink pad
+       GstPad *sinkpad = gst_element_get_pad (gst_element->audiosink, "sink");
+       GstPad *srcpad = gst_element_get_pad (gst_element->bin, "src");
+       gst_pad_link (srcpad, sinkpad);
+       gst_object_unref (GST_OBJECT (srcpad));
+       gst_object_unref (GST_OBJECT (sinkpad));
+
+       // Set the volume
+       g_object_set (G_OBJECT (gst_element->volume), "volume", 
static_cast<double>(sounddata->volume) / 100.0, NULL);
+
+       //gst_pad_add_event_probe(pad, G_CALLBACK(event_callback), sounddata);
+
+       // Put the gst_element on the vector
+       sounddata->m_gst_elements.push_back(gst_element);
+
+       // If not already playing, start doing it
+       gst_element_set_state (GST_ELEMENT (gst_element->pipeline), 
GST_STATE_PLAYING);
+
+       ++_soundsStarted;
+
+}
+
+
+void   GST_sound_handler::stop_sound(int sound_handle)
+{
+       try_mutex::scoped_lock lock(_mutex);
+
+       // Check if the sound exists.
+       if (sound_handle < 0 || (unsigned int) sound_handle >= 
m_sound_data.size())
+       {
+               // Invalid handle.
+               return;
+       }
+
+       sound_data* sounddata = m_sound_data[sound_handle];
+
+       // Stop all the instances of this sound.
+       // TODO: fix the loop to use size_t instead of i
+       for (int i = sounddata->m_gst_elements.size()-1; i >= 0 ; i--)
+       {
+               gst_elements* elements = sounddata->m_gst_elements[i];
+
+               // Check if we can succesfully stop the elements
+               // playback - if not we skip cleaning this for now
+               // FIXME: what if it ain't possible to stop an element when 
this is called from ~GST_sound_handler
+
+               // Disconnect signals
+               g_signal_handler_disconnect (elements->input, 
elements->handoff_signal_id);
+
+               gst_element_set_state (GST_ELEMENT (elements->pipeline), 
GST_STATE_NULL);
+               gst_object_unref (GST_OBJECT (elements->pipeline));
+
+               // Delete the gst_element struct
+               // @@ we're deleting the elements from the start, so half-way 
of the loop we will be referring to undefined elements. Is this intended ? 
--strk;
+               delete elements;
+               
sounddata->m_gst_elements.erase(sounddata->m_gst_elements.begin() + i);
+       }
+
+       ++_soundsStopped;
+}
+
+
+void   GST_sound_handler::delete_sound(int sound_handle)
+// this gets called when it's done with a sample.
+{
+       try_mutex::scoped_lock lock(_mutex);
+
+       if (sound_handle >= 0 && (unsigned int) sound_handle < 
m_sound_data.size())
+       {
+               delete m_sound_data[sound_handle];
+               m_sound_data.erase (m_sound_data.begin() + sound_handle);
+       }
+
+}
+
+// This will stop all sounds playing. Will cause problems if the soundhandler 
is made static
+// and supplys sound_handling for many SWF's, since it will stop all sounds 
with no regard
+// for what sounds is associated with what SWF.
+void   GST_sound_handler::stop_all_sounds()
+{
+       for (size_t i=0, e=m_sound_data.size(); i < e; ++i) 
+               stop_sound(i);
+}
+
+
+//     returns the sound volume level as an integer from 0 to 100,
+//     where 0 is off and 100 is full volume. The default setting is 100.
+int    GST_sound_handler::get_volume(int sound_handle) {
+
+       try_mutex::scoped_lock lock(_mutex);
+
+       // Check if the sound exists.
+       if (sound_handle >= 0 && (unsigned int) sound_handle < 
m_sound_data.size())
+       {
+               return m_sound_data[sound_handle]->volume;
+       } else {
+               return 0; // Invalid handle
+       }
+}
+
+
+//     A number from 0 to 100 representing a volume level. 
+//     100 is full volume and 0 is no volume. The default setting is 100.
+void   GST_sound_handler::set_volume(int sound_handle, int volume) {
+
+       try_mutex::scoped_lock lock(_mutex);
+
+       // Check if the sound exists.
+       if (sound_handle < 0 || (unsigned int) sound_handle >= 
m_sound_data.size())
+       {
+               // Invalid handle.
+               return;
+       }
+
+       sound_data* sd = m_sound_data[sound_handle];
+
+       // Set volume for this sound. Should this only apply to the active 
sounds?
+
+       sd->volume = volume;
+       
+       for (size_t i=0, n=sd->m_gst_elements.size(); i<n; ++i)
+       {
+               g_object_set (
+                       G_OBJECT (sd->m_gst_elements[i]->volume),
+                       "volume",
+                       static_cast<double>(volume/100.0),
+                       NULL);
+       }
+
+}
+
+SoundInfo* GST_sound_handler::get_sound_info(int sound_handle) {
+
+       try_mutex::scoped_lock lock(_mutex);
+
+       // Check if the sound exists.
+       if (sound_handle >= 0 && static_cast<unsigned int>(sound_handle) < 
m_sound_data.size())
+       {
+               return m_sound_data[sound_handle]->soundinfo.get();
+       } else {
+               return NULL;
+       }
+
+}
+
+// gnash calls this to mute audio
+void GST_sound_handler::mute() {
+       stop_all_sounds();
+       muted = true;
+}
+
+// gnash calls this to unmute audio
+void GST_sound_handler::unmute() {
+       muted = false;
+}
+
+bool GST_sound_handler::is_muted() {
+       return muted;
+}
+
+void GST_sound_handler::attach_aux_streamer(aux_streamer_ptr /*ptr*/, void* 
/*owner*/)
+{
+       log_unimpl(__PRETTY_FUNCTION__);
+}
+
+void GST_sound_handler::detach_aux_streamer(void* /*owner*/)
+{
+       log_unimpl(__PRETTY_FUNCTION__);
+}
+
+unsigned int GST_sound_handler::get_duration(int sound_handle)
+{
+       try_mutex::scoped_lock lock(_mutex);
+
+       // Check if the sound exists.
+       if (sound_handle < 0 || (unsigned int) sound_handle >= 
m_sound_data.size())
+       {
+               // Invalid handle.
+               return 0;
+       }
+
+       sound_data* sounddata = m_sound_data[sound_handle];
+
+       uint32_t sampleCount = sounddata->soundinfo->getSampleCount();
+       uint32_t sampleRate = sounddata->soundinfo->getSampleRate();
+
+       // Return the sound duration in milliseconds
+       if (sampleCount > 0 && sampleRate > 0) {
+               unsigned int ret = sampleCount / sampleRate * 1000;
+               ret += ((sampleCount % sampleRate) * 1000) / sampleRate;
+               if (sounddata->soundinfo->isStereo()) ret = ret / 2;
+               return ret;
+       } else {
+               return 0;
+       }
+}
+
+unsigned int GST_sound_handler::get_position(int sound_handle)
+{
+       try_mutex::scoped_lock lock(_mutex);
+
+       // Check if the sound exists.
+       if (sound_handle < 0 || (unsigned int) sound_handle >= 
m_sound_data.size())
+       {
+               // Invalid handle.
+               return 0;
+       }
+
+       sound_data* sounddata = m_sound_data[sound_handle];
+
+       // If there is no active sounds, return 0
+       if (sounddata->m_gst_elements.size() == 0) {
+               return 0;
+       }
+
+       // return the position of the last element added
+       GstElement *pipeline,*audioconvert;
+       GstStateChangeReturn ret;
+       GstState current, pending;
+       int64_t pos;
+       GstFormat fmt = GST_FORMAT_TIME;
+       
+       pipeline = 
sounddata->m_gst_elements[sounddata->m_gst_elements.size()-1]->pipeline;
+       
+       ret = gst_element_get_state (GST_ELEMENT (pipeline), &current, 
&pending, 0);
+
+       if (current != GST_STATE_NULL) {
+               audioconvert = 
sounddata->m_gst_elements[sounddata->m_gst_elements.size()-1]->audioconvert;
+               if (gst_element_query_position (audioconvert, &fmt, &pos)) {
+                       return static_cast<unsigned int>(pos / GST_MSECOND);
+               } else {
+                       return 0;
+               }
+       }
+       return 0;
+}
+
+// Pointer handling and checking functions
+const uint8_t* gst_elements::get_data_ptr(unsigned long int pos)
+{
+       assert(data_size > pos);
+       return data + pos;
+}
+
+void gst_elements::set_data(const uint8_t* idata) {
+       data = idata;
+}
+
+sound_handler* create_sound_handler_gst()
+// Factory.
+{
+       return new GST_sound_handler;
+}
+
+} // namespace gnash
+
+#endif // SOUND_GST
+
+// Local Variables:
+// mode: C++
+// End:
+

Index: libmedia/gst/sound_handler_gst.h
===================================================================
RCS file: libmedia/gst/sound_handler_gst.h
diff -N libmedia/gst/sound_handler_gst.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/sound_handler_gst.h    27 Sep 2007 23:59:54 -0000      1.1
@@ -0,0 +1,204 @@
+//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+
+// This program 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 General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+#ifndef SOUND_HANDLER_GST_H
+#define SOUND_HANDLER_GST_H
+
+//#include "gnash.h"
+#include "sound_handler.h" // for inheritance
+
+#include <vector>
+
+#include <gst/gst.h>
+#include <boost/thread/thread.hpp>
+#include <boost/bind.hpp>
+#include <boost/thread/mutex.hpp>
+
+#define BUFFER_SIZE 5000
+
+namespace gnash {
+
+// forward declaration
+class GST_sound_handler;
+
+// Used to hold the gstreamer when doing on-demand-decoding
+class gst_elements
+{
+public:
+       // gstreamer pipeline objects
+
+       // the main bin containing the adder and output (sink)
+       GstElement *pipeline;
+       GstElement *audiosink;
+
+       // gstreamer objects
+       GstElement *input;
+       GstElement *decoder;
+       GstElement *capsfilter;
+       GstElement *audioconvert;
+       GstElement *audioresample;
+       GstElement *volume;
+       GstElement *bin;
+       GstPad     *addersinkpad;
+       
+       // position in the stream
+       unsigned long position;
+
+       // data size
+       unsigned long data_size;
+
+       long loop_count;
+       
+       // signal id
+       guint handoff_signal_id;
+
+       // The sound handler. Used to get access to the 
GST_sound_handler->_mutex
+       GST_sound_handler* handler;
+
+       /// Returns the data pointer in the undecoded datastream
+       /// for the given position. Boundaries are checked.
+       const uint8_t* get_data_ptr(unsigned long int pos);
+
+       /// Set the undecoded data pointer
+       void set_data(const uint8_t*);
+
+private:
+       // The (un)compressed data
+       const guint8* data;
+
+};
+
+
+// Used to hold the sounddata when doing on-demand-decoding
+class sound_data
+{
+       // The (un)compressed data
+       Buffer _data;
+
+public:
+
+       sound_data()
+       {}
+
+       /// Append size bytes to this sound
+       //
+       /// @param data
+       ///     Data bytes, allocated with new[]. Ownership transferred.
+       ///
+       /// @param size
+       ///     Size of the 'data' buffer.
+       ///
+       void append(unsigned char* data, unsigned int size)
+       {
+               _data.append(data, size);
+       }
+
+       /// Return data size
+       size_t dataSize() const { return _data.size(); }
+
+       /// Return data buffer
+       const uint8_t* data() { return _data.data(); }
+
+       // Object holding information about the sound
+       std::auto_ptr<SoundInfo> soundinfo;
+
+       // Volume, SWF range: 0-100, GST range 0-10 (we only use 0-1, the rest 
is amplified)
+       // It's the SWF range that is represented here
+       int volume;
+
+       // gstreamer objects
+       std::vector<gst_elements*>      m_gst_elements;
+
+};
+
+// Use gstreamer to handle sounds.
+class GST_sound_handler : public gnash::sound_handler
+{
+private:
+       /// Vector containing all the sounds
+       std::vector<sound_data*>        m_sound_data;
+       
+       /// Is the loop running?
+       bool looping;
+       
+       /// Is the audio muted?
+       bool muted;
+
+       /// Mutex for making sure threads doesn't mess things up
+       boost::try_mutex _mutex;
+
+public:
+
+       /// Gstreamer callback function
+       static void callback_handoff (GstElement * /*c*/, GstBuffer *buffer, 
GstPad* /*pad*/, gpointer user_data);
+
+       GST_sound_handler();
+       virtual ~GST_sound_handler();
+
+       /// Called to create a sound.
+       virtual int     create_sound(void* data, unsigned int data_bytes,
+                                    std::auto_ptr<SoundInfo> sinfo);
+
+       /// this gets called when a stream gets more data
+       virtual long    fill_stream_data(unsigned char* data, unsigned int 
data_bytes,
+                                        unsigned int sample_count, int 
handle_id);
+
+       /// Play the index'd sample.
+       virtual void    play_sound(int sound_handle, int loop_count, int offset,
+                                  long start_position, const 
std::vector<sound_envelope>* envelopes);
+
+       /// Stop the index'd sample.
+       virtual void    stop_sound(int sound_handle);
+
+       /// This gets called when it's done with a sample.
+       virtual void    delete_sound(int sound_handle);
+
+       /// This will stop all sounds playing.
+       virtual void    stop_all_sounds();
+
+       /// Returns the sound volume level as an integer from 0 to 100. 
AS-script only.
+       virtual int     get_volume(int sound_handle);
+
+       /// Sets the sound volume level as an integer from 0 to 100. AS-script 
only.
+       virtual void    set_volume(int sound_handle, int volume);
+               
+       /// Gnash uses this to get info about a sound. Used when a stream needs 
more data.
+       virtual SoundInfo* get_sound_info(int sound_handle);
+
+       /// Gnash calls this to mute audio.
+       virtual void    mute();
+
+       /// Gnash calls this to unmute audio.
+       virtual void    unmute();
+
+       /// Gnash calls this to get the mute state.
+       virtual bool    is_muted();
+
+       /// Gets the duration in milliseconds of an event sound connected to an 
AS Sound obejct.
+       virtual unsigned int get_duration(int sound_handle);
+
+       /// Gets the playhead position in milliseconds of an event sound 
connected to an AS Soound obejct.
+       virtual unsigned int get_position(int sound_handle);
+
+       virtual void    attach_aux_streamer(aux_streamer_ptr ptr, void* owner); 
//vv
+       virtual void    detach_aux_streamer(void* owner);       //vv
+       
+};
+
+} // namespace gnash
+
+#endif // SOUND_HANDLER_GST_H
+

Index: libmedia/sdl/AudioDecoderFfmpeg.cpp
===================================================================
RCS file: libmedia/sdl/AudioDecoderFfmpeg.cpp
diff -N libmedia/sdl/AudioDecoderFfmpeg.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/sdl/AudioDecoderFfmpeg.cpp 27 Sep 2007 23:59:55 -0000      1.1
@@ -0,0 +1,251 @@
+// AudioDecoderFfmpeg.cpp: Audio decoding using the FFMPEG library.
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "AudioDecoderFfmpeg.h"
+
+namespace gnash {
+       
+AudioDecoderFfmpeg::AudioDecoderFfmpeg ()
+       :
+       _audioCodec(NULL),
+       _audioCodecCtx(NULL),
+       _parser(NULL)
+{}
+
+AudioDecoderFfmpeg::~AudioDecoderFfmpeg()
+{
+       if (_audioCodec) avcodec_close(_audioCodecCtx);
+       if (_parser) av_parser_close(_parser);
+}
+
+bool AudioDecoderFfmpeg::setup(SoundInfo* info)
+{
+       // Init the avdecoder-decoder
+       avcodec_init();
+       avcodec_register_all();// change this to only register need codec?
+
+       enum CodecID codec_id;
+
+       switch(info->getFormat()) {
+               case AUDIO_CODEC_RAW:
+                       codec_id = CODEC_ID_PCM_U16LE;
+                       break;
+               case AUDIO_CODEC_ADPCM:
+                       codec_id = CODEC_ID_ADPCM_SWF;
+                       break;
+               case AUDIO_CODEC_MP3:
+                       codec_id = CODEC_ID_MP3;
+                       // Init the parser
+                       _parser = av_parser_init(codec_id);
+
+                       if (!_parser) { 
+                               log_error(_("libavcodec can't parse the current 
audio format"));
+                               return false;
+                       }
+                       break;
+               default:
+                       log_error(_("Unsupported audio codec %d"), 
static_cast<int>(info->getFormat()));
+                       return false;
+       }
+       _audioCodec = avcodec_find_decoder(codec_id);
+
+       if (!_audioCodec) {
+               log_error(_("libavcodec can't decode the current audio 
format"));
+               return false;
+       }
+
+       _audioCodecCtx = avcodec_alloc_context();
+       if (!_audioCodecCtx) {
+               log_error(_("libavcodec couldn't allocate context"));
+               return false;
+       }
+
+       int ret = avcodec_open(_audioCodecCtx, _audioCodec);
+       if (ret < 0) {
+               avcodec_close(_audioCodecCtx);
+               log_error(_("libavcodec failed to initialize codec"));
+               return false;
+       }
+
+       if (_audioCodecCtx->codec->id != CODEC_ID_MP3) {
+               _audioCodecCtx->channels = (info->isStereo() ? 2 : 1);
+               _audioCodecCtx->sample_rate = info->getSampleRate();
+               _audioCodecCtx->sample_fmt = SAMPLE_FMT_S16;
+       }
+
+       return true;
+}
+
+bool AudioDecoderFfmpeg::setup(AudioInfo* info)
+{
+       // Init the avdecoder-decoder
+       avcodec_init();
+       avcodec_register_all();// change this to only register need codec?
+
+       if (info->type == FLASH) {
+               enum CodecID codec_id;
+
+               switch(info->codec) {
+                       case AUDIO_CODEC_RAW:
+                               codec_id = CODEC_ID_PCM_U16LE;
+                               break;
+                       case AUDIO_CODEC_ADPCM:
+                               codec_id = CODEC_ID_ADPCM_SWF;
+                               break;
+                       case AUDIO_CODEC_MP3:
+                               codec_id = CODEC_ID_MP3;
+                               break;
+                       default:
+                               log_error(_("Unsupported audio codec %d"), 
static_cast<int>(info->codec));
+                               return false;
+               }
+               _audioCodec = avcodec_find_decoder(codec_id);
+               // Init the parser
+               _parser = av_parser_init(codec_id);
+       } else if (info->type == FFMPEG) {
+               _audioCodec = 
avcodec_find_decoder(static_cast<CodecID>(info->codec));
+               // Init the parser
+               _parser = av_parser_init(static_cast<CodecID>(info->codec));
+       } else {
+               return false;
+       }
+
+       if (!_parser) { 
+               log_error(_("libavcodec can't parse the current audio format"));
+               return false;
+       }
+
+       if (!_audioCodec) {
+               log_error(_("libavcodec can't decode the current audio 
format"));
+               return false;
+       }
+
+       _audioCodecCtx = avcodec_alloc_context();
+       if (!_audioCodecCtx) {
+               log_error(_("libavcodec couldn't allocate context"));
+               return false;
+       }
+
+       int ret = avcodec_open(_audioCodecCtx, _audioCodec);
+       if (ret < 0) {
+               avcodec_close(_audioCodecCtx);
+               log_error(_("libavcodec failed to initialize codec"));
+               return false;
+       }
+
+       if (_audioCodecCtx->codec->id != CODEC_ID_MP3) {
+               _audioCodecCtx->channels = (info->stereo ? 2 : 1);
+               _audioCodecCtx->sample_rate = info->sampleRate;
+               //_audioCodecCtx->sample_fmt = SAMPLE_FMT_S16;
+       }
+
+       return true;
+}
+
+uint8_t* AudioDecoderFfmpeg::decode(uint8_t* input, uint32_t inputSize, 
uint32_t& outputSize, uint32_t& decodedBytes, bool parse)
+{
+
+       long bytes_decoded = 0;
+       int bufsize = (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2;
+       uint8_t* output = new uint8_t[bufsize];
+       uint32_t orgbufsize = bufsize;
+       decodedBytes = 0;
+
+       if (parse) {
+               bufsize = 0;
+               while (bufsize == 0 && decodedBytes < inputSize) {
+                       uint8_t* frame;
+                       int framesize;
+
+                       bytes_decoded = av_parser_parse(_parser, 
_audioCodecCtx, &frame, &framesize, input+decodedBytes, inputSize-decodedBytes, 
0, 0); //the last 2 is pts & dts
+
+                       int tmp = 0;
+#ifdef FFMPEG_AUDIO2
+                       bufsize = AVCODEC_MAX_AUDIO_FRAME_SIZE;
+                       tmp = avcodec_decode_audio2(_audioCodecCtx, 
reinterpret_cast<int16_t*>(output), &bufsize, frame, framesize);
+#else
+                       tmp = avcodec_decode_audio(_audioCodecCtx, 
reinterpret_cast<int16_t*>(output), &bufsize, frame, framesize);
+#endif
+
+                       if (bytes_decoded < 0 || tmp < 0 || bufsize < 0) {
+                               log_error(_("Error while decoding audio data. 
Upgrading ffmpeg/libavcodec might fix this issue."));
+                               // Setting data position to data size will get 
the sound removed
+                               // from the active sound list later on.
+                               decodedBytes = inputSize;
+                               break;
+                       }
+
+                       decodedBytes += bytes_decoded;
+               }
+
+       } else {
+
+               int tmp = 0;
+#ifdef FFMPEG_AUDIO2
+               tmp = avcodec_decode_audio2(_audioCodecCtx, 
reinterpret_cast<int16_t*>(output), &bufsize, input, inputSize);
+#else
+               tmp = avcodec_decode_audio(_audioCodecCtx, 
reinterpret_cast<int16_t*>(output), &bufsize, input, inputSize);
+#endif
+
+               if (bytes_decoded < 0 || tmp < 0 || bufsize < 0) {
+                       log_error(_("Error while decoding audio data. Upgrading 
ffmpeg/libavcodec might fix this issue."));
+                       // Setting data position to data size will get the 
sound removed
+                       // from the active sound list later on.
+                       decodedBytes = 0;
+                       outputSize = 0;
+                       return NULL;
+               }
+
+               decodedBytes = inputSize;
+       }
+
+       // Error handling
+       if (bufsize < 1) {
+               decodedBytes = 0;
+               outputSize = 0;
+               return NULL;
+       }
+
+       // Resampling is needed.
+       if (_resampler.init(_audioCodecCtx)) {
+               bool stereo = _audioCodecCtx->channels > 1 ? true : false;
+               int samples = stereo ? bufsize >> 2 : bufsize >> 1;
+
+               uint8_t* tmp = new uint8_t[orgbufsize];
+                       
+               samples = 
_resampler.resample(reinterpret_cast<int16_t*>(output),
+                                                
reinterpret_cast<int16_t*>(tmp),
+                                                samples);
+               outputSize = samples *2 *2; // the resampled audio has 
samplesize 2, and is stereo
+               uint8_t* ret = new uint8_t[outputSize];
+               memcpy(ret, tmp, outputSize);
+               delete [] tmp;
+               delete [] output;
+               return ret;
+       } else {
+               outputSize = bufsize;
+               uint8_t* ret = new uint8_t[outputSize];
+               memcpy(ret, output, outputSize);
+               delete [] output;
+               return ret;             
+       }
+}
+
+
+}

Index: libmedia/sdl/AudioDecoderFfmpeg.h
===================================================================
RCS file: libmedia/sdl/AudioDecoderFfmpeg.h
diff -N libmedia/sdl/AudioDecoderFfmpeg.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/sdl/AudioDecoderFfmpeg.h   27 Sep 2007 23:59:55 -0000      1.1
@@ -0,0 +1,115 @@
+// AudioDecoderFfmpeg.h: Audio decoding using the FFMPEG library.
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+//  $Id:
+
+#ifndef __AUDIODECODERFFMPEG_H__
+#define __AUDIODECODERFFMPEG_H__
+
+#ifndef __STDC_CONSTANT_MACROS
+#define __STDC_CONSTANT_MACROS
+#endif
+
+extern "C" {
+#include <ffmpeg/avcodec.h>
+}
+
+#include "log.h"
+#include "AudioDecoder.h"
+
+namespace gnash {
+
+/// This class is used to provide an easy interface to libavcodecs audio 
resampler.
+///
+class AudioResampler
+{
+public:
+       AudioResampler() : _context(NULL) {}
+       ~AudioResampler()
+       { 
+               if(_context) {
+                       audio_resample_close (_context);
+               }
+       }
+       
+       /// Initializes the resampler
+       //
+       /// @param ctx
+       /// The audio format container.
+       ///
+       /// @return true if resampling is needed, if not false
+       ///
+       bool init(AVCodecContext* ctx)
+       {
+               if (ctx->sample_rate != 44100 || ctx->channels != 2) {
+                       if (!_context) {
+                               _context = audio_resample_init(2,  
ctx->channels, 
+                                       44100, ctx->sample_rate);
+                       }
+                       return true;
+               }
+               return false;
+       }
+       
+       /// Resamples audio
+       //
+       /// @param input
+       /// A pointer to the audio data that needs resampling
+       ///
+       /// @param output
+       /// A pointer to where the resampled output should be placed
+       ///
+       /// @param samples
+       /// Number of samples in the audio
+       ///
+       /// @return the number of samples in the output data.
+       ///
+       int resample(int16_t* input, int16_t* output, int samples)
+       {
+               return audio_resample (_context, output, input, samples);
+       }
+
+private:
+       /// The container of the resample format information.
+       ReSampleContext* _context;
+};
+
+class AudioDecoderFfmpeg : public AudioDecoder {
+       
+public:
+       AudioDecoderFfmpeg();
+       ~AudioDecoderFfmpeg();
+
+       bool setup(AudioInfo* info);
+       bool setup(SoundInfo* info);
+
+       uint8_t* decode(uint8_t* input, uint32_t inputSize, uint32_t& 
outputSize, uint32_t& decodedBytes, bool parse);
+
+private:
+
+       AVCodec* _audioCodec;
+       AVCodecContext* _audioCodecCtx;
+       AVCodecParserContext* _parser;
+
+       // Use for resampling audio
+       AudioResampler _resampler;
+};
+       
+} // gnash namespace
+
+#endif // __AUDIODECODERFFMPEG_H__

Index: libmedia/sdl/AudioDecoderMad.cpp
===================================================================
RCS file: libmedia/sdl/AudioDecoderMad.cpp
diff -N libmedia/sdl/AudioDecoderMad.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/sdl/AudioDecoderMad.cpp    27 Sep 2007 23:59:55 -0000      1.1
@@ -0,0 +1,172 @@
+// AudioDecoderMad.cpp: Audio decoding using the mad library.
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "AudioDecoderMad.h"
+#include "utility.h"
+#ifdef USE_FFMPEG
+#include <ffmpeg/avcodec.h>
+#endif
+
+namespace gnash {
+       
+AudioDecoderMad::AudioDecoderMad ()
+{
+       // Init the mad decoder
+       mad_stream_init(&_stream);
+       mad_frame_init(&_frame);
+       mad_synth_init(&_synth);
+}
+
+AudioDecoderMad::~AudioDecoderMad()
+{
+       mad_synth_finish(&_synth);
+       mad_frame_finish(&_frame);
+       mad_stream_finish(&_stream);
+}
+
+
+bool AudioDecoderMad::setup(SoundInfo* info)
+{
+       if (info->getFormat() == FORMAT_MP3) return true;
+       else return false;
+}
+
+bool AudioDecoderMad::setup(AudioInfo* info)
+{
+#ifdef USE_FFMPEG
+       if (info->type == FFMPEG && info->codec == CODEC_ID_MP3) {
+               return true;
+       } 
+#endif
+       if (info->type == FLASH && info->codec == AUDIO_CODEC_MP3) {
+               return true;
+       } else {
+               return false;
+       }
+}
+
+uint8_t* AudioDecoderMad::decode(uint8_t* input, uint32_t inputSize, uint32_t& 
outputSize, uint32_t& decodedBytes, bool parse)
+{
+       // Setup the mad decoder
+       mad_stream_buffer(&_stream, input, inputSize);
+
+       int ret;
+       const unsigned char* old_next_frame = _stream.next_frame;
+       int loops = 0;
+       while(true) {
+
+               ret = mad_frame_decode(&_frame, &_stream);
+               loops++;
+               
+               // There is always some junk in front of the data, 
+               // so we continue until we get past it.
+               if (ret && _stream.error == MAD_ERROR_LOSTSYNC) continue;
+               
+               // Error handling is done by relooping (max. 8 times) and just 
hooping that it will work...
+               if (loops > 8) break;
+               if (ret == -1 && _stream.error != MAD_ERROR_BUFLEN && 
MAD_RECOVERABLE(_stream.error)) {
+                       log_debug(_("Recoverable error while decoding 
MP3-stream, MAD error: %s"), mad_stream_errorstr (&_stream));
+                       continue;
+               }
+               
+               break;
+       }
+
+       if (ret == -1 && _stream.error != MAD_ERROR_BUFLEN) {
+               log_error(_("Unrecoverable error while decoding MP3-stream, MAD 
error: %s"), mad_stream_errorstr (&_stream));
+               outputSize = 0;
+               decodedBytes = 0;
+               return NULL;
+       } else if (ret == -1 && _stream.error == MAD_ERROR_BUFLEN) {
+               // the buffer is empty, no more to decode!
+               decodedBytes = inputSize;
+       } else {
+               decodedBytes = _stream.next_frame - old_next_frame;
+       }
+
+       mad_synth_frame (&_synth, &_frame);
+       
+       uint32_t outsize = _synth.pcm.length * _synth.pcm.channels * 2;
+
+       uint8_t* tmp_raw_buffer = new uint8_t[outsize];
+       uint32_t tmp_raw_buffer_size = 0;
+       int sample;
+       
+       int16_t* dst = reinterpret_cast<int16_t*>(tmp_raw_buffer);
+
+       // transfer the decoded samples into the sound-struct, and do some
+       // scaling while we're at it.
+       for(int f = 0; f < _synth.pcm.length; f++)
+       {
+               for (int e = 0; e < _synth.pcm.channels; e++) { // channels 
(stereo/mono)
+
+                       mad_fixed_t mad_sample = _synth.pcm.samples[e][f];
+
+                       // round
+                       mad_sample += (1L << (MAD_F_FRACBITS - 16));
+
+                       // clip
+                       if (mad_sample >= MAD_F_ONE) mad_sample = MAD_F_ONE - 1;
+                       else if (mad_sample < -MAD_F_ONE) mad_sample = 
-MAD_F_ONE;
+
+                       // quantize
+                       sample = mad_sample >> (MAD_F_FRACBITS + 1 - 16);
+
+                       if ( sample != static_cast<int16_t>(sample) ) sample = 
sample < 0 ? -32768 : 32767;
+
+                       *dst++ = sample;
+               }
+       }
+       
+       // If we need to convert samplerate or/and from mono to stereo...
+       if (outsize > 0 && ( _synth.pcm.samplerate != 44100 || 
_synth.pcm.channels != 2)) {
+
+               int16_t* adjusted_data = 0;
+               int     adjusted_size = 0;
+               int sample_count = outsize / 2; // samples are of size 2
+
+               // Convert to needed samplerate - this converter only support 
standard flash samplerates
+               convert_raw_data(&adjusted_data, &adjusted_size, 
tmp_raw_buffer, sample_count, 0, 
+                               _synth.pcm.samplerate, (_synth.pcm.channels == 
2 ? true : false),
+                               44100,  true /* stereo */);
+
+               // Hopefully this wont happen
+               if (!adjusted_data) {
+                       log_error(_("Error in sound sample conversion"));
+                       delete[] tmp_raw_buffer;
+                       outputSize = 0;
+                       decodedBytes = 0;
+                       return NULL;
+               }
+
+               // Move the new data to the sound-struct
+               delete[] tmp_raw_buffer;
+               tmp_raw_buffer = reinterpret_cast<uint8_t*>(adjusted_data);
+               tmp_raw_buffer_size = adjusted_size;
+
+       } else {
+               tmp_raw_buffer_size = outsize;
+       }
+
+       outputSize = tmp_raw_buffer_size;
+       return tmp_raw_buffer;
+}
+
+} // gnash namespace
+

Index: libmedia/sdl/AudioDecoderMad.h
===================================================================
RCS file: libmedia/sdl/AudioDecoderMad.h
diff -N libmedia/sdl/AudioDecoderMad.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/sdl/AudioDecoderMad.h      27 Sep 2007 23:59:55 -0000      1.1
@@ -0,0 +1,54 @@
+// AudioDecoderMad.h: Audio decoding using the mad library.
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+//  $Id:
+
+#ifndef __AUDIODECODERMAD_H__
+#define __AUDIODECODERMAD_H__
+
+#include "log.h"
+#include "AudioDecoder.h"
+
+#include <mad.h>
+
+
+namespace gnash {
+
+class AudioDecoderMad : public AudioDecoder {
+
+public:
+       AudioDecoderMad();
+       ~AudioDecoderMad();
+
+       bool setup(AudioInfo* info);
+       bool setup(SoundInfo* info);
+
+       uint8_t* decode(uint8_t* input, uint32_t inputSize, uint32_t& 
outputSize, uint32_t& decodedBytes, bool parse);
+
+private:
+
+       /// mad stuff
+       mad_stream _stream;
+       mad_frame _frame;
+       mad_synth _synth;
+};
+       
+} // gnash namespace
+
+#endif // __AUDIODECODERMAD_H__
+       

Index: libmedia/sdl/MediaDecoderSdl.cpp
===================================================================
RCS file: libmedia/sdl/MediaDecoderSdl.cpp
diff -N libmedia/sdl/MediaDecoderSdl.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/sdl/MediaDecoderSdl.cpp    27 Sep 2007 23:59:55 -0000      1.1
@@ -0,0 +1,306 @@
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+//  $Id:
+
+#include "MediaDecoderSdl.h"
+#include "AudioDecoderNellymoser.h"
+
+#ifdef USE_FFMPEG
+#include "AudioDecoderFfmpeg.h"
+#include "VideoDecoderFfmpeg.h"
+#include "MediaParserFfmpeg.h"
+#endif
+
+#ifdef USE_MAD
+#include "AudioDecoderMad.h"
+#endif
+
+#include "log.h"
+
+#include <boost/scoped_array.hpp>
+
+#if defined(_WIN32) || defined(WIN32)
+# include <windows.h>  // for sleep()
+# define usleep(x) Sleep(x/1000)
+#else
+# include "unistd.h" // for usleep()
+#endif
+
+namespace gnash {
+
+MediaDecoderSdl::MediaDecoderSdl(tu_file* stream, MediaBuffer* buffer, 
uint16_t swfVersion, int format)
+       :
+       MediaDecoder(stream, buffer, swfVersion, format),
+
+       _decodeThread(NULL),
+
+       _running(true),
+       _audioDecoder(NULL),
+       _videoDecoder(NULL)
+{
+       // Buffer a bit to make sure the stream is accessable
+       if (_stream->set_position(512) != 0) {
+               _error = streamError;
+               pushOnStatus(streamNotFound);
+               return;
+       }
+       _lastConfirmedPosition = 512;
+       _streamSize = _stream->get_size();
+
+       // Check if the file is a FLV, in which case we use our own parser
+       char head[4] = {0, 0, 0, 0};
+       _stream->set_position(0);
+       _stream->read_bytes(head, 3);
+       _stream->set_position(0);
+
+       // Setup the decoding and parser
+       bool ret = false;
+       if (std::string(head) == "FLV") {
+               _parser.reset(new FLVParser(_stream));
+#ifdef USE_FFMPEG
+       } else {
+               _parser.reset(new MediaParserFfmpeg(_stream));
+#endif
+       }
+
+       ret = _parser->setupParser();
+
+       if (ret) {
+               ret = setupDecoding();
+       } else {
+               log_error("Setup of media parser failed");
+               return;
+       }
+
+       // If the setup failed, there is no reason to start the decoding thread
+       if (ret) {
+               // Start the decoding thread which will also setup the decoder 
and parser
+               _decodeThread = new 
boost::thread(boost::bind(MediaDecoderSdl::decodeThread, this)); 
+       } else {
+               log_error("Setup of media decoder failed");
+       }
+}
+
+MediaDecoderSdl::~MediaDecoderSdl()
+{
+       _running = false;
+printf("waiting for thread to stop\n");
+       _decodeThread->join();
+printf("thread stopped\n");
+
+       delete _decodeThread;
+       printf("MediaDecoderSdl deleted!");
+}
+
+void MediaDecoderSdl::pause()
+{
+}
+
+void MediaDecoderSdl::decode()
+{
+}
+
+bool MediaDecoderSdl::setupDecoding()
+{
+       bool video = false;
+       bool audio = false;
+
+       std::auto_ptr<VideoInfo> vInfo = _parser->getVideoInfo();
+       if (vInfo.get() != NULL) {
+#ifdef USE_FFMPEG
+               _videoDecoder.reset(new VideoDecoderFfmpeg());
+#endif
+               if (_videoDecoder.get() != NULL) {
+                       if (!_videoDecoder->setup(vInfo.get())) {
+                               _videoDecoder.reset(NULL); // Delete the 
videoDecoder if it is of no use
+                               log_error("No video decoder could be created, 
since no decoder for this format is available.");
+                       }
+                       video = true;
+               } else {
+                       log_error("No video decoder could be created, since no 
decoder is enabled.");
+               }
+       }
+
+       std::auto_ptr<AudioInfo> aInfo = _parser->getAudioInfo();
+       if (aInfo.get() != NULL) {
+#ifdef USE_MAD
+               if (_parser->isAudioMp3()) {
+                       _audioDecoder.reset(new AudioDecoderMad());
+               }
+#endif
+               if (_parser->isAudioNellymoser()) {
+                       _audioDecoder.reset(new AudioDecoderNellymoser());
+               }
+
+#ifdef USE_FFMPEG
+               if (_audioDecoder.get() == NULL) _audioDecoder.reset(new 
AudioDecoderFfmpeg());
+#endif
+               if (_audioDecoder.get() != NULL) {
+                       if (!_audioDecoder->setup(aInfo.get())) {
+                               _audioDecoder.reset(NULL); // Delete the 
audioDecoder if it is of no use
+                               log_error("No audio decoder could be created, 
since no decoder for this format is available.");
+                       }
+                       audio = true;
+               } else {
+                       log_error("No audio decoder could be created, since no 
decoder is enabled.");
+               }
+       }
+
+       // We don't need both audio and video to be happy :)
+       return (audio || video);
+}
+
+
+uint32_t MediaDecoderSdl::seek(uint32_t pos)
+{
+       uint32_t ret = 0;
+       if (_parser.get()) ret = _parser->seek(pos);
+       else ret = 0;
+
+       // Flush the buffer
+       _buffer->flush();
+
+       return ret;
+}
+
+void MediaDecoderSdl::decodeThread(MediaDecoderSdl* decoder)
+{
+printf("\t in the decode thread\n");
+       // The decode loop
+       while (decoder->_running) {
+
+               // If the buffer is not full, put something into it!
+               if (!decoder->_buffer->isFull()) {
+                       decoder->decodeAndBufferFrame();
+                       //log_debug("decoded a frame");
+
+               // "Warm up" the data.
+               } else if (decoder->_streamSize > 
decoder->_lastConfirmedPosition) {
+                       if 
(decoder->_stream->set_position(decoder->_lastConfirmedPosition+10000) != 0) {
+                               // We assume we're done now
+                               // TODO: check for errors
+                               decoder->_lastConfirmedPosition = 
decoder->_streamSize;
+                       } else {
+                               decoder->_lastConfirmedPosition += 10000;
+                       }
+                       //log_debug("warming up the file");
+
+               }
+               usleep(1); // task switch, to avoid 100% CPU
+       }
+       log_debug("Left the decoding loop");
+}
+
+
+void MediaDecoderSdl::decodeAndBufferFrame()
+{
+
+       MediaFrame* frame = _parser->parseMediaFrame();
+       uint32_t parserPosition = _parser->getLastParsedPos();
+       if (parserPosition > _lastConfirmedPosition) _lastConfirmedPosition = 
parserPosition;
+
+       if (frame == NULL) {
+               if (_lastConfirmedPosition+1 >= _streamSize)
+               {
+#ifdef GNASH_DEBUG_THREADS
+                       log_debug("decodeFLVFrame: load completed, stopping");
+#endif
+                       // Stop!
+                       //m_go = false;
+               } else {
+                       log_error("FLV parsing problems! stopping buffering.");
+                       _running = false;
+               }
+//log_error("FLV parsing problems!");
+               return;
+       }
+
+       if (frame->tag == 9) {
+               decodeVideo(frame);
+       } else {
+               decodeAudio(frame);
+       }
+
+}
+
+void MediaDecoderSdl::decodeAudio(MediaFrame* packet)
+{
+       // We don't handle audio
+       if (!_audioDecoder.get()) return;
+
+       uint32_t datasize;
+       uint32_t bufsize;
+
+       uint8_t* ptr = _audioDecoder->decode(packet->data, packet->dataSize, 
bufsize, datasize, false);
+
+       if (bufsize > 0 && ptr != NULL)
+       {
+               raw_mediadata_t* raw = new raw_mediadata_t();
+               
+               raw->m_data = ptr;
+               raw->m_ptr = raw->m_data;
+               raw->m_size = bufsize;
+               raw->m_pts = packet->timestamp;
+               _buffer->pushAudio(raw);
+               return;
+       }
+       log_debug(_("Problems decoding audio frame."));
+       /*_running = false;
+       _error = decodingError;
+       pushOnStatus(playStop);*/
+}
+
+void MediaDecoderSdl::decodeVideo(MediaFrame* packet)
+{
+       // We don't handle video decoding today
+       if (!_videoDecoder.get()) return;
+
+       uint32_t bufsize;
+
+       uint8_t* ptr = _videoDecoder->decode(packet->data, packet->dataSize, 
bufsize);
+
+       if (bufsize > 0 && ptr != NULL)
+       {
+               raw_mediadata_t* raw = new raw_mediadata_t();
+
+               raw->m_data = ptr;
+               raw->m_ptr = raw->m_data;
+               raw->m_size = bufsize;
+               raw->m_pts = packet->timestamp;
+               _buffer->pushVideo(raw);
+               return;
+       }
+       log_debug(_("Problems decoding video frame."));
+/*     _running = false;
+       _error = decodingError;
+       pushOnStatus(playStop);*/
+}
+
+
+std::pair<uint32_t, uint32_t>
+MediaDecoderSdl::getWidthAndHeight()
+{
+       if (_parser.get()) {
+               std::auto_ptr<VideoInfo> vInfo = _parser->getVideoInfo();
+               if (vInfo.get()) return std::pair<uint32_t, 
uint32_t>(vInfo->width, vInfo->height);
+       }
+       return std::pair<uint32_t, uint32_t>(0,0);
+}
+       
+
+} // namespace gnash

Index: libmedia/sdl/MediaDecoderSdl.h
===================================================================
RCS file: libmedia/sdl/MediaDecoderSdl.h
diff -N libmedia/sdl/MediaDecoderSdl.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/sdl/MediaDecoderSdl.h      27 Sep 2007 23:59:55 -0000      1.1
@@ -0,0 +1,155 @@
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+//  $Id:
+
+#ifndef __MEDIADECODERFFMPEG_H__
+#define __MEDIADECODERFFMPEG_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef __STDC_CONSTANT_MACROS
+#define __STDC_CONSTANT_MACROS
+#endif
+
+#include "MediaDecoder.h"
+#include "MediaParser.h"
+#include "AudioDecoder.h"
+#include "VideoDecoder.h"
+
+#include "image.h"
+
+namespace gnash {
+
+class MediaDecoderSdl: public MediaDecoder {
+public:
+       MediaDecoderSdl(tu_file* stream, MediaBuffer* buffer, uint16_t 
swfVersion, int format);
+       ~MediaDecoderSdl();
+
+       /// Pause decoding (needed ?)
+       void pause();
+
+       /// Resume/start decoding (needed ?)
+       void decode();
+
+       /// Seeks to pos
+       uint32_t seek(uint32_t pos);
+
+       std::pair<uint32_t, uint32_t> getWidthAndHeight();
+
+/*     // Used for ffmpeg data read and seek callbacks with non-FLV
+       static int readPacket(void* opaque, uint8_t* buf, int buf_size);
+
+       // Used for ffmpeg data read and seek callbacks with non-FLV
+       static offset_t seekMedia(void *opaque, offset_t offset, int whence);*/
+
+private:
+       /// The decoding thread. Sets up the decoder, and decodes.
+       static void decodeThread(MediaDecoderSdl* decoder);
+
+       /// Decodes a frame and push it unto the buffer
+       void decodeAndBufferFrame();
+
+       // Used to decode a video frame and push it on the videoqueue
+       void decodeVideo(MediaFrame* packet);
+
+       // Used to decode a audio frame and push it on the audioqueue
+       void decodeAudio(MediaFrame* packet);
+
+       /// Sets up the decoder and parser
+       bool setupDecoding();
+
+#if 0
+       /// Sets up the decoder and parser for FLVs
+       bool setupFLVdecoding();
+
+       // Used to decode and push the next available (non-FLV) frame to the 
audio or video queue
+       void decodeMediaFrame();
+
+       /// Used to decode push the next available FLV frame to the audio or 
video queue
+       //
+       /// Called by ::av_streamer to buffer more a/v frames when possible.
+       ///
+       /// This is a non-blocking call, if data isn't available in the parser 
no
+       /// new frame is decoded and this method returns false. Note that this 
doesn't
+       /// necessarely means the FLV stream is ended, rather it is possible 
the loader
+       /// thread is starving. 
+       ///
+       /// TODO: return a more informative value to distinguish between EOF 
and starving
+       ///       conditions ?
+       ///
+       void decodeFLVFrame();
+
+       // Used to decode a video frame and push it on the videoqueue
+       void decodeVideo(AVPacket* packet);
+
+       // Used to decode a audio frame and push it on the audioqueue
+       void decodeAudio(AVPacket* packet);
+
+       // Used to calculate a decimal value from a ffmpeg fraction
+       inline double as_double(AVRational time)
+       {
+               return time.num / (double) time.den;
+       }
+
+       int _videoIndex;
+       int _audioIndex;
+       
+       // video
+       AVCodecContext* _videoCodecCtx;
+       AVStream* _videoStream;
+
+       // audio
+       AVCodecContext* _audioCodecCtx;
+       AVStream* _audioStream;
+
+       // the format (mp3, avi, etc.)
+       AVFormatContext *_formatCtx;
+
+       // A ffmpeg frame
+       AVFrame* _frame;
+#endif
+       // The decoding thread
+       boost::thread* _decodeThread;
+
+       // The timestamp of the last decoded video frame, in seconds.
+       volatile uint32_t _lastVideoTimestamp;
+
+       // The timestamp of the last decoded audio frame, in seconds.
+       volatile uint32_t _lastAudioTimestamp;
+
+       // The time we started playing in seconds (since VM start ?)
+       volatile uint64_t _startClock;
+
+       // A ffmpeg thingy
+       //ByteIOContext _byteIOCxt;
+
+       // Should the decode loop run or not
+       volatile bool _running;
+       
+       // An audio decoder, either using ffmpeg or mad
+       std::auto_ptr<AudioDecoder> _audioDecoder;
+
+       // A video decoder, using ffmpeg
+       std::auto_ptr<VideoDecoder> _videoDecoder;
+};
+
+} // namespace gnash
+
+#endif // __MEDIADECODERFFMPEG_H__

Index: libmedia/sdl/MediaParserFfmpeg.cpp
===================================================================
RCS file: libmedia/sdl/MediaParserFfmpeg.cpp
diff -N libmedia/sdl/MediaParserFfmpeg.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/sdl/MediaParserFfmpeg.cpp  27 Sep 2007 23:59:55 -0000      1.1
@@ -0,0 +1,406 @@
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+//  $Id:
+
+#include "MediaParserFfmpeg.h"
+#include "log.h"
+#include <boost/scoped_array.hpp>
+
+namespace gnash {
+
+MediaParserFfmpeg::MediaParserFfmpeg(tu_file* stream)
+       :
+       MediaParser(stream),
+       _videoIndex(-1),
+       _audioIndex(-1),
+
+       _videoCodecCtx(NULL),
+       _audioCodecCtx(NULL),
+       _formatCtx(NULL),
+       _frame(NULL),
+
+       _lastVideoTimestamp(0),
+       _lastAudioTimestamp(0),
+
+       _inputPos(0),
+       _maxInputPos(0)
+{
+}
+
+MediaParserFfmpeg::~MediaParserFfmpeg()
+{
+
+}
+
+
+/// Probe the stream and try to figure out what the format is.
+//
+/// @param stream the tu_file to use for reading
+/// @return a pointer to the AVInputFormat structure containing
+///         information about the input format, or NULL.
+static AVInputFormat*
+probeStream(tu_file* stream)
+{
+       boost::scoped_array<uint8_t> buffer(new uint8_t[4096]);
+
+       // Probe the file to detect the format
+       AVProbeData probe_data;
+       probe_data.filename = "";
+       probe_data.buf = buffer.get();
+       probe_data.buf_size = 4096;
+
+       // Check if the needed amount of data is available
+       if (stream->set_position(probe_data.buf_size) != 0) {
+               log_error(_("Gnash could not read from movie url"));
+               return NULL;
+       }
+       
+       stream->read_bytes(probe_data.buf, probe_data.buf_size);
+
+       return av_probe_input_format(&probe_data, 1);
+}
+
+bool MediaParserFfmpeg::setupParser()
+{
+
+       // This registers all available file formats and codecs 
+       // with the library so they will be used automatically when
+       // a file with the corresponding format/codec is opened
+       // XXX should we call avcodec_init() first?
+       av_register_all();
+
+       AVInputFormat* inputFmt = probeStream(_stream);
+       if (!inputFmt) {
+               log_error(_("Couldn't determine stream input format"));
+               //pushOnStatus(streamNotFound);
+               return false;
+       }
+
+       // After the format probe, reset to the beginning of the file.
+       _stream->set_position(0);
+
+       // Setup the filereader/seeker mechanism. 7th argument (NULL) is the 
writer function,
+       // which isn't needed.
+       init_put_byte(&_byteIOCxt, new uint8_t[500000], 500000, 0, this, 
MediaParserFfmpeg::readPacket, NULL, MediaParserFfmpeg::seekMedia);
+       _byteIOCxt.is_streamed = 1;
+
+       _formatCtx = av_alloc_format_context();
+
+       // Open the stream. the 4th argument is the filename, which we ignore.
+       if(av_open_input_stream(&_formatCtx, &_byteIOCxt, "", inputFmt, NULL) < 
0){
+               log_error(_("Couldn't open stream for decoding"));
+               //pushOnStatus(streamNotFound);
+               return false;
+       }
+
+       // Next, we need to retrieve information about the streams contained in 
the file
+       // This fills the streams field of the AVFormatContext with valid 
information
+       int ret = av_find_stream_info(_formatCtx);
+       if (ret < 0)
+       {
+               log_error(_("Couldn't find stream information, error code: 
%d"), ret);
+               //pushOnStatus(streamNotFound);
+               return false;
+       }
+
+//     _formatCtx->pb.eof_reached = 0;
+//     av_read_play(_formatCtx);
+
+       // Find the first video & audio stream
+       _videoIndex = -1;
+       _audioIndex = -1;
+       //assert(_formatCtx->nb_streams >= 0); useless assert. 
+       for (unsigned int i = 0; i <  static_cast<unsigned 
int>(_formatCtx->nb_streams); i++)
+       {
+               AVCodecContext* enc = _formatCtx->streams[i]->codec; 
+
+               switch (enc->codec_type)
+               {
+                       case CODEC_TYPE_AUDIO:
+                               if (_audioIndex < 0)
+                               {
+                                       _audioIndex = i;
+                                       _audioStream = _formatCtx->streams[i];
+                               }
+                               break;
+
+                       case CODEC_TYPE_VIDEO:
+                               if (_videoIndex < 0)
+                               {
+                                       _videoIndex = i;
+                                       _videoStream = _formatCtx->streams[i];
+                               }
+                               break;
+                       default:
+                               break;
+               }
+       }
+
+       if (_videoIndex >= 0)
+       {
+
+               // Get a pointer to the codec context for the video stream
+               _videoCodecCtx = _formatCtx->streams[_videoIndex]->codec;
+
+/*             // Find the decoder for the video stream
+               AVCodec* pCodec = 
avcodec_find_decoder(_videoCodecCtx->codec_id);
+               if (pCodec == NULL)
+               {
+                       _videoCodecCtx = NULL;
+                       log_error(_("Video decoder %d not found"), 
_videoCodecCtx->codec_id);
+                       return false;
+               }
+
+               // Open codec
+               if (avcodec_open(_videoCodecCtx, pCodec) < 0)
+               {
+                       log_error(_("Could not open codec %d"), 
_videoCodecCtx->codec_id);
+                       return false;
+               }
+
+               // Allocate a frame to store the decoded frame in
+               _frame = avcodec_alloc_frame();*/
+               
+       }
+
+       if (_audioIndex >= 0) {
+               // Get a pointer to the audio codec context for the video stream
+               _audioCodecCtx = _formatCtx->streams[_audioIndex]->codec;
+
+/*             // Find the decoder for the audio stream
+               AVCodec* pACodec = 
avcodec_find_decoder(_audioCodecCtx->codec_id);
+           if(pACodec == NULL)
+               {
+                       log_error(_("No available audio decoder %d to process 
stream"), _audioCodecCtx->codec_id);
+                       return false;
+               }
+        
+               // Open codec
+               if (avcodec_open(_audioCodecCtx, pACodec) < 0)
+               {
+                       log_error(_("Could not open audio codec %d for 
stream"),_audioCodecCtx->codec_id);
+                       return false;
+               }*/
+
+       }
+       return true;
+}      
+
+MediaFrame* MediaParserFfmpeg::parseMediaFrame()
+{
+       AVPacket packet;
+       int rc = av_read_frame(_formatCtx, &packet);
+       
+       if (rc >= 0)
+       {
+               MediaFrame* ret = new MediaFrame;
+               ret->dataSize = packet.size;
+               ret->data = new uint8_t[packet.size];
+               memcpy(ret->data, packet.data, packet.size);
+
+               if (packet.stream_index == _audioIndex)
+               {
+                       ret->tag = AUDIO_TAG;
+
+                       // set presentation timestamp
+                       if (packet.dts != static_cast<signed 
long>(AV_NOPTS_VALUE))
+                       {
+                               ret->timestamp = 
static_cast<uint64_t>(as_double(_audioStream->time_base) * packet.dts * 1000.0);
+                       }
+
+                       if (ret->timestamp != 0)
+                       {       
+                               // update audio clock with pts, if present
+                               _lastAudioTimestamp = ret->timestamp;
+                       } else {
+                               ret->timestamp = _lastAudioTimestamp;
+                       }
+
+                       // update video clock for next frame
+                       uint32_t frame_delay;
+                       frame_delay = 
static_cast<uint32_t>((as_double(_audioStream->time_base) * packet.dts) * 
1000.0);
+
+                       _lastAudioTimestamp += frame_delay;
+
+               } else if (packet.stream_index == _videoIndex) {
+                       ret->tag = VIDEO_TAG;
+
+                       ret->timestamp = 0;
+
+                       // set presentation timestamp
+                       if (packet.dts != static_cast<signed 
long>(AV_NOPTS_VALUE))
+                       {
+                               ret->timestamp = 
static_cast<uint32_t>((as_double(_videoStream->time_base) * packet.dts) * 
1000.0);
+                       }
+
+                       if (ret->timestamp != 0)
+                       {       
+                               // update video clock with pts, if present
+                               _lastVideoTimestamp = ret->timestamp;
+                       } else {
+                               ret->timestamp = _lastVideoTimestamp;
+                       }
+
+                       // update video clock for next frame
+                       uint32_t frame_delay;
+                       frame_delay = 
static_cast<uint32_t>(as_double(_videoStream->codec->time_base) * 1000.0);
+
+                       // for MPEG2, the frame can be repeated, so we update 
the clock accordingly
+                       //frame_delay += 
static_cast<uint32_t>(_frame->repeat_pict * (frame_delay * 0.5) * 1000.0);
+
+                       _lastVideoTimestamp += frame_delay;
+
+               } else {
+                       delete ret;
+                       return NULL;
+               }
+               av_free_packet(&packet);
+               return ret;
+       } else {
+               return NULL;
+       }
+
+}
+
+uint32_t MediaParserFfmpeg::seek(uint32_t pos)
+{
+       long newpos = 0;
+       double timebase = 0;
+       uint32_t ret = 0;
+
+       AVStream* videostream = _formatCtx->streams[_videoIndex];
+       timebase = static_cast<double>(videostream->time_base.num / 
videostream->time_base.den);
+       newpos = static_cast<long>(pos / timebase);
+
+       if (av_seek_frame(_formatCtx, _videoIndex, newpos, 0) < 0) {
+               log_error(_("%s: seeking failed"), __FUNCTION__);
+               return 0;
+       }
+       // We have to do parse a new frame to get
+       // the new position. This is kindof hackish and ugly :-(
+       AVPacket Packet;
+       av_init_packet(&Packet);
+       double newtime = 0;
+       while (newtime == 0) {
+               if ( av_read_frame(_formatCtx, &Packet) < 0) {
+                       av_seek_frame(_formatCtx, -1, 0,AVSEEK_FLAG_BACKWARD);
+                       av_free_packet(&Packet);
+                       return 0;
+               }
+
+               newtime = timebase * 
static_cast<double>(_formatCtx->streams[_videoIndex]->cur_dts);
+       }
+
+       av_free_packet(&Packet);
+       av_seek_frame(_formatCtx, _videoIndex, newpos, 0);
+       uint32_t newtime_ms = static_cast<int32_t>(newtime / 1000.0);
+
+       _lastAudioTimestamp = newtime_ms;
+       _lastVideoTimestamp = newtime_ms;
+       ret = newtime_ms;
+
+       return ret;
+}
+
+std::auto_ptr<VideoInfo> 
+MediaParserFfmpeg::getVideoInfo() 
+{
+       if (!_videoCodecCtx || !_videoStream) return 
std::auto_ptr<VideoInfo>(NULL);
+
+       std::auto_ptr<VideoInfo> ret (new VideoInfo(_videoCodecCtx->codec_id,
+                                                                               
                _videoCodecCtx->width, 
+                                                                               
                _videoCodecCtx->height,
+                                                                               
                static_cast<int16_t>(as_double(_videoStream->r_frame_rate)), // 
Is this correct? What do we use the framerate for?
+                                                                               
                _videoStream->duration,
+                                                                               
                FFMPEG));
+       ret->videoCodecCtx = _videoCodecCtx;
+       return ret;
+}
+
+std::auto_ptr<AudioInfo> 
+MediaParserFfmpeg::getAudioInfo() 
+{
+       if (!_audioCodecCtx || !_audioStream) return 
std::auto_ptr<AudioInfo>(NULL);
+
+       if (_audioCodecCtx->codec_id == CODEC_ID_MP3) _isAudioMp3 = true;
+
+       return std::auto_ptr<AudioInfo>(new AudioInfo(_audioCodecCtx->codec_id,
+                                                                               
                _audioCodecCtx->sample_rate,
+                                                                               
                _audioCodecCtx->sample_fmt + 1, // see definition of 
SampleFormat in avcodec.h
+                                                                               
                _audioCodecCtx->channels > 1 ? true : false,
+                                                                               
                _audioStream->duration,
+                                                                               
                FFMPEG));
+}
+
+
+// ffmpeg callback function
+int 
+MediaParserFfmpeg::readPacket(void* opaque, uint8_t* buf, int buf_size)
+{
+
+       MediaParserFfmpeg* decoder = static_cast<MediaParserFfmpeg*>(opaque);
+       
+       size_t ret = decoder->_stream->read_bytes(static_cast<void*>(buf), 
buf_size);
+       decoder->_inputPos += ret;
+
+       if (decoder->_inputPos > decoder->_maxInputPos) decoder->_maxInputPos = 
decoder->_inputPos;
+
+       return ret;
+
+}
+
+// ffmpeg callback function
+offset_t 
+MediaParserFfmpeg::seekMedia(void *opaque, offset_t offset, int whence){
+
+       MediaParserFfmpeg* decoder = static_cast<MediaParserFfmpeg*>(opaque);
+
+       // Offset is absolute new position in the file
+       if (whence == SEEK_SET) {
+               if (decoder->_stream->set_position(offset) != 0) {
+                       decoder->_inputPos = decoder->_stream->get_position();
+               } else {
+                       decoder->_inputPos = offset;
+               }
+
+       // New position is offset + old position
+       } else if (whence == SEEK_CUR) {
+               if (decoder->_stream->set_position(decoder->_inputPos + offset) 
!= 0) {
+                       decoder->_inputPos = decoder->_stream->get_position();
+               } else {
+                       decoder->_inputPos += offset;
+               }
+
+       //      // New position is offset + end of file
+       } else if (whence == SEEK_END) {
+               // This is (most likely) a file being downloaded, so we can't 
seek to the end
+               // without causing big delays! Instead we seek to 50.000 
bytes... seems to work fine...
+               if (decoder->_stream->set_position(50000) != 0) {
+                       decoder->_inputPos = decoder->_stream->get_position();
+               } else {
+                       decoder->_inputPos = 50000;
+               }
+               
+       }
+
+       if (decoder->_inputPos > decoder->_maxInputPos) decoder->_maxInputPos = 
decoder->_inputPos;
+
+       return decoder->_inputPos;
+}
+
+} // namespace gnash

Index: libmedia/sdl/MediaParserFfmpeg.h
===================================================================
RCS file: libmedia/sdl/MediaParserFfmpeg.h
diff -N libmedia/sdl/MediaParserFfmpeg.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/sdl/MediaParserFfmpeg.h    27 Sep 2007 23:59:55 -0000      1.1
@@ -0,0 +1,127 @@
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+//  $Id:
+
+#ifndef __MEDIAPARSERFFMPEG_H__
+#define __MEDIAPARSERFFMPEG_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef __STDC_CONSTANT_MACROS
+#define __STDC_CONSTANT_MACROS
+#endif
+
+#include "MediaParser.h"
+#include "MediaBuffer.h"
+
+extern "C" {
+#include <ffmpeg/avformat.h>
+}
+
+namespace gnash {
+
+
+
+/// \brief
+/// The MediaParser class detects the format of the input file, and parses it 
on demand.
+///
+class MediaParserFfmpeg : public MediaParser
+{
+public:
+       MediaParserFfmpeg(tu_file* stream);
+       ~MediaParserFfmpeg();
+
+       /// Setup the parser
+       //
+       /// @return whether we'll be able to parse the file.
+       bool setupParser();
+
+       /// Used to parse the next media frame in the stream and return it
+       MediaFrame* parseMediaFrame();
+
+       /// Try to seek to the given millisecond. Returns the millisecond where 
the
+       /// seek got to.
+       uint32_t seek(uint32_t);
+
+       /// Returns a VideoInfo class about the videostream
+       //
+       /// @return a VideoInfo class about the videostream
+       std::auto_ptr<VideoInfo> getVideoInfo();
+
+       /// Returns a AudioInfo class about the audiostream
+       //
+       /// @return a AudioInfo class about the audiostream
+       std::auto_ptr<AudioInfo> getAudioInfo();
+
+       // Used for ffmpeg data read and seek callbacks
+       static int readPacket(void* opaque, uint8_t* buf, int buf_size);
+
+       // Used for ffmpeg data read and seek callbacks
+       static offset_t seekMedia(void *opaque, offset_t offset, int whence);
+
+       /// Returns the last parsed position in the file in bytes
+       uint32_t getLastParsedPos() { return _maxInputPos; }
+
+private:
+
+       // Used to calculate a decimal value from a ffmpeg fraction
+       inline double as_double(AVRational time)
+       {
+               return time.num / (double) time.den;
+       }
+
+       int _videoIndex;
+       int _audioIndex;
+       
+       // video
+       AVCodecContext* _videoCodecCtx;
+       AVStream* _videoStream;
+
+       // audio
+       AVCodecContext* _audioCodecCtx;
+       AVStream* _audioStream;
+
+       // the format (mp3, avi, etc.)
+       AVFormatContext *_formatCtx;
+
+       // A ffmpeg frame
+       AVFrame* _frame;
+
+       // A ffmpeg thingy
+       ByteIOContext _byteIOCxt;
+
+       // The timestamp of the last parsed video frame, in milseconds.
+       uint32_t _lastVideoTimestamp;
+
+       // The timestamp of the last parsed audio frame, in seconds.
+       uint32_t _lastAudioTimestamp;
+
+       // The position of the parserhead.
+       uint32_t _inputPos;
+
+       // The max value inputPos ever had.
+       uint32_t _maxInputPos;
+};
+
+
+
+} // namespace gnash
+
+#endif // __MEDIAPARSERFFMPEG_H__

Index: libmedia/sdl/VideoDecoderFfmpeg.cpp
===================================================================
RCS file: libmedia/sdl/VideoDecoderFfmpeg.cpp
diff -N libmedia/sdl/VideoDecoderFfmpeg.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/sdl/VideoDecoderFfmpeg.cpp 27 Sep 2007 23:59:55 -0000      1.1
@@ -0,0 +1,330 @@
+// VideoDecoderFfmpeg.cpp: Video decoding using the FFMPEG library.
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "VideoDecoderFfmpeg.h"
+
+#ifdef HAVE_SWSCALE_H
+extern "C" {
+#include <ffmpeg/swscale.h>
+}
+#endif
+#include <boost/scoped_array.hpp>
+
+namespace gnash {
+       
+VideoDecoderFfmpeg::VideoDecoderFfmpeg ()
+       :
+       _videoCodec(NULL),
+       _videoCodecCtx(NULL)
+{}
+
+VideoDecoderFfmpeg::~VideoDecoderFfmpeg()
+{
+       if (_videoCodec) avcodec_close(_videoCodecCtx);
+}
+
+bool VideoDecoderFfmpeg::setup(
+               int width,
+               int height,
+               int /*deblocking*/,
+               bool /*smoothing*/,
+               videoCodecType format, // should this argument be of codecType 
type ?
+               int /*outputFormat*/)
+{
+       // Init the avdecoder-decoder
+       avcodec_init();
+       avcodec_register_all();// change this to only register need codec?
+
+       enum CodecID codec_id;
+
+       // Find the decoder and init the parser
+       switch(format) {
+               case VIDEO_CODEC_H263:
+                       codec_id = CODEC_ID_FLV1;
+                       break;
+#ifdef FFMPEG_VP6
+               case VIDEO_CODEC_VP6:
+                       codec_id = CODEC_ID_VP6F;
+                       break;
+#endif
+               case VIDEO_CODEC_SCREENVIDEO:
+                       codec_id = CODEC_ID_FLASHSV;
+                       break;
+               default:
+                       log_error(_("Unsupported audio codec %d"), 
static_cast<int>(format));
+                       return false;
+       }
+
+       _videoCodec = avcodec_find_decoder(static_cast<CodecID>(codec_id));
+
+       if (!_videoCodec) {
+               log_error(_("libavcodec can't decode the current video 
format"));
+               return false;
+       }
+
+       _videoCodecCtx = avcodec_alloc_context();
+       if (!_videoCodecCtx) {
+               log_error(_("libavcodec couldn't allocate context"));
+               return false;
+       }
+
+       int ret = avcodec_open(_videoCodecCtx, _videoCodec);
+       if (ret < 0) {
+               avcodec_close(_videoCodecCtx);
+               log_error(_("libavcodec failed to initialize codec"));
+               return false;
+       }
+       _videoCodecCtx->width = width;
+       _videoCodecCtx->height = height;
+
+       assert(_videoCodecCtx->width > 0);
+       assert(_videoCodecCtx->height > 0);
+       return true;
+}
+
+bool VideoDecoderFfmpeg::setup(VideoInfo* info)
+{
+       // Init the avdecoder-decoder
+       avcodec_init();
+       avcodec_register_all();// change this to only register need codec?
+
+       if (info->type == FLASH) {
+               enum CodecID codec_id;
+
+               // Find the decoder and init the parser
+               switch(info->codec) {
+                       case VIDEO_CODEC_H263:
+                               codec_id = CODEC_ID_FLV1;
+                               break;
+#ifdef FFMPEG_VP6
+                       case VIDEO_CODEC_VP6:
+                               codec_id = CODEC_ID_VP6F;
+                               break;
+#endif
+                       case VIDEO_CODEC_SCREENVIDEO:
+                               codec_id = CODEC_ID_FLASHSV;
+                               break;
+                       default:
+                               log_error(_("Unsupported audio codec %d"), 
static_cast<int>(info->codec));
+                               return false;
+               }
+               _videoCodec = 
avcodec_find_decoder(static_cast<CodecID>(codec_id));
+       } else if (info->type == FFMPEG) {
+               _videoCodec = 
avcodec_find_decoder(static_cast<CodecID>(info->codec));
+       } else {
+               //log_error("Video codecType unknown: %d, %d, %d", info->type, 
FLASH, FFMPEG);
+               return false;
+       }
+
+       if (!_videoCodec) {
+               log_error(_("libavcodec can't decode the current video 
format"));
+               return false;
+       }
+
+       // Reuse the videoCodecCtx from the ffmpeg parser if exists/possible
+       if (info->videoCodecCtx) {
+       printf("re-using the parsers videoCodecCtx\n");
+               _videoCodecCtx = info->videoCodecCtx;
+       } else {
+               _videoCodecCtx = avcodec_alloc_context();
+       }
+
+       if (!_videoCodecCtx) {
+               log_error(_("libavcodec couldn't allocate context"));
+               return false;
+       }
+
+       int ret = avcodec_open(_videoCodecCtx, _videoCodec);
+       if (ret < 0) {
+               avcodec_close(_videoCodecCtx);
+               log_error(_("libavcodec failed to initialize codec"));
+               return false;
+       }
+
+       return true;
+}
+
+uint8_t*
+VideoDecoderFfmpeg::convertRGB24(AVCodecContext* srcCtx, AVFrame* srcFrame)
+{
+       int width = srcCtx->width, height = srcCtx->height;
+
+       int bufsize = avpicture_get_size(PIX_FMT_RGB24, width, height);
+       if (bufsize == -1) {
+               return NULL;
+       }
+
+       uint8_t* buffer = new uint8_t[bufsize];
+       if (!buffer) {
+               return NULL;
+       }
+
+       AVPicture picture;
+
+       avpicture_fill(&picture, buffer, PIX_FMT_RGB24, width, height);
+#ifndef HAVE_SWSCALE_H
+       img_convert(&picture, PIX_FMT_RGB24, (AVPicture*) srcFrame, 
srcCtx->pix_fmt,
+                   width, height);
+#else
+       static SwsContext* context = NULL;
+
+       if (!context) {
+               context = sws_getContext(width, height, srcCtx->pix_fmt,
+                                        width, height, PIX_FMT_RGB24,
+                                        SWS_FAST_BILINEAR, NULL, NULL, NULL);
+               if (!context) {
+                       delete [] buffer;
+                       return NULL;
+               }
+       }
+
+       int rv = sws_scale(context, srcFrame->data, srcFrame->linesize, 0, 
+                          width, picture.data, picture.linesize);
+       if (rv == -1) {
+               delete [] buffer;
+               return NULL;
+       }
+
+#endif // HAVE_SWSCALE_H
+
+       srcFrame->linesize[0] = picture.linesize[0];
+       srcFrame->data[0] = picture.data[0];
+
+       return buffer;
+}
+
+uint8_t* VideoDecoderFfmpeg::decode(uint8_t* input, uint32_t inputSize, 
uint32_t& outputSize)
+{
+       // Allocate a frame to store the decoded frame in
+       AVFrame* frame = avcodec_alloc_frame();
+
+       int got = 0;
+       avcodec_decode_video(_videoCodecCtx, frame, &got, input, inputSize);
+       if (got) {
+               boost::scoped_array<uint8_t> buffer;
+
+               uint8_t* decodedData = new uint8_t[_videoCodecCtx->width * 
_videoCodecCtx->height * 3];
+               buffer.reset(convertRGB24(_videoCodecCtx, frame));
+
+
+               // Copy the data to the buffer in the correct RGB format
+               uint8_t* srcptr = frame->data[0];
+               uint8_t* srcend = frame->data[0] + frame->linesize[0] * 
_videoCodecCtx->height;
+               uint8_t* dstptr = decodedData;
+               unsigned int srcwidth = _videoCodecCtx->width * 3;
+
+               outputSize = 0;
+
+               while (srcptr < srcend) {
+                       memcpy(dstptr, srcptr, srcwidth);
+                       srcptr += frame->linesize[0];
+                       dstptr += srcwidth;
+                       outputSize += srcwidth;
+               }
+
+               return decodedData;
+
+/*             if (_videoFrameFormat == NONE) { // NullGui?
+                       return;
+
+               } else if (_videoFrameFormat == YUV && _videoCodecCtx->pix_fmt 
!= PIX_FMT_YUV420P) {
+                       assert(0);      // TODO
+                       //img_convert((AVPicture*) pFrameYUV, PIX_FMT_YUV420P, 
(AVPicture*) pFrame, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
+                       // Don't use depreceted img_convert, use sws_scale
+
+               } else if (_videoFrameFormat == RGB && _videoCodecCtx->pix_fmt 
!= PIX_FMT_RGB24) {
+                       buffer.reset(convertRGB24(_videoCodecCtx, frame));
+               }
+
+               raw_mediadata_t* video = new raw_mediadata_t;
+               if (_videoFrameFormat == YUV) {
+                       assert(0); // See image.cpp to see what yuv size is
+                       //video->m_data = new 
uint8_t[static_cast<image::yuv*>(m_imageframe)->size()];
+               } else if (_videoFrameFormat == RGB) {
+                       video->m_data = new uint8_t[_videoCodecCtx->width * 
_videoCodecCtx->height * 3];
+               //}
+
+               video->m_ptr = video->m_data;
+               video->m_stream_index = _videoIndex;
+               video->m_pts = 0;
+
+               video->m_pts = 
static_cast<uint32_t>((as_double(_videoStream->time_base) * packet->dts) * 
1000.0);
+
+
+               if (_videoFrameFormat == YUV) {
+                       //image::yuv* yuvframe = 
static_cast<image::yuv*>(_imageframe);
+                       int copied = 0;
+                       uint8_t* ptr = video->m_data;
+                       for (int i = 0; i < 3 ; i++)
+                       {
+                               int shift = (i == 0 ? 0 : 1);
+                               uint8_t* yuv_factor = _frame->data[i];
+                               int h = _videoCodecCtx->height >> shift;
+                               int w = _videoCodecCtx->width >> shift;
+                               for (int j = 0; j < h; j++)
+                               {
+                                       copied += w;
+                                       //assert(copied <= yuvframe->size());
+                                       memcpy(ptr, yuv_factor, w);
+                                       yuv_factor += _frame->linesize[i];
+                                       ptr += w;
+                               }
+                       }
+                       video->m_size = copied;
+               } else if (_videoFrameFormat == RGB) {
+
+                       uint8_t* srcptr = _frame->data[0];
+                       uint8_t* srcend = _frame->data[0] + _frame->linesize[0] 
* _videoCodecCtx->height;
+                       uint8_t* dstptr = video->m_data;
+                       unsigned int srcwidth = _videoCodecCtx->width * 3;
+
+                       video->m_size = 0;
+
+                       while (srcptr < srcend) {
+                               memcpy(dstptr, srcptr, srcwidth);
+                               srcptr += _frame->linesize[0];
+                               dstptr += srcwidth;
+                               video->m_size += srcwidth;
+                       }
+
+               }*/
+       } else {
+               log_error("Decoding of a video frame failed");
+               return NULL;
+       }
+}
+
+std::auto_ptr<image::image_base> 
+VideoDecoderFfmpeg::decodeToImage(uint8_t* input, uint32_t inputSize)
+{
+       uint32_t outputSize = 0;
+       uint8_t* decodedData = decode(input, inputSize, outputSize);
+
+       if (!decodedData || outputSize == 0) {
+               return std::auto_ptr<image::image_base>(NULL);
+       }
+
+       std::auto_ptr<image::image_base> ret;
+       ret.reset(new image::rgb(_videoCodecCtx->width, 
_videoCodecCtx->height));
+       ret->update(decodedData);
+       return ret;
+       
+}
+
+}

Index: libmedia/sdl/VideoDecoderFfmpeg.h
===================================================================
RCS file: libmedia/sdl/VideoDecoderFfmpeg.h
diff -N libmedia/sdl/VideoDecoderFfmpeg.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/sdl/VideoDecoderFfmpeg.h   27 Sep 2007 23:59:55 -0000      1.1
@@ -0,0 +1,69 @@
+// VideoDecoderFfmpeg.h: Video decoding using the FFMPEG library.
+// 
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+//  $Id:
+
+#ifndef __VIDEODECODERFFMPEG_H__
+#define __VIDEODECODERFFMPEG_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "log.h"
+#include "VideoDecoder.h"
+
+extern "C" {
+#include <ffmpeg/avcodec.h>
+}
+
+
+namespace gnash {
+
+
+class VideoDecoderFfmpeg : public VideoDecoder {
+       
+public:
+       VideoDecoderFfmpeg();
+       ~VideoDecoderFfmpeg();
+
+       bool setup(VideoInfo* info);
+
+       bool setup(
+               int /*width*/,
+               int /*height*/,
+               int /*deblocking*/,
+               bool /*smoothing*/,
+               videoCodecType /*format*/, // should this argument be of 
codecType type ?
+               int /*outputFormat*/);
+
+       uint8_t* decode(uint8_t* input, uint32_t inputSize, uint32_t& 
outputSize);
+
+       std::auto_ptr<image::image_base> decodeToImage(uint8_t* /*input*/, 
uint32_t /*inputSize*/);
+private:
+
+       uint8_t* convertRGB24(AVCodecContext* srcCtx, AVFrame* srcFrame);
+
+       AVCodec* _videoCodec;
+       AVCodecContext* _videoCodecCtx;
+
+};
+       
+} // gnash namespace
+
+#endif // __VIDEODECODERFFMPEG_H__

Index: libmedia/sdl/sound_handler_sdl.cpp
===================================================================
RCS file: libmedia/sdl/sound_handler_sdl.cpp
diff -N libmedia/sdl/sound_handler_sdl.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/sdl/sound_handler_sdl.cpp  27 Sep 2007 23:59:55 -0000      1.1
@@ -0,0 +1,807 @@
+//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+
+// This program 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 General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+// Based on sound_handler_sdl.cpp by Thatcher Ulrich http://tulrich.com 2003
+// which has been donated to the Public Domain.
+
+// $Id: sound_handler_sdl.cpp,v 1.1 2007/09/27 23:59:55 tgc Exp $
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "sound_handler_sdl.h"
+#include "utility.h" // for convert_raw_data
+#include "AudioDecoderSimple.h"
+#include "AudioDecoderNellymoser.h"
+
+#ifdef USE_FFMPEG
+#include "AudioDecoderFfmpeg.h"
+#endif
+
+#ifdef USE_MAD
+#include "AudioDecoderMad.h"
+#endif
+
+#include "log.h"
+#include <cmath>
+#include <vector>
+#include <SDL.h>
+
+namespace gnash {
+
+SDL_sound_handler::SDL_sound_handler()
+       : soundOpened(false),
+               soundsPlaying(0),
+               muted(false)
+{
+       // This is our sound settings
+       audioSpec.freq = 44100;
+       audioSpec.format = AUDIO_S16SYS; // AUDIO_S8 AUDIO_U8;
+       audioSpec.channels = 2;
+       audioSpec.callback = SDL_sound_handler::sdl_audio_callback;
+       audioSpec.userdata = this;
+       audioSpec.samples = 2048;               //512 - not enough for  
videostream
+}
+
+SDL_sound_handler::~SDL_sound_handler()
+{
+       for (size_t i=0, e=m_sound_data.size(); i < e; ++i)
+       {
+               stop_sound(i);
+               delete_sound(i);
+       }
+       if (soundOpened) SDL_CloseAudio();
+}
+
+
+int    SDL_sound_handler::create_sound(
+       void* data,
+       unsigned int data_bytes,
+       std::auto_ptr<SoundInfo> sinfo)
+// Called to create a sample.  We'll return a sample ID that
+// can be use for playing it.
+{
+
+       assert(sinfo.get());
+       std::auto_ptr<sound_data> sounddata ( new sound_data );
+
+       //sounddata->data_size = data_bytes;
+       sounddata->volume = 100;
+       sounddata->soundinfo = sinfo;
+
+       int16_t*        adjusted_data = 0;
+       int     adjusted_size = 0;
+
+       boost::mutex::scoped_lock lock(_mutex);
+
+       switch (sounddata->soundinfo->getFormat())
+       {
+       case AUDIO_CODEC_MP3:
+#ifndef USE_FFMPEG
+#ifndef USE_MAD
+               log_error(_("gnash has not been compiled to handle mp3 audio"));
+               return -1;
+#endif
+#endif
+               sounddata->append(reinterpret_cast<uint8_t*>(data), data_bytes);
+               break;
+
+       case AUDIO_CODEC_RAW:
+       case AUDIO_CODEC_ADPCM:
+       case AUDIO_CODEC_UNCOMPRESSED:
+       case AUDIO_CODEC_NELLYMOSER:
+               sounddata->append(reinterpret_cast<uint8_t*>(data), data_bytes);
+               break;
+
+       default:
+               // Unhandled format.
+               log_error(_("unknown sound format %d requested; gnash does not 
handle it"), (int)sounddata->soundinfo->getFormat());
+               return -1; // Unhandled format, set to NULL.
+       }
+
+       m_sound_data.push_back(sounddata.release()); // the vector takes 
ownership
+       int sound_id = m_sound_data.size()-1;
+
+       return sound_id;
+
+}
+
+// this gets called when a stream gets more data
+long   SDL_sound_handler::fill_stream_data(unsigned char* data, unsigned int 
data_bytes, unsigned int /*sample_count*/, int handle_id)
+
+{
+
+       boost::mutex::scoped_lock lock(_mutex);
+       // @@ does a negative handle_id have any meaning ?
+       //    should we change it to unsigned instead ?
+       if (handle_id < 0 || (unsigned int) handle_id+1 > m_sound_data.size())
+       {
+               delete [] data;
+               return -1;
+       }
+       sound_data* sounddata = m_sound_data[handle_id];
+
+       // If doing ADPCM, knowing the framesize is needed to decode!
+       if (sounddata->soundinfo->getFormat() == AUDIO_CODEC_ADPCM) {
+               sounddata->m_frames_size[sounddata->size()] = data_bytes;
+       }
+
+       // Handling of the sound data
+       size_t start_size = sounddata->size();
+       sounddata->append(reinterpret_cast<uint8_t*>(data), data_bytes);
+
+       return start_size;
+}
+
+
+void   SDL_sound_handler::play_sound(int sound_handle, int loop_count, int 
offset, long start_position, const std::vector<sound_envelope>* envelopes)
+// Play the index'd sample.
+{
+       boost::mutex::scoped_lock lock(_mutex);
+
+       // Check if the sound exists, or if audio is muted
+       if (sound_handle < 0 || static_cast<unsigned int>(sound_handle) >= 
m_sound_data.size() || muted)
+       {
+               // Invalid handle or muted
+               return;
+       }
+
+       sound_data* sounddata = m_sound_data[sound_handle];
+
+       // If this is called from a streamsoundblocktag, we only start if this
+       // sound isn't already playing.
+       if (start_position > 0 && sounddata->m_active_sounds.size() > 0) {
+               return;
+       }
+
+       // Make sure sound actually got some data
+       if (sounddata->size() < 1) {
+               IF_VERBOSE_MALFORMED_SWF(
+                       log_swferror(_("Trying to play sound with size 0"));
+               );
+               return;
+       }
+
+       // Make a "active_sound" for this sound which is later placed on the 
vector of instances of this sound being played
+       std::auto_ptr<active_sound> sound ( new active_sound );
+
+       // Set source data to the active_sound
+       sound->set_data(sounddata);
+
+       // Set the given options of the sound
+       if (start_position < 0) sound->position = 0;
+       else sound->position = start_position;
+
+       if (offset < 0) sound->offset = 0;
+       else sound->offset = (sounddata->soundinfo->isStereo() ? offset : 
offset*2); // offset is stored as stereo
+
+       sound->envelopes = envelopes;
+
+       // Set number of loop we should do. -1 is infinte loop, 0 plays it 
once, 1 twice etc.
+       sound->loop_count = loop_count;
+
+       sound->decoder = NULL;
+
+       switch (sounddata->soundinfo->getFormat()) {
+       case AUDIO_CODEC_NELLYMOSER:
+       case AUDIO_CODEC_NELLYMOSER_8HZ_MONO:
+               sound->decoder = new AudioDecoderNellymoser();
+
+               if (!sound->decoder->setup(sounddata->soundinfo.get())) {
+                       log_error("The audio decoder can't decode the audio");
+                       delete sound->decoder;
+                       sound->decoder = NULL;
+               }
+
+               break;
+       case AUDIO_CODEC_MP3:
+#ifdef USE_MAD
+               sound->decoder = new AudioDecoderMad();
+
+               if (!sound->decoder->setup(sounddata->soundinfo.get())) {
+                       log_error("The audio decoder can't decode the audio");
+                       delete sound->decoder;
+                       sound->decoder = NULL;
+               }
+
+               break;
+#endif
+       case AUDIO_CODEC_ADPCM:
+#ifdef USE_FFMPEG
+               sound->decoder = new AudioDecoderFfmpeg();
+
+               if (!sound->decoder->setup(sounddata->soundinfo.get())) {
+                       log_error("The audio decoder can't decode the audio");
+                       delete sound->decoder;
+                       sound->decoder = NULL;
+               }
+
+               break;
+#endif
+       default:
+
+               sound->decoder = new AudioDecoderSimple();
+
+               if (!sound->decoder->setup(sounddata->soundinfo.get())) {
+                       log_error("The audio decoder can't decode the audio");
+                       delete sound->decoder;
+                       sound->decoder = NULL;
+               }
+
+       }
+               
+       if (!soundOpened) {
+               if (SDL_OpenAudio(&audioSpec, NULL) < 0 ) {
+                       log_error(_("Unable to start SDL sound: %s"), 
SDL_GetError());
+                       return;
+               }
+               soundOpened = true;
+
+       }
+
+       ++soundsPlaying;
+       ++_soundsStarted;
+       sounddata->m_active_sounds.push_back(sound.release());
+
+       if (soundsPlaying == 1) {
+               SDL_PauseAudio(0);
+       }
+
+}
+
+
+void   SDL_sound_handler::stop_sound(int sound_handle)
+{
+       boost::mutex::scoped_lock lock(_mutex);
+
+       // Check if the sound exists.
+       if (sound_handle < 0 || (unsigned int) sound_handle >= 
m_sound_data.size())
+       {
+               // Invalid handle.
+       } else {
+       
+               sound_data* sounddata = m_sound_data[sound_handle];
+       
+               for (int32_t i = (int32_t) sounddata->m_active_sounds.size()-1; 
i >-1; i--) {
+
+                       //active_sound* sound = sounddata->m_active_sounds[i];
+
+                       // Stop sound, remove it from the active list
+                       //sound->delete_raw_data();
+                       //delete sound->decoder;
+                       
sounddata->m_active_sounds.erase(sounddata->m_active_sounds.begin() + i);
+                       
+                       --soundsPlaying;
+                       ++_soundsStopped;
+               }
+       }
+
+}
+
+
+// this gets called when it's done with a sample.
+void   SDL_sound_handler::delete_sound(int sound_handle)
+{
+       boost::mutex::scoped_lock lock(_mutex);
+
+       if (sound_handle >= 0 && static_cast<unsigned int>(sound_handle) < 
m_sound_data.size())
+       {
+               delete m_sound_data[sound_handle];
+               m_sound_data[sound_handle] = NULL;
+       }
+
+}
+
+// This will stop all sounds playing. Will cause problems if the soundhandler 
is made static
+// and supplys sound_handling for many SWF's, since it will stop all sounds 
with no regard
+// for what sounds is associated with what SWF.
+void   SDL_sound_handler::stop_all_sounds()
+{
+       boost::mutex::scoped_lock lock(_mutex);
+
+       int32_t num_sounds = (int32_t) m_sound_data.size()-1;
+       for (int32_t j = num_sounds; j > -1; j--) {//Optimized
+               sound_data* sounddata = m_sound_data[j];
+               int32_t num_active_sounds = (int32_t) 
sounddata->m_active_sounds.size()-1;
+               for (int32_t i = num_active_sounds; i > -1; i--) {
+
+                       //active_sound* sound = sounddata->m_active_sounds[i];
+
+                       // Stop sound, remove it from the active list
+                       //delete sound->decoder;
+                       
sounddata->m_active_sounds.erase(sounddata->m_active_sounds.begin() + i);
+                       
+                       --soundsPlaying;
+                       ++_soundsStopped;
+               }
+       }
+}
+
+
+//     returns the sound volume level as an integer from 0 to 100,
+//     where 0 is off and 100 is full volume. The default setting is 100.
+int    SDL_sound_handler::get_volume(int sound_handle) {
+
+       boost::mutex::scoped_lock lock(_mutex);
+
+       int ret;
+       // Check if the sound exists.
+       if (sound_handle >= 0 && static_cast<unsigned int>(sound_handle) < 
m_sound_data.size())
+       {
+               ret = m_sound_data[sound_handle]->volume;
+       } else {
+               ret = 0; // Invalid handle
+       }
+       return ret;
+}
+
+
+//     A number from 0 to 100 representing a volume level.
+//     100 is full volume and 0 is no volume. The default setting is 100.
+void   SDL_sound_handler::set_volume(int sound_handle, int volume) {
+
+       boost::mutex::scoped_lock lock(_mutex);
+
+       // Check if the sound exists.
+       if (sound_handle < 0 || static_cast<unsigned int>(sound_handle) >= 
m_sound_data.size())
+       {
+               // Invalid handle.
+       } else {
+
+               // Set volume for this sound. Should this only apply to the 
active sounds?
+               m_sound_data[sound_handle]->volume = volume;
+       }
+
+
+}
+       
+SoundInfo* SDL_sound_handler::get_sound_info(int sound_handle) {
+
+       boost::mutex::scoped_lock lock(_mutex);
+
+       // Check if the sound exists.
+       if (sound_handle >= 0 && static_cast<unsigned int>(sound_handle) < 
m_sound_data.size())
+       {
+               return m_sound_data[sound_handle]->soundinfo.get();
+       } else {
+               return NULL;
+       }
+
+}
+
+// gnash calls this to mute audio
+void SDL_sound_handler::mute() {
+       stop_all_sounds();
+       muted = true;
+}
+
+// gnash calls this to unmute audio
+void SDL_sound_handler::unmute() {
+       muted = false;
+}
+
+bool SDL_sound_handler::is_muted()
+{
+       return muted;
+}
+
+void   SDL_sound_handler::attach_aux_streamer(aux_streamer_ptr ptr, void* 
owner)
+{
+       boost::mutex::scoped_lock lock(_mutex);
+       assert(owner);
+       assert(ptr);
+
+       aux_streamer_ptr p;
+       if (m_aux_streamer.get(owner, &p))
+       {
+               // Already in the hash.
+               return;
+       }
+       m_aux_streamer[owner] = ptr;
+
+       ++soundsPlaying;
+
+       if (!soundOpened) {
+               if (SDL_OpenAudio(&audioSpec, NULL) < 0 ) {
+                       log_error(_("Unable to start aux SDL sound: %s"), 
SDL_GetError());
+                       return;
+               }
+               soundOpened = true;
+       }
+       SDL_PauseAudio(0);
+
+}
+
+void   SDL_sound_handler::detach_aux_streamer(void* owner)
+{
+       boost::mutex::scoped_lock lock(_mutex);
+       aux_streamer_ptr p;     
+       if (m_aux_streamer.get(owner, &p))
+       {
+               --soundsPlaying;
+               m_aux_streamer.erase(owner);
+       }
+
+}
+
+unsigned int SDL_sound_handler::get_duration(int sound_handle)
+{
+       boost::mutex::scoped_lock lock(_mutex);
+
+       // Check if the sound exists.
+       if (sound_handle < 0 || (unsigned int) sound_handle >= 
m_sound_data.size())
+       {
+               // Invalid handle.
+               return 0;
+       }
+
+       sound_data* sounddata = m_sound_data[sound_handle];
+
+       uint32_t sampleCount = sounddata->soundinfo->getSampleCount();
+       uint32_t sampleRate = sounddata->soundinfo->getSampleRate();
+
+       // Return the sound duration in milliseconds
+       if (sampleCount > 0 && sampleRate > 0) {
+               unsigned int ret = sampleCount / sampleRate * 1000;
+               ret += ((sampleCount % sampleRate) * 1000) / sampleRate;
+               if (sounddata->soundinfo->isStereo()) ret = ret / 2;
+               return ret;
+       } else {
+               return 0;
+       }
+}
+
+unsigned int SDL_sound_handler::get_position(int sound_handle)
+{
+       boost::mutex::scoped_lock lock(_mutex);
+
+       // Check if the sound exists.
+       if (sound_handle < 0 || (unsigned int) sound_handle >= 
m_sound_data.size())
+       {
+               // Invalid handle.
+               return 0;
+       }
+
+       sound_data* sounddata = m_sound_data[sound_handle];
+
+       // If there is no active sounds, return 0
+       if (sounddata->m_active_sounds.size() == 0) return 0;
+
+       // We use the first active sound of this.
+       active_sound* asound = sounddata->m_active_sounds[0];
+
+       // Return the playhead position in milliseconds
+       unsigned int ret = asound->samples_played / audioSpec.freq * 1000;
+       ret += ((asound->samples_played % audioSpec.freq) * 1000) / 
audioSpec.freq;
+       if (audioSpec.channels > 1) ret = ret / audioSpec.channels;
+       return ret;
+}
+
+sound_handler*
+create_sound_handler_sdl()
+// Factory.
+{
+       return new SDL_sound_handler;
+}
+
+// Pointer handling and checking functions
+uint8_t*
+active_sound::get_raw_data_ptr(unsigned long int pos)
+{
+       if ( _decodedData.get() )
+       {
+               return _decodedData->data(pos);
+       }
+       else return 0;
+}
+
+uint8_t*
+active_sound::get_data_ptr(unsigned long int pos)
+{
+       assert(_undecodedData);
+       return _undecodedData->data(pos);
+}
+
+void active_sound::set_data(sound_data* idata)
+{
+       _undecodedData = idata;
+}
+
+void active_sound::deleteDecodedData()
+{
+       _decodedData.reset();
+}
+
+// AS-volume adjustment
+void adjust_volume(int16_t* data, int size, int volume)
+{
+       for (int i=0; i < size*0.5; i++) {
+               data[i] = data[i] * volume/100;
+       }
+}
+
+// envelope-volume adjustment
+static void
+use_envelopes(active_sound* sound, unsigned int length)
+{
+       // Check if this is the time to use envelopes yet
+       if (sound->current_env == 0 && (*sound->envelopes)[0].m_mark44 > 
sound->samples_played+length/2)
+       {
+               return;
+
+       }
+       // switch to the next envelope if needed and possible
+       else if (sound->current_env < sound->envelopes->size()-1 && 
(*sound->envelopes)[sound->current_env+1].m_mark44 >= sound->samples_played)
+       {
+               sound->current_env++;
+       }
+
+       // Current envelope position
+       int32_t cur_env_pos = 
sound->envelopes->operator[](sound->current_env).m_mark44;
+
+       // Next envelope position
+       uint32_t next_env_pos = 0;
+       if (sound->current_env == (sound->envelopes->size()-1)) {
+               // If there is no "next envelope" then set the next envelope 
start point to be unreachable
+               next_env_pos = cur_env_pos + length;
+       } else {
+               next_env_pos = 
(*sound->envelopes)[sound->current_env+1].m_mark44;
+       }
+
+       unsigned int startpos = 0;
+       // Make sure we start adjusting at the right sample
+       if (sound->current_env == 0 && 
(*sound->envelopes)[sound->current_env].m_mark44 > sound->samples_played) {
+               startpos = sound->raw_position + 
((*sound->envelopes)[sound->current_env].m_mark44 - sound->samples_played)*2;
+       } else {
+               startpos = sound->raw_position;
+       }
+
+       int16_t* data = 
reinterpret_cast<int16_t*>(sound->get_raw_data_ptr(startpos));
+
+       for (unsigned int i=0; i < length/2; i+=2) {
+               float left = 
static_cast<float>((*sound->envelopes)[sound->current_env].m_level0 / 32768.0);
+               float right = 
static_cast<float>((*sound->envelopes)[sound->current_env].m_level1 / 32768.0);
+
+               data[i] = static_cast<int16_t>(data[i] * left); // Left
+               data[i+1] = static_cast<int16_t>(data[i+1] * right); // Right
+
+               if ((sound->samples_played+(length/2-i)) >= next_env_pos && 
sound->current_env != (sound->envelopes->size()-1)) {
+                       sound->current_env++;
+                       // Next envelope position
+                       if (sound->current_env == (sound->envelopes->size()-1)) 
{
+                               // If there is no "next envelope" then set the 
next envelope start point to be unreachable
+                               next_env_pos = cur_env_pos + length;
+                       } else {
+                               next_env_pos = 
(*sound->envelopes)[sound->current_env+1].m_mark44;
+                       }
+               }
+       }
+}
+
+
+// Prepare for mixing/adding (volume adjustments) and mix/add.
+static void
+do_mixing(Uint8* stream, active_sound* sound, Uint8* data, unsigned int 
mix_length, unsigned int volume) {
+       // If the volume needs adjustments we call a function to do that
+       if (volume != 100) {
+               adjust_volume(reinterpret_cast<int16_t*>(data), mix_length, 
volume);
+       } else if (sound->envelopes != NULL) {
+               use_envelopes(sound, mix_length);
+       }
+
+       // Mix the raw data
+       SDL_MixAudio(static_cast<Uint8*>(stream),static_cast<const 
Uint8*>(data), mix_length, SDL_MIX_MAXVOLUME);
+
+       // Update sound info
+       sound->raw_position += mix_length;
+
+       // Sample size is always 2
+       sound->samples_played += mix_length / 2;
+}
+
+
+// Callback invoked by the SDL audio thread.
+void SDL_sound_handler::sdl_audio_callback (void *udata, Uint8 *stream, int 
buffer_length_in)
+{
+       if ( buffer_length_in < 0 )
+       {
+               log_error(_("Negative buffer length in sdl_audio_callback 
(%d)"), buffer_length_in);
+               return;
+       }
+
+       if ( buffer_length_in == 0 )
+       {
+               log_error(_("Zero buffer length in sdl_audio_callback"));
+               return;
+       }
+
+       unsigned int buffer_length = static_cast<unsigned 
int>(buffer_length_in);
+
+       // Get the soundhandler
+       SDL_sound_handler* handler = static_cast<SDL_sound_handler*>(udata);
+
+       // If nothing to play there is no reason to play
+       // Is this a potential deadlock problem?
+       if (handler->soundsPlaying == 0 && handler->m_aux_streamer.size() == 0) 
{
+               SDL_PauseAudio(1);
+               return;
+       }
+
+       boost::mutex::scoped_lock lock(handler->_mutex);
+
+       // Mixed sounddata buffer
+       Uint8* buffer = stream;
+       memset(buffer, 0, buffer_length);
+
+       // call NetStream or Sound audio callbacks
+       if (handler->m_aux_streamer.size() > 0)
+       {
+               uint8_t* buf = new uint8_t[buffer_length];
+
+               // Loop through the attached sounds
+               hash_wrapper< void*, sound_handler::aux_streamer_ptr 
>::iterator it = handler->m_aux_streamer.begin();
+               hash_wrapper< void*, sound_handler::aux_streamer_ptr 
>::iterator end = handler->m_aux_streamer.end();
+               while (it != end) {
+                       memset(buf, 0, buffer_length);
+
+                       SDL_sound_handler::aux_streamer_ptr aux_streamer = 
it->second; //handler->m_aux_streamer[i]->ptr;
+                       void* owner = it->first;
+
+                       // If false is returned the sound doesn't want to be 
attached anymore
+                       bool ret = (aux_streamer)(owner, buf, buffer_length);
+                       if (!ret) {
+                               handler->m_aux_streamer.erase(it++);
+                               handler->soundsPlaying--;
+                       } else {
+                               ++it;
+                       }
+                       SDL_MixAudio(stream, buf, buffer_length, 
SDL_MIX_MAXVOLUME);
+
+               }
+               delete [] buf;
+       }
+
+       // Run through all the sounds.
+       for(uint32_t i=0; i < handler->m_sound_data.size(); i++) {
+               sound_data* sounddata = handler->m_sound_data[i];
+               for(uint32_t j = 0; j < sounddata->m_active_sounds.size(); j++) 
{
+
+                       // Temp variables to make the code simpler and easier 
to read
+                       active_sound* sound = sounddata->m_active_sounds[j];
+
+                       // If there exist no decoder, then we can't decode!
+                       if (sound->decoder == NULL) continue;
+
+                       // When the current sound dont have enough decoded data 
to fill the buffer, 
+                       // we first mix what is already decoded, then decode 
some more data, and
+                       // mix some more until the buffer is full. If a sound 
loops the magic
+                       // happens here ;)
+                       if (sound->rawDataSize() - sound->raw_position < 
buffer_length 
+                               && (sound->position < sound->dataSize() || 
sound->loop_count != 0)) {
+                               // First we mix what is decoded
+                               unsigned int index = 0;
+                               if (sound->rawDataSize() - sound->raw_position 
> 0)
+                               {
+                                       index = sound->rawDataSize() - 
sound->raw_position;
+
+                                       do_mixing(stream, sound, 
sound->get_raw_data_ptr(sound->raw_position),
+                                               index, sounddata->volume);
+
+                               }
+
+                               // Then we decode some data
+                               // We loop until the size of the decoded sound 
is greater than the buffer size,
+                               // or there is no more to decode.
+                               unsigned int decoded_size = 0;
+                               // TODO: should we delete any previous raw_data 
?
+                               while(decoded_size < buffer_length)
+                               {
+
+                                       // If we need to loop, we reset the 
data pointer
+                                       if (sound->dataSize() == 
sound->position && sound->loop_count != 0) {
+                                               sound->loop_count--;
+                                               sound->position = 0;
+                                               sound->samples_played = 0;
+                                       }
+
+                                       // Test if we will get problems... 
Should not happen...
+                                       assert(sound->dataSize() > 
sound->position);
+                                       
+                                       // temp raw buffer
+                                       Uint8* tmp_raw_buffer;
+                                       uint32_t tmp_raw_buffer_size = 0;
+                                       uint32_t decodedBytes = 0;
+
+                                       uint32_t inputSize = 0;
+                                       bool parse = true;
+                                       if (sounddata->soundinfo->getFormat() 
== AUDIO_CODEC_ADPCM) {
+                                               parse = false;
+                                               if 
(sounddata->m_frames_size.size() > 0) inputSize = 
sounddata->m_frames_size[sound->position];
+                                               else inputSize = 
sound->dataSize() - sound->position;
+                                       } else {
+                                               inputSize = sound->dataSize() - 
sound->position;
+                                       }
+
+                                       tmp_raw_buffer = 
sound->decoder->decode(sound->get_data_ptr(sound->position), 
+                                                                               
                        inputSize, tmp_raw_buffer_size, decodedBytes, parse);
+
+                                       sound->position += decodedBytes;
+
+                                       sound->deleteDecodedData();
+                                       
sound->appendDecodedData(tmp_raw_buffer, tmp_raw_buffer_size);
+
+                                       decoded_size += tmp_raw_buffer_size;
+
+                                       // no more to decode from this sound, 
so we break the loop
+                                       if (sound->dataSize() <= 
sound->position && sound->loop_count == 0) {
+                                               break;
+                                       }
+
+                               } // end of "decode min. bufferlength data" 
while loop
+
+                               sound->raw_position = 0;
+
+                               // Determine how much should be mixed
+                               unsigned int mix_length = 0;
+                               if (decoded_size >= buffer_length - index) {
+                                       mix_length = buffer_length - index;
+                               } else { 
+                                       mix_length = decoded_size;
+                               }
+                               if (sound->rawDataSize() < 2) continue; // 
something went terrible wrong
+                               do_mixing(stream+index, sound, 
sound->get_raw_data_ptr(0), mix_length, sounddata->volume);
+
+                       // When the current sound has enough decoded data to 
fill 
+                       // the buffer, we do just that.
+                       } else if (sound->rawDataSize() > sound->raw_position 
&& sound->rawDataSize() - sound->raw_position > buffer_length ) {
+
+                               do_mixing(stream, sound, 
sound->get_raw_data_ptr(sound->raw_position), 
+                                       buffer_length, sounddata->volume);
+
+                       // When the current sound doesn't have anymore data to 
decode,
+                       // and doesn't loop (anymore), but still got unplayed 
data,
+                       // we put the last data on the stream
+                       } else if (sound->rawDataSize() - sound->raw_position 
<= buffer_length && sound->rawDataSize() > sound->raw_position+1) {
+                       
+
+                               do_mixing(stream, sound, 
sound->get_raw_data_ptr(sound->raw_position), 
+                                       sound->rawDataSize() - 
sound->raw_position, sounddata->volume);
+
+                               sound->raw_position = sound->rawDataSize();
+                       } 
+
+                       // Sound is done, remove it from the active list
+                       if (sound->position == sound->dataSize() && 
sound->loop_count == 0) {
+                               /*delete sound->decoder;
+                               sound->deleteDecodedData();*/
+                               
sounddata->m_active_sounds.erase(sounddata->m_active_sounds.begin() + j);
+                               handler->soundsPlaying--;
+                               handler->_soundsStopped++;
+
+                       } 
+               } // active sounds loop
+       } // existing sounds loop
+
+}
+
+} // namespace gnash
+
+// Local Variables:
+// mode: C++
+// End:
+

Index: libmedia/sdl/sound_handler_sdl.h
===================================================================
RCS file: libmedia/sdl/sound_handler_sdl.h
diff -N libmedia/sdl/sound_handler_sdl.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/sdl/sound_handler_sdl.h    27 Sep 2007 23:59:55 -0000      1.1
@@ -0,0 +1,390 @@
+//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+
+// This program 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 General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+// $Id: sound_handler_sdl.h,v 1.1 2007/09/27 23:59:55 tgc Exp $
+
+#ifndef SOUND_HANDLER_SDL_H
+#define SOUND_HANDLER_SDL_H
+
+
+#include "sound_handler.h" // for inheritance
+#include "hash_wrapper.h"
+#include "AudioDecoder.h"
+
+#include "log.h"
+
+#ifdef USE_FFMPEG
+extern "C" {
+#include <ffmpeg/avcodec.h>
+}
+#elif defined(USE_MAD)
+#include <mad.h>
+#endif
+
+#include <vector>
+
+#include <SDL_audio.h>
+#include <boost/thread/thread.hpp>
+#include <boost/bind.hpp>
+#include <boost/thread/mutex.hpp>
+
+namespace gnash {
+
+class active_sound;
+
+/// Used to hold the sounddata when doing on-demand-decoding
+class sound_data
+{
+       /// The undecoded data
+       Buffer _buf;
+
+public:
+
+       sound_data()
+       {}
+
+       ~sound_data();
+
+       /// Object holding information about the sound
+       std::auto_ptr<SoundInfo> soundinfo;
+
+       std::map<uint32_t,uint32_t> m_frames_size;
+
+       /// Append size bytes to this sound
+       //
+       /// @param data
+       ///     Data bytes, allocated with new[]. Ownership transferred.
+       ///
+       /// @param size
+       ///     Size of the 'data' buffer.
+       ///
+       void append(uint8_t* data, unsigned int size)
+       {
+               _buf.append(data, size);
+       }
+
+       /// Return size of the data buffer
+       size_t size() const 
+       {
+               return _buf.size();
+       }
+
+       /// Return a pointer to the underlying buffer
+       const uint8_t* data() const {
+               return _buf.data();
+       }
+
+       /// Return a pointer to the underlying buffer
+       uint8_t* data() {
+               return _buf.data();
+       }
+
+       /// Return a pointer to an offset in the underlying buffer
+       //
+       /// @param pos The offset value.
+       ///     An assertion will fail if pos > size()
+       ///
+       const uint8_t* data(size_t pos) const {
+               return _buf.data(pos);
+       }
+
+       /// Return a pointer to an offset in the underlying buffer
+       //
+       /// @param pos The offset value.
+       ///     An assertion will fail if pos > size()
+       ///
+       uint8_t* data(size_t pos) {
+               return _buf.data(pos);
+       }
+
+       /// Volume for AS-sounds, range: 0-100.
+       /// It's the SWF range that is represented here.
+       int volume;
+
+       /// Vector containing the active instances of this sounds being played
+       //
+       /// NOTE: This class *owns* all active sounds
+       ///
+       typedef std::vector<active_sound*> ActiveSounds;
+
+       ActiveSounds m_active_sounds;
+
+};
+
+/// Used to hold the info about active sounds
+//
+/// This class contains a pointer to the sound_data used for playing
+/// and an optional Buffer to use when decoding is needed.
+///
+/// When the Buffer is NULL we'll play the sound_data bytes directly
+/// (we assume they are decoded already)
+///
+class active_sound
+{
+public:
+       active_sound()
+               :
+               position(0),
+               raw_position(0),
+               loop_count(0),
+               offset(0),
+               current_env(0),
+               samples_played(0),
+               _undecodedData(0)
+       {}
+
+       ~active_sound()
+       {
+               deleteDecodedData();
+               delete decoder;
+       }
+
+       /// The decoder object used to convert the data into the playable format
+       AudioDecoder* decoder;
+
+       /// Current decoding position in the stream
+       unsigned long position;
+
+       /// Current playing position in the decoded stream
+       unsigned long raw_position;
+
+       /// Numbers of loops: -1 means loop forever, 0 means play once.
+       /// For every loop completed, it is decremented.
+       long loop_count;
+
+       /// Offset to make playback start in-sync, only used with mp3 streams.
+       unsigned int offset;
+
+       /// Sound envelopes for the current sound, which determine the volume 
level
+       /// from a given position. Only used with sound events.
+       const std::vector<gnash::sound_handler::sound_envelope>* envelopes;
+
+       /// Index of current envelope.
+       uint32_t current_env;
+
+       /// Number of samples played so far.
+       unsigned long samples_played;
+
+       /// Set the undecoded data pointer
+       //
+       /// @param newUndecodedData
+       ///     Pointer to a sound_data being the undecoded data
+       ///     Ownership will NOT be transferred.
+       ///
+       void set_data(sound_data* newUndecodedData);
+
+       /// Returns the data pointer in the undecoded datastream
+       /// for the given position. Boundaries are checked.
+       uint8_t* get_data_ptr(unsigned long int pos);
+
+       /// Returns the data pointer in the decoded datastream
+       /// for the given position. Boundaries are checked.
+       uint8_t* get_raw_data_ptr(unsigned long int pos);
+
+       /// Release resources associated with decoded data, if any.
+       //
+       /// After this call, the active_sound will have no decoded data
+       /// buffer, thus any pointer to the decoded data will be fetched
+       /// from the undecoded one.
+       ///
+       void deleteDecodedData();
+
+       /// Append size bytes to this raw data 
+       //
+       /// @param data
+       ///     Data bytes, allocated with new[]. Ownership transferred.
+       ///
+       /// @param size
+       ///     Size of the 'data' buffer.
+       ///
+       void appendDecodedData(uint8_t* data, unsigned int size)
+       {
+               if ( ! _decodedData.get() )
+               {
+                       _decodedData.reset( new Buffer );
+               }
+  
+               _decodedData->append(data, size);
+       }
+  
+       /// Set decoded data
+       //
+       /// @param data
+       ///     Data bytes, allocated with new[]. Ownership transferred.
+       ///
+       /// @param size
+       ///     Size of the 'data' buffer.
+       ///
+       void setDecodedData(uint8_t* data, unsigned int size)
+       {
+               if ( ! _decodedData.get() )
+               {
+                       _decodedData.reset( new Buffer(data, size) );
+               }
+               else
+               {
+                       _decodedData->assign(data, size);
+               }
+       }
+
+       size_t rawDataSize() const
+       {
+               if ( _decodedData.get() )
+               {
+                       return _decodedData->size();
+               }
+               else return 0;
+       }
+  
+       size_t dataSize() const
+       {
+               return _undecodedData ? _undecodedData->size() : 0;
+       }
+  
+private:
+
+       /// The undecoded data
+       sound_data* _undecodedData;
+
+       /// The decoded buffer
+       //
+       /// If NULL, the _undecodedData will be considered
+       /// decoded instead
+       ///
+       std::auto_ptr<Buffer> _decodedData;
+
+};
+
+// This is here as it needs definition of active_sound
+sound_data::~sound_data()
+{
+       for (ActiveSounds::iterator i=m_active_sounds.begin(), 
e=m_active_sounds.end(); i!=e; ++i)
+       {
+               delete *i;
+       }
+}
+
+// Use SDL and ffmpeg/mad/nothing to handle sounds.
+class SDL_sound_handler : public gnash::sound_handler
+{
+private:
+       /// NetStream audio callbacks
+       hash_wrapper< void* /* owner */, aux_streamer_ptr /* callback */> 
m_aux_streamer;       //vv
+
+       /// Vector containing all sounds.
+       //
+       /// Elemenst of the vector are owned by this class
+       ///
+       std::vector<sound_data*>        m_sound_data;
+
+       /// Is sound device opened?
+       bool soundOpened;
+
+       /// The SDL_audio specs
+       SDL_AudioSpec audioSpec;
+       
+       /// Keeps track of numbers of playing sounds
+       int soundsPlaying;
+
+       /// Is the audio muted?
+       bool muted;
+       
+       /// Mutex for making sure threads doesn't mess things up
+       boost::mutex _mutex;
+
+public:
+       SDL_sound_handler();
+       virtual ~SDL_sound_handler();
+
+       /// Called to create a sound.
+       virtual int     create_sound(void* data, unsigned int data_bytes, 
std::auto_ptr<SoundInfo> sinfo);
+
+       /// this gets called when a stream gets more data
+       virtual long    fill_stream_data(unsigned char* data, unsigned int 
data_bytes,
+                                        unsigned int sample_count, int 
handle_id);
+
+       /// Play the index'd sample.
+       virtual void    play_sound(int sound_handle, int loop_count, int offset,
+                                  long start_position, const 
std::vector<sound_envelope>* envelopes);
+
+       /// Stop the index'd sample.
+       virtual void    stop_sound(int sound_handle);
+
+       /// This gets called when it's done with a sample.
+       virtual void    delete_sound(int sound_handle);
+
+       /// This will stop all sounds playing.
+       virtual void    stop_all_sounds();
+
+       /// Returns the sound volume level as an integer from 0 to 100. 
AS-script only.
+       virtual int     get_volume(int sound_handle);
+
+       /// Sets the sound volume level as an integer from 0 to 100. AS-script 
only.
+       virtual void    set_volume(int sound_handle, int volume);
+               
+       /// Gnash uses this to get info about a sound. Used when a stream needs 
more data.
+       virtual SoundInfo* get_sound_info(int sound_handle);
+
+       /// Gnash calls this to mute audio.
+       virtual void    mute();
+
+       /// Gnash calls this to unmute audio.
+       virtual void    unmute();
+
+       /// Gnash calls this to get the mute state.
+       virtual bool    is_muted();
+
+       /// Gets the duration in milliseconds of an event sound connected to an 
AS Sound obejct.
+       virtual unsigned int get_duration(int sound_handle);
+
+       /// Gets the playhead position in milliseconds of an event sound 
connected to an AS Soound obejct.
+       virtual unsigned int get_position(int sound_handle);
+       
+       virtual void    attach_aux_streamer(aux_streamer_ptr ptr, void* owner); 
//vv
+       virtual void    detach_aux_streamer(void* owner);       //vv
+
+       /// Callback invoked by the SDL audio thread.
+       //
+       /// Refills the output stream/buffer with data.
+       ///
+       /// We run trough all the attached auxiliary streamers fetching decoded
+       /// audio blocks and mixing them into the given output stream.
+       ///
+       /// If sound is compresssed (mp3) a mp3-frame is decoded into a buffer,
+       /// and resampled if needed. When the buffer has been sampled, another
+       /// frame is decoded until all frames has been decoded.
+       /// If a sound is looping it will be decoded from the beginning again.
+       ///
+       /// TODO: make a static method of the SDL_sound_handler class
+       ///
+       /// @param udata
+       ///     User data pointer (SDL_sound_handler instance in our case).
+       ///     We'll lock the SDL_sound_handler::_mutex during operations.
+       ///
+       /// @param stream
+       ///     The output stream/buffer to fill
+       ///
+       /// @param buffer_length_in
+       ///     Length of the buffer.
+       ///     If zero or negative we log an error and return
+       ///     (negative is probably an SDL bug, zero dunno yet).
+       ///
+       static void sdl_audio_callback (void *udata, Uint8 *stream, int 
buffer_length_in);
+};
+
+} // namespace gnash
+
+#endif // SOUND_HANDLER_SDL_H

Index: backend/sound_handler.h
===================================================================
RCS file: backend/sound_handler.h
diff -N backend/sound_handler.h
--- backend/sound_handler.h     26 Sep 2007 10:15:52 -0000      1.31
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,543 +0,0 @@
-// 
-//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-// 
-// This program 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 General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-// 
-//
-
-/* $Id: sound_handler.h,v 1.31 2007/09/26 10:15:52 strk Exp $ */
-
-/// \page sound_handler_intro Sound handler introduction
-///
-/// This page must be written, volunteers ? :)
-///
-
-#ifndef SOUND_HANDLER_H
-#define SOUND_HANDLER_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "tu_config.h" // for DSOEXPORT
-#include "tu_types.h"
-
-#include <vector>
-#include <memory>
-#include <cassert>
-
-namespace gnash {
-       class stream;
-       class SoundInfo;
-}
-
-namespace gnash {
-
-/// A buffer of bytes
-class Buffer {
-public:
-       Buffer()
-               :
-               _capacity(0),
-               _data(0),
-               _size(0)
-       {}
-
-       /// Create a Buffer with the given initial content
-       //
-       /// @param newData data to assign to this buffer.
-       ///     Allocated with new[]. Ownership transferred.
-       ///
-       /// @param size number of bytes in the new data
-       ///
-       Buffer(uint8_t* newData, size_t size)
-               :
-               _capacity(size),
-               _data(newData),
-               _size(size)
-       {}
-
-       /// Append data to this buffer
-       //
-       /// @param newData data to append to this buffer.
-       ///     Allocated with new[]. Ownership transferred.
-       ///
-       /// @param size number of bytes in the new data
-       ///
-       void append(uint8_t* newData, size_t size)
-       {
-               if ( ! _capacity )
-               {
-                       _data = newData;
-                       _size = size;
-                       _capacity = _size;
-                       return;
-               }
-
-               reserve(_size+size);
-
-               assert(_capacity >= _size+size);
-               memcpy(_data+_size, newData, size);
-               _size += size;
-               delete [] newData;
-       }
-
-       /// Assign data to this buffer
-       //
-       /// @param newData data to assign to this buffer.
-       ///     Allocated with new[]. Ownership transferred.
-       ///
-       /// @param size number of bytes in the new data
-       ///
-       void assign(uint8_t* newData, size_t size)
-       {
-               if ( ! _capacity )
-               {
-                       _data = newData;
-                       _size = size;
-                       _capacity = _size;
-                       return;
-               }
-
-               _size=0; // so reserve won't memcpy...
-               reserve(size);
-
-               assert(_capacity >= size);
-
-               memcpy(_data, newData, size);
-               _size = size;
-
-               delete [] newData;
-       }
-
-       const uint8_t* data() const
-       {
-               return _data;
-       }
-
-       uint8_t* data() 
-       {
-               return _data;
-       }
-
-       const uint8_t* data(size_t pos) const
-       {
-               assert(pos < _capacity);
-               return _data+pos;
-       }
-
-       uint8_t* data(size_t pos) 
-       {
-               assert(pos < _capacity);
-               return _data+pos;
-       }
-
-       void resize(size_t newSize)
-       {
-               // we won't change capacity here
-               // (should we?)
-               _size = newSize;
-       }
-
-       void reserve(size_t newCapacity)
-       {
-               if ( _capacity > newCapacity ) return;
-
-               // TODO: use smalles power of 2 bigger then newCapacity
-               _capacity = std::max(newCapacity, _capacity*2);
-
-               uint8_t* tmp = _data;
-               _data = new uint8_t[_capacity];
-               if ( tmp )
-               {
-                       if ( _size ) memcpy(_data, tmp, _size);
-                       delete [] tmp;
-               }
-       }
-
-       size_t size() const
-       {
-               return _size;
-       }
-
-       ~Buffer()
-       {
-               delete [] _data;
-       }
-
-private:
-
-       size_t _capacity;
-
-       uint8_t* _data;
-
-       size_t _size;
-
-};
-
-
-/// Sound handler.
-//
-/// Stores the audio found by the parser and plays on demand.
-/// Can also play sound from AS classes NetStream and Sound using callbacks
-/// (see attach_aux_streamer and dettach_aux_streamer).
-///
-/// You may define a subclass of this, and pass an instance to
-/// set_sound_handler().
-///
-class DSOEXPORT sound_handler
-{
-public:
-
-       // See attach_aux_streamer
-       // TODO: change third parameter type to unsigned
-       typedef bool (*aux_streamer_ptr)(void *udata, uint8_t *stream, int len);
-
-       /// Used to control volume for event sounds. It basically tells that 
from
-       /// sample X the volume for left out is Y and for right out is Z. 
Several
-       /// envelopes can be assigned to a sound to make a fade out or similar 
stuff.
-       struct sound_envelope
-       {
-               uint32_t m_mark44;
-               uint16_t m_level0;
-               uint16_t m_level1;
-       };
-
-       /// Format type that the sound can be.
-       enum format_type
-       {
-               FORMAT_RAW = 0,         // Host-endian 8- or 16-bit
-               FORMAT_ADPCM = 1,       // decoded in the tag loader and passed 
through as NATIVE16
-               FORMAT_MP3 = 2,
-               FORMAT_UNCOMPRESSED = 3,// Little-endian 8- or 16-bit, should 
be passed through as FORMAT_NATIVE16
-               FORMAT_NELLYMOSER_8HZ_MONO = 5, // According to ffmpeg
-               FORMAT_NELLYMOSER = 6,  // Mystery proprietary format; see 
nellymoser.com
-                               
-               // gnash tries to convert data to this format when possible:
-               FORMAT_NATIVE16 = 7     // gnash extension: 16 bits/sample, 
native-endian
-       };
-       // If stereo is true, samples are interleaved w/ left sample first.
-       
-       /// gnash's parser calls this to create sounds to be played later.
-       //
-       /// @param data
-       ///     The data to be stored. For soundstream this is NULL.
-       ///     If not NULL, ownership of the data is transferred.
-       ///     The data is assumed to have been allocated using new[].
-       ///
-       /// @param data_bytes
-       ///     The size of the data to be stored. For soundstream this is 0.
-       ///
-       /// @param sinfo
-       ///     A SoundInfo object contained in an auto_ptr, which contains 
info about samplerate,
-       ///     samplecount, stereo and more. The SoundObject must be not-NULL!
-       ///
-       /// @return the id given by the soundhandler for later identification.
-       ///
-       virtual int     create_sound(
-               void*           data,
-               unsigned int    data_bytes,
-               std::auto_ptr<SoundInfo> sinfo
-               ) = 0;
-
-       /// gnash's parser calls this to fill up soundstreams data
-       //
-       /// @param data
-       ///     The sound data to be saved, allocated by new[]. Ownership is 
transferred.
-       ///     TODO: define a class for containing both data and data_bytes ? 
or use vector ?
-       ///
-       /// @param data_bytes
-       ///     Size of the data in bytes
-       ///
-       /// @param sample_count
-       ///     Number of samples in the data
-       ///
-       /// @param handle_id
-       ///     The soundhandlers id of the sound we want some info about.
-       ///
-       /// @return size of the data buffer before the new data is appended
-       ///
-       virtual long    fill_stream_data(unsigned char* data, unsigned int 
data_bytes, unsigned int sample_count, int handle_id) = 0;
-
-       /// Returns a pointer to the SoundInfo object for the sound with the 
given id.
-       /// The SoundInfo object is still owned by the soundhandler.
-       //
-       /// @param soundhandle
-       /// The soundhandlers id of the sound we want some info about.
-       ///
-       /// @return a pointer to the SoundInfo object for the sound with the 
given id.
-       ///
-       virtual SoundInfo* get_sound_info(int sound_handle) = 0;
-
-       /// gnash calls this when it wants you to play the defined sound.
-       //
-       /// @param sound_handle
-       ///     The sound_handlers id for the sound to start playing
-       ///
-       /// @param loop_count
-       /// loop_count == 0 means play the sound once (1 means play it twice, 
etc)
-       ///
-       /// @param secondOffset
-       /// When starting soundstreams there sometimes is a offset to make the 
sound
-       /// start at the exact right moment.
-       ///
-       /// @param start
-       /// When starting a soundstream from a random frame, this tells where 
in the
-       /// data the decoding should start.
-       ///
-       /// @param envelopes
-       /// Some eventsounds have some volume control mechanism called 
envelopes.
-       /// They basically tells that from sample X the volume should be Y.
-       ///
-       virtual void    play_sound(int sound_handle, int loop_count, int 
secondOffset, long start, const std::vector<sound_envelope>* envelopes) = 0;
-
-       /// stops all sounds currently playing in a SWF file without stopping 
the playhead.
-       /// Sounds set to stream will resume playing as the playhead moves over 
the frames they are in.
-       virtual void    stop_all_sounds() = 0;
-
-       /// Gets the volume for a given sound. Only used by the AS Sound class
-       //
-       /// @param sound_handle
-       ///     The sound_handlers id for the sound to be deleted
-       ///
-       /// @return the sound volume level as an integer from 0 to 100,
-       /// where 0 is off and 100 is full volume. The default setting is 100.
-       virtual int     get_volume(int sound_handle) = 0;
-       
-       /// Sets the volume for a given sound. Only used by the AS Sound class
-       //
-       /// @param sound_handle
-       ///     The sound_handlers id for the sound to be deleted
-       ///
-       /// @param volume
-       /// A number from 0 to 100 representing a volume level. 
-       /// 100 is full volume and 0 is no volume. The default setting is 100.
-       ///
-       virtual void    set_volume(int sound_handle, int volume) = 0;
-               
-       /// Stop the specified sound if it's playing.
-       /// (Normally a full-featured sound API would take a
-       /// handle specifying the *instance* of a playing
-       /// sample, but SWF is not expressive that way.)
-       //
-       /// @param sound_handle
-       ///     The sound_handlers id for the sound to be deleted
-       ///
-       virtual void    stop_sound(int sound_handle) = 0;
-               
-       /// gnash calls this when it's done with a particular sound.
-       //
-       /// @param sound_handle
-       ///     The sound_handlers id for the sound to be deleted
-       ///
-       virtual void    delete_sound(int sound_handle) = 0;
-               
-       /// gnash calls this to mute audio
-       virtual void    mute() = 0;
-
-       /// gnash calls this to unmute audio
-       virtual void    unmute() = 0;
-
-       /// Returns whether or not sound is muted.
-       //
-       /// @return true if muted, false if not
-       ///
-       virtual bool    is_muted() = 0;
-
-       /// This is called by AS classes NetStream or Sound to attach callback, 
so
-       /// that audio from the classes will be played through the soundhandler.
-       //
-       /// This is actually only used by the SDL sound_handler. It uses these 
"auxiliary"
-       /// streamers to fetch decoded audio data to mix and send to the output 
channel.
-       ///
-       /// The "aux streamer" will be called with the 'udata' pointer as first 
argument,
-       /// then will be passed a buffer pointer as second argument and it's 
length
-       /// as third. The callbacks should fill the given buffer if possible.
-       /// The callback should return true if wants to remain attached, false 
if wants
-       /// to be detached. 
-       ///
-       /// @param ptr
-       ///     The pointer to the callback function
-       ///
-       /// @param udata
-       ///     User data pointer, passed as first argument to the registered 
callback.
-       ///     WARNING: this is currently also used to *identify* the callback 
for later
-       ///     removal, see detach_aux_streamer. TODO: stop using the data 
pointer for 
-       ///     identification purposes and use the callback pointer directly 
instead.
-       ///
-       virtual void    attach_aux_streamer(aux_streamer_ptr ptr, void* owner) 
= 0;
-
-       /// This is called by AS classes NetStream or Sound to dettach 
callback, so
-       /// that audio from the classes no longer will be played through the 
-       /// soundhandler.
-       //
-       /// @param udata
-       ///     The key identifying the auxiliary streamer.
-       ///     WARNING: this need currently be the 'udata' pointer passed to 
attach_aux_streamer.
-       ///     TODO: get the aux_streamer_ptr as key !!
-       ///
-       virtual void    detach_aux_streamer(void* udata) = 0;
-
-       sound_handler()
-               :
-               _soundsStarted(0),
-               _soundsStopped(0)
-       {}
-
-       virtual ~sound_handler() {};
-       
-       /// \brief
-       /// Gets the duration in milliseconds of an event sound connected
-       /// to an AS Sound obejct.
-       //
-       /// @param sound_handle
-       /// The id of the event sound
-       ///
-       /// @return the duration of the sound in milliseconds
-       virtual unsigned int get_duration(int sound_handle) = 0;
-
-       /// \brief
-       /// Gets the playhead position in milliseconds of an event sound 
connected
-       /// to an AS Sound obejct.
-       //
-       /// @param sound_handle
-       /// The id of the event sound
-       ///
-       /// @return the duration of the sound in milliseconds
-       virtual unsigned int get_position(int sound_handle) = 0;
-
-       /// Special test-fuction. Reports how many times a sound has been 
started
-       size_t numSoundsStarted() const { return _soundsStarted; }
-
-       /// Special test-fuction. Reports how many times a sound has been 
stopped
-       size_t numSoundsStopped() const { return _soundsStopped; }
-
-protected:
-
-       /// Special test-member. Stores count of started sounds.
-       size_t _soundsStarted;
-
-       /// Special test-member. Stores count of stopped sounds.
-       size_t _soundsStopped;
-};
-
-///
-/// Class containing information about a sound. Is created by the parser while
-/// parsing, and ownership is then transfered to sound_data. When the parser is
-/// parsing streams, it will ask the soundhandler for this to know what 
properties
-/// the stream has.
-///
-class SoundInfo {
-public:
-       /// Constructor
-       //
-       /// @param format
-       /// The format of the sound. Can be MP3, ADPCM, uncompressed or 
Nellymoser
-       ///
-       /// @param stero
-       /// Defines whether the sound is in stereo.
-       ///
-       /// @param sampleRate
-       /// The sample rate of the sound.
-       ///
-       /// @param sampleCount
-       /// The sample count in the sound. In soundstreams this is an average 
for each frame.
-       ///
-       /// @param is16bit
-       /// Defines whether the sound is in stereo.
-       /// Defines whether the sound is in 16bit format (samplesize == 2)? 
else it 
-       /// is 8bit (samplesize == 1). Used for streams when decoding adpcm.
-       ///
-       SoundInfo(sound_handler::format_type format, sound_handler::format_type 
orgFormat, bool stereo, uint32_t sampleRate, uint32_t sampleCount, bool is16bit)
-       :       _format(format),
-               _orgFormat(orgFormat),
-               _stereo(stereo),
-               _sampleRate(sampleRate),
-               _sampleCount(sampleCount),
-               _is16bit(is16bit)
-       {
-       }
-
-       /// Returns the current format of the sound
-       ///
-       /// @return the current format of the sound
-       sound_handler::format_type getFormat() { return _format; }
-
-       /// Returns the original format of the sound
-       ///
-       /// @return the original format of the sound
-       sound_handler::format_type getOrgFormat() { return _orgFormat; }
-
-       /// Returns the stereo status of the sound
-       ///
-       /// @return the stereo status of the sound
-       bool isStereo() { return _stereo; }
-
-       /// Returns the samplerate of the sound
-       ///
-       /// @return the samplerate of the sound
-       unsigned long getSampleRate() { return _sampleRate; }
-
-       /// Returns the samplecount of the sound
-       ///
-       /// @return the samplecount of the sound
-       unsigned long getSampleCount() { return _sampleCount; }
-
-       /// Returns the 16bit status of the sound
-       ///
-       /// @return the 16bit status of the sound
-       bool is16bit() { return _is16bit; }
-
-private:
-       /// Current format of the sound (MP3, raw, etc).
-       sound_handler::format_type _format;
-
-       /// Original format of the sound (ADPCM, etc).
-       sound_handler::format_type _orgFormat;
-
-       /// The size of the undecoded data
-       unsigned long _dataSize;
-
-       /// Stereo or not
-       bool _stereo;
-
-       /// Sample rate, one of 5512, 11025, 22050, 44100
-       uint32_t _sampleRate;
-
-       /// Number of samples
-       uint32_t _sampleCount;
-
-       /// Is the audio in 16bit format (samplesize == 2)? else it 
-       /// is 8bit (samplesize == 1). Used for streams when decoding adpcm.
-       bool _is16bit;
-};
-
-// TODO: move to appropriate specific sound handlers
-DSOEXPORT sound_handler*       create_sound_handler_sdl();
-DSOEXPORT sound_handler*       create_sound_handler_gst();
-DSOEXPORT sound_handler*       create_sound_handler_test();
-
-       
-
-}      // namespace gnash
-
-#endif // SOUND_HANDLER_H
-
-
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:

Index: backend/sound_handler_gst.cpp
===================================================================
RCS file: backend/sound_handler_gst.cpp
diff -N backend/sound_handler_gst.cpp
--- backend/sound_handler_gst.cpp       26 Sep 2007 10:15:52 -0000      1.65
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,696 +0,0 @@
-// sound_handler_gst.cpp: Audio output via GStreamer, for Gnash.
-//
-//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program 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 General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-//
-
-// Based on sound_handler_sdl.cpp by Thatcher Ulrich http://tulrich.com 2003
-// which has been donated to the Public Domain.
-
-/* $Id: sound_handler_gst.cpp,v 1.65 2007/09/26 10:15:52 strk Exp $ */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "utility.h" // for convert_raw_data
-
-// Assume people running --enable-media=gst know what they are doing
-// (HAVE_GST_GST_H seems broken atm, specifically when an older glib
-//  install is around)
-//
-
-#ifdef SOUND_GST
-
-#include "sound_handler_gst.h"
-#include "gnash.h"
-#include "container.h"
-#include "log.h"
-#include "types.h"     // for IF_VERBOSE_* macros
-#include <cmath>
-#include <vector>
-
-#include <gst/gst.h>
-
-#define BUFFER_SIZE 5000
-
-using namespace boost;
-
-namespace gnash {
-
-GST_sound_handler::GST_sound_handler()
-       : looping(false),
-         muted(false)
-{
-               // init gstreamer
-       gst_init(NULL, NULL);
-}
-
-GST_sound_handler::~GST_sound_handler()
-{
-
-       for (size_t i=0, e=m_sound_data.size(); i < e; ++i)  {
-               stop_sound(i);
-               delete_sound(i);
-       }
-}
-
-
-int    GST_sound_handler::create_sound(
-       void* data_,
-       unsigned int data_bytes,
-       std::auto_ptr<SoundInfo> sinfo)
-// Called to create a sample.  We'll return a sample ID that
-// can be use for playing it.
-{
-
-       try_mutex::scoped_lock lock(_mutex);
-
-       unsigned char* data = static_cast<unsigned char*>(data_);
-
-       assert(sinfo.get());
-       sound_data *sounddata = new sound_data;
-       if (!sounddata) {
-               log_error(_("could not allocate memory for sound data"));
-               return -1;
-       }
-
-       sounddata->volume = 100;
-       sounddata->soundinfo = sinfo;
-
-       switch (sounddata->soundinfo->getFormat())
-       {
-       case FORMAT_NATIVE16:
-               if ( data ) sounddata->append(data, data_bytes);
-               break;
-
-       case FORMAT_MP3:
-       //case FORMAT_VORBIS:
-               if ( data ) sounddata->append(data, data_bytes);
-               break;
-
-       case FORMAT_RAW:
-       case FORMAT_ADPCM:
-       case FORMAT_UNCOMPRESSED:
-               // These should have been converted to FORMAT_NATIVE16
-               log_error(_("Sound data format not properly converted"));
-               assert(0);
-               break;
-
-       case FORMAT_NELLYMOSER:
-               log_unimpl(_("Nellymoser sound format requested; gnash does not 
handle it"));
-               return -1;
-
-       default:
-               // Unhandled format.
-               log_error(_("Unknown sound format %d requested; gnash does not 
handle it"), (int)sounddata->soundinfo->getFormat());
-               return -1; // Unhandled format, set to NULL.
-       }
-
-       m_sound_data.push_back(sounddata);
-
-       return m_sound_data.size()-1;
-}
-
-
-// this gets called when a stream gets more data
-long   GST_sound_handler::fill_stream_data(unsigned char* data, unsigned int 
data_bytes, unsigned int /*sample_count*/, int handle_id)
-{
-       try_mutex::scoped_lock lock(_mutex);
-
-       // @@ does a negative handle_id have any meaning ?
-       //    should we change it to unsigned instead ?
-       if (handle_id >= 0 && (unsigned int) handle_id < m_sound_data.size())
-       {
-               sound_data* sounddata = m_sound_data[handle_id];
-
-               long startSize = sounddata->dataSize();
-
-               sounddata->append(data, data_bytes);
-
-               // If playback has already started, we also update the active 
sounds
-               for (size_t i=0, e=sounddata->m_gst_elements.size(); i < e; 
++i) {
-                       gst_elements* sound = sounddata->m_gst_elements[i];
-                       sound->data_size = sounddata->dataSize();
-                       sound->set_data(sounddata->data());
-               }
-
-               return startSize;
-       }
-       else
-       {
-               delete [] data;
-               return 0;
-       }
-}
-
-// This stops sounds when they are done playing
-static gboolean sound_killer (gpointer user_data)
-{
-       gst_elements *gstelements = static_cast<gst_elements*>(user_data);
-       gst_element_set_state (GST_ELEMENT (gstelements->pipeline), 
GST_STATE_NULL);
-       return false;
-}
-
-// The callback function which refills the buffer with data
-void GST_sound_handler::callback_handoff (GstElement * /*c*/, GstBuffer 
*buffer, GstPad* /*pad*/, gpointer user_data)
-{
-       gst_elements *gstelements = static_cast<gst_elements*>(user_data);
-
-       try_mutex::scoped_try_lock lock(gstelements->handler->_mutex);
-
-       // If we couldn't obtain a lock return to avoid a deadlock
-       if (!lock.locked()) {
-
-               // We return nothing in this case to avoid noise being decoded 
and played
-               if (GST_BUFFER_SIZE(buffer) != 0 && GST_BUFFER_DATA(buffer)) {
-                       GST_BUFFER_DATA(buffer) = 0;
-                       GST_BUFFER_SIZE(buffer) = 0;
-               }
-               return;
-       }
-
-       // First callback or after a couldn't-get-lock-return 
-       if (GST_BUFFER_SIZE(buffer) == 0) {
-               if (gstelements->data_size > BUFFER_SIZE) {
-                       GST_BUFFER_SIZE(buffer) = BUFFER_SIZE;
-               } else {
-                       GST_BUFFER_SIZE(buffer) = gstelements->data_size;
-               }
-
-               // Reallocate the required memory.
-               guint8* tmp_buf = new guint8[GST_BUFFER_SIZE(buffer)];
-               memcpy(tmp_buf, GST_BUFFER_DATA(buffer), sizeof(buffer));
-
-               delete [] GST_BUFFER_DATA(buffer);
-               GST_BUFFER_DATA(buffer) = tmp_buf;
-       }
-
-       // All the data has been given to the pipeline, so now we need to stop
-       // the pipeline. g_idle_add() makes sure sound_killer is called soon.
-       if (gstelements->position > gstelements->data_size) {
-               g_idle_add(sound_killer, user_data);
-               GST_BUFFER_SIZE(buffer) = 0;
-               GST_BUFFER_DATA(buffer) = 0;
-               return;
-       }
-
-       const guint8* data_pos = 
gstelements->get_data_ptr(gstelements->position);
-
-       // Last callback - the last re-fill
-       if (gstelements->position+BUFFER_SIZE > gstelements->data_size) {
-       
-               unsigned int chunk_size = 
gstelements->data_size-gstelements->position;
-               // Check if we should loop. If loop_count is 0 we have we just
-               // played the sound for the last (and perhaps first) time.
-               // If loop_count is anything else we continue to loop.
-               if (gstelements->loop_count == 0) {
-                       GST_BUFFER_SIZE(buffer) = chunk_size;
-                       memcpy(GST_BUFFER_DATA(buffer), data_pos, chunk_size);
-                       gstelements->position += BUFFER_SIZE;
-
-                       gst_element_set_state (GST_ELEMENT 
(gstelements->input), GST_STATE_PAUSED);
-
-               } else {
-                       // Copy what's left of the data, and then fill the rest 
with "new" data.
-                       memcpy(GST_BUFFER_DATA(buffer), data_pos,  chunk_size);
-                       memcpy(GST_BUFFER_DATA(buffer) + chunk_size, 
gstelements->get_data_ptr(0), GST_BUFFER_SIZE(buffer)- chunk_size);
-                       gstelements->position = GST_BUFFER_SIZE(buffer) - 
chunk_size;
-                       gstelements->loop_count--;
-
-               }
-
-               return;
-
-       }
-
-       // Standard re-fill
-       memcpy(GST_BUFFER_DATA(buffer), data_pos, BUFFER_SIZE);
-       gstelements->position += BUFFER_SIZE;
-
-}
-
-
-void   GST_sound_handler::play_sound(int sound_handle, int loop_count, int 
/*offset*/, long start_position, const std::vector<sound_envelope>* 
/*envelopes*/)
-// Play the index'd sample.
-{
-       try_mutex::scoped_lock lock(_mutex);
-
-       // Check if the sound exists, or if audio is muted
-       if (sound_handle < 0 || (unsigned int) sound_handle >= 
m_sound_data.size() || muted)
-       {
-               // Invalid handle, or audio is muted.
-               return;
-       }
-
-       sound_data* sounddata = m_sound_data[sound_handle];
-
-       // If this is called from a streamsoundblocktag, we only start if this
-       // sound isn't already playing.
-       if (start_position > 0 && sounddata->m_gst_elements.size() > 0) {
-               return;
-       }
-       // Make sure sound actually got some data
-       if (sounddata->dataSize() < 1) {
-               IF_VERBOSE_MALFORMED_SWF(
-                       log_swferror(_("Trying to play sound with size 0"));
-               );
-               return;
-       }
-
-       // Make a "gst_elements" for this sound which is latter placed on the 
vector of instances of this sound being played
-       gst_elements* gst_element = new gst_elements;
-       if (gst_element == NULL) {
-               log_error (_("Could not allocate memory for gst_element"));
-               return;
-       }
-
-       // Set the handler
-       gst_element->handler = this;
-
-       // Copy data-info to the "gst_elements"
-       gst_element->data_size = sounddata->dataSize();
-       gst_element->set_data(sounddata->data());
-       gst_element->position = start_position;
-
-       // Set number of loop we should do. -1 is infinte loop, 0 plays it 
once, 1 twice etc.
-       gst_element->loop_count = loop_count;
-
-       // create main pipeline
-       gst_element->pipeline = gst_pipeline_new (NULL);
-
-       // create an audio sink - use oss, alsa or...? make a commandline 
option?
-       // we first try atudetect, then alsa, then oss, then esd, then...?
-#if !defined(__NetBSD__)
-       gst_element->audiosink = gst_element_factory_make ("autoaudiosink", 
NULL);
-       if (!gst_element->audiosink) gst_element->audiosink = 
gst_element_factory_make ("alsasink", NULL);
-       if (!gst_element->audiosink) gst_element->audiosink = 
gst_element_factory_make ("osssink", NULL);
-#endif
-       if (!gst_element->audiosink) gst_element->audiosink = 
gst_element_factory_make ("esdsink", NULL);
-
-       // Check if the creation of the gstreamer pipeline, adder and audiosink 
was a succes
-       if (!gst_element->pipeline) {
-               log_error(_("The gstreamer pipeline element could not be 
created"));
-       }
-       if (!gst_element->audiosink) {
-               log_error(_("The gstreamer audiosink element could not be 
created"));
-       }
-
-       // link adder and output to bin
-       gst_bin_add (GST_BIN (gst_element->pipeline), gst_element->audiosink);
-
-       gst_element->bin = gst_bin_new(NULL);
-       gst_element->input = gst_element_factory_make ("fakesrc", NULL);
-       gst_element->capsfilter = gst_element_factory_make ("capsfilter", NULL);
-       gst_element->audioconvert = gst_element_factory_make ("audioconvert", 
NULL);
-       gst_element->audioresample = gst_element_factory_make ("audioresample", 
NULL);
-       gst_element->volume = gst_element_factory_make ("volume", NULL);
-
-       // Put the gstreamer elements in the pipeline
-       gst_bin_add_many (GST_BIN (gst_element->bin), gst_element->input,
-                                       gst_element->capsfilter,
-                                       gst_element->audioconvert,
-                                       gst_element->audioresample, 
-                                       gst_element->volume, NULL);
-
-       // Test if the fakesrc, typefind and audio* elements was correctly 
created
-       if (!gst_element->input
-               || !gst_element->capsfilter
-               || !gst_element->audioconvert
-               || !gst_element->audioresample) {
-
-               log_error(_("Gstreamer element for audio handling could not be 
created"));
-               return;
-       }
-
-       // Create a gstreamer decoder for the chosen sound.
-
-       // Temp variables to make the code simpler and easier to read
-       format_type soundFormat = sounddata->soundinfo->getFormat();
-       bool soundStereo = sounddata->soundinfo->isStereo();
-       uint32_t soundSampleRate = sounddata->soundinfo->getSampleRate();
-
-       if (soundFormat == FORMAT_MP3) {
-
-               gst_element->decoder = gst_element_factory_make ("mad", NULL);
-               if (gst_element->decoder == NULL) {
-                       gst_element->decoder = gst_element_factory_make 
("flump3dec", NULL);
-                       if (gst_element->decoder != NULL && 
!gst_default_registry_check_feature_version("flump3dec", 0, 10, 4))
-                       {
-                               static bool warned=false;
-                               if ( ! warned ) 
-                               {
-                                       // I keep getting these messages even 
if I hear sound... too much paranoia ?
-                                       log_debug(_("This version of fluendos 
mp3 plugin does not support flash streaming sounds, please upgrade to version 
0.10.4 or higher"));
-                                       warned=true;
-                               }
-                       }
-               }
-               // Check if the element was correctly created
-               if (!gst_element->decoder) {
-                       log_error(_("A gstreamer mp3-decoder element could not 
be created.  You probably need to install a mp3-decoder plugin like 
gstreamer0.10-mad or gstreamer0.10-fluendo-mp3."));
-                       return;
-               }
-               gst_bin_add (GST_BIN (gst_element->bin), gst_element->decoder);
-
-               // Set the info about the stream so that gstreamer knows what 
it is.
-               GstCaps *caps = gst_caps_new_simple ("audio/mpeg",
-                       "mpegversion", G_TYPE_INT, 1,
-                       "layer", G_TYPE_INT, 3,
-                       "rate", G_TYPE_INT, soundSampleRate,
-                       "channels", G_TYPE_INT, soundStereo ? 2 : 1, NULL);
-               g_object_set (G_OBJECT (gst_element->capsfilter), "caps", caps, 
NULL);
-               gst_caps_unref (caps);
-
-               // setup fake source
-               g_object_set (G_OBJECT (gst_element->input),
-                                       "sizetype", 2, "can-activate-pull", 
FALSE, "signal-handoffs", TRUE,
-                                       "sizemax", BUFFER_SIZE, NULL);
-               // Setup the callback
-               gst_element->handoff_signal_id = g_signal_connect 
(gst_element->input, "handoff", G_CALLBACK (callback_handoff), gst_element);
-
-               // link data, decoder, audio* and adder
-               gst_element_link_many (gst_element->input,
-                                               gst_element->capsfilter,
-                                               gst_element->decoder,
-                                               gst_element->audioconvert,
-                                               gst_element->audioresample, 
-                                               gst_element->volume, NULL);
-
-       } else if (soundFormat == FORMAT_NATIVE16) {
-
-               // Set the info about the stream so that gstreamer knows what 
it is.
-               GstCaps *caps = gst_caps_new_simple ("audio/x-raw-int",
-                       "rate", G_TYPE_INT, soundSampleRate,
-                       "channels", G_TYPE_INT, soundStereo ? 2 : 1,
-                       "endianness", G_TYPE_INT, G_BIG_ENDIAN,
-                       "width", G_TYPE_INT, 16,
-                       "depth", G_TYPE_INT, 16,
-                       /*"signed", G_TYPE_INT, 1,*/ NULL);
-               g_object_set (G_OBJECT (gst_element->capsfilter), "caps", caps, 
NULL);
-               gst_caps_unref (caps);
-
-               // setup fake source
-               g_object_set (G_OBJECT (gst_element->input),
-                                       "sizetype", 2, "can-activate-pull", 
FALSE, "signal-handoffs", TRUE,
-                                       "sizemax", BUFFER_SIZE, NULL);
-               // Setup the callback
-               gst_element->handoff_signal_id = g_signal_connect 
(gst_element->input, "handoff", G_CALLBACK (callback_handoff), gst_element);
-
-/*     caps info:
-    audio/x-raw-int
-                rate: [ 1, 2147483647 ]
-            channels: [ 1, 8 ]
-            endianness: { 1234, 4321 }
-                width: 16
-                depth: [ 1, 16 ]
-                signed: { true, false }*/
-               // Raw native sound-data, output directly
-               gst_element_link_many (gst_element->input, 
-                                       gst_element->capsfilter, 
-                                       gst_element->audioconvert,
-                                       gst_element->audioresample,
-                                       gst_element->volume, NULL);
-       }
-       // Add ghostpad
-       GstPad *pad = gst_element_get_pad (gst_element->volume, "src");
-       gst_element_add_pad (gst_element->bin, gst_ghost_pad_new ("src", pad));
-       gst_object_unref (GST_OBJECT (pad));
-       
-       // Add the bin to the main pipeline
-       gst_bin_add(GST_BIN (gst_element->pipeline), gst_element->bin);
-       // Link to the adder sink pad
-       GstPad *sinkpad = gst_element_get_pad (gst_element->audiosink, "sink");
-       GstPad *srcpad = gst_element_get_pad (gst_element->bin, "src");
-       gst_pad_link (srcpad, sinkpad);
-       gst_object_unref (GST_OBJECT (srcpad));
-       gst_object_unref (GST_OBJECT (sinkpad));
-
-       // Set the volume
-       g_object_set (G_OBJECT (gst_element->volume), "volume", 
static_cast<double>(sounddata->volume) / 100.0, NULL);
-
-       //gst_pad_add_event_probe(pad, G_CALLBACK(event_callback), sounddata);
-
-       // Put the gst_element on the vector
-       sounddata->m_gst_elements.push_back(gst_element);
-
-       // If not already playing, start doing it
-       gst_element_set_state (GST_ELEMENT (gst_element->pipeline), 
GST_STATE_PLAYING);
-
-       ++_soundsStarted;
-
-}
-
-
-void   GST_sound_handler::stop_sound(int sound_handle)
-{
-       try_mutex::scoped_lock lock(_mutex);
-
-       // Check if the sound exists.
-       if (sound_handle < 0 || (unsigned int) sound_handle >= 
m_sound_data.size())
-       {
-               // Invalid handle.
-               return;
-       }
-
-       sound_data* sounddata = m_sound_data[sound_handle];
-
-       // Stop all the instances of this sound.
-       // TODO: fix the loop to use size_t instead of i
-       for (int i = sounddata->m_gst_elements.size()-1; i >= 0 ; i--)
-       {
-               gst_elements* elements = sounddata->m_gst_elements[i];
-
-               // Check if we can succesfully stop the elements
-               // playback - if not we skip cleaning this for now
-               // FIXME: what if it ain't possible to stop an element when 
this is called from ~GST_sound_handler
-
-               // Disconnect signals
-               g_signal_handler_disconnect (elements->input, 
elements->handoff_signal_id);
-
-               gst_element_set_state (GST_ELEMENT (elements->pipeline), 
GST_STATE_NULL);
-               gst_object_unref (GST_OBJECT (elements->pipeline));
-
-               // Delete the gst_element struct
-               // @@ we're deleting the elements from the start, so half-way 
of the loop we will be referring to undefined elements. Is this intended ? 
--strk;
-               delete elements;
-               
sounddata->m_gst_elements.erase(sounddata->m_gst_elements.begin() + i);
-       }
-
-       ++_soundsStopped;
-}
-
-
-void   GST_sound_handler::delete_sound(int sound_handle)
-// this gets called when it's done with a sample.
-{
-       try_mutex::scoped_lock lock(_mutex);
-
-       if (sound_handle >= 0 && (unsigned int) sound_handle < 
m_sound_data.size())
-       {
-               delete m_sound_data[sound_handle];
-               m_sound_data.erase (m_sound_data.begin() + sound_handle);
-       }
-
-}
-
-// This will stop all sounds playing. Will cause problems if the soundhandler 
is made static
-// and supplys sound_handling for many SWF's, since it will stop all sounds 
with no regard
-// for what sounds is associated with what SWF.
-void   GST_sound_handler::stop_all_sounds()
-{
-       for (size_t i=0, e=m_sound_data.size(); i < e; ++i) 
-               stop_sound(i);
-}
-
-
-//     returns the sound volume level as an integer from 0 to 100,
-//     where 0 is off and 100 is full volume. The default setting is 100.
-int    GST_sound_handler::get_volume(int sound_handle) {
-
-       try_mutex::scoped_lock lock(_mutex);
-
-       // Check if the sound exists.
-       if (sound_handle >= 0 && (unsigned int) sound_handle < 
m_sound_data.size())
-       {
-               return m_sound_data[sound_handle]->volume;
-       } else {
-               return 0; // Invalid handle
-       }
-}
-
-
-//     A number from 0 to 100 representing a volume level. 
-//     100 is full volume and 0 is no volume. The default setting is 100.
-void   GST_sound_handler::set_volume(int sound_handle, int volume) {
-
-       try_mutex::scoped_lock lock(_mutex);
-
-       // Check if the sound exists.
-       if (sound_handle < 0 || (unsigned int) sound_handle >= 
m_sound_data.size())
-       {
-               // Invalid handle.
-               return;
-       }
-
-       sound_data* sd = m_sound_data[sound_handle];
-
-       // Set volume for this sound. Should this only apply to the active 
sounds?
-
-       sd->volume = volume;
-       
-       for (size_t i=0, n=sd->m_gst_elements.size(); i<n; ++i)
-       {
-               g_object_set (
-                       G_OBJECT (sd->m_gst_elements[i]->volume),
-                       "volume",
-                       static_cast<double>(volume/100.0),
-                       NULL);
-       }
-
-}
-
-SoundInfo* GST_sound_handler::get_sound_info(int sound_handle) {
-
-       try_mutex::scoped_lock lock(_mutex);
-
-       // Check if the sound exists.
-       if (sound_handle >= 0 && static_cast<unsigned int>(sound_handle) < 
m_sound_data.size())
-       {
-               return m_sound_data[sound_handle]->soundinfo.get();
-       } else {
-               return NULL;
-       }
-
-}
-
-// gnash calls this to mute audio
-void GST_sound_handler::mute() {
-       stop_all_sounds();
-       muted = true;
-}
-
-// gnash calls this to unmute audio
-void GST_sound_handler::unmute() {
-       muted = false;
-}
-
-bool GST_sound_handler::is_muted() {
-       return muted;
-}
-
-void GST_sound_handler::attach_aux_streamer(aux_streamer_ptr /*ptr*/, void* 
/*owner*/)
-{
-       log_unimpl(__PRETTY_FUNCTION__);
-}
-
-void GST_sound_handler::detach_aux_streamer(void* /*owner*/)
-{
-       log_unimpl(__PRETTY_FUNCTION__);
-}
-
-unsigned int GST_sound_handler::get_duration(int sound_handle)
-{
-       try_mutex::scoped_lock lock(_mutex);
-
-       // Check if the sound exists.
-       if (sound_handle < 0 || (unsigned int) sound_handle >= 
m_sound_data.size())
-       {
-               // Invalid handle.
-               return 0;
-       }
-
-       sound_data* sounddata = m_sound_data[sound_handle];
-
-       uint32_t sampleCount = sounddata->soundinfo->getSampleCount();
-       uint32_t sampleRate = sounddata->soundinfo->getSampleRate();
-
-       // Return the sound duration in milliseconds
-       if (sampleCount > 0 && sampleRate > 0) {
-               unsigned int ret = sampleCount / sampleRate * 1000;
-               ret += ((sampleCount % sampleRate) * 1000) / sampleRate;
-               if (sounddata->soundinfo->isStereo()) ret = ret / 2;
-               return ret;
-       } else {
-               return 0;
-       }
-}
-
-unsigned int GST_sound_handler::get_position(int sound_handle)
-{
-       try_mutex::scoped_lock lock(_mutex);
-
-       // Check if the sound exists.
-       if (sound_handle < 0 || (unsigned int) sound_handle >= 
m_sound_data.size())
-       {
-               // Invalid handle.
-               return 0;
-       }
-
-       sound_data* sounddata = m_sound_data[sound_handle];
-
-       // If there is no active sounds, return 0
-       if (sounddata->m_gst_elements.size() == 0) {
-               return 0;
-       }
-
-       // return the position of the last element added
-       GstElement *pipeline,*audioconvert;
-       GstStateChangeReturn ret;
-       GstState current, pending;
-       int64_t pos;
-       GstFormat fmt = GST_FORMAT_TIME;
-       
-       pipeline = 
sounddata->m_gst_elements[sounddata->m_gst_elements.size()-1]->pipeline;
-       
-       ret = gst_element_get_state (GST_ELEMENT (pipeline), &current, 
&pending, 0);
-
-       if (current != GST_STATE_NULL) {
-               audioconvert = 
sounddata->m_gst_elements[sounddata->m_gst_elements.size()-1]->audioconvert;
-               if (gst_element_query_position (audioconvert, &fmt, &pos)) {
-                       return static_cast<unsigned int>(pos / GST_MSECOND);
-               } else {
-                       return 0;
-               }
-       }
-       return 0;
-}
-
-// Pointer handling and checking functions
-const uint8_t* gst_elements::get_data_ptr(unsigned long int pos)
-{
-       assert(data_size > pos);
-       return data + pos;
-}
-
-void gst_elements::set_data(const uint8_t* idata) {
-       data = idata;
-}
-
-sound_handler* create_sound_handler_gst()
-// Factory.
-{
-       return new GST_sound_handler;
-}
-
-} // namespace gnash
-
-#endif // SOUND_GST
-
-// Local Variables:
-// mode: C++
-// End:
-

Index: backend/sound_handler_gst.h
===================================================================
RCS file: backend/sound_handler_gst.h
diff -N backend/sound_handler_gst.h
--- backend/sound_handler_gst.h 26 Sep 2007 07:09:02 -0000      1.18
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,204 +0,0 @@
-//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-
-// This program 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 General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-#ifndef SOUND_HANDLER_GST_H
-#define SOUND_HANDLER_GST_H
-
-//#include "gnash.h"
-#include "sound_handler.h" // for inheritance
-
-#include <vector>
-
-#include <gst/gst.h>
-#include <boost/thread/thread.hpp>
-#include <boost/bind.hpp>
-#include <boost/thread/mutex.hpp>
-
-#define BUFFER_SIZE 5000
-
-namespace gnash {
-
-// forward declaration
-class GST_sound_handler;
-
-// Used to hold the gstreamer when doing on-demand-decoding
-class gst_elements
-{
-public:
-       // gstreamer pipeline objects
-
-       // the main bin containing the adder and output (sink)
-       GstElement *pipeline;
-       GstElement *audiosink;
-
-       // gstreamer objects
-       GstElement *input;
-       GstElement *decoder;
-       GstElement *capsfilter;
-       GstElement *audioconvert;
-       GstElement *audioresample;
-       GstElement *volume;
-       GstElement *bin;
-       GstPad     *addersinkpad;
-       
-       // position in the stream
-       unsigned long position;
-
-       // data size
-       unsigned long data_size;
-
-       long loop_count;
-       
-       // signal id
-       guint handoff_signal_id;
-
-       // The sound handler. Used to get access to the 
GST_sound_handler->_mutex
-       GST_sound_handler* handler;
-
-       /// Returns the data pointer in the undecoded datastream
-       /// for the given position. Boundaries are checked.
-       const uint8_t* get_data_ptr(unsigned long int pos);
-
-       /// Set the undecoded data pointer
-       void set_data(const uint8_t*);
-
-private:
-       // The (un)compressed data
-       const guint8* data;
-
-};
-
-
-// Used to hold the sounddata when doing on-demand-decoding
-class sound_data
-{
-       // The (un)compressed data
-       Buffer _data;
-
-public:
-
-       sound_data()
-       {}
-
-       /// Append size bytes to this sound
-       //
-       /// @param data
-       ///     Data bytes, allocated with new[]. Ownership transferred.
-       ///
-       /// @param size
-       ///     Size of the 'data' buffer.
-       ///
-       void append(unsigned char* data, unsigned int size)
-       {
-               _data.append(data, size);
-       }
-
-       /// Return data size
-       size_t dataSize() const { return _data.size(); }
-
-       /// Return data buffer
-       const uint8_t* data() { return _data.data(); }
-
-       // Object holding information about the sound
-       std::auto_ptr<SoundInfo> soundinfo;
-
-       // Volume, SWF range: 0-100, GST range 0-10 (we only use 0-1, the rest 
is amplified)
-       // It's the SWF range that is represented here
-       int volume;
-
-       // gstreamer objects
-       std::vector<gst_elements*>      m_gst_elements;
-
-};
-
-// Use gstreamer to handle sounds.
-class GST_sound_handler : public gnash::sound_handler
-{
-private:
-       /// Vector containing all the sounds
-       std::vector<sound_data*>        m_sound_data;
-       
-       /// Is the loop running?
-       bool looping;
-       
-       /// Is the audio muted?
-       bool muted;
-
-       /// Mutex for making sure threads doesn't mess things up
-       boost::try_mutex _mutex;
-
-public:
-
-       /// Gstreamer callback function
-       static void callback_handoff (GstElement * /*c*/, GstBuffer *buffer, 
GstPad* /*pad*/, gpointer user_data);
-
-       GST_sound_handler();
-       virtual ~GST_sound_handler();
-
-       /// Called to create a sound.
-       virtual int     create_sound(void* data, unsigned int data_bytes,
-                                    std::auto_ptr<SoundInfo> sinfo);
-
-       /// this gets called when a stream gets more data
-       virtual long    fill_stream_data(unsigned char* data, unsigned int 
data_bytes,
-                                        unsigned int sample_count, int 
handle_id);
-
-       /// Play the index'd sample.
-       virtual void    play_sound(int sound_handle, int loop_count, int offset,
-                                  long start_position, const 
std::vector<sound_envelope>* envelopes);
-
-       /// Stop the index'd sample.
-       virtual void    stop_sound(int sound_handle);
-
-       /// This gets called when it's done with a sample.
-       virtual void    delete_sound(int sound_handle);
-
-       /// This will stop all sounds playing.
-       virtual void    stop_all_sounds();
-
-       /// Returns the sound volume level as an integer from 0 to 100. 
AS-script only.
-       virtual int     get_volume(int sound_handle);
-
-       /// Sets the sound volume level as an integer from 0 to 100. AS-script 
only.
-       virtual void    set_volume(int sound_handle, int volume);
-               
-       /// Gnash uses this to get info about a sound. Used when a stream needs 
more data.
-       virtual SoundInfo* get_sound_info(int sound_handle);
-
-       /// Gnash calls this to mute audio.
-       virtual void    mute();
-
-       /// Gnash calls this to unmute audio.
-       virtual void    unmute();
-
-       /// Gnash calls this to get the mute state.
-       virtual bool    is_muted();
-
-       /// Gets the duration in milliseconds of an event sound connected to an 
AS Sound obejct.
-       virtual unsigned int get_duration(int sound_handle);
-
-       /// Gets the playhead position in milliseconds of an event sound 
connected to an AS Soound obejct.
-       virtual unsigned int get_position(int sound_handle);
-
-       virtual void    attach_aux_streamer(aux_streamer_ptr ptr, void* owner); 
//vv
-       virtual void    detach_aux_streamer(void* owner);       //vv
-       
-};
-
-} // namespace gnash
-
-#endif // SOUND_HANDLER_GST_H
-

Index: backend/sound_handler_mp3.cpp
===================================================================
RCS file: backend/sound_handler_mp3.cpp
diff -N backend/sound_handler_mp3.cpp
--- backend/sound_handler_mp3.cpp       1 Jul 2007 10:53:49 -0000       1.7
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,250 +0,0 @@
-// sound_handler_mp3.cpp: Audio output via libmad (MP3), for Gnash.
-//
-//   Copyright (C) 2007 Free Software Foundation, Inc.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program 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 General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-//
-
-// Based on sound_handler_mp3.cpp by "tbp", 2003
-// which has been donated to the Public Domain.
-
-/*
- * Some brain damaged helpers to decode mp3 streams for use in
- * a gnash::sound_handler that uses SDL for output.
- * (even comments are cut&paste compliant)
- */
-
-/* $Id: sound_handler_mp3.cpp,v 1.7 2007/07/01 10:53:49 bjacques Exp $ */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifndef HAVE_MAD_H
-#error "You need to have the libmad development package installed\
-to compile this file. You can either reconfigure without --enable-mp3,\
- or install libmad0-dev (using apt-get) or libmad (using yum)."
-#else
-
-#include "gnash.h"
-#include "container.h"
-#include "log.h"
-
-#include <cstdio>
-
-#include <mad.h>
-#ifdef _MSC_VER
-       #pragma comment(lib, "libmad")
-       #define snprintf _snprintf
-#endif
-
-using gnash::log_error;
-using gnash::log_msg;
-
-namespace mad_helpers {
-       static const char *parse_layer(const mad_header& h)
-       {
-               switch(h.layer) {
-                       case MAD_LAYER_I:       return "I";
-                       case MAD_LAYER_II:      return "II";
-                       case MAD_LAYER_III:     return "III";
-                       default: return "bogus";
-               }
-       }
-
-       static const char *parse_channel_mode(const mad_header& h)
-       {
-               switch (h.mode) {
-                       case MAD_MODE_SINGLE_CHANNEL:
-                               return "single channel";
-                       case MAD_MODE_DUAL_CHANNEL:
-                               return "dual channel";
-                       case MAD_MODE_JOINT_STEREO:
-                               return "joint (MS/intensity) stereo";
-                       case MAD_MODE_STEREO:
-                               return "normal LR stereo";
-                       default:
-                               return "bogus";
-               }
-       }
-
-       static const char *parse_emphasis(const mad_header& h)
-       {
-               switch (h.emphasis) {
-                       case MAD_EMPHASIS_NONE:
-                               return "none";
-                       case MAD_EMPHASIS_50_15_US:
-                               return "50/15 us";
-                       case MAD_EMPHASIS_CCITT_J_17:
-                               return "CCITT J.17";
-                       default:
-                               return "bogus";
-               }
-       }
-
-#if 1
-       static const char* parse_frame_info(const mad_header& h)
-       {
-               static char buf[1024];
-               size_t len = 1024;
-
-               snprintf(buf, len, "%lu kb/s audio mpeg layer %s "
-                       "stream crc [%s] mode '%s' with '%s' "
-                       "emphasis at %u Hz sample rate",
-                       h.bitrate, parse_layer(h),
-                       (h.flags&MAD_FLAG_PROTECTION) ? "X" : " ",
-                       parse_channel_mode(h), parse_emphasis(h),
-                       h.samplerate);
-               buf[len-1] = 0;
-               return buf;
-       }
-#endif
-  
-       template <const unsigned int stride> static void 
pcm_fixed_to_native(const mad_fixed_t *src, int16_t *dst, const unsigned int 
count)
-       {
-               assert(count > 0);
-               unsigned int 
-                       dec = count,
-                       idx = 0;                        
-               do {
-                       dst[idx*stride] = src[idx] >> (MAD_F_FRACBITS-15); // 
no fancy dithering...
-                       ++idx;
-               } while (--dec);
-       }
-
-}
-
-// some intermediary buffer to hold a frame worth of samples
-// fugly.
-class pcm_buff_t {
-public:
-       //enum { frame_payload = 1152 };
-       int16_t *samples;
-       unsigned int count;
-
-       ~pcm_buff_t() {
-               delete samples;
-       }
-
-       // from mad fixed point to native 16 bits in a temp. buffer
-       unsigned int transmogrify(const mad_synth &synth, const bool stereo) {
-               count = synth.pcm.length;
-               if (stereo) {
-                       samples = new int16_t[count*2];
-                       
mad_helpers::pcm_fixed_to_native<2>(&synth.pcm.samples[0][0], &samples[0], 
count);
-                       
mad_helpers::pcm_fixed_to_native<2>(&synth.pcm.samples[1][0], &samples[1], 
count);
-                       return count * 2;
-               }
-               else {
-                       samples = new int16_t[count];
-                       
mad_helpers::pcm_fixed_to_native<1>(&synth.pcm.samples[0][0], samples, count);
-                       return count;
-               }
-       }
-
-       void *collate(void *p, const bool stereo) const
-       {
-               const unsigned int bytes = count * (stereo ? 2 : 1) * 
sizeof(int16_t);
-               memcpy(p, samples, bytes);
-               return (void *) (((char *)p) + bytes); // geez
-       }
-};
-
-// there's quite some (useless) copying around since there's no infrastructure
-// for streaming and we need to decode it all at once
-void convert_mp3_data(int16_t **adjusted_data, int *adjusted_size, void *data,
-               const int sample_count, const int /*sample_size*/,
-               const int sample_rate, const bool stereo)
-{
-
-       //log_msg("convert_mp3_data sample count %d rate %d stereo %s", 
sample_count, sample_rate, stereo?"yes":"no");
-
-       mad_stream      stream;
-       mad_frame       frame;
-       mad_synth       synth;
-       mad_timer_t     timer;
-
-       mad_stream_init(&stream);
-       mad_frame_init(&frame);
-       mad_synth_init(&synth);
-       mad_timer_reset(&timer);
-
-       // decode stream
-       mad_stream_buffer(&stream, (const unsigned char *)data, sample_count);
-       stream.error = MAD_ERROR_NONE;
-
-       // decode frames
-       unsigned int fc = 0, total = 0;
-       std::vector<pcm_buff_t *> out; // holds decoded frames
-
-       while (true)
-       {
-               if (mad_frame_decode(&frame, &stream)) {
-                       // there's always some garbage in front of the buffer
-                       // so i guess, it's not so garbagish. anyway, skip.
-                       if (fc == 0 && stream.error == MAD_ERROR_LOSTSYNC)
-                       {
-                               continue;
-                       }
-                       else
-                       {
-                               // kludge as we stop decoding on LOSTSYNC.
-                               if (stream.error != MAD_ERROR_LOSTSYNC)
-                               {
-                                       log_error(_("** MP3 frame error: %s"), 
mad_stream_errorstr(&stream));
-                               }
-                               break;
-                       }
-               }
-
-               if (fc == 0)
-               {
-                       log_msg("%s", 
mad_helpers::parse_frame_info(frame.header));
-               }
-
-               ++fc;
-               mad_timer_add(&timer,frame.header.duration);
-
-               mad_synth_frame(&synth,&frame);
-               pcm_buff_t *pcm = new pcm_buff_t;
-               total += pcm->transmogrify(synth, stereo);
-               out.push_back(pcm);
-       }
-
-       if (total == 0) goto cleanup; // yay
-
-       log_msg("decoded frames %d bytes %d (diff %d) -- original rate %d", fc, 
total, total - sample_count, sample_rate);
-
-       // assemble together all decoded frames. another round of memcpy.
-       {
-               void *p = new int16_t[total];
-               *adjusted_data = (int16_t*) p;
-               *adjusted_size = total * sizeof(int16_t);
-               // stuff all that crap together
-               {for (unsigned int i=0; i<out.size(); ++i)
-                       p = out[i]->collate(p,stereo);
-               }
-       }
-
-cleanup:
-       {for (unsigned int i=0; i<out.size(); ++i) delete out[i]; }
-       mad_synth_finish(&synth);
-       mad_frame_finish(&frame);
-       mad_stream_finish(&stream);
-}
-
-// HAVE_MAD_H
-#endif
-

Index: backend/sound_handler_sdl.cpp
===================================================================
RCS file: backend/sound_handler_sdl.cpp
diff -N backend/sound_handler_sdl.cpp
--- backend/sound_handler_sdl.cpp       25 Sep 2007 18:58:43 -0000      1.85
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,1053 +0,0 @@
-//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-
-// This program 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 General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-//
-
-// Based on sound_handler_sdl.cpp by Thatcher Ulrich http://tulrich.com 2003
-// which has been donated to the Public Domain.
-
-// $Id: sound_handler_sdl.cpp,v 1.85 2007/09/25 18:58:43 strk Exp $
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "sound_handler_sdl.h"
-#include "utility.h" // for convert_raw_data
-
-#include "log.h"
-#include <cmath>
-#include <vector>
-#include <SDL.h>
-
-namespace gnash {
-
-SDL_sound_handler::SDL_sound_handler()
-       : soundOpened(false),
-               soundsPlaying(0),
-               muted(false)
-{
-       // This is our sound settings
-       audioSpec.freq = 44100;
-       audioSpec.format = AUDIO_S16SYS; // AUDIO_S8 AUDIO_U8;
-       audioSpec.channels = 2;
-       audioSpec.callback = SDL_sound_handler::sdl_audio_callback;
-       audioSpec.userdata = this;
-       audioSpec.samples = 2048;               //512 - not enough for  
videostream
-}
-
-SDL_sound_handler::~SDL_sound_handler()
-{
-       for (size_t i=0, e=m_sound_data.size(); i < e; ++i)
-       {
-               stop_sound(i);
-               delete_sound(i);
-       }
-       if (soundOpened) SDL_CloseAudio();
-}
-
-
-int    SDL_sound_handler::create_sound(
-       void* data,
-       unsigned int data_bytes,
-       std::auto_ptr<SoundInfo> sinfo)
-// Called to create a sample.  We'll return a sample ID that
-// can be use for playing it.
-{
-
-       assert(sinfo.get());
-       sound_data *sounddata = new sound_data;
-       if (!sounddata) {
-               log_error(_("could not allocate memory for sound data"));
-               return -1;
-       }
-
-       sounddata->data_size = data_bytes;
-       sounddata->volume = 100;
-       sounddata->soundinfo = sinfo;
-
-       int16_t*        adjusted_data = 0;
-       int     adjusted_size = 0;
-
-        boost::mutex::scoped_lock lock(_mutex);
-
-       switch (sounddata->soundinfo->getFormat())
-       {
-       case FORMAT_NATIVE16:
-
-               if (sounddata->data_size > 0) {
-                       convert_raw_data(&adjusted_data, &adjusted_size, data, 
sounddata->soundinfo->getSampleCount(), 
-                                       2, 
sounddata->soundinfo->getSampleRate(), sounddata->soundinfo->isStereo(),
-                                        audioSpec.freq, (audioSpec.channels == 
2 ? true : false));
-                       if (!adjusted_data) {
-                               log_error(_("Some kind of error occurred with 
sound data"));
-                               return -1;
-                       }
-                       sounddata->data_size = adjusted_size;
-                       sounddata->data = 
reinterpret_cast<uint8_t*>(adjusted_data);
-               }
-               break;
-
-       case FORMAT_MP3:
-#ifndef USE_FFMPEG
-#ifndef USE_MAD
-               log_error(_("gnash has not been compiled to handle mp3 audio"));
-               return -1;
-#endif
-#endif
-               sounddata->data = new Uint8[data_bytes];
-               if (!sounddata->data) {
-                       log_error(_("could not allocate space for data in sound 
handler"));
-                       return -1;
-               }
-               memcpy(sounddata->data, data, data_bytes);
-               break;
-
-       //case FORMAT_VORBIS:
-
-       case FORMAT_RAW:
-       case FORMAT_ADPCM:
-       case FORMAT_UNCOMPRESSED:
-               // These should have been converted to FORMAT_NATIVE16
-               log_error(_("Sound data format not properly converted"));
-               return -1;
-               break;
-
-       case FORMAT_NELLYMOSER:
-               log_unimpl("Nellymoser sound format requested, gnash does not 
handle it.");
-               return -1;
-
-       default:
-               // Unhandled format.
-               log_error(_("unknown sound format %d requested; gnash does not 
handle it"), (int)sounddata->soundinfo->getFormat());
-               return -1; // Unhandled format, set to NULL.
-       }
-
-       m_sound_data.push_back(sounddata);
-       int sound_id = m_sound_data.size()-1;
-
-       return sound_id;
-
-}
-
-// this gets called when a stream gets more data
-long   SDL_sound_handler::fill_stream_data(unsigned char* data, unsigned int 
data_bytes, unsigned int sample_count, int handle_id)
-{
-
-       boost::mutex::scoped_lock lock(_mutex);
-       // @@ does a negative handle_id have any meaning ?
-       //    should we change it to unsigned instead ?
-       if (handle_id < 0 || (unsigned int) handle_id+1 > m_sound_data.size())
-       {
-               delete [] data;
-               return -1;
-       }
-       int start_size = 0;
-       sound_data* sounddata = m_sound_data[handle_id];
-
-       // Handling of the sound data
-       switch (sounddata->soundinfo->getFormat()) {
-       case FORMAT_NATIVE16:
-           {
-               int16_t*        adjusted_data = 0;
-               int     adjusted_size = 0;
-
-               convert_raw_data(&adjusted_data, &adjusted_size,
-                                data, sample_count, 2 /*sample size*/,
-                                sounddata->soundinfo->getSampleRate(), 
sounddata->soundinfo->isStereo(),
-                                audioSpec.freq, (audioSpec.channels == 2));
-               if (!adjusted_data || adjusted_size < 1)
-               {
-                       log_error(_("Some kind of error with resampling sound 
data"));
-                       delete [] data;
-                       return -1;
-               }
-
-               // Reallocate the required memory.
-               Uint8* tmp_data = new Uint8[adjusted_size + 
sounddata->data_size];
-               memcpy(tmp_data, sounddata->data, sounddata->data_size);
-               memcpy(tmp_data + sounddata->data_size, adjusted_data, 
adjusted_size);
-               if (sounddata->data_size > 0) delete [] sounddata->data;
-               sounddata->data = tmp_data;
-
-               start_size = sounddata->data_size;
-               sounddata->data_size += adjusted_size;
-               std::vector<active_sound*> asounds = sounddata->m_active_sounds;
-
-               // If playback has already started, we also update the active 
sounds
-               for(uint32_t i=0; i < asounds.size(); i++) {
-                       active_sound* sound = asounds[i];
-                       sound->raw_data_size = sounddata->data_size;
-                       sound->set_raw_data(sounddata->data);
-               }
-           }
-           break;
-
-       case FORMAT_MP3:
-           {
-
-               // Reallocate the required memory.
-               Uint8* tmp_data = new Uint8[data_bytes + sounddata->data_size];
-               memcpy(tmp_data, sounddata->data, sounddata->data_size);
-               memcpy(tmp_data + sounddata->data_size, data, data_bytes);
-               if (sounddata->data_size > 0) delete [] sounddata->data;
-               sounddata->data = tmp_data;
-
-               start_size = sounddata->data_size;
-               sounddata->data_size += data_bytes;
-               std::vector<active_sound*> asounds = sounddata->m_active_sounds;
-               
-               // If playback has already started, we also update the active 
sounds
-               for(uint32_t i=0; i < asounds.size(); i++) {
-                       active_sound* sound = asounds[i];
-                       sound->set_data(sounddata->data);
-                       sound->data_size = sounddata->data_size;
-               }
-
-           }
-           break;
-
-       default:
-               log_error(_("Behavior for this audio codec %d is unknown.  
Please send this SWF to the developers"), 
(int)(sounddata->soundinfo->getFormat()));
-       }
-
-       delete [] data;
-       return start_size;
-}
-
-
-void   SDL_sound_handler::play_sound(int sound_handle, int loop_count, int 
offset, long start_position, const std::vector<sound_envelope>* envelopes)
-// Play the index'd sample.
-{
-       boost::mutex::scoped_lock lock(_mutex);
-
-       // Check if the sound exists, or if audio is muted
-       if (sound_handle < 0 || static_cast<unsigned int>(sound_handle) >= 
m_sound_data.size() || muted)
-       {
-               // Invalid handle or muted
-               return;
-       }
-
-       sound_data* sounddata = m_sound_data[sound_handle];
-
-       // If this is called from a streamsoundblocktag, we only start if this
-       // sound isn't already playing.
-       if (start_position > 0 && sounddata->m_active_sounds.size() > 0) {
-               return;
-       }
-
-       // Make sure sound actually got some data
-       if (sounddata->data_size < 1) {
-               IF_VERBOSE_MALFORMED_SWF(
-                       log_swferror(_("Trying to play sound with size 0"));
-               );
-               return;
-       }
-
-       // Make a "active_sound" for this sound which is later placed on the 
vector of instances of this sound being played
-       active_sound* sound = new active_sound;
-
-       // Copy data-info to the active_sound
-       sound->data_size = sounddata->data_size;
-       sound->set_data(sounddata->data);
-
-       // Set the given options of the sound
-       if (start_position < 0) sound->position = 0;
-       else sound->position = start_position;
-
-       if (offset < 0) sound->offset = 0;
-       else sound->offset = (sounddata->soundinfo->isStereo() ? offset : 
offset*2); // offset is stored as stereo
-
-       sound->envelopes = envelopes;
-       sound->current_env = 0;
-       sound->samples_played = 0;
-
-       // Set number of loop we should do. -1 is infinte loop, 0 plays it 
once, 1 twice etc.
-       sound->loop_count = loop_count;
-
-       if (sounddata->soundinfo->getFormat() == FORMAT_MP3) {
-
-#ifdef USE_FFMPEG
-               // Init the avdecoder-decoder
-               avcodec_init();
-               avcodec_register_all();// change this to only register mp3?
-               sound->codec = avcodec_find_decoder(CODEC_ID_MP3);
-
-               // Init the parser
-               sound->parser = av_parser_init(CODEC_ID_MP3);
-
-               if (!sound->codec) {
-                       log_error(_("Your FFMPEG can't decode MP3?!"));
-                       return;
-               }
-
-               sound->cc = avcodec_alloc_context();
-               avcodec_open(sound->cc, sound->codec);
-
-#elif defined(USE_MAD)
-               // Init the mad decoder
-               mad_stream_init(&sound->stream);
-               mad_frame_init(&sound->frame);
-               mad_synth_init(&sound->synth);
-#endif
-
-               sound->set_raw_data(NULL);
-               sound->raw_position = 0;
-               sound->raw_data_size = 0;
-
-       } else {
-               sound->raw_data_size = sounddata->data_size;
-               sound->set_raw_data(sounddata->data);
-               sound->raw_position = 0;
-               sound->position = 0;
-               sound->data_size = 0;
-
-       }
-
-       if (!soundOpened) {
-               if (SDL_OpenAudio(&audioSpec, NULL) < 0 ) {
-                       log_error(_("Unable to start SDL sound: %s"), 
SDL_GetError());
-                       return;
-               }
-               soundOpened = true;
-
-       }
-
-       ++soundsPlaying;
-       ++_soundsStarted;
-       sounddata->m_active_sounds.push_back(sound);
-
-       if (soundsPlaying == 1) {
-               SDL_PauseAudio(0);
-       }
-
-}
-
-
-void   SDL_sound_handler::stop_sound(int sound_handle)
-{
-       boost::mutex::scoped_lock lock(_mutex);
-
-       // Check if the sound exists.
-       if (sound_handle < 0 || (unsigned int) sound_handle >= 
m_sound_data.size())
-       {
-               // Invalid handle.
-       } else {
-       
-               sound_data* sounddata = m_sound_data[sound_handle];
-       
-               for (int32_t i = (int32_t) sounddata->m_active_sounds.size()-1; 
i >-1; i--) {
-
-                       active_sound* sound = sounddata->m_active_sounds[i];
-
-                       // Stop sound, remove it from the active list (mp3)
-                       if (sounddata->soundinfo->getFormat() == FORMAT_MP3) {
-#ifdef USE_FFMPEG
-                               avcodec_close(sound->cc);
-                               av_parser_close(sound->parser);
-#elif defined(USE_MAD)
-                               mad_synth_finish(&sound->synth);
-                               mad_frame_finish(&sound->frame);
-                               mad_stream_finish(&sound->stream);
-#endif
-                               sound->delete_raw_data();
-                               
sounddata->m_active_sounds.erase(sounddata->m_active_sounds.begin() + i);
-
-                       // Stop sound, remove it from the active list 
(adpcm/native16)
-                       } else {
-                               
sounddata->m_active_sounds.erase(sounddata->m_active_sounds.begin() + i);
-                       }
-                       --soundsPlaying;
-                       ++_soundsStopped;
-               }
-       }
-
-}
-
-
-// this gets called when it's done with a sample.
-void   SDL_sound_handler::delete_sound(int sound_handle)
-{
-       boost::mutex::scoped_lock lock(_mutex);
-
-       if (sound_handle >= 0 && static_cast<unsigned int>(sound_handle) < 
m_sound_data.size())
-       {
-               delete m_sound_data[sound_handle];
-               m_sound_data[sound_handle] = NULL;
-       }
-
-}
-
-// This will stop all sounds playing. Will cause problems if the soundhandler 
is made static
-// and supplys sound_handling for many SWF's, since it will stop all sounds 
with no regard
-// for what sounds is associated with what SWF.
-void   SDL_sound_handler::stop_all_sounds()
-{
-       boost::mutex::scoped_lock lock(_mutex);
-
-       int32_t num_sounds = (int32_t) m_sound_data.size()-1;
-       for (int32_t j = num_sounds; j > -1; j--) {//Optimized
-               sound_data* sounddata = m_sound_data[j];
-               int32_t num_active_sounds = (int32_t) 
sounddata->m_active_sounds.size()-1;
-               for (int32_t i = num_active_sounds; i > -1; i--) {
-
-                       active_sound* sound = sounddata->m_active_sounds[i];
-
-                       // Stop sound, remove it from the active list (mp3)
-                       if (sounddata->soundinfo->getFormat() == FORMAT_MP3) {
-#ifdef USE_FFMPEG
-                               avcodec_close(sound->cc);
-                               av_parser_close(sound->parser);
-#elif defined(USE_MAD)
-                               mad_synth_finish(&sound->synth);
-                               mad_frame_finish(&sound->frame);
-                               mad_stream_finish(&sound->stream);
-#endif
-                               sound->delete_raw_data();
-                               
sounddata->m_active_sounds.erase(sounddata->m_active_sounds.begin() + i);
-                               soundsPlaying--;
-
-                       // Stop sound, remove it from the active list 
(adpcm/native16)
-                       } else {
-                               
sounddata->m_active_sounds.erase(sounddata->m_active_sounds.begin() + i);
-                               soundsPlaying--;
-                       }
-               }
-       }
-}
-
-
-//     returns the sound volume level as an integer from 0 to 100,
-//     where 0 is off and 100 is full volume. The default setting is 100.
-int    SDL_sound_handler::get_volume(int sound_handle) {
-
-       boost::mutex::scoped_lock lock(_mutex);
-
-       int ret;
-       // Check if the sound exists.
-       if (sound_handle >= 0 && static_cast<unsigned int>(sound_handle) < 
m_sound_data.size())
-       {
-               ret = m_sound_data[sound_handle]->volume;
-       } else {
-               ret = 0; // Invalid handle
-       }
-       return ret;
-}
-
-
-//     A number from 0 to 100 representing a volume level.
-//     100 is full volume and 0 is no volume. The default setting is 100.
-void   SDL_sound_handler::set_volume(int sound_handle, int volume) {
-
-       boost::mutex::scoped_lock lock(_mutex);
-
-       // Check if the sound exists.
-       if (sound_handle < 0 || static_cast<unsigned int>(sound_handle) >= 
m_sound_data.size())
-       {
-               // Invalid handle.
-       } else {
-
-               // Set volume for this sound. Should this only apply to the 
active sounds?
-               m_sound_data[sound_handle]->volume = volume;
-       }
-
-
-}
-       
-SoundInfo* SDL_sound_handler::get_sound_info(int sound_handle) {
-
-       boost::mutex::scoped_lock lock(_mutex);
-
-       // Check if the sound exists.
-       if (sound_handle >= 0 && static_cast<unsigned int>(sound_handle) < 
m_sound_data.size())
-       {
-               return m_sound_data[sound_handle]->soundinfo.get();
-       } else {
-               return NULL;
-       }
-
-}
-
-// gnash calls this to mute audio
-void SDL_sound_handler::mute() {
-       stop_all_sounds();
-       muted = true;
-}
-
-// gnash calls this to unmute audio
-void SDL_sound_handler::unmute() {
-       muted = false;
-}
-
-bool SDL_sound_handler::is_muted()
-{
-       return muted;
-}
-
-void   SDL_sound_handler::attach_aux_streamer(aux_streamer_ptr ptr, void* 
owner)
-{
-       boost::mutex::scoped_lock lock(_mutex);
-       assert(owner);
-       assert(ptr);
-
-       aux_streamer_ptr p;
-       if (m_aux_streamer.get(owner, &p))
-       {
-               // Already in the hash.
-               return;
-       }
-       m_aux_streamer[owner] = ptr;
-
-       ++soundsPlaying;
-
-       if (!soundOpened) {
-               if (SDL_OpenAudio(&audioSpec, NULL) < 0 ) {
-                       log_error(_("Unable to start aux SDL sound: %s"), 
SDL_GetError());
-                       return;
-               }
-               soundOpened = true;
-       }
-       SDL_PauseAudio(0);
-
-}
-
-void   SDL_sound_handler::detach_aux_streamer(void* owner)
-{
-       boost::mutex::scoped_lock lock(_mutex);
-       aux_streamer_ptr p;     
-       if (m_aux_streamer.get(owner, &p))
-       {
-               --soundsPlaying;
-               m_aux_streamer.erase(owner);
-       }
-
-}
-
-unsigned int SDL_sound_handler::get_duration(int sound_handle)
-{
-       boost::mutex::scoped_lock lock(_mutex);
-
-       // Check if the sound exists.
-       if (sound_handle < 0 || (unsigned int) sound_handle >= 
m_sound_data.size())
-       {
-               // Invalid handle.
-               return 0;
-       }
-
-       sound_data* sounddata = m_sound_data[sound_handle];
-
-       uint32_t sampleCount = sounddata->soundinfo->getSampleCount();
-       uint32_t sampleRate = sounddata->soundinfo->getSampleRate();
-
-       // Return the sound duration in milliseconds
-       if (sampleCount > 0 && sampleRate > 0) {
-               unsigned int ret = sampleCount / sampleRate * 1000;
-               ret += ((sampleCount % sampleRate) * 1000) / sampleRate;
-               if (sounddata->soundinfo->isStereo()) ret = ret / 2;
-               return ret;
-       } else {
-               return 0;
-       }
-}
-
-unsigned int SDL_sound_handler::get_position(int sound_handle)
-{
-       boost::mutex::scoped_lock lock(_mutex);
-
-       // Check if the sound exists.
-       if (sound_handle < 0 || (unsigned int) sound_handle >= 
m_sound_data.size())
-       {
-               // Invalid handle.
-               return 0;
-       }
-
-       sound_data* sounddata = m_sound_data[sound_handle];
-
-       // If there is no active sounds, return 0
-       if (sounddata->m_active_sounds.size() == 0) return 0;
-
-       // We use the first active sound of this.
-       active_sound* asound = sounddata->m_active_sounds[0];
-
-       // Return the playhead position in milliseconds
-       unsigned int ret = asound->samples_played / audioSpec.freq * 1000;
-       ret += ((asound->samples_played % audioSpec.freq) * 1000) / 
audioSpec.freq;
-       if (audioSpec.channels > 1) ret = ret / audioSpec.channels;
-       return ret;
-}
-
-sound_handler*
-create_sound_handler_sdl()
-// Factory.
-{
-       return new SDL_sound_handler;
-}
-
-
-// Pointer handling and checking functions
-uint8_t* active_sound::get_raw_data_ptr(unsigned long int pos) {
-       assert(raw_data_size > pos);
-       return raw_data + pos;
-}
-
-uint8_t* active_sound::get_data_ptr(unsigned long int pos) {
-       assert(data_size > pos);
-       return data + pos;
-}
-
-void active_sound::set_raw_data(uint8_t* iraw_data) {
-       raw_data = iraw_data;
-}
-
-void active_sound::set_data(uint8_t* idata) {
-       data = idata;
-}
-
-void active_sound::delete_raw_data() {
-       delete [] raw_data;
-}
-
-// AS-volume adjustment
-void adjust_volume(int16_t* data, int size, int volume)
-{
-       for (int i=0; i < size*0.5; i++) {
-               data[i] = data[i] * volume/100;
-       }
-}
-
-// envelope-volume adjustment
-static void
-use_envelopes(active_sound* sound, unsigned int length)
-{
-       // Check if this is the time to use envelopes yet
-       if (sound->current_env == 0 && (*sound->envelopes)[0].m_mark44 > 
sound->samples_played+length/2)
-       {
-               return;
-
-       }
-       // switch to the next envelope if needed and possible
-       else if (sound->current_env < sound->envelopes->size()-1 && 
(*sound->envelopes)[sound->current_env+1].m_mark44 >= sound->samples_played)
-       {
-               sound->current_env++;
-       }
-
-       // Current envelope position
-       int32_t cur_env_pos = 
sound->envelopes->operator[](sound->current_env).m_mark44;
-
-       // Next envelope position
-       uint32_t next_env_pos = 0;
-       if (sound->current_env == (sound->envelopes->size()-1)) {
-               // If there is no "next envelope" then set the next envelope 
start point to be unreachable
-               next_env_pos = cur_env_pos + length;
-       } else {
-               next_env_pos = 
(*sound->envelopes)[sound->current_env+1].m_mark44;
-       }
-
-       unsigned int startpos = 0;
-       // Make sure we start adjusting at the right sample
-       if (sound->current_env == 0 && 
(*sound->envelopes)[sound->current_env].m_mark44 > sound->samples_played) {
-               startpos = sound->raw_position + 
((*sound->envelopes)[sound->current_env].m_mark44 - sound->samples_played)*2;
-       } else {
-               startpos = sound->raw_position;
-       }
-
-       int16_t* data = 
reinterpret_cast<int16_t*>(sound->get_raw_data_ptr(startpos));
-
-       for (unsigned int i=0; i < length/2; i+=2) {
-               float left = 
static_cast<float>((*sound->envelopes)[sound->current_env].m_level0 / 32768.0);
-               float right = 
static_cast<float>((*sound->envelopes)[sound->current_env].m_level1 / 32768.0);
-
-               data[i] = static_cast<int16_t>(data[i] * left); // Left
-               data[i+1] = static_cast<int16_t>(data[i+1] * right); // Right
-
-               if ((sound->samples_played+(length/2-i)) >= next_env_pos && 
sound->current_env != (sound->envelopes->size()-1)) {
-                       sound->current_env++;
-                       // Next envelope position
-                       if (sound->current_env == (sound->envelopes->size()-1)) 
{
-                               // If there is no "next envelope" then set the 
next envelope start point to be unreachable
-                               next_env_pos = cur_env_pos + length;
-                       } else {
-                               next_env_pos = 
(*sound->envelopes)[sound->current_env+1].m_mark44;
-                       }
-               }
-       }
-}
-
-
-// Prepare for mixing/adding (volume adjustments) and mix/add.
-static void
-do_mixing(Uint8* stream, active_sound* sound, Uint8* data, unsigned int 
mix_length, unsigned int volume) {
-       // If the volume needs adjustments we call a function to do that
-       if (volume != 100) {
-               adjust_volume(reinterpret_cast<int16_t*>(data), mix_length, 
volume);
-       } else if (sound->envelopes != NULL) {
-               use_envelopes(sound, mix_length);
-       }
-
-       // Mix the raw data
-       SDL_MixAudio(static_cast<Uint8*>(stream),static_cast<const 
Uint8*>(data), mix_length, SDL_MIX_MAXVOLUME);
-
-       // Update sound info
-       sound->raw_position += mix_length;
-
-       // Sample size is always 2
-       sound->samples_played += mix_length / 2;
-}
-
-
-// Callback invoked by the SDL audio thread.
-void SDL_sound_handler::sdl_audio_callback (void *udata, Uint8 *stream, int 
buffer_length_in)
-{
-       if ( buffer_length_in < 0 )
-       {
-               log_error(_("Negative buffer length in sdl_audio_callback 
(%d)"), buffer_length_in);
-               return;
-       }
-
-       if ( buffer_length_in == 0 )
-       {
-               log_error(_("Zero buffer length in sdl_audio_callback"));
-               return;
-       }
-
-       unsigned int buffer_length = static_cast<unsigned 
int>(buffer_length_in);
-
-       // Get the soundhandler
-       SDL_sound_handler* handler = static_cast<SDL_sound_handler*>(udata);
-
-       // If nothing to play there is no reason to play
-       // Is this a potential deadlock problem?
-       if (handler->soundsPlaying == 0 && handler->m_aux_streamer.size() == 0) 
{
-               SDL_PauseAudio(1);
-               return;
-       }
-
-       boost::mutex::scoped_lock lock(handler->_mutex);
-
-       // Mixed sounddata buffer
-       Uint8* buffer = stream;
-       memset(buffer, 0, buffer_length);
-
-       // call NetStream or Sound audio callbacks
-       if (handler->m_aux_streamer.size() > 0)
-       {
-               uint8_t* buf = new uint8_t[buffer_length];
-
-               // Loop through the attached sounds
-               hash_wrapper< void*, sound_handler::aux_streamer_ptr 
>::iterator it = handler->m_aux_streamer.begin();
-               hash_wrapper< void*, sound_handler::aux_streamer_ptr 
>::iterator end = handler->m_aux_streamer.end();
-               while (it != end) {
-                       memset(buf, 0, buffer_length);
-
-                       SDL_sound_handler::aux_streamer_ptr aux_streamer = 
it->second; //handler->m_aux_streamer[i]->ptr;
-                       void* owner = it->first;
-
-                       // If false is returned the sound doesn't want to be 
attached anymore
-                       bool ret = (aux_streamer)(owner, buf, buffer_length);
-                       if (!ret) {
-                               handler->m_aux_streamer.erase(it++);
-                               handler->soundsPlaying--;
-                       } else {
-                               ++it;
-                       }
-                       SDL_MixAudio(stream, buf, buffer_length, 
SDL_MIX_MAXVOLUME);
-
-               }
-               delete [] buf;
-       }
-
-       // Run through all the sounds.
-       for(uint32_t i=0; i < handler->m_sound_data.size(); i++) {
-               sound_data* sounddata = handler->m_sound_data[i];
-               for(uint32_t j = 0; j < sounddata->m_active_sounds.size(); j++) 
{
-
-                       // Temp variables to make the code simpler and easier 
to read
-                       active_sound* sound = sounddata->m_active_sounds[j];
-                       format_type soundFormat = 
sounddata->soundinfo->getFormat();
-                       bool soundStereo = sounddata->soundinfo->isStereo();
-                       uint32_t soundSampleRate = 
sounddata->soundinfo->getSampleRate();
-
-                       // When the current sound dont have enough decoded data 
to fill the buffer, 
-                       // we first mix what is already decoded, then decode 
some more data, and
-                       // mix some more until the buffer is full. If a sound 
loops the magic
-                       // happens here ;)
-                       if (sound->raw_data_size - sound->raw_position < 
buffer_length 
-                               && (sound->position < sound->data_size || 
sound->loop_count != 0)) {
-
-                               // First we mix what is decoded
-                               unsigned int index = 0;
-                               if (sound->raw_data_size - sound->raw_position 
> 0) {
-                                       index = sound->raw_data_size - 
sound->raw_position;
-
-                                       do_mixing(stream, sound, 
sound->get_raw_data_ptr(sound->raw_position),
-                                               index, sounddata->volume);
-
-                               }
-
-                               // If this isn't MP3 (which means its NATIVE16) 
there is nothing to decode,
-                               // reusing the available data is the only 
option.
-                               if (soundFormat != FORMAT_MP3) {
-                                       if (index < buffer_length) {
-                                               sound->loop_count--;
-                                               sound->raw_position = 0;
-                                               sound->samples_played = 0;
-                                               unsigned int mix_length = 
((buffer_length - index) > sound->raw_data_size ? sound->raw_data_size : 
(buffer_length - index));
-                                               do_mixing(stream+index, sound, 
sound->get_raw_data_ptr(sound->raw_position), 
-                                                       mix_length, 
sounddata->volume);
-                                       }
-                                       continue;
-                               }
-                               
-                               // Then we decode some data
-                               // We loop until the size of the decoded sound 
is greater than the buffer size,
-                               // or there is no more to decode.
-                               unsigned int decoded_size = 0;
-                               sound->raw_data_size = 0;
-                               while(decoded_size < buffer_length) {
-
-                                       // If we need to loop, we reset the 
data pointer
-                                       if (sound->data_size == sound->position 
&& sound->loop_count != 0) {
-                                               sound->loop_count--;
-                                               sound->position = 0;
-                                               sound->samples_played = 0;
-                                       }
-
-                                       // Test if we will get problems... 
Should not happen...
-                                       assert(sound->data_size > 
sound->position);
-                                       
-                                       // temp raw buffer
-                                       Uint8* tmp_raw_buffer;
-                                       unsigned int tmp_raw_buffer_size;
-                                       int outsize = 0;
-
-#ifdef USE_FFMPEG
-                                       tmp_raw_buffer = new 
Uint8[AVCODEC_MAX_AUDIO_FRAME_SIZE];
-                                       tmp_raw_buffer_size = 
AVCODEC_MAX_AUDIO_FRAME_SIZE;
-
-                                       long bytes_decoded = 0;
-
-                                       while (outsize == 0 && sound->position 
< sound->data_size) {
-                                               uint8_t* frame;
-                                               int framesize;
-
-                                               bytes_decoded = 
av_parser_parse(sound->parser, sound->cc, &frame, &framesize,
-                                                                       
static_cast<uint8_t *>(sound->get_data_ptr(sound->position)), sound->data_size 
- sound->position,
-                                                                       0 ,0);  
//pts, dts
-
-                                               int tmp = 0;
-#ifdef FFMPEG_AUDIO2
-                                               outsize = 
AVCODEC_MAX_AUDIO_FRAME_SIZE;
-                                               tmp = 
avcodec_decode_audio2(sound->cc, (int16_t*)(tmp_raw_buffer), &outsize, frame, 
framesize);
-#else
-                                               tmp = 
avcodec_decode_audio(sound->cc, (int16_t*)(tmp_raw_buffer), &outsize, frame, 
framesize);
-#endif
-
-                                               if (bytes_decoded < 0 || tmp < 
0 || outsize < 0) {
-                                                       log_error(_("Error 
while decoding MP3-stream.  Upgrading ffmpeg/libavcodec might fix this 
issue."));
-                                                       // Setting data 
position to data size will get the sound removed
-                                                       // from the active 
sound list later on.
-                                                       sound->position = 
sound->data_size;
-                                                       break;
-                                               }
-
-                                               sound->position += 
bytes_decoded;
-                                       }
-
-#elif defined(USE_MAD)
-
-                                       // Setup the mad decoder
-                                       mad_stream_buffer(&sound->stream, 
sound->get_data_ptr(sound->position), sound->data_size-sound->position);
-
-                                       int ret;
-                                       const unsigned char* old_next_frame = 
sound->stream.next_frame;
-                                       int loops = 0;
-                                       while(true) {
-
-                                               ret = 
mad_frame_decode(&sound->frame, &sound->stream);
-                                               loops++;
-                                               
-                                               // There is always some junk in 
front of the data, 
-                                               // so we continue until we get 
past it.
-                                               if (ret && sound->stream.error 
== MAD_ERROR_LOSTSYNC) continue;
-                                               
-                                               // Error handling is done by 
relooping (max. 8 times) and just hooping that it will work...
-                                               if (loops > 8) break;
-                                               if (ret == -1 && 
sound->stream.error != MAD_ERROR_BUFLEN && 
MAD_RECOVERABLE(sound->stream.error)) {
-                                                       
log_error(_("Recoverable error while decoding MP3-stream, MAD error: %s"), 
mad_stream_errorstr (&sound->stream));
-                                                       continue;
-                                               }
-                                               
-                                               break;
-                                       }
-
-                                       if (ret == -1 && sound->stream.error != 
MAD_ERROR_BUFLEN) {
-                                               log_error(_("Unrecoverable 
error while decoding MP3-stream, MAD error: %s"), mad_stream_errorstr 
(&sound->stream));
-                                               sound->position = 
sound->data_size;
-                                               continue;
-                                       } else if (ret == -1 && 
sound->stream.error == MAD_ERROR_BUFLEN) {
-                                               // the buffer is empty, no more 
to decode!
-                                               sound->position = 
sound->data_size;
-                                       } else {
-                                               sound->position += 
sound->stream.next_frame - old_next_frame;
-                                       }
-
-                                       mad_synth_frame (&sound->synth, 
&sound->frame);
-                                       
-                                       outsize = sound->synth.pcm.length * 
((soundStereo == true) ? 4 : 2);
-
-                                       tmp_raw_buffer = new Uint8[outsize];
-                                       int sample;
-                                       
-                                       int16_t* dst = 
reinterpret_cast<int16_t*>(tmp_raw_buffer);
-
-                                       // transfer the decoded samples into 
the sound-struct, and do some
-                                       // scaling while we're at it.
-                                       for(int f = 0; f < 
sound->synth.pcm.length; f++)
-                                       {
-                                               for (int e = 0; e < 
((soundStereo == true) ? 2 : 1); e++){ // channels (stereo/mono)
-
-                                                       mad_fixed_t mad_sample 
= sound->synth.pcm.samples[e][f];
-
-                                                       // round
-                                                       mad_sample += (1L << 
(MAD_F_FRACBITS - 16));
-
-                                                       // clip
-                                                       if (mad_sample >= 
MAD_F_ONE) mad_sample = MAD_F_ONE - 1;
-                                                       else if (mad_sample < 
-MAD_F_ONE) mad_sample = -MAD_F_ONE;
-
-                                                       // quantize
-                                                       sample = mad_sample >> 
(MAD_F_FRACBITS + 1 - 16);
-
-                                                       if ( sample != 
static_cast<int16_t>(sample) ) sample = sample < 0 ? -32768 : 32767;
-
-                                                       *dst++ = sample;
-                                               }
-                                       }
-#endif // defined(USE_MAD)
-
-                                       // If we need to convert samplerate 
or/and from mono to stereo...
-                                       if (outsize > 0 && 
(static_cast<int>(soundSampleRate) != handler->audioSpec.freq || !soundStereo)) 
{
-
-                                               int16_t* adjusted_data = 0;
-                                               int     adjusted_size = 0;
-                                               int sample_count = outsize / 
((soundStereo == true) ? 4 : 2);
-
-                                               // Convert to needed samplerate
-                                               
convert_raw_data(&adjusted_data, &adjusted_size, tmp_raw_buffer, sample_count, 
0, 
-                                                               
soundSampleRate, soundStereo,
-                                                               
handler->audioSpec.freq, (handler->audioSpec.channels == 2 ? true : false));
-
-                                               // Hopefully this wont happen
-                                               if (!adjusted_data) {
-                                                       log_error(_("Error in 
sound sample conversion"));
-                                                       continue;
-                                               }
-
-                                               // Move the new data to the 
sound-struct
-                                               delete[] tmp_raw_buffer;
-                                               tmp_raw_buffer = 
reinterpret_cast<Uint8*>(adjusted_data);
-                                               tmp_raw_buffer_size = 
adjusted_size;
-
-                                       } else {
-                                               tmp_raw_buffer_size = outsize;
-                                       }
-
-                                       Uint8* tmp_buf = new Uint8[decoded_size 
+ tmp_raw_buffer_size];
-                                       sound->raw_data_size = 1;
-                                       memcpy(tmp_buf, 
sound->get_raw_data_ptr(0), decoded_size);
-                                       memcpy(tmp_buf+decoded_size, 
tmp_raw_buffer, tmp_raw_buffer_size);
-                                       decoded_size += tmp_raw_buffer_size;
-                                       sound->delete_raw_data();
-                                       sound->set_raw_data(tmp_buf);
-                                       delete[] tmp_raw_buffer;
-
-                                       // no more to decode from this sound, 
so we break the loop
-                                       if (sound->data_size <= sound->position 
&& sound->loop_count == 0) {
-                                               break;
-                                       }
-
-                               } // end of "decode min. bufferlength data" 
while loop
-
-                               sound->raw_data_size = decoded_size;
-                                                               
-                               sound->raw_position = 0;
-
-                               // Determine how much should be mixed
-                               unsigned int mix_length = 0;
-                               if (decoded_size >= buffer_length - index) {
-                                       mix_length = buffer_length - index;
-                               } else { 
-                                       mix_length = decoded_size;
-                               }
-                               if (sound->raw_data_size < 2) continue; // 
something went terrible wrong
-                               do_mixing(stream+index, sound, 
sound->get_raw_data_ptr(0), mix_length, sounddata->volume);
-
-                       // When the current sound has enough decoded data to 
fill 
-                       // the buffer, we do just that.
-                       } else if (sound->raw_data_size - sound->raw_position > 
buffer_length ) {
-                       
-                               do_mixing(stream, sound, 
sound->get_raw_data_ptr(sound->raw_position), 
-                                       buffer_length, sounddata->volume);
-
-                       // When the current sound doesn't have anymore data to 
decode,
-                       // and doesn't loop (anymore), but still got unplayed 
data,
-                       // we put the last data on the stream
-                       } else if (sound->raw_data_size - sound->raw_position 
<= buffer_length && sound->raw_data_size > sound->raw_position+1) {
-                       
-
-                               do_mixing(stream, sound, 
sound->get_raw_data_ptr(sound->raw_position), 
-                                       sound->raw_data_size - 
sound->raw_position, sounddata->volume);
-
-                               sound->raw_position = sound->raw_data_size;
-                       } 
-
-                       // Sound is done, remove it from the active list (mp3)
-                       if (sound->position == sound->data_size && 
sound->loop_count == 0 && soundFormat == FORMAT_MP3) {
-#ifdef USE_FFMPEG
-                               avcodec_close(sound->cc);
-                               av_parser_close(sound->parser);
-#elif defined(USE_MAD)
-                               mad_synth_finish(&sound->synth);
-                               mad_frame_finish(&sound->frame);
-                               mad_stream_finish(&sound->stream);
-#endif
-                               sound->delete_raw_data();
-                               
sounddata->m_active_sounds.erase(sounddata->m_active_sounds.begin() + j);
-                               handler->soundsPlaying--;
-                               handler->_soundsStopped++;
-
-
-                       // Sound is done, remove it from the active list 
(adpcm/native16)
-                       } else if (sound->loop_count == 0 && soundFormat == 
FORMAT_NATIVE16 && sound->raw_position >= sound->raw_data_size && 
sound->raw_data_size != 0) {
-                               
sounddata->m_active_sounds.erase(sounddata->m_active_sounds.begin() + j);
-                               handler->soundsPlaying--;
-                               handler->_soundsStopped++;
-                       } else if (sound->raw_position == 0 && 
sound->raw_data_size == 0) {
-                               
sounddata->m_active_sounds.erase(sounddata->m_active_sounds.begin() + j);
-                               handler->soundsPlaying--;
-                               handler->_soundsStopped++;
-                       }
-
-               } // active sounds loop
-       } // existing sounds loop
-
-}
-
-} // namespace gnash
-
-// Local Variables:
-// mode: C++
-// End:
-

Index: backend/sound_handler_sdl.h
===================================================================
RCS file: backend/sound_handler_sdl.h
diff -N backend/sound_handler_sdl.h
--- backend/sound_handler_sdl.h 25 Sep 2007 18:58:43 -0000      1.33
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,258 +0,0 @@
-//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-
-// This program 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 General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-// $Id: sound_handler_sdl.h,v 1.33 2007/09/25 18:58:43 strk Exp $
-
-#ifndef SOUND_HANDLER_SDL_H
-#define SOUND_HANDLER_SDL_H
-
-
-#include "sound_handler.h" // for inheritance
-#include "hash_wrapper.h"
-
-#include "log.h"
-
-#ifdef USE_FFMPEG
-extern "C" {
-#include <ffmpeg/avcodec.h>
-}
-#elif defined(USE_MAD)
-#include <mad.h>
-#endif
-
-#include <vector>
-
-#include <SDL_audio.h>
-#include <boost/thread/thread.hpp>
-#include <boost/bind.hpp>
-#include <boost/thread/mutex.hpp>
-
-namespace gnash {
-
-/// Used to hold the info about active sounds
-class active_sound
-{
-public:
-#ifdef USE_FFMPEG
-       /// ffmpeg stuff
-       AVCodec *codec;
-       AVCodecContext *cc;
-       AVCodecParserContext* parser;
-#elif defined(USE_MAD)
-       /// mad stuff
-       mad_stream      stream;
-       mad_frame       frame;
-       mad_synth       synth;
-#endif
-
-       /// The size of the undecoded data
-       unsigned long data_size;
-
-       /// Current decoding position in the stream
-       unsigned long position;
-
-       /// Size of the decoded data
-       unsigned long raw_data_size;
-
-       /// Current playing position in the decoded stream
-       unsigned long raw_position;
-
-       /// Numbers of loops: -1 means loop forever, 0 means play once.
-       /// For every loop completed, it is decremented.
-       long loop_count;
-
-       /// Offset to make playback start in-sync, only used with mp3 streams.
-       unsigned int offset;
-
-       /// Sound envelopes for the current sound, which determine the volume 
level
-       /// from a given position. Only used with sound events.
-       const std::vector<gnash::sound_handler::sound_envelope>* envelopes;
-
-       /// Index of current envelope.
-       uint32_t current_env;
-
-       /// Number of samples played so far.
-       unsigned long samples_played;
-
-       /// Returns the data pointer in the undecoded datastream
-       /// for the given position. Boundaries are checked.
-       uint8_t* get_data_ptr(unsigned long int pos);
-
-       /// Returns the data pointer in the decoded datastream
-       /// for the given position. Boundaries are checked.
-       uint8_t* get_raw_data_ptr(unsigned long int pos);
-
-       /// Set the undecoded data pointer
-       void set_data(uint8_t*);
-
-       /// Set the decoded data pointer
-       void set_raw_data(uint8_t*);
-
-       /// Deletes the decoded data
-       void delete_raw_data();
-
-private:
-       /// The undecoded data
-       uint8_t* data;
-
-       /// The decoded data
-       uint8_t* raw_data;
-
-};
-
-
-/// Used to hold the sounddata when doing on-demand-decoding
-class sound_data
-{
-public:
-       /// The undecoded data
-       //
-       /// TODO: use boost::scoped_array
-       uint8_t* data;
-
-       /// Object holding information about the sound
-       std::auto_ptr<SoundInfo> soundinfo;
-
-       /// The size of the undecoded data
-       unsigned int data_size;
-
-       /// Volume for AS-sounds, range: 0-100.
-       /// It's the SWF range that is represented here.
-       int volume;
-
-       /// Vector containing the active instances of this sounds being played
-       //
-       /// TODO: define ownership of the active_sound elements
-       ///
-       std::vector<active_sound*>      m_active_sounds;
-
-       ~sound_data()
-       {
-               // TODO: use boost::scoped_array
-               delete [] data;
-       }
-
-};
-
-
-// Use SDL and ffmpeg/mad/nothing to handle sounds.
-class SDL_sound_handler : public gnash::sound_handler
-{
-private:
-       /// NetStream audio callbacks
-       hash_wrapper< void* /* owner */, aux_streamer_ptr /* callback */> 
m_aux_streamer;       //vv
-
-       /// Vector containing all sounds.
-       std::vector<sound_data*>        m_sound_data;
-
-       /// Is sound device opened?
-       bool soundOpened;
-
-       /// The SDL_audio specs
-       SDL_AudioSpec audioSpec;
-       
-       /// Keeps track of numbers of playing sounds
-       int soundsPlaying;
-
-       /// Is the audio muted?
-       bool muted;
-       
-       /// Mutex for making sure threads doesn't mess things up
-       boost::mutex _mutex;
-
-public:
-       SDL_sound_handler();
-       virtual ~SDL_sound_handler();
-
-       /// Called to create a sound.
-       virtual int     create_sound(void* data, unsigned int data_bytes, 
std::auto_ptr<SoundInfo> sinfo);
-
-       /// this gets called when a stream gets more data
-       virtual long    fill_stream_data(unsigned char* data, unsigned int 
data_bytes,
-                                        unsigned int sample_count, int 
handle_id);
-
-       /// Play the index'd sample.
-       virtual void    play_sound(int sound_handle, int loop_count, int offset,
-                                  long start_position, const 
std::vector<sound_envelope>* envelopes);
-
-       /// Stop the index'd sample.
-       virtual void    stop_sound(int sound_handle);
-
-       /// This gets called when it's done with a sample.
-       virtual void    delete_sound(int sound_handle);
-
-       /// This will stop all sounds playing.
-       virtual void    stop_all_sounds();
-
-       /// Returns the sound volume level as an integer from 0 to 100. 
AS-script only.
-       virtual int     get_volume(int sound_handle);
-
-       /// Sets the sound volume level as an integer from 0 to 100. AS-script 
only.
-       virtual void    set_volume(int sound_handle, int volume);
-               
-       /// Gnash uses this to get info about a sound. Used when a stream needs 
more data.
-       virtual SoundInfo* get_sound_info(int sound_handle);
-
-       /// Gnash calls this to mute audio.
-       virtual void    mute();
-
-       /// Gnash calls this to unmute audio.
-       virtual void    unmute();
-
-       /// Gnash calls this to get the mute state.
-       virtual bool    is_muted();
-
-       /// Gets the duration in milliseconds of an event sound connected to an 
AS Sound obejct.
-       virtual unsigned int get_duration(int sound_handle);
-
-       /// Gets the playhead position in milliseconds of an event sound 
connected to an AS Soound obejct.
-       virtual unsigned int get_position(int sound_handle);
-       
-       virtual void    attach_aux_streamer(aux_streamer_ptr ptr, void* owner); 
//vv
-       virtual void    detach_aux_streamer(void* owner);       //vv
-
-       /// Callback invoked by the SDL audio thread.
-       //
-       /// Refills the output stream/buffer with data.
-       ///
-       /// We run trough all the attached auxiliary streamers fetching decoded
-       /// audio blocks and mixing them into the given output stream.
-       ///
-       /// If sound is compresssed (mp3) a mp3-frame is decoded into a buffer,
-       /// and resampled if needed. When the buffer has been sampled, another
-       /// frame is decoded until all frames has been decoded.
-       /// If a sound is looping it will be decoded from the beginning again.
-       ///
-       /// TODO: make a static method of the SDL_sound_handler class
-       ///
-       /// @param udata
-       ///     User data pointer (SDL_sound_handler instance in our case).
-       ///     We'll lock the SDL_sound_handler::_mutex during operations.
-       ///
-       /// @param stream
-       ///     The output stream/buffer to fill
-       ///
-       /// @param buffer_length_in
-       ///     Length of the buffer.
-       ///     If zero or negative we log an error and return
-       ///     (negative is probably an SDL bug, zero dunno yet).
-       ///
-       static void sdl_audio_callback (void *udata, Uint8 *stream, int 
buffer_length_in);
-};
-
-} // namespace gnash
-
-#endif // SOUND_HANDLER_SDL_H

Index: libbase/embedVideoDecoder.h
===================================================================
RCS file: libbase/embedVideoDecoder.h
diff -N libbase/embedVideoDecoder.h
--- libbase/embedVideoDecoder.h 1 Jul 2007 10:54:07 -0000       1.9
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,120 +0,0 @@
-// 
-//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-// 
-// This program 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 General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-// 
-//
-//
-
-//  $Id: embedVideoDecoder.h,v 1.9 2007/07/01 10:54:07 bjacques Exp $
-
-#ifndef __EMBEDVIDEODECODER_H__
-#define __EMBEDVIDEODECODER_H__
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "image.h"
-#include "log.h"
-
-namespace gnash {
-
-///
-/// \brief
-/// The embedVideoDecoder is used to decodes a video frame which has been
-/// embedded in a SWF.
-///
-class embedVideoDecoder
-{
-public:
-
-       /// This is copied from the render and should be changed if the 
original is.
-       enum videoOutputFormat
-       {
-               NONE,
-               YUV,
-               RGB
-       };
-
-       /// Codecs type we know of
-       enum codecType
-       {
-               CODEC_H263 = 2, // H263/SVQ3 video codec
-               CODEC_SCREENVIDEO = 3,  // Screenvideo codec
-               CODEC_VP6 = 4,          // On2 VP6 video codec
-               CODEC_VP6A = 5,         // On2 VP6 Alpha video codec
-               CODEC_SCREENVIDEO2 = 6  // Screenvideo2 codec
-       };
-
-       /// Sets up the decoder.
-       //
-       /// @param width
-       ///     The width of the video
-       ///
-       /// @param height
-       ///     The height of the video
-       ///
-       /// @param deblocking
-       ///     Should a deblocking filter be used? 1 = off, 2 = on
-       ///
-       /// @param smoothing
-       ///     Should the video be smoothed?
-       ///
-       /// @param format
-       ///     The codec of the video, see codecType
-       ///
-       /// @param outputFormat
-       ///     The outputFormat of the video, see videoOutputFormat
-       ///
-       /// The default implementation is a no-op
-       ///
-       /// TODO: shouldn't this initialization be done by the constructor ?
-       ///
-       virtual void createDecoder(int /*width*/,
-               int /*height*/,
-               int /*deblocking*/,
-               bool /*smoothing*/,
-               int /*format*/, // should this argument be of codecType type ?
-               int /*outputFormat*/) // should this argument be of 
VideoOutputFormat type ?
-       {}
-
-       /// gnash calls this when it wants to decode the given videoframe.
-       //
-       /// @param data
-       ///     The video frame that is to be decoded.
-       ///     Data is expected to be in the format specified with the 
-       ///     "format" parameter in the createDecoder call.
-       ///
-       /// @param size
-       ///     The sizes of the undecoded videoframe in bytes.
-       ///
-       /// @return
-       ///     An auto_ptr containing the image which is a result of the 
decoding.
-       ///     A NULL one on error.
-       ///
-       /// The default implementation always returns a NULL auto pointer.
-       ///
-       virtual std::auto_ptr<image::image_base> decodeFrame(uint8_t* /*data*/, 
int /*size*/)
-       {
-               return std::auto_ptr<image::image_base>(NULL); 
-       }
-
-       virtual ~embedVideoDecoder() {};
-};
-
-} // end of gnash namespace
-#endif // __EMBEDVIDEODECODER_H__

Index: libbase/embedVideoDecoderFfmpeg.cpp
===================================================================
RCS file: libbase/embedVideoDecoderFfmpeg.cpp
diff -N libbase/embedVideoDecoderFfmpeg.cpp
--- libbase/embedVideoDecoderFfmpeg.cpp 10 Sep 2007 16:53:29 -0000      1.22
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,282 +0,0 @@
-// 
-//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-// 
-// This program 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 General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef USE_FFMPEG
-
-#include <cstring>
-
-#include "embedVideoDecoderFfmpeg.h"
-
-#ifdef HAVE_SWSCALE_H
-extern "C" {
-#include <ffmpeg/swscale.h>
-}
-#endif
-
-#include <boost/scoped_array.hpp>
-
-namespace gnash {
-
-embedVideoDecoderFfmpeg::embedVideoDecoderFfmpeg() :
-       codec(NULL),
-       cc(NULL),
-       decodedFrame(NULL)
-{
-}
-
-embedVideoDecoderFfmpeg::~embedVideoDecoderFfmpeg()
-{
-       if (cc) avcodec_close(cc);
-
-}
-
-void
-embedVideoDecoderFfmpeg::createDecoder(int widthi, int heighti, int 
deblockingi, bool smoothingi, int formati, int outputFormati)
-{
-       // Init the avdecoder-decoder
-       avcodec_init();
-       avcodec_register_all();
-
-       // Save video attributes
-       width = widthi;
-       height = heighti;
-       deblocking = deblockingi;
-       smoothing = smoothingi;
-       format = formati;
-       outputFormat = outputFormati;
-
-       // Find the decoder and init the parser
-       if (format == CODEC_H263) {
-               codec = avcodec_find_decoder(CODEC_ID_FLV1);
-#ifdef FFMPEG_VP6
-       } else if (format == CODEC_VP6) {
-               codec = avcodec_find_decoder(CODEC_ID_VP6F);
-#endif
-       } else if (format == CODEC_SCREENVIDEO) {
-               codec = avcodec_find_decoder(CODEC_ID_FLASHSV);
-       } else {
-               gnash::log_error("Unsupported embedded video format, it might 
help if you upgrade ffmpeg and recompile gnash");
-               return;
-       }
-
-       if (codec == NULL) {
-               gnash::log_error("Unsupported embedded video format, it might 
help if you upgrade ffmpeg and recompile gnash");
-               return;
-       }
-
-       cc = avcodec_alloc_context();
-       avcodec_open(cc, codec);
-       cc->width = width;
-       cc->height = height;
-
-       assert(cc->width > 0);
-       assert(cc->height > 0);
-
-       // Determine required buffer size and allocate buffer
-       if (outputFormat == YUV) {
-               decodedFrame.reset(new image::yuv(width, height));
-       } else if (outputFormat == RGB) {
-               decodedFrame.reset(new image::rgb(width, height));
-       }
-}
-
-uint8_t*
-embedVideoDecoderFfmpeg::convertRGB24(AVCodecContext* srcCtx, AVFrame* 
srcFrame)
-{
-       int width = srcCtx->width, height = srcCtx->height;
-
-       int bufsize = avpicture_get_size(PIX_FMT_RGB24, width, height);
-       if (bufsize == -1) {
-               return NULL;
-       }
-
-       uint8_t* buffer = new uint8_t[bufsize];
-       if (!buffer) {
-               return NULL;
-       }
-
-       AVPicture picture;
-
-       avpicture_fill(&picture, buffer, PIX_FMT_RGB24, width, height);
-#ifndef HAVE_SWSCALE_H
-       img_convert(&picture, PIX_FMT_RGB24, (AVPicture*) srcFrame, 
srcCtx->pix_fmt,
-                   width, height);
-#else
-       static SwsContext* context = NULL;
-
-       if (!context) {
-               context = sws_getContext(width, height, srcCtx->pix_fmt,
-                                        width, height, PIX_FMT_RGB24,
-                                        SWS_FAST_BILINEAR, NULL, NULL, NULL);
-               if (!context) {
-                       delete [] buffer;
-                       return NULL;
-               }
-       }
-
-       int rv = sws_scale(context, srcFrame->data, srcFrame->linesize, 0, 
-                          width, picture.data, picture.linesize);
-       if (rv == -1) {
-               delete [] buffer;
-               return NULL;
-       }
-
-#endif // HAVE_SWSCALE_H
-
-       srcFrame->linesize[0] = picture.linesize[0];
-       srcFrame->data[0] = picture.data[0];
-
-       return buffer;
-}
-
-// gnash calls this when it wants you to decode the given videoframe
-std::auto_ptr<image::image_base> 
-embedVideoDecoderFfmpeg::decodeFrame(uint8_t* data, int size)
-{
-
-       std::auto_ptr<image::image_base> ret_image;
-
-       if (outputFormat == YUV) {
-               ret_image.reset(new image::yuv(width, height));
-       } else if (outputFormat == RGB) {
-               ret_image.reset(new image::rgb(width, height));
-       } else {
-               ret_image.reset(NULL);
-               return ret_image;
-       }
-
-       // If there is nothing to decode in the new frame
-       // we just return the lastest.
-       if (data == NULL || codec == NULL || size == 0)
-       {
-               // If haven't decoded any frame yet, return
-               // the null pointer.
-               if ( ! decodedFrame.get() )
-               {
-                       ret_image.reset(NULL);
-                       return ret_image;
-               }
-
-               // clone decodedFrame instead ?
-               ret_image->update(*decodedFrame);
-               return ret_image;
-       }
-
-
-       // Allocate a frame to store the decoded frame in
-       AVFrame* frame = avcodec_alloc_frame();
-       
-       int got = 0;
-       avcodec_decode_video(cc, frame, &got, data, size);
-
-       // If the size of the video frame changed, adjust.
-       // This could happen if the decoded video frame is
-       // bigger than the defined SWF videoframe.
-       if (static_cast<uint32_t>(cc->width) != width || 
static_cast<uint32_t>(cc->height) != height) {
-               width = cc->width;
-               height = cc->height;
-               if (outputFormat == YUV) {
-                       decodedFrame.reset(new image::yuv(width, height));
-                       ret_image.reset(new image::yuv(width, height));
-               } else if (outputFormat == RGB) {
-                       decodedFrame.reset(new image::rgb(width, height));
-                       ret_image.reset(new image::rgb(width, height));
-               }
-       }
-       
-       if (got) {
-               log_debug("Got");
-               boost::scoped_array<uint8_t> buffer;
-
-               if (outputFormat == NONE) { // NullGui?
-                       av_free(frame);
-                       ret_image->update(*decodedFrame);
-                       return ret_image;
-
-               } else if (outputFormat == YUV && cc->pix_fmt != 
PIX_FMT_YUV420P) {
-                       //assert(0);    // TODO
-                       //img_convert((AVPicture*) pFrameYUV, PIX_FMT_YUV420P, 
(AVPicture*) pFrame, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
-                       // Don't use depreceted img_convert, use sws_scale
-
-               } else if (outputFormat == RGB && cc->pix_fmt != PIX_FMT_RGB24) 
{
-                       buffer.reset(convertRGB24(cc, frame));
-               }
-
-               if (outputFormat == YUV) {
-                       image::yuv* yuvframe = 
static_cast<image::yuv*>(decodedFrame.get());
-                       size_t copied = 0;
-                       uint8_t* ptr = yuvframe->data();
-                       for (int i = 0; i < 3 ; i++)
-                       {
-                               int shift = (i == 0 ? 0 : 1);
-                               uint8_t* yuv_factor = frame->data[i];
-                               int h = cc->height >> shift;
-                               int w = cc->width >> shift;
-                               for (int j = 0; j < h; j++)
-                               {
-                                       copied += w;
-                                       //assert(copied <= yuvframe->size());
-                                       memcpy(ptr, yuv_factor, w);
-                                       yuv_factor += frame->linesize[i];
-                                       ptr += w;
-                               }
-                       }
-                       //yuvframe->m_size = copied;
-                       assert(yuvframe->size() == copied); // correct ?
-               } else if (outputFormat == RGB) {
-
-               log_debug("updating decodedFrame with data from ffmpeg");
-
-                       uint8_t* srcptr = frame->data[0];
-                       uint8_t* srcend = frame->data[0] + frame->linesize[0] * 
cc->height;
-                       uint8_t* dstptr = decodedFrame->data();
-                       uint8_t* dstend = 
decodedFrame->data()+decodedFrame->size();
-                       unsigned int srcwidth = cc->width * 3;
-
-                       while (srcptr < srcend) {
-                               assert( dstptr < dstend );
-                               memcpy(dstptr, srcptr, srcwidth);
-                               srcptr += frame->linesize[0];
-                               dstptr += srcwidth;
-                       }
-
-               }
-       }
-       else log_debug("Didn't get");
-
-       av_free(frame);
-       // If haven't decoded any frame yet, return
-       // the null pointer.
-       if ( ! decodedFrame.get() )
-       {
-               ret_image.reset(NULL);
-               return ret_image;
-       }
-
-       log_debug("Returning a clone of decodedFrame");
-       return decodedFrame->clone();
-       //ret_image->update(*decodedFrame);
-       //return ret_image;
-}
-
-} // end of gnash namespace
-
-#endif // USE_FFMPEG

Index: libbase/embedVideoDecoderFfmpeg.h
===================================================================
RCS file: libbase/embedVideoDecoderFfmpeg.h
diff -N libbase/embedVideoDecoderFfmpeg.h
--- libbase/embedVideoDecoderFfmpeg.h   17 Jul 2007 22:05:03 -0000      1.8
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,89 +0,0 @@
-// 
-//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-// 
-// This program 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 General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-// $Id: embedVideoDecoderFfmpeg.h,v 1.8 2007/07/17 22:05:03 nihilus Exp $
-
-#ifndef __EMBEDVIDEODECODERFFMPEG_H__
-#define __EMBEDVIDEODECODERFFMPEG_H__
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef USE_FFMPEG
-
-#include <vector>
-#include "embedVideoDecoder.h"
-extern "C" {
-#include <ffmpeg/avcodec.h>
-}
-#include "image.h"
-
-namespace gnash {
-
-class DSOEXPORT embedVideoDecoderFfmpeg: public embedVideoDecoder {
-public:
-       embedVideoDecoderFfmpeg();
-       
-       ~embedVideoDecoderFfmpeg();
-
-       void createDecoder(
-               int width,
-               int height,
-               int deblocking,
-               bool smoothing,
-               int format,
-               int outputFormat);
-
-       // gnash calls this when it wants you to decode the given videoframe
-       std::auto_ptr<image::image_base> decodeFrame(uint8_t* data, int size);
-
-       /// Convert the given srcFrame to RGB24 pixel format.
-       //
-       /// @param srcCtx The codec context with which srcFrame is associated.
-       /// @param srcFrame The source frame to convert. The data and linesize 
members
-       ///                 of srcFrame will be changed to match the conversion.
-       /// @return A pointer to the newly allocated and freshly converted 
video data.
-       ///         The caller owns the pointer! It must be freed with delete 
[] when
-       ///         the frame has been processed.
-       ///
-       static uint8_t* convertRGB24(AVCodecContext* srcCtx, AVFrame* srcFrame);
-
-private:
-
-       /// ffmpeg stuff
-       AVCodec *codec;
-       AVCodecContext *cc;
-
-       /// Info from the video tag header. Might be usefull...
-       uint32_t width;
-       uint32_t height;
-       int deblocking;
-       bool smoothing;
-       int format;
-       int outputFormat;
-
-       /// Last decoded frame
-       std::auto_ptr<image::image_base> decodedFrame;
-
-};
-
-} // end of gnash namespace
-
-#endif // USE_FFMPEG
-
-#endif //  __EMBEDVIDEODECODERFFMPEG_H__

Index: libbase/embedVideoDecoderGst.cpp
===================================================================
RCS file: libbase/embedVideoDecoderGst.cpp
diff -N libbase/embedVideoDecoderGst.cpp
--- libbase/embedVideoDecoderGst.cpp    10 Sep 2007 16:53:29 -0000      1.11
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,309 +0,0 @@
-// 
-//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-// 
-// This program 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 General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-// $Id: embedVideoDecoderGst.cpp,v 1.11 2007/09/10 16:53:29 strk Exp $
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef SOUND_GST
-
-#include "embedVideoDecoderGst.h"
-
-namespace gnash {
-
-embedVideoDecoderGst::embedVideoDecoderGst() :
-       pipeline(NULL),
-       input(NULL),
-       inputcaps(NULL),
-       videocaps(NULL),
-       output(NULL),
-       decoder(NULL),
-       colorspace(NULL),
-       decodedFrame(NULL),
-       stop(false)
-
-{
-}
-
-embedVideoDecoderGst::~embedVideoDecoderGst()
-{
-
-       if (pipeline) {
-               stop = true;
-               delete input_lock;
-               gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
-               gst_object_unref (GST_OBJECT (pipeline));
-       }
-}
-
-void
-embedVideoDecoderGst::createDecoder(int widthi, int heighti, int deblockingi, 
bool smoothingi, int formati, int outputFormati)
-{
-       // Save video attributes
-       width = widthi;
-       height = heighti;
-       deblocking = deblockingi;
-       smoothing = smoothingi;
-       format = formati;
-       outputFormat = outputFormati;
-
-       // For now only H263/SVQ3, VP6 and screenvideo1 is supported
-       if (format != CODEC_H263 && format != CODEC_VP6 && format != 
CODEC_SCREENVIDEO) return;
-
-       // init GStreamer
-       gst_init (NULL, NULL);
-
-       // setup the pipeline
-       pipeline = gst_pipeline_new (NULL);
-
-       // Setup the pipeline elements
-
-       // setup fake source
-       input = gst_element_factory_make ("fakesrc", NULL);
-       g_object_set (G_OBJECT (input), "sizetype", 3, /*"can-activate-pull", 
FALSE,*/ "signal-handoffs", TRUE, NULL);
-       // Setup the callback
-       g_signal_connect (input, "handoff", G_CALLBACK 
(embedVideoDecoderGst::callback_handoff), this);
-
-       // Setup the input capsfilter
-       inputcaps = gst_element_factory_make ("capsfilter", NULL);
-       GstCaps* caps = NULL;
-       if (format == CODEC_H263) {
-               caps = gst_caps_new_simple ("video/x-flash-video",
-                       "width", G_TYPE_INT, width,
-                       "height", G_TYPE_INT, height,
-                       "framerate", GST_TYPE_FRACTION, 25, 1,
-                       "flvversion", G_TYPE_INT, 1,
-                       NULL);
-       } else if (format == CODEC_VP6) {
-               caps = gst_caps_new_simple ("video/x-vp6-flash",
-                       "width", G_TYPE_INT, width,
-                       "height", G_TYPE_INT, height,
-                       "framerate", GST_TYPE_FRACTION, 25, 1,
-                       NULL);
-       } else if (format == CODEC_SCREENVIDEO) {
-               caps = gst_caps_new_simple ("video/x-flash-screen",
-                       "width", G_TYPE_INT, width,
-                       "height", G_TYPE_INT, height,
-                       "framerate", GST_TYPE_FRACTION, 25, 1,
-                       NULL);
-       }
-
-       if ( caps ) 
-       {
-               g_object_set (G_OBJECT (inputcaps), "caps", caps, NULL);
-               gst_caps_unref (caps);
-#ifndef NDEBUG
-               caps = NULL; // to check it is not null on next use ...
-#endif
-       }
-       else
-       {
-               log_error("Unknown codec format %d", format);
-       }
-
-       // Setup the capsfilter which demands either YUV or RGB videoframe 
format
-       videocaps = gst_element_factory_make ("capsfilter", NULL);
-       if (outputFormat == YUV) {
-               caps = gst_caps_new_simple ("video/x-raw-yuv", NULL);
-       } else if ( outputFormat == RGB ) {
-               caps = gst_caps_new_simple ("video/x-raw-rgb", NULL);
-       }
-       else
-       {
-               assert(outputFormat == NONE);
-               return; // nothing to do, right ? TODO: some cleanup ?
-       }
-
-       assert(caps); // ok, this is a silly assertion *now*, but as long as 
-                     // the code is implemented with such long function bodies
-                     // a day will come in which someone will change something
-                     // a few screefulls above and the assertion would make
-                     // sense (maybe boost compile-time assertions could help
-                     // in this reguard).
-
-       g_object_set (G_OBJECT (videocaps), "caps", caps, NULL);
-       gst_caps_unref (caps);
-
-       // setup the videosink with callback
-       output = gst_element_factory_make ("fakesink", NULL);
-       g_object_set (G_OBJECT (output), "signal-handoffs", TRUE, NULL);
-       g_signal_connect (output, "handoff", G_CALLBACK 
(embedVideoDecoderGst::callback_output), this);
-
-       // setup the video colorspaceconverter converter
-       colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
-
-       // Find the decoder
-       if (format == CODEC_H263) {
-               decoder = gst_element_factory_make ("ffdec_flv", NULL);
-       } else if (format == CODEC_VP6) {
-               decoder = gst_element_factory_make ("ffdec_vp6f", NULL);
-       } else if (format == CODEC_SCREENVIDEO) {
-               decoder = gst_element_factory_make ("ffdec_flashsv", NULL);
-       } else {
-               gnash::log_error("Unsupported embedded video format");
-               return;
-       }
-
-       if (!pipeline || !input || !inputcaps || !videocaps || !output || 
!colorspace) {
-               gnash::log_error("Creation of Gstreamer baisc elements failed, 
is your Gstreamer installation complete?");
-               return;
-       }
-
-       if (!decoder) {
-               gnash::log_error("Creation of decoder element failed, do you 
have gstreamer-0.10-ffmpeg installed?");
-               return;
-       }
-
-       // Put the elemets in the pipeline and link them
-       gst_bin_add_many (GST_BIN (pipeline), input, inputcaps, decoder, 
colorspace, videocaps, output, NULL);
-
-       // link the elements
-       gst_element_link_many(input, inputcaps, decoder, colorspace, videocaps, 
output, NULL);
-
-       // This make callback_handoff wait for data
-       input_lock = new boost::mutex::scoped_lock(input_mutex);
-
-       // This make decodeFrame wait for data
-       output_lock = new boost::mutex::scoped_lock(output_mutex);
-
-       // Determine required buffer size and allocate buffer
-       if (outputFormat == YUV) {
-               decodedFrame.reset(new image::yuv(width, height));
-       } else if (outputFormat == RGB) {
-               decodedFrame.reset(new image::rgb(width, height));
-       }
-
-       // Start "playing"
-       gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
-}
-
-
-// gnash calls this when it wants you to decode the given videoframe
-std::auto_ptr<image::image_base>
-embedVideoDecoderGst::decodeFrame(uint8_t* data, int size)
-{
-
-       std::auto_ptr<image::image_base> ret_image;
-
-       if (outputFormat == YUV) {
-               ret_image.reset(new image::yuv(width, height));
-       } else if (outputFormat == RGB) {
-               ret_image.reset(new image::rgb(width, height));
-       } else {
-               ret_image.reset(NULL);
-               return ret_image;
-       }
-
-       // If there is nothing to decode in the new frame
-       // we just return the lastest.
-       if (data == NULL || size == 0 || !decoder)
-       {
-               // If we never decoded any frame return a NULL
-               // auto pointer ..
-               if ( ! decodedFrame.get() )
-               {
-                       ret_image.reset(NULL);
-                       return ret_image;
-               }
-
-               // return decodedFrame->clone() ?
-               ret_image->update(*decodedFrame);
-               return ret_image;
-       }
-
-       frame = data;
-       frameSize = size;
-
-       delete input_lock;
-
-       output_lock = new boost::mutex::scoped_lock(output_mutex);
-
-       // If we never decoded any frame return a NULL
-       // auto pointer ..
-       if ( ! decodedFrame.get() )
-       {
-               ret_image.reset(NULL);
-               return ret_image;
-       }
-
-       // return decodedFrame->clone() ?
-       ret_image->update(*decodedFrame);
-       return ret_image;
-}
-
-// The callback function which refills the buffer with data
-void
-embedVideoDecoderGst::callback_handoff (GstElement * /*c*/, GstBuffer *buffer, 
GstPad* /*pad*/, gpointer user_data)
-{
-       embedVideoDecoderGst* decoder = 
static_cast<embedVideoDecoderGst*>(user_data);
-
-       if (decoder->stop) return;
-
-       decoder->input_lock = new 
boost::mutex::scoped_lock(decoder->input_mutex);
-
-       GST_BUFFER_SIZE(buffer) = decoder->frameSize;
-
-       GST_BUFFER_DATA(buffer) = decoder->frame;
-}
-
-// The callback function which passes the decoded video frame
-void
-embedVideoDecoderGst::callback_output (GstElement * /*c*/, GstBuffer *buffer, 
GstPad* /*pad*/, gpointer user_data)
-{
-       embedVideoDecoderGst* decoder = 
static_cast<embedVideoDecoderGst*>(user_data);
-
-       if (decoder->stop) return;
-
-       if (decoder->decodedFrame.get())
-       {
-
-               if (decoder->outputFormat == YUV) {
-                       assert(0);
-
-               /*      image::yuv* yuvframe = 
static_cast<image::yuv*>(decoder->decodedFrame);
-                       int copied = 0;
-                       uint8_t* ptr = GST_BUFFER_DATA(buffer);
-                       for (int i = 0; i < 3 ; i++)
-                       {
-                               int shift = (i == 0 ? 0 : 1);
-                               uint8_t* yuv_factor = m_Frame->data[i];
-                               int h = ns->videoheight >> shift;
-                               int w = ns->videowidth >> shift;
-                               for (int j = 0; j < h; j++)
-                               {
-                                       copied += w;
-                                       assert(copied <= yuvframe->size());
-                                       memcpy(ptr, yuv_factor, w);
-                                       yuv_factor += m_Frame->linesize[i];
-                                       ptr += w;
-                               }
-                       }
-                       video->m_size = copied;*/
-               } else {
-                       decoder->decodedFrame->update(GST_BUFFER_DATA(buffer));
-               }
-       }
-
-       delete decoder->output_lock;
-
-}
-
-} // end of gnash namespace
-
-#endif // SOUND_GST

Index: libbase/embedVideoDecoderGst.h
===================================================================
RCS file: libbase/embedVideoDecoderGst.h
diff -N libbase/embedVideoDecoderGst.h
--- libbase/embedVideoDecoderGst.h      1 Jul 2007 10:54:08 -0000       1.5
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,103 +0,0 @@
-// 
-//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-// 
-// This program 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 General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-// $Id: embedVideoDecoderGst.h,v 1.5 2007/07/01 10:54:08 bjacques Exp $
-
-#ifndef __EMBEDVIDEODECODERGST_H__
-#define __EMBEDVIDEODECODERGST_H__
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef SOUND_GST
-
-#include "embedVideoDecoder.h"
-#include <gst/gst.h>
-#include "image.h"
-#include <boost/thread/thread.hpp>
-#include <boost/bind.hpp> 
-#include <boost/thread/mutex.hpp>
-
-namespace gnash {
-
-class embedVideoDecoderGst : public embedVideoDecoder {
-public:
-       embedVideoDecoderGst();
-       
-       ~embedVideoDecoderGst();
-
-       void createDecoder(
-               int width,
-               int height,
-               int deblocking,
-               bool smoothing,
-               int format,
-               int outputFormat);
-
-       // gnash calls this when it wants you to decode the given videoframe
-       std::auto_ptr<image::image_base> decodeFrame(uint8_t* data, int size);
-
-       // Callback functions used to handle input and output
-       static void callback_handoff (GstElement * /*c*/, GstBuffer *buffer, 
GstPad* /*pad*/, gpointer user_data);
-       static void callback_output (GstElement* /*c*/, GstBuffer *buffer, 
GstPad* /*pad*/, gpointer user_data);
-
-private:
-
-       // gstreamer pipeline objects
-
-       /// the main bin containing the elements
-       GstElement *pipeline;
-
-       /// Gstreamer objects
-       GstElement *input;
-       GstElement *inputcaps;
-       GstElement *videocaps;
-       GstElement *output;
-       GstElement *decoder;
-       GstElement *colorspace;
-
-       /// mutexes and locks used to handle input and output.
-       boost::mutex input_mutex;
-       boost::mutex output_mutex;
-       boost::mutex::scoped_lock *input_lock;
-       boost::mutex::scoped_lock *output_lock;
-
-       /// Info from the video tag header. Might be usefull...
-       uint32_t width;
-       uint32_t height;
-       int deblocking;
-       bool smoothing;
-       int format;
-       int outputFormat;
-
-       /// Input data and size for current frame
-       uint8_t* frame;
-       int frameSize;
-       
-       /// Last decoded frame
-       std::auto_ptr<image::image_base> decodedFrame;
-
-       /// If we should stop this will be true
-       volatile bool stop;
-};
-
-} // end of gnash namespace
-
-#endif // SOUND_GST
-
-#endif //  __EMBEDVIDEODECODERGST_H__




reply via email to

[Prev in Thread] Current Thread [Next in Thread]