gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] gnash ChangeLog backend/sound_handler_sdl.cpp l...


From: Tomas Groth
Subject: [Gnash-commit] gnash ChangeLog backend/sound_handler_sdl.cpp l...
Date: Fri, 23 Mar 2007 00:30:10 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Tomas Groth <tgc>       07/03/23 00:30:10

Modified files:
        .              : ChangeLog 
        backend        : sound_handler_sdl.cpp 
        libbase        : LoadThread.cpp LoadThread.h Makefile.am 
        macros         : libXML.m4 
        server         : video_stream_instance.cpp 
        server/asobj   : NetConnection.cpp NetConnection.h NetStream.cpp 
                         NetStream.h NetStreamFfmpeg.cpp 
                         NetStreamFfmpeg.h NetStreamGst.cpp 
                         NetStreamGst.h SoundGst.cpp 
Added files:
        libbase        : FLVParser.cpp FLVParser.h 

Log message:
        * backend/sound_handler_sdl.cpp: Count videos sounds.
        * libbase/FLVParser.{h,cpp}: Added. Our own homegrown FLV parser.
        * libbase/LoadThread.{h,cpp}: Use auto_ptr<tu_file> instead of tu_file,
          and added the isPositionConfirmed() function.
        * libbase/Makefile.am: Added FLVParser.{h,cpp}.
        * macros/libXML.m4: A fix for when using --with-libxml-incl
        * server/video_stream_instance.cpp: Use Advance to investigate if a new
          video frame is ready, and decide if the bouds should be invalidated.
        * server/asobj/NetConnection.{h,cpp}: Pass a auto_ptr<tu_file> to 
          LoadThread. Always check if the loader exists before using it.
          Added connectParser to make it possible for the parser to access the 
file.
        * server/asobj/NetStream.{h,cpp}: Implemented setBufferTime and 
onStatus.
        * server/asobj/NetStreamFfmpeg.{h,cpp}: Use the new FLVParser when we
          play a FLV. Added more comments. Implemented setBufferTime, and made
          things ready for onStatus.
        * server/asobj/NetStreamGst.{cpp,h}: Added stubs and small updates to 
          keep up with NetStreamFfmpeg. Some work on supporting the -r1 switch.
        * server/asobj/SoundGst.cpp: Removed a printf.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.2677&r2=1.2678
http://cvs.savannah.gnu.org/viewcvs/gnash/backend/sound_handler_sdl.cpp?cvsroot=gnash&r1=1.48&r2=1.49
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/LoadThread.cpp?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/LoadThread.h?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/Makefile.am?cvsroot=gnash&r1=1.60&r2=1.61
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/FLVParser.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/FLVParser.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/macros/libXML.m4?cvsroot=gnash&r1=1.28&r2=1.29
http://cvs.savannah.gnu.org/viewcvs/gnash/server/video_stream_instance.cpp?cvsroot=gnash&r1=1.16&r2=1.17
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetConnection.cpp?cvsroot=gnash&r1=1.31&r2=1.32
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetConnection.h?cvsroot=gnash&r1=1.21&r2=1.22
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStream.cpp?cvsroot=gnash&r1=1.32&r2=1.33
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStream.h?cvsroot=gnash&r1=1.23&r2=1.24
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamFfmpeg.cpp?cvsroot=gnash&r1=1.22&r2=1.23
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamFfmpeg.h?cvsroot=gnash&r1=1.14&r2=1.15
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamGst.cpp?cvsroot=gnash&r1=1.14&r2=1.15
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamGst.h?cvsroot=gnash&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/SoundGst.cpp?cvsroot=gnash&r1=1.3&r2=1.4

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.2677
retrieving revision 1.2678
diff -u -b -r1.2677 -r1.2678
--- ChangeLog   22 Mar 2007 22:37:45 -0000      1.2677
+++ ChangeLog   23 Mar 2007 00:30:10 -0000      1.2678
@@ -1,3 +1,24 @@
+2007-03-23 Tomas Groth Christensen <address@hidden>
+
+       * backend/sound_handler_sdl.cpp: Count videos sounds.
+       * libbase/FLVParser.{h,cpp}: Added. Our own homegrown FLV parser.
+       * libbase/LoadThread.{h,cpp}: Use auto_ptr<tu_file> instead of tu_file,
+         and added the isPositionConfirmed() function.
+       * libbase/Makefile.am: Added FLVParser.{h,cpp}.
+       * macros/libXML.m4: A fix for when using --with-libxml-incl
+       * server/video_stream_instance.cpp: Use Advance to investigate if a new
+         video frame is ready, and decide if the bouds should be invalidated.
+       * server/asobj/NetConnection.{h,cpp}: Pass a auto_ptr<tu_file> to 
+         LoadThread. Always check if the loader exists before using it.
+         Added connectParser to make it possible for the parser to access the 
file.
+       * server/asobj/NetStream.{h,cpp}: Implemented setBufferTime and 
onStatus.
+       * server/asobj/NetStreamFfmpeg.{h,cpp}: Use the new FLVParser when we
+         play a FLV. Added more comments. Implemented setBufferTime, and made
+         things ready for onStatus.
+       * server/asobj/NetStreamGst.{cpp,h}: Added stubs and small updates to 
+         keep up with NetStreamFfmpeg. Some work on supporting the -r1 switch.
+       * server/asobj/SoundGst.cpp: Removed a printf.
+
 2007-03-22 Sandro Santilli <address@hidden>
 
        * testsuite/swfdec/PASSING: two more successes.

Index: backend/sound_handler_sdl.cpp
===================================================================
RCS file: /sources/gnash/gnash/backend/sound_handler_sdl.cpp,v
retrieving revision 1.48
retrieving revision 1.49
diff -u -b -r1.48 -r1.49
--- backend/sound_handler_sdl.cpp       21 Feb 2007 19:18:45 -0000      1.48
+++ backend/sound_handler_sdl.cpp       23 Mar 2007 00:30:10 -0000      1.49
@@ -18,7 +18,7 @@
 // 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.48 2007/02/21 19:18:45 tgc Exp $
+// $Id: sound_handler_sdl.cpp,v 1.49 2007/03/23 00:30:10 tgc Exp $
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -490,6 +490,8 @@
        }
        m_aux_streamer[owner] = ptr;
 
+       ++soundsPlaying;
+
        if (!soundOpened) {
                if (SDL_OpenAudio(&audioSpec, NULL) < 0 ) {
                        gnash::log_error("Unable to START SOUND: %s.", 
SDL_GetError());
@@ -503,6 +505,7 @@
 
 void   SDL_sound_handler::detach_aux_streamer(void* owner)
 {
+       --soundsPlaying;
        m_aux_streamer.erase(owner);
 }
 
@@ -760,7 +763,10 @@
                        SDL_sound_handler::aux_streamer_ptr aux_streamer = 
it->second; //handler->m_aux_streamer[i]->ptr;
                        void* owner = it->first;
                        bool ret = (aux_streamer)(owner, buf, buffer_length);
-                       if (!ret) handler->m_aux_streamer.erase(it);
+                       if (!ret) {
+                               handler->m_aux_streamer.erase(it);
+                               handler->soundsPlaying--;
+                       }
                        SDL_MixAudio(stream, buf, buffer_length, 
SDL_MIX_MAXVOLUME);
 
                }

Index: libbase/LoadThread.cpp
===================================================================
RCS file: /sources/gnash/gnash/libbase/LoadThread.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- libbase/LoadThread.cpp      9 Mar 2007 14:38:29 -0000       1.1
+++ libbase/LoadThread.cpp      23 Mar 2007 00:30:10 -0000      1.2
@@ -16,11 +16,11 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //
 
-// $Id: LoadThread.cpp,v 1.1 2007/03/09 14:38:29 tgc Exp $
+// $Id: LoadThread.cpp,v 1.2 2007/03/23 00:30:10 tgc Exp $
 
 #include "LoadThread.h"
 
-LoadThread::LoadThread(tu_file* stream)
+LoadThread::LoadThread(std::auto_ptr<tu_file> stream)
        :
        _stream(stream),
        _bytesLoaded(0),
@@ -146,3 +146,9 @@
        _loadPosition = pos;
        _actualPosition = pos;
 }
+
+bool LoadThread::isPositionConfirmed(size_t pos)
+{
+       boost::mutex::scoped_lock lock(_mutex);
+       return (static_cast<uint32_t>(pos) <= _loadPosition);
+}

Index: libbase/LoadThread.h
===================================================================
RCS file: /sources/gnash/gnash/libbase/LoadThread.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- libbase/LoadThread.h        9 Mar 2007 23:15:57 -0000       1.2
+++ libbase/LoadThread.h        23 Mar 2007 00:30:10 -0000      1.3
@@ -16,7 +16,10 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //
 
-// $Id: LoadThread.h,v 1.2 2007/03/09 23:15:57 tgc Exp $
+#ifndef __LOADTHREAD_H__
+#define __LOADTHREAD_H__
+
+// $Id: LoadThread.h,v 1.3 2007/03/23 00:30:10 tgc Exp $
 #include <boost/thread/thread.hpp>
 #include <boost/thread/mutex.hpp>
 #include <boost/bind.hpp>
@@ -27,9 +30,12 @@
 /// \brief
 /// The LoadThread class can be used to download from a file
 /// or stream using a thread, without having to block.
-/// When the object is created it starts a thread which downloads
-/// from the tu_file given as an argument to the constructor, and
-/// keeps downloading until the download is complete. It is possible
+///
+/// When the object is created it starts a thread which seeks forward
+/// in the tu_file given as an argument to the constructor, which will
+/// make cause the tu_file backend to download the amount of data needed
+/// to complete the seek. This is repeated until the complete file is
+/// downloaded. It is possible
 /// for the object owner to query for data, position, loaded data,
 /// total data while downloading, without blocking. Though if there has 
 /// not been downloaded enough data to accomendate a request (seek/read)
@@ -47,7 +53,9 @@
 public:
        /// Creating the object starts the threaded loading 
        /// of the stream/file passed as an argument.
-       LoadThread(tu_file* stream);
+       LoadThread(std::auto_ptr<tu_file> stream);
+
+       /// Stops the download if still running
        ~LoadThread();
 
        /// Put read pointer at given position
@@ -67,7 +75,7 @@
        /// Report global position within the file
        size_t tell();
 
-       ///     Returns the number of bytes cached
+       ///     Returns the number of bytes known to be accessable
        long getBytesLoaded();
 
        ///     Returns the total size of the file
@@ -76,6 +84,9 @@
        /// Check if the load is completed
        bool completed();
 
+       /// Check if given position is confirmed to be accessable
+       bool isPositionConfirmed(size_t pos);
+
 private:
 
        /// The thread function used to download from the stream
@@ -100,3 +111,4 @@
        long _actualPosition;
 };
 
+#endif // __LOADTHREAD_H__

Index: libbase/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/libbase/Makefile.am,v
retrieving revision 1.60
retrieving revision 1.61
diff -u -b -r1.60 -r1.61
--- libbase/Makefile.am 9 Mar 2007 14:38:29 -0000       1.60
+++ libbase/Makefile.am 23 Mar 2007 00:30:10 -0000      1.61
@@ -21,11 +21,14 @@
 # this is where Gnash plugins get installed
 pluginsdir = $(prefix)/lib/gnash/plugins
 
-lib_LTLIBRARIES = libgnashbase.la
+lib_LTLIBRARIES = \
+       libgnashbase.la
+       libgnashamf.la
 
 libgnashbase_la_CPPFLAGS = -DPLUGINSDIR=\"$(pluginsdir)\" \
        -I.. -I$(srcdir) \
        -I$(top_srcdir) \
+       -I$(top_srcdir)/libamf  \
        -I$(top_srcdir)/server  \
        -I$(top_srcdir)/server/swf      \
        $(PTHREAD_CFLAGS) \
@@ -96,8 +99,8 @@
        zlib_adapter.cpp \
        Thread.cpp \
        URL.cpp \
-       LoadThread.cpp
-
+       LoadThread.cpp \
+       FLVParser.cpp
 
 noinst_HEADERS = \
        container.h \
@@ -136,7 +139,8 @@
        zlib_adapter.h \
        Thread.h \
        URL.h \
-       LoadThread.h
+       LoadThread.h \
+       FLVParser.h
 
 if USE_SOUND_GST
 libgnashbase_la_SOURCES += gstgnashsrc.c embedVideoDecoderGst.cpp

Index: macros/libXML.m4
===================================================================
RCS file: /sources/gnash/gnash/macros/libXML.m4,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -b -r1.28 -r1.29
--- macros/libXML.m4    21 Jan 2007 22:41:03 -0000      1.28
+++ macros/libXML.m4    23 Mar 2007 00:30:10 -0000      1.29
@@ -14,7 +14,7 @@
 dnl  along with this program; if not, write to the Free Software
 dnl  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-dnl $Id: libXML.m4,v 1.28 2007/01/21 22:41:03 rsavoye Exp $
+dnl $Id: libXML.m4,v 1.29 2007/03/23 00:30:10 tgc Exp $
 
 AC_DEFUN([GNASH_PATH_LIBXML], [
   has_xml=no
@@ -22,10 +22,10 @@
   AC_ARG_WITH(libxml-incl, AC_HELP_STRING([--with-libxml-incl], [directory 
where libxml2 header is]), with_libxml_incl=${withval})
   AC_CACHE_VAL(ac_cv_path_libxml_incl, [
     if test x"${with_libxml_incl}" != x ; then
-      if test -f ${with_libxml_incl}/xmlmemory.h ; then
+      if test -f ${with_libxml_incl}/libxml/xmlmemory.h ; then
         ac_cv_path_libxml_incl=-I`(cd ${with_libxml_incl}; pwd)`
       else
-        AC_MSG_ERROR([${with_libxml_incl} directory doesn't contain 
xmlmemory.h])
+        AC_MSG_ERROR([${with_libxml_incl} directory doesn't contain 
libxml/xmlmemory.h])
       fi
     fi
   ])

Index: server/video_stream_instance.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/video_stream_instance.cpp,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -b -r1.16 -r1.17
--- server/video_stream_instance.cpp    20 Mar 2007 15:01:20 -0000      1.16
+++ server/video_stream_instance.cpp    23 Mar 2007 00:30:10 -0000      1.17
@@ -15,7 +15,7 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 // 
-// $Id: video_stream_instance.cpp,v 1.16 2007/03/20 15:01:20 strk Exp $
+// $Id: video_stream_instance.cpp,v 1.17 2007/03/23 00:30:10 tgc Exp $
 
 #include "sprite_instance.h"
 #include "video_stream_instance.h"
@@ -26,6 +26,7 @@
 #include "render.h"
 #include "Range2d.h"
 #include "builtin_function.h" // for getter/setter properties
+#include "VM.h"
 
 namespace gnash {
 
@@ -83,7 +84,6 @@
        matrix m = get_world_matrix();
        rect bounds(0.0f, 0.0f, PIXELS_TO_TWIPS(m_def->m_width), 
PIXELS_TO_TWIPS(m_def->m_height));
 
-
        // If this is a video from a NetStream object, retrieve a video frame 
from there.
        if (_ns)
        {
@@ -119,6 +119,10 @@
 void
 video_stream_instance::advance(float /*delta_time*/)
 {
+       if (_ns) {
+               _ns->advance();
+               if (_ns->newFrameReady()) set_invalidated();
+       }
 }
 
 void

Index: server/asobj/NetConnection.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetConnection.cpp,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -b -r1.31 -r1.32
--- server/asobj/NetConnection.cpp      20 Mar 2007 15:01:20 -0000      1.31
+++ server/asobj/NetConnection.cpp      23 Mar 2007 00:30:10 -0000      1.32
@@ -14,7 +14,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: NetConnection.cpp,v 1.31 2007/03/20 15:01:20 strk Exp $ */
+/* $Id: NetConnection.cpp,v 1.32 2007/03/23 00:30:10 tgc Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -61,7 +61,7 @@
 }
 
 NetConnection::~NetConnection() {
-
+       if (_loader) delete _loader;
 }
 
 /// Open a connection to stream FLV files.
@@ -95,7 +95,7 @@
                return false;
        }
 
-       _loader = new 
LoadThread(StreamProvider::getDefaultInstance().getStream(uri));
+       _loader = new 
LoadThread(std::auto_ptr<tu_file>(StreamProvider::getDefaultInstance().getStream(uri)));
 
        return true;
 }
@@ -113,7 +113,7 @@
 bool
 NetConnection::eof()
 {
-
+       if (!_loader) return true;
        return _loader->eof();
 }
 
@@ -121,6 +121,7 @@
 size_t
 NetConnection::read(void *dst, size_t bytes)
 {
+       if (!_loader) return 0;
        return _loader->read(dst, bytes);
 }
 
@@ -128,6 +129,7 @@
 bool
 NetConnection::seek(size_t pos)
 {
+       if (!_loader) return false;
        return _loader->seek(pos);
 
 }
@@ -136,6 +138,7 @@
 size_t
 NetConnection::tell()
 {
+       if (!_loader) return 0;
        return _loader->tell();
 
 }
@@ -144,6 +147,7 @@
 long
 NetConnection::getBytesLoaded()
 {
+       if (!_loader) return 0;
        return _loader->getBytesLoaded();
 }
 
@@ -152,9 +156,18 @@
 long
 NetConnection::getBytesTotal()
 {
+       if (!_loader) return 0;
        return _loader->getBytesLoaded();
 }
 
+bool
+NetConnection::connectParser(FLVParser* parser)
+{
+       if (_loader == NULL) return false;
+
+       parser->setLoadThread(_loader);
+       return true;
+}
 
 /// \brief callback to instantiate a new NetConnection object.
 /// \param fn the parameters from the Flash movie

Index: server/asobj/NetConnection.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetConnection.h,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -b -r1.21 -r1.22
--- server/asobj/NetConnection.h        20 Mar 2007 15:01:20 -0000      1.21
+++ server/asobj/NetConnection.h        23 Mar 2007 00:30:10 -0000      1.22
@@ -14,7 +14,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: NetConnection.h,v 1.21 2007/03/20 15:01:20 strk Exp $ */
+/* $Id: NetConnection.h,v 1.22 2007/03/23 00:30:10 tgc Exp $ */
 
 #ifndef __NETCONNECTION_H__
 #define __NETCONNECTION_H__
@@ -25,6 +25,7 @@
 
 #include "tu_file.h"
 #include "LoadThread.h"
+#include "FLVParser.h"
 
 #include <stdexcept>
 #include <cstdio>
@@ -79,6 +80,8 @@
        ///     Returns the total size of the file
        long getBytesTotal();
 
+       /// Connects FLV parser with the LoadThread
+       bool connectParser(FLVParser* parser);
 
 private:
 
@@ -86,7 +89,7 @@
        std::string _url;
 
        /// the as_object which owns the connection
-       as_object* _owner;
+       boost::intrusive_ptr<as_object> _owner;
 
        /// The file/stream loader thread and interface
        LoadThread* _loader;

Index: server/asobj/NetStream.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStream.cpp,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -b -r1.32 -r1.33
--- server/asobj/NetStream.cpp  20 Mar 2007 15:01:20 -0000      1.32
+++ server/asobj/NetStream.cpp  23 Mar 2007 00:30:10 -0000      1.33
@@ -15,7 +15,7 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //
 
-/* $Id: NetStream.cpp,v 1.32 2007/03/20 15:01:20 strk Exp $ */
+/* $Id: NetStream.cpp,v 1.33 2007/03/23 00:30:10 tgc Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -58,7 +58,7 @@
 netstream_new(const fn_call& fn)
 {
 
-       NetStream *netstream_obj;
+       boost::intrusive_ptr<NetStream> netstream_obj;
        
 #ifdef SOUND_GST
        netstream_obj = new NetStreamGst();
@@ -86,7 +86,7 @@
                        );
                }
        }
-       return as_value(netstream_obj);
+       return as_value(netstream_obj.get());
 
 }
 
@@ -144,8 +144,14 @@
 }
 static as_value netstream_setbuffertime(const fn_call& fn) {
        boost::intrusive_ptr<NetStream> ns = ensureType<NetStream>(fn.this_ptr);
-       UNUSED(ns);
-    log_msg("%s:unimplemented \n", __FUNCTION__);
+
+       double time = 0;
+       if (fn.nargs > 0)
+       {
+               time = fn.arg(0).to_number();
+       }
+       ns->setBufferTime(time);
+
        return as_value();
 }
 
@@ -209,6 +215,27 @@
        return as_value();
 }
 
+// Both a getter and a setter for onStatus
+static as_value
+netstream_onstatus(const fn_call& fn)
+{
+
+       boost::intrusive_ptr<NetStream> ns = ensureType<NetStream>(fn.this_ptr);
+
+       if ( fn.nargs == 0 ) // getter
+       {
+               as_function* h = ns->getStatusHandler();
+               if ( h ) return as_value(h);
+               else return as_value();
+       }
+       else // setter
+       {
+               as_function* h = fn.arg(0).to_as_function();
+               if ( h ) ns->setStatusHandler(h);
+       }
+       return as_value();
+}
+
 void
 attachNetStreamInterface(as_object& o)
 {
@@ -233,6 +260,8 @@
     gettersetter = new builtin_function(&netstream_bytestotal, NULL);
     o.init_property("bytesTotal", *gettersetter, *gettersetter);
 
+    gettersetter = new builtin_function(&netstream_onstatus, NULL);
+    o.init_property("onStatus", *gettersetter, *gettersetter);
 }
 
 static as_object*

Index: server/asobj/NetStream.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStream.h,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -b -r1.23 -r1.24
--- server/asobj/NetStream.h    20 Mar 2007 15:01:20 -0000      1.23
+++ server/asobj/NetStream.h    23 Mar 2007 00:30:10 -0000      1.24
@@ -18,7 +18,7 @@
 //
 //
 
-/*  $Id: NetStream.h,v 1.23 2007/03/20 15:01:20 strk Exp $ */
+/*  $Id: NetStream.h,v 1.24 2007/03/23 00:30:10 tgc Exp $ */
 
 #ifndef __NETSTREAM_H__
 #define __NETSTREAM_H__
@@ -63,7 +63,7 @@
 
        virtual void seek(double /*pos*/){}
 
-       virtual void setBufferTime(unsigned int /*pos*/){}
+       virtual void setBufferTime(double /*time*/){}
 
        virtual void set_status(const char* /*code*/){}
 
@@ -85,6 +85,13 @@
                return false;
        }
 
+       virtual void advance(){}
+
+       virtual bool newFrameReady() { return false; }
+
+       virtual as_function* getStatusHandler() { return NULL; }
+
+       virtual void setStatusHandler(as_function*) { }
 };
 
 

Index: server/asobj/NetStreamFfmpeg.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamFfmpeg.cpp,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -b -r1.22 -r1.23
--- server/asobj/NetStreamFfmpeg.cpp    20 Mar 2007 15:57:56 -0000      1.22
+++ server/asobj/NetStreamFfmpeg.cpp    23 Mar 2007 00:30:10 -0000      1.23
@@ -14,7 +14,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: NetStreamFfmpeg.cpp,v 1.22 2007/03/20 15:57:56 bjacques Exp $ */
+/* $Id: NetStreamFfmpeg.cpp,v 1.23 2007/03/23 00:30:10 tgc Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -38,6 +38,10 @@
        #include "unistd.h" // for usleep()
 #endif
 
+// Used to free data in the AVPackets we create our self
+static void avpacket_destruct(AVPacket* av) {
+       delete av->data;
+}
 
 
 namespace gnash {
@@ -61,20 +65,26 @@
        m_video_clock(0),
        m_pause(false),
        m_unqueued_data(NULL),
-       inputPos(0)
+       inputPos(0),
+       m_parser(NULL),
+       m_isFLV(false),
+       m_newFrameReady(false),
+       m_bufferTime(100),
+       m_statusChanged(false)
 {
 }
 
 NetStreamFfmpeg::~NetStreamFfmpeg()
 {
        close();
+       if (m_parser) delete m_parser;
 }
 
-// called from avstreamer thread
-void NetStreamFfmpeg::set_status(const char* /*code*/)
+// called from avstreamer thread, and a few other places... (thread safe?)
+void NetStreamFfmpeg::set_status(const char* status)
 {
-       //m_netstream_object->init_member("onStatus_Code", code);
-       //push_video_event(this);
+       m_status = status;
+       m_statusChanged = true;
 }
 
 void NetStreamFfmpeg::pause(int mode)
@@ -221,12 +231,23 @@
        }
 
        m_go = true;
+       m_pause = true;
 
+       if (!m_parser && !m_FormatCtx) {
        // To avoid blocking while connecting, we use a thread.
        startThread = new 
boost::thread(boost::bind(NetStreamFfmpeg::startPlayback, this));
 
-       // This starts the decoding thread
+               // This lock prevents the decoding from starting before the 
Connection
+               // and decoder is ready.
        lock = new boost::mutex::scoped_lock(start_mutex);
+       } else {
+               // We need to restart the audio
+               sound_handler* s = get_sound_handler();
+               if (s) s->attach_aux_streamer(audio_streamer, (void*) this);
+
+       }
+
+       // This starts the decoding thread
        m_thread = new boost::thread(boost::bind(NetStreamFfmpeg::av_streamer, 
this)); 
 
        return 0;
@@ -243,11 +264,92 @@
        assert(ns);
        if ( !nc->openConnection(ns->url.c_str(), ns) ) {
                log_warning("Gnash could not open movie url: %s", 
ns->url.c_str());
+               ns->set_status("NetStream.Buffer.StreamNotFound");
                return;
        }
 
        ns->inputPos = 0;
 
+       // Check if the file is a FLV, in which case we use our own parser
+       uint8_t head[3];
+       nc->read(head, 3);
+       nc->seek(0);
+       if (head[0] == 'F' && head[1] == 'L' && head[2] == 'V') {
+               
+               ns->m_isFLV = true;
+
+               ns->m_parser = new FLVParser();
+               nc->connectParser(ns->m_parser);
+
+               // Init the avdecoder-decoder
+               avcodec_init();
+               avcodec_register_all();
+
+               // Get video info from the parser
+               FLVVideoInfo* videoInfo = ns->m_parser->getVideoInfo();
+               if (videoInfo != NULL) {
+                       // Find the decoder and init the parser
+                       AVCodec* vcodec;
+                       if (videoInfo->codec == VIDEO_CODEC_H263) {
+                               vcodec = avcodec_find_decoder(CODEC_ID_FLV1);
+#ifdef FFMPEG_VP6
+                       } else if (videoInfo->codec == VIDEO_CODEC_VP6) {
+                               vcodec = avcodec_find_decoder(CODEC_ID_VP6F);
+#endif
+                       } else if (videoInfo->codec == VIDEO_CODEC_SCREENVIDEO) 
{
+                               vcodec = avcodec_find_decoder(CODEC_ID_FLASHSV);
+                       } else {
+                               log_error("Unsupported video codec");
+                               return;
+                       }
+
+                       if (vcodec == NULL) {
+                               return;
+                       }
+
+                       ns->m_VCodecCtx = avcodec_alloc_context();
+                       avcodec_open(ns->m_VCodecCtx, vcodec);
+               }
+
+               // Get audio info from the parser
+               FLVAudioInfo* audioInfo = ns->m_parser->getAudioInfo();
+               if (audioInfo != NULL) {
+
+                       AVCodec* acodec;
+                       if (audioInfo->codec == AUDIO_CODEC_RAW) {
+                               acodec = 
avcodec_find_decoder(CODEC_ID_PCM_U16LE);
+                       } else if (audioInfo->codec == AUDIO_CODEC_ADPCM) {
+                               acodec = 
avcodec_find_decoder(CODEC_ID_ADPCM_SWF);
+                       } else if (audioInfo->codec == AUDIO_CODEC_MP3) {
+                               acodec = avcodec_find_decoder(CODEC_ID_MP3);
+                       } else {
+                               log_error("Unsupported audio codec");
+                               return;
+                       }
+
+                       ns->m_ACodecCtx = avcodec_alloc_context();
+                       avcodec_open(ns->m_ACodecCtx, acodec);
+               }
+
+               // We just define the indexes here, they're not really used when
+               // the file format is FLV
+               ns->m_video_index = 0;
+               ns->m_audio_index = 1;
+
+               sound_handler* s = get_sound_handler();
+               if (s) s->attach_aux_streamer(audio_streamer, (void*) ns);
+
+//             ns->m_pause = false;
+
+               // Allocate a frame to store the decoded frame in
+               ns->m_Frame = avcodec_alloc_frame();
+
+               // By deleting this lock we allow the av_streamer-thread to 
start its work
+               delete ns->lock;
+               return;
+       }
+
+
        // 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
@@ -269,6 +371,7 @@
        }
 
        AVInputFormat* inputFmt = av_probe_input_format(pd, 1);
+       delete[] pd->buf;
 
        // After the format probe, reset to the beginning of the file.
        nc->seek(0);
@@ -324,9 +427,6 @@
                                        ns->m_video_stream = 
ns->m_FormatCtx->streams[i];
                                }
                                break;
-                       /*case CODEC_TYPE_DATA:
-                       case CODEC_TYPE_SUBTITLE:
-                       case CODEC_TYPE_UNKNOWN:*/
                        default:
                                break;
                }
@@ -454,10 +554,11 @@
                                ns->m_qvideo.pop();
                                delete video;
                                delay = 0;
+                               ns->m_newFrameReady = true;
                        }
                        else
                        {
-                               delay = int((video_clock - clock)*10000000); 
+                               delay = int((video_clock - clock)*1000000); 
                        }
 
                        // Don't hog the CPU.
@@ -470,6 +571,7 @@
                        }
                }
        }
+       ns->m_go = false;
        ns->set_status("NetStream.Play.Stop");
 
 }
@@ -481,6 +583,8 @@
 
        boost::mutex::scoped_lock  lock(ns->decoding_mutex);
 
+       if (!ns->m_go) return false;
+
        while (len > 0 && ns->m_qaudio.size() > 0)
        {
                raw_videodata_t* samples = ns->m_qaudio.front();
@@ -525,21 +629,38 @@
                {
                        log_warning("read_frame: not audio & video stream\n");
                }
-
                return true;
        }
 
        AVPacket packet;
-       int rc = av_read_frame(m_FormatCtx, &packet);
+       int rc;
+       if (m_isFLV) {
+               FLVFrame* frame = m_parser->nextMediaFrame();
+               if (frame == NULL) {
+                       set_status("NetStream.Buffer.Empty");
+                       return false;
+               }
+               
+               if (frame->tag == 9) {
+                       packet.stream_index = 0;
+               } else {
+                       packet.stream_index = 1;
+               }
+               packet.destruct = avpacket_destruct;
+               packet.size = frame->dataSize;
+               packet.data = frame->data;
+               packet.pts = static_cast<int64_t>(frame->timestamp);
+               rc = 0;
+       } else {
+               rc = av_read_frame(m_FormatCtx, &packet);
+       }
+
        if (rc >= 0)
        {
-               if (packet.stream_index == m_audio_index)
-               {
-                       sound_handler* s = get_sound_handler();
-                       if (s)
+               if (packet.stream_index == m_audio_index && get_sound_handler())
                        {
                                int frame_size;
-                               uint8_t* ptr = (uint8_t*) 
malloc((AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2);
+                       uint8_t* ptr = new 
uint8_t[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
 #ifdef FFMPEG_AUDIO2
                                frame_size = (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) 
/ 2;
                                if (avcodec_decode_audio2(m_ACodecCtx, 
(int16_t*) ptr, &frame_size, packet.data, packet.size) >= 0)
@@ -568,17 +689,25 @@
 
                                        m_unqueued_data = m_qaudio.push(raw) ? 
NULL : raw;
                                }
-                               free(ptr);
-                       }
+                       delete[] ptr;
                }
                else
                if (packet.stream_index == m_video_index)
                {
+
                        int got = 0;
                        avcodec_decode_video(m_VCodecCtx, m_Frame, &got, 
packet.data, packet.size);
                        if (got) {
                                uint8_t *buffer = NULL;
+
                                int videoFrameFormat = 
gnash::render::videoFrameFormat();
+                               if (m_imageframe == NULL) {
+                                       if (videoFrameFormat == render::YUV) {
+                                               m_imageframe = new 
image::yuv(m_VCodecCtx->width, m_VCodecCtx->height);
+                                       } else if (videoFrameFormat == 
render::RGB) {
+                                               m_imageframe = new 
image::rgb(m_VCodecCtx->width, m_VCodecCtx->height);
+                                       }
+                               }
 
                                if (videoFrameFormat == render::NONE) { // 
NullGui?
                                        av_free_packet(&packet);
@@ -612,7 +741,8 @@
                                // set presentation timestamp
                                if (packet.dts != static_cast<signed 
long>(AV_NOPTS_VALUE))
                                {
-                                       video->m_pts = 
as_double(m_video_stream->time_base) * packet.dts;
+                                       if (!m_isFLV)   video->m_pts = 
as_double(m_video_stream->time_base) * packet.dts;
+                                       else video->m_pts = 
as_double(m_VCodecCtx->time_base) * packet.dts;
                                }
 
                                if (video->m_pts != 0)
@@ -626,7 +756,9 @@
                                }
 
                                // update video clock for next frame
-                               double frame_delay = 
as_double(m_video_stream->codec->time_base);
+                               double frame_delay;
+                               if (!m_isFLV) frame_delay = 
as_double(m_video_stream->codec->time_base);
+                               else frame_delay = 
static_cast<double>(m_parser->videoFrameDelay())/1000.0;
 
                                // for MPEG2, the frame can be repeated, so we 
update the clock accordingly
                                frame_delay += m_Frame->repeat_pict * 
(frame_delay * 0.5);
@@ -688,22 +820,34 @@
 {
        boost::mutex::scoped_lock  lock(decoding_mutex);
 
+       long newpos;
+       double timebase;
+
        // Seek to new position
-       double timebase = 
(double)m_FormatCtx->streams[m_video_index]->time_base.num / 
(double)m_FormatCtx->streams[m_video_index]->time_base.den;
+       if (m_isFLV) {
+               newpos = m_parser->seek(static_cast<uint32_t>(pos*1000));
+       } else {
 
-       long newpos = (long)(pos / timebase);
+               timebase = 
static_cast<double>(m_FormatCtx->streams[m_video_index]->time_base.num) / 
static_cast<double>(m_FormatCtx->streams[m_video_index]->time_base.den);
+               newpos = static_cast<long>(pos / timebase);
 
        if (av_seek_frame(m_FormatCtx, m_video_index, newpos, 0) < 0) {
                log_warning("seeking failed");
                return;
        }
+       }
 
        // This is kindof hackish and ugly :-(
        if (newpos == 0) {
                m_video_clock = 0;
                m_start_clock = 
tu_timer::ticks_to_seconds(tu_timer::get_ticks());
-       } else {
 
+       } else if (m_isFLV) {
+               double newtime = static_cast<double>(newpos) / 1000.0;
+               m_start_clock +=  m_video_clock - newtime;
+
+               m_video_clock = newtime;
+       } else {
                AVPacket Packet;
                av_init_packet(&Packet);
                double newtime = 0;
@@ -736,12 +880,34 @@
                delete m_qaudio.front();
                m_qaudio.pop();
        }
+
 }
 
 void
-NetStreamFfmpeg::setBufferTime()
+NetStreamFfmpeg::setBufferTime(double time)
 {
-    log_msg("%s:unimplemented \n", __FUNCTION__);
+       // The argument is in seconds, but we store in milliseconds
+    m_bufferTime = static_cast<uint32_t>(time*1000);
+}
+
+void
+NetStreamFfmpeg::advance()
+{
+       if (m_go && m_pause && !m_imageframe && m_parser && 
m_parser->isTimeLoaded(m_bufferTime)) {
+               set_status("NetStream.Buffer.Full");
+               m_pause = false;
+       }
+
+       if (m_statusChanged) {
+/*             fn_call dummy(NULL, NULL, 0, 0);
+               as_value info_asv(infoobject_new(dummy));
+               boost::intrusive_ptr<as_object> info = info_asv.to_object();
+
+               fn_call fn(this, v, 0, 0);
+
+               m_statusHandler.get()->call(fn);*/
+
+       }
 }
 
 int64_t
@@ -751,6 +917,8 @@
        if (m_FormatCtx && m_FormatCtx->nb_streams > 0) {
                double time = (double)m_FormatCtx->streams[0]->time_base.num / 
(double)m_FormatCtx->streams[0]->time_base.den * 
(double)m_FormatCtx->streams[0]->cur_dts;
        return static_cast<int64_t>(time);
+       } else if (m_isFLV) {
+               return static_cast<int64_t>(m_video_clock / 1000);
        } else {
                return 0;
        }
@@ -759,14 +927,41 @@
 long
 NetStreamFfmpeg::bytesLoaded()
 {
+       if (_netCon == NULL) return 0;
        return _netCon->getBytesLoaded();
 }
 
 long
 NetStreamFfmpeg::bytesTotal()
 {
+       if (_netCon == NULL) return 0;
        return _netCon->getBytesTotal();
 }
+
+bool
+NetStreamFfmpeg::newFrameReady()
+{
+       if (m_newFrameReady) {
+               m_newFrameReady = false;
+               return true;
+       } else {
+               return false;
+       }
+}
+
+as_function* 
+NetStreamFfmpeg::getStatusHandler()
+{
+       return m_statusHandler.get();
+}
+
+void 
+NetStreamFfmpeg::setStatusHandler(as_function* handler)
+{
+       m_statusHandler = handler;
+}
+
+
 } // gnash namespcae
 
 #endif // USE_FFMPEG

Index: server/asobj/NetStreamFfmpeg.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamFfmpeg.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -b -r1.14 -r1.15
--- server/asobj/NetStreamFfmpeg.h      9 Mar 2007 14:38:29 -0000       1.14
+++ server/asobj/NetStreamFfmpeg.h      23 Mar 2007 00:30:10 -0000      1.15
@@ -14,7 +14,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: NetStreamFfmpeg.h,v 1.14 2007/03/09 14:38:29 tgc Exp $ */
+/* $Id: NetStreamFfmpeg.h,v 1.15 2007/03/23 00:30:10 tgc Exp $ */
 
 #ifndef __NETSTREAMFFMPEG_H__
 #define __NETSTREAMFFMPEG_H__
@@ -43,6 +43,8 @@
 #include "StreamProvider.h"    
 #include "NetStream.h" // for inheritance
 
+#include "FLVParser.h"
+
 namespace gnash {
   
 struct raw_videodata_t
@@ -58,7 +60,7 @@
 
        ~raw_videodata_t()
        {
-               delete [] m_data;
+               if (m_size > 0) delete [] m_data;
        };
 
        int m_stream_index;
@@ -144,12 +146,16 @@
        void pause(int mode);
        int play(const char* source);
        void seek(double pos);
-       void setBufferTime();
+       void setBufferTime(double time);
        void set_status(const char* code);
        void setNetCon(as_object* nc);
        int64_t time();
        long bytesLoaded();
        long bytesTotal();
+       void advance();
+       bool newFrameReady();
+       as_function* getStatusHandler();
+       void setStatusHandler(as_function*);
 
        // Used for ffmpeg data read and seek callbacks
        static int readPacket(void* opaque, uint8_t* buf, int buf_size);
@@ -194,10 +200,12 @@
        AVCodecContext *m_ACodecCtx;
        AVStream* m_audio_stream;
 
+       // the format (mp3, avi, etc.)
        AVFormatContext *m_FormatCtx;
 
        AVFrame* m_Frame;
 
+       // Use for resampling audio
        ReSampleContext *m_Resample;
 
        boost::thread *m_thread;
@@ -206,24 +214,55 @@
        boost::mutex start_mutex;
        boost::mutex::scoped_lock *lock;
 
+       // Are the playing loop running or not
        volatile bool m_go;
        unsigned int runtime;
 
+       // The image/videoframe which is given to the renderer
        image::image_base* m_imageframe;
 
+       // The current time-position of the video
        double m_video_clock;
 
+       // The queues of audio and video data.
        multithread_queue <raw_videodata_t*> m_qaudio;
        multithread_queue <raw_videodata_t*> m_qvideo;
+
+       // paused or not
        bool m_pause;
+
+       // The time ws started playing
        double m_start_clock;
        raw_videodata_t* m_unqueued_data;
 
        ByteIOContext ByteIOCxt;
-       tu_file* input;
+
+       // The position in the inputfile, only used when not playing a FLV
        long inputPos;
-       StreamProvider streamProvider;
+
        std::string url;
+
+       // The homegrown parser we use for FLV
+       FLVParser* m_parser;
+
+       // Are we playing a FLV?
+       bool m_isFLV;
+
+       // Are a new frame ready to be returned?
+       volatile bool m_newFrameReady;
+
+       // The size of the buffer in milliseconds
+       uint32_t m_bufferTime;
+
+       // The status message
+       std::string m_status;
+
+       // Has the status message been updated?
+       volatile bool m_statusChanged;
+
+       // The handler which is invoked on status change
+       boost::intrusive_ptr<as_function> m_statusHandler;
+
 };
 
 } // gnash namespace

Index: server/asobj/NetStreamGst.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamGst.cpp,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -b -r1.14 -r1.15
--- server/asobj/NetStreamGst.cpp       20 Mar 2007 15:01:20 -0000      1.14
+++ server/asobj/NetStreamGst.cpp       23 Mar 2007 00:30:10 -0000      1.15
@@ -76,8 +76,8 @@
        m_pause(false),
        inputPos(0),
        videowidth(0),
-       videoheight(0)
-
+       videoheight(0),
+       m_newFrameReady(false)
 {
 }
 
@@ -89,8 +89,7 @@
 // called from avstreamer thread
 void NetStreamGst::set_status(const char* /*code*/)
 {
-       //m_netstream_object->init_member("onStatus_Code", code);
-       //push_video_event(this);
+
 }
 
 void NetStreamGst::pause(int mode)
@@ -254,6 +253,7 @@
                        video->m_size = copied;*/
                } else {
                        ns->m_imageframe->update(GST_BUFFER_DATA(buffer));
+                       ns->m_newFrameReady = true;
                }
 
        }
@@ -285,8 +285,17 @@
        // setup the pipeline
        ns->pipeline = gst_pipeline_new (NULL);
 
+       // Check if the creation of the gstreamer pipeline and audiosink was a 
succes
+       if (!ns->pipeline) {
+               gnash::log_error("The gstreamer pipeline element could not be 
created\n");
+               return;
+       }
+
+       // If sound is enabled we set it up
+       sound_handler* sound = get_sound_handler();
+       if (sound) {
        // create an audio sink - use oss, alsa or...? make a commandline 
option?
-       // we first try atudetect, then alsa, then oss, then esd, then...?
+               // we first try autodetect, then alsa, then oss, then esd, 
then...?
        // If the gstreamer adder ever gets fixed this should be connected to 
the
        // adder in the soundhandler.
 #if !defined(__NetBSD__)
@@ -296,15 +305,26 @@
 #endif
        if (!ns->audiosink) ns->audiosink = gst_element_factory_make 
("esdsink", NULL);
 
-       // Check if the creation of the gstreamer pipeline and audiosink was a 
succes
-       if (!ns->pipeline) {
-               gnash::log_error("The gstreamer pipeline element could not be 
created\n");
-               return;
-       }
        if (!ns->audiosink) {
                gnash::log_error("The gstreamer audiosink element could not be 
created\n");
                return;
        }
+       } else {
+               ns->audiosink = gst_element_factory_make ("fakesink", NULL);
+       }
+
+       // setup the audio converter
+       ns->audioconv = gst_element_factory_make ("audioconvert", NULL);
+
+       // setup the volume controller
+       ns->volume = gst_element_factory_make ("volume", NULL);
+
+       if (!ns->audioconv || !ns->volume) {
+               gnash::log_error("Gstreamer audio element(s) for movie handling 
could not be created\n");
+               return;
+       }
+
+       gst_bin_add_many (GST_BIN (ns->pipeline),ns->audiosink, ns->audioconv, 
NULL);
 
        // setup gnashnc source (our homegrown source element)
        ns->source = gst_element_factory_make ("gnashsrc", NULL);
@@ -313,11 +333,6 @@
        gc->seek = NetStreamGst::seekMedia;
        g_object_set (G_OBJECT (ns->source), "data", ns, "callbacks", gc, NULL);
 
-       // setup the audio converter
-       ns->audioconv = gst_element_factory_make ("audioconvert", NULL);
-
-       // setup the volume controller
-       ns->volume = gst_element_factory_make ("volume", NULL);
 
        // setup the decoder with callback
        ns->decoder = gst_element_factory_make ("decodebin", NULL);
@@ -345,21 +360,23 @@
        g_object_set (G_OBJECT (ns->videosink), "signal-handoffs", TRUE, 
"sync", TRUE, NULL);
        g_signal_connect (ns->videosink, "handoff", G_CALLBACK 
(NetStreamGst::callback_output), ns);
 
-       if (!ns->source || !ns->audioconv || !ns->volume || !ns->decoder || 
!ns->colorspace || !ns->videocaps || !ns->videorate || !ns->videosink) {
-               gnash::log_error("Gstreamer element(s) for movie handling could 
not be created\n");
+       if (!ns->source || !ns->decoder || !ns->colorspace || !ns->videocaps || 
!ns->videorate || !ns->videosink) {
+               gnash::log_error("Gstreamer element(s) for video movie handling 
could not be created\n");
                return;
        }
 
        // put it all in the pipeline
-       gst_bin_add_many (GST_BIN (ns->pipeline), ns->source, ns->decoder, 
ns->audiosink, ns->audioconv, ns->colorspace, ns->videosink, ns->videorate, 
ns->videocaps, ns->volume, NULL);
+       gst_bin_add_many (GST_BIN (ns->pipeline), ns->source, ns->decoder, 
ns->colorspace, ns->videosink, ns->videorate, ns->videocaps, ns->volume, NULL);
 
        // link the elements
        gst_element_link(ns->source, ns->decoder);
-       gst_element_link_many(ns->audioconv, ns->volume, ns->audiosink, NULL);
        gst_element_link_many(ns->colorspace, ns->videocaps, ns->videorate, 
ns->videosink, NULL);
        
+       gst_element_link_many(ns->audioconv, ns->volume, ns->audiosink, NULL);
+       
        // start playing        
        gst_element_set_state (ns->pipeline, GST_STATE_PLAYING);
+
        return;
 }
 
@@ -371,18 +388,39 @@
 void
 NetStreamGst::seek(double pos)
 {
-
        if (!gst_element_seek (pipeline, 1.0, GST_FORMAT_TIME, 
GST_SEEK_FLAG_FLUSH,
                GST_SEEK_TYPE_SET, GST_SECOND * static_cast<long>(pos),
                GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
                log_warning("Seek failed");
        }
+
 }
 
 void
-NetStreamGst::setBufferTime()
+NetStreamGst::setBufferTime(double time)
 {
-    log_msg("%s:unimplemented \n", __FUNCTION__);
+       // The argument is in seconds, but we store in milliseconds
+    m_bufferTime = static_cast<uint32_t>(time*1000);
+}
+
+void
+NetStreamGst::advance()
+{
+/*     if (m_go && m_pause && !m_imageframe && m_parser && 
m_parser->isTimeLoaded(m_bufferTime)) {
+               set_status("NetStream.Buffer.Full");
+               m_pause = false;
+       }
+*/
+       if (m_statusChanged) {
+/*             fn_call dummy(NULL, NULL, 0, 0);
+               as_value info_asv(infoobject_new(dummy));
+               boost::intrusive_ptr<as_object> info = info_asv.to_object();
+
+               fn_call fn(this, v, 0, 0);
+
+               m_statusHandler.get()->call(fn);*/
+
+       }
 }
 
 int64_t
@@ -399,6 +437,8 @@
        ret = gst_element_get_state (GST_ELEMENT (pipeline), &current, 
&pending, 0);
 
        if (current != GST_STATE_NULL && gst_element_query_position (pipeline, 
&fmt, &pos)) {
+               pos = pos / 1000000000;
+
                return pos;
        } else {
                return 0;
@@ -417,6 +457,29 @@
        return _netCon->getBytesTotal();
 }
 
+bool
+NetStreamGst::newFrameReady()
+{
+       if (m_newFrameReady) {
+               m_newFrameReady = false;
+               return true;
+       } else {
+               return false;
+       }
+}
+
+as_function* 
+NetStreamGst::getStatusHandler()
+{
+       return m_statusHandler.get();
+}
+
+void 
+NetStreamGst::setStatusHandler(as_function* handler)
+{
+       m_statusHandler = handler;
+}
+
 // Gstreamer callback function
 int 
 NetStreamGst::readPacket(void* opaque, char* buf, int buf_size){

Index: server/asobj/NetStreamGst.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamGst.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- server/asobj/NetStreamGst.h 4 Mar 2007 21:35:31 -0000       1.8
+++ server/asobj/NetStreamGst.h 23 Mar 2007 00:30:10 -0000      1.9
@@ -44,12 +44,16 @@
        void pause(int mode);
        int play(const char* source);
        void seek(double pos);
-       void setBufferTime();
+       void setBufferTime(double time);
        void set_status(const char* code);
        void setNetCon(as_object* nc);
        int64_t time();
        long bytesLoaded();
        long bytesTotal();
+       void advance();
+       bool newFrameReady();
+       as_function* getStatusHandler();
+       void setStatusHandler(as_function*);
 
        // Used for gstreamer data read and seek callbacks
        static int readPacket(void* opaque, char* buf, int buf_size);
@@ -88,8 +92,10 @@
        GstElement *videoflip;
        GstElement *audioconv;
 
+       // Are the playing loop running or not
        volatile bool m_go;
 
+       // The image/videoframe which is given to the renderer
        image::image_base* m_imageframe;
 
        boost::thread *startThread;
@@ -101,6 +107,21 @@
        // video info
        int videowidth;
        int videoheight;
+
+       volatile bool m_newFrameReady;
+       
+       // The size of the buffer in milliseconds
+       uint32_t m_bufferTime;
+
+       // The status message
+       std::string m_status;
+
+       // Has the status message been updated?
+       volatile bool m_statusChanged;
+
+       // The handler which is invoked on status change
+       boost::intrusive_ptr<as_function> m_statusHandler;
+
 };
 
 } // gnash namespace

Index: server/asobj/SoundGst.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/SoundGst.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- server/asobj/SoundGst.cpp   27 Feb 2007 09:10:20 -0000      1.3
+++ server/asobj/SoundGst.cpp   23 Mar 2007 00:30:10 -0000      1.4
@@ -263,7 +263,6 @@
                }
                // start playing        
                gst_element_set_state (pipeline, GST_STATE_PLAYING);
-printf("playback started\n");
 
        }
 

Index: libbase/FLVParser.cpp
===================================================================
RCS file: libbase/FLVParser.cpp
diff -N libbase/FLVParser.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libbase/FLVParser.cpp       23 Mar 2007 00:30:10 -0000      1.1
@@ -0,0 +1,458 @@
+// 
+//   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 2 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/03/23 00:30:10 tgc Exp $
+
+#include "FLVParser.h"
+#include "amf.h"
+
+FLVParser::FLVParser()
+       :
+       _lt(NULL),
+       _lastParsedPosition(0),
+       _parsingComplete(false),
+       _videoInfo(NULL),
+       _audioInfo(NULL),
+       _lastAudioFrame(-1),
+       _lastVideoFrame(-1),
+       _audio(false),
+       _video(false)
+{
+}
+
+FLVParser::~FLVParser()
+{
+       _videoFrames.clear();
+
+       _audioFrames.clear();
+}
+
+uint32_t FLVParser::videoFrameDelay()
+{
+       if (!_video || _lastVideoFrame < 1) return 0;
+
+       return _videoFrames[_lastVideoFrame]->timestamp - 
_videoFrames[_lastVideoFrame-1]->timestamp;
+}
+
+FLVFrame* FLVParser::nextMediaFrame()
+{
+       uint32_t video_size = _videoFrames.size();
+       uint32_t audio_size = _audioFrames.size();
+       
+
+       // Parse a media frame if any left or if needed
+       while(video_size == _videoFrames.size() && audio_size == 
_audioFrames.size() && !_parsingComplete) {
+               parseNextFrame();
+       }
+
+       // Find the next frame in the file
+       bool audioReady = _audioFrames.size() > _lastAudioFrame+1;
+       bool videoReady = _videoFrames.size() > _lastVideoFrame+1;
+       bool useAudio = false;
+
+       if (audioReady && videoReady) {
+               useAudio = _audioFrames[_lastAudioFrame+1]->dataPosition < 
_videoFrames[_lastVideoFrame+1]->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) {
+               _lastAudioFrame++;
+
+               FLVFrame* frame = new FLVFrame;
+               frame->dataSize = _audioFrames[_lastAudioFrame]->dataSize;
+               frame->timestamp = _audioFrames[_lastAudioFrame]->timestamp;
+
+               _lt->seek(_audioFrames[_lastAudioFrame]->dataPosition);
+               frame->data = new 
uint8_t[_audioFrames[_lastAudioFrame]->dataSize];
+               _lt->read(frame->data, _audioFrames[_lastAudioFrame]->dataSize);
+               frame->tag = 8;
+               return frame;
+       
+       } else {
+               _lastVideoFrame++;
+
+               FLVFrame* frame = new FLVFrame;
+               frame->dataSize = _videoFrames[_lastVideoFrame]->dataSize;
+               frame->timestamp = _videoFrames[_lastVideoFrame]->timestamp;
+
+               _lt->seek(_videoFrames[_lastVideoFrame]->dataPosition);
+               frame->data = new 
uint8_t[_videoFrames[_lastVideoFrame]->dataSize];
+               _lt->read(frame->data, _videoFrames[_lastVideoFrame]->dataSize);
+               frame->tag = 9;
+               return frame;
+       }
+
+}
+
+FLVFrame* FLVParser::nextAudioFrame()
+{
+       // 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() <= static_cast<uint32_t>(_lastAudioFrame+1) 
&& !_parsingComplete) {
+               parseNextFrame();
+       }
+
+       // If the needed frame can't be parsed (EOF reached) return NULL
+       if (_audioFrames.size() < static_cast<uint32_t>(_lastAudioFrame+1)) 
return NULL;
+
+       _lastAudioFrame++;
+
+       FLVFrame* frame = new FLVFrame;
+       frame->dataSize = _audioFrames[_lastAudioFrame]->dataSize;
+       frame->timestamp = _audioFrames[_lastAudioFrame]->timestamp;
+
+       _lt->seek(_audioFrames[_lastAudioFrame]->dataPosition);
+       frame->data = new uint8_t[_audioFrames[_lastAudioFrame]->dataSize];
+       _lt->read(frame->data, _audioFrames[_lastAudioFrame]->dataSize);
+       return frame;
+
+}
+
+FLVFrame* FLVParser::nextVideoFrame()
+{
+       // If there are no video in this FLV return NULL
+       if (!_video && _lastParsedPosition > 0) return NULL;
+
+       // Make sure that there are parsed enough frames to return the need 
frame
+       while(_videoFrames.size() <= static_cast<uint32_t>(_lastVideoFrame+1) 
&& !_parsingComplete) {
+               parseNextFrame();
+       }
+
+       // If the needed frame can't be parsed (EOF reached) return NULL
+       if (_videoFrames.size() < static_cast<uint32_t>(_lastVideoFrame+1)) 
return NULL;
+
+       _lastVideoFrame++;
+
+       FLVFrame* frame = new FLVFrame;
+       frame->dataSize = _videoFrames[_lastVideoFrame]->dataSize;
+       frame->timestamp = _videoFrames[_lastVideoFrame]->timestamp;
+
+       _lt->seek(_videoFrames[_lastVideoFrame]->dataPosition);
+       frame->data = new uint8_t[_videoFrames[_lastVideoFrame]->dataSize];
+       _lt->read(frame->data, _videoFrames[_lastVideoFrame]->dataSize);
+       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
+       if (_audioFrames.back()->timestamp < time) {
+               _lastVideoFrame = _audioFrames.size() - 2;
+               return _audioFrames.back()->timestamp;
+       }
+
+       // We try to guess where in the vector the audioframe
+       // with the correct timestamp is
+       uint32_t numFrames = _audioFrames.size();
+       uint32_t guess = _audioFrames[numFrames-1]->timestamp / numFrames * 
time;
+
+       // Here we test if the guess was ok, and adjust if needed.
+       uint32_t bestFrame = guess;
+       uint32_t diff = abs(_audioFrames[bestFrame]->timestamp - time);
+       while (true) {
+               if (bestFrame+1 < numFrames && 
static_cast<uint32_t>(abs(_audioFrames[bestFrame+1]->timestamp - time)) < diff) 
{
+                       bestFrame = bestFrame + 1;
+                       diff = abs(_audioFrames[bestFrame+1]->timestamp - time);
+               } else if (bestFrame-1 > 0 && 
static_cast<uint32_t>(abs(_audioFrames[bestFrame+1]->timestamp - time)) < diff) 
{
+                       bestFrame = bestFrame - 1;
+                       diff = abs(_audioFrames[bestFrame-1]->timestamp - time);
+               } else {
+                       break;
+               }
+       }
+
+       _lastAudioFrame = bestFrame -1;
+       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();
+       uint32_t numFrames = _audioFrames.size();
+       if (lastFrame->timestamp < time) {
+               uint32_t lastFrameNum = numFrames -1;
+               while (lastFrame->frameType != KEY_FRAME) {
+                       lastFrameNum--;
+                       lastFrame = _videoFrames[lastFrameNum];
+               }
+
+               _lastVideoFrame = lastFrameNum-1;
+               return lastFrame->timestamp;
+
+       }
+
+       // We try to guess where in the vector the videoframe
+       // with the correct timestamp is
+       uint32_t guess = lastFrame->timestamp / numFrames * time;
+
+       // Here we test if the guess was ok, and adjust if needed.
+       uint32_t bestFrame = guess;
+       uint32_t diff = abs(_audioFrames[bestFrame]->timestamp - time);
+       while (true) {
+               if (bestFrame+1 < numFrames && 
static_cast<uint32_t>(abs(_audioFrames[bestFrame+1]->timestamp - time)) < diff) 
{
+                       bestFrame = bestFrame + 1;
+                       diff = abs(_audioFrames[bestFrame+1]->timestamp - time);
+               } else if (bestFrame-1 > 0 && 
static_cast<uint32_t>(abs(_audioFrames[bestFrame+1]->timestamp - time)) < diff) 
{
+                       bestFrame = bestFrame - 1;
+                       diff = abs(_audioFrames[bestFrame-1]->timestamp - time);
+               } else {
+                       break;
+               }
+       }
+
+       uint32_t rewindKeyframe = bestFrame;
+       uint32_t forwardKeyframe = bestFrame;
+
+       // Rewind to the lastest keyframe
+       while (_videoFrames[rewindKeyframe]->frameType != KEY_FRAME) {
+               rewindKeyframe--;
+       }
+
+       // Forward to the next keyframe
+       uint32_t size = _videoFrames.size();
+       while (size > forwardKeyframe && 
_videoFrames[forwardKeyframe]->frameType != KEY_FRAME) {
+               forwardKeyframe++;
+       }
+
+       int32_t forwardDiff = _videoFrames[forwardKeyframe]->timestamp - time;
+       int32_t rewindDiff = time - _videoFrames[rewindKeyframe]->timestamp;
+
+       if (forwardDiff < rewindDiff) bestFrame = forwardKeyframe;
+       else bestFrame = rewindKeyframe;
+
+       _lastVideoFrame = bestFrame - 1;
+       return _audioFrames[bestFrame]->timestamp;
+}
+
+
+
+FLVVideoInfo* FLVParser::getVideoInfo()
+{
+       // If there are no video in this FLV return NULL
+       if (!_video && _lastParsedPosition > 0) return NULL;
+
+       // Make sure that there are parsed some video frames
+       while(_videoInfo == NULL && !_parsingComplete) {
+               parseNextFrame();
+       }
+
+       // If there are no audio data return NULL
+       if (_videoInfo == NULL) return NULL;
+
+       FLVVideoInfo* info = new FLVVideoInfo(_videoInfo->codec, 
_videoInfo->width, _videoInfo->height, _videoInfo->frameRate, 
_videoInfo->duration);
+       return info;
+
+}
+
+FLVAudioInfo* FLVParser::getAudioInfo()
+{
+       // If there are no audio in this FLV return NULL
+       if (!_audio && _lastParsedPosition > 0) return NULL;
+
+       // Make sure that there are parsed some audio frames
+       while(_audioInfo == NULL && !_parsingComplete) {
+               parseNextFrame();
+       }
+
+       // If there are no audio data return NULL
+       if (_audioInfo == NULL) return NULL;
+
+       FLVAudioInfo* info = new FLVAudioInfo(_audioInfo->codec, 
_audioInfo->sampleRate, _audioInfo->sampleSize, _audioInfo->stereo, 
_audioInfo->duration);
+       return info;
+
+}
+
+bool FLVParser::isTimeLoaded(uint32_t time)
+{
+       // Parse frames until the need time is found, or EOF
+       while (!_parsingComplete && (_videoFrames.size() > 0 && 
_videoFrames.back()->timestamp < time) && (_audioFrames.size() > 0 && 
_audioFrames.back()->timestamp < time)) {
+               parseNextFrame();
+       }
+
+       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)
+{
+
+       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
+       _lt->seek(_lastParsedPosition+4);
+
+       // Read the tag info
+       uint8_t 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 (tag[0] == AUDIO_TAG) {
+               FLVAudioFrame* frame = new FLVAudioFrame;
+               frame->dataSize = bodyLength - 1;
+               frame->timestamp = timestamp;
+               frame->dataPosition = _lt->tell();
+               _audioFrames.push_back(frame);
+               
+               // If this is the first audioframe no info about the
+               // audio format has been noted, so we do that now
+               if (_audioInfo == NULL) {
+                       _audioInfo = new FLVAudioInfo((tag[11] & 0xf0) >> 4, 
(tag[11] & 0x0C) >> 2, (tag[11] & 0x02) >> 1, (tag[11] & 0x01) >> 0, 0);
+               }
+               _lastParsedPosition += 15 + bodyLength;
+
+       } else if (tag[0] == VIDEO_TAG) {
+               FLVVideoFrame* frame = new FLVVideoFrame;
+               frame->dataSize = bodyLength - 1;
+               frame->timestamp = timestamp;
+               frame->dataPosition = _lt->tell();
+               frame->frameType = (tag[11] & 0xf0) >> 4;
+               _videoFrames.push_back(frame);
+               
+               // If this is the first videoframe no info about the
+               // video format has been noted, so we do that now
+               if (_videoInfo == NULL) {
+
+                       // TODO: parse the video frame header to extract info 
about the width and height.
+                       _videoInfo = new FLVVideoInfo((tag[11] & 0x0f) >> 0, 0 
/*width*/, 0 /*height*/, 0 /*frameRate*/, 0 /*duration*/);
+               }
+               _lastParsedPosition += 15 + bodyLength;
+
+       } else if (tag[0] == 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 += 15 + bodyLength;
+       } else {
+               _parsingComplete = true;
+       }
+       return true;
+}
+
+bool FLVParser::parseHeader()
+{
+       // seek to the begining of the file
+       _lt->seek(0);
+       
+       // Read the header
+       uint8_t 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;
+
+       // Parse the audio+video bitmask
+       if (header[4] == 5) {
+               _audio = true;
+               _video = true;
+       } else if (header[4] == 4) {
+               _audio = true;
+               _video = false;
+       } else if (header[4] == 4) {
+               _audio = false;
+               _video = true;
+       } else {
+               printf("Weird bit mask\n");
+       }
+
+       _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];
+}
+
+void FLVParser::setLoadThread(LoadThread* lt)
+{
+       _lt = lt;
+}

Index: libbase/FLVParser.h
===================================================================
RCS file: libbase/FLVParser.h
diff -N libbase/FLVParser.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libbase/FLVParser.h 23 Mar 2007 00:30:10 -0000      1.1
@@ -0,0 +1,246 @@
+// 
+//   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 2 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/03/23 00:30:10 tgc Exp $
+
+// Information about the FLV format can be found at http://osflash.org/flv
+
+#ifndef __FLVPARSER_H__
+#define __FLVPARSER_H__
+
+#include "LoadThread.h"
+#include <vector>
+
+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 = 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
+/// timestamp, 
+class FLVFrame
+{
+public:
+       int dataSize;
+       uint8_t* data;
+       uint32_t timestamp;
+       uint8_t tag;
+};
+
+/// \brief
+/// The FLVAudioInfo class contains information about the audiostream
+/// in the FLV being parsed. The information stored is codec-type,
+/// samplerate, samplesize, stereo and duration.
+/// timestamp, 
+class FLVAudioInfo
+{
+public:
+       FLVAudioInfo(int codeci, int sampleRatei, int sampleSizei, bool 
stereoi, long durationi)
+               : codec(codeci),
+               sampleRate(sampleRatei),
+               sampleSize(sampleSizei),
+               stereo(stereoi),
+               duration(durationi)
+               {
+               }
+
+       int codec;
+       int sampleRate;
+       int sampleSize;
+       bool stereo;
+       long duration;
+};
+
+/// \brief
+/// The FLVVideoInfo class contains information about the videostream
+/// in the FLV being parsed. The information stored is codec-type,
+/// width, height, framerate and duration.
+/// timestamp, 
+class FLVVideoInfo
+{
+public:
+       FLVVideoInfo(int codeci, int widthi, int heighti, int frameRatei, long 
durationi)
+               : codec(codeci),
+               width(widthi),
+               height(heighti),
+               frameRate(frameRatei),
+               duration(durationi)
+               {
+               }
+
+       uint16_t codec;
+       uint16_t width;
+       uint16_t height;
+       uint16_t frameRate;
+       long duration;
+};
+
+
+class FLVVideoFrame
+{
+public:
+       uint16_t frameType;
+       uint32_t dataSize;
+       long dataPosition;
+       uint32_t timestamp;
+       
+};
+
+class FLVAudioFrame
+{
+public:
+       uint32_t dataSize;
+       long dataPosition;
+       uint32_t timestamp;
+       
+};
+
+/// \brief
+/// The FLVParser class parses a FLV file, and can return
+/// video or audio frames for a specific time, or just 
+/// get the next in the timeline.
+
+class FLVParser
+{
+
+public:
+       /// Creating the object...
+       FLVParser();
+
+       /// Kills the parser...
+       ~FLVParser();
+
+       FLVFrame* nextMediaFrame();
+
+       /// Returns the next audio frame in the timeline. If no frame has been
+       /// played before the first frame is returned. If there is no more 
frames
+       /// in the timeline NULL is returned.
+       FLVFrame* nextAudioFrame();
+
+       /// Returns the next video frame in the timeline. If no frame has been
+       /// played before the first frame is returned. If there is no more 
frames
+       /// in the timeline NULL is returned.
+       FLVFrame* nextVideoFrame();
+
+       /// Returns a FLVVideoInfo class about the videostream
+       FLVVideoInfo* getVideoInfo();
+
+       /// Returns a FLVAudioInfo class about the audiostream
+       FLVAudioInfo* getAudioInfo();
+
+       /// Sets the LoadThread which is used as interface
+       void setLoadThread(LoadThread* lt);
+
+       /// 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.
+       bool isTimeLoaded(uint32_t time);
+
+       /// seeks to the closest possible position the given position,
+       /// and returns the new position.
+       uint32_t seek(uint32_t);
+
+       /// Returns the framedelay from the last to the current
+       /// videoframe in milliseconds. This is used for framerate.
+       uint32_t videoFrameDelay();
+
+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 is 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
+       LoadThread* _lt;
+
+       /// list of videoframes, does no contain the frame data.
+       std::vector<FLVVideoFrame*> _videoFrames;
+
+       /// list of audioframes, does no contain the frame data.
+       std::vector<FLVAudioFrame*> _audioFrames;
+
+       /// The position where the parsing should continue from.
+       long _lastParsedPosition;
+
+       /// Whether the parsing is complete or not
+       bool _parsingComplete;
+
+       /// Info about the video stream
+       FLVVideoInfo* _videoInfo;
+
+       /// Info about the audio stream
+       FLVAudioInfo* _audioInfo;
+
+       /// Last audio frame returned
+       int _lastAudioFrame;
+
+       /// Last video frame returned
+       int _lastVideoFrame;
+
+       /// Audio stream is present
+       bool _audio;
+
+       /// Audio stream is present
+       bool _video;
+};
+
+#endif // __FLVPARSER_H__




reply via email to

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