gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] gnash ChangeLog backend/render_handler_ogl.cpp ...


From: Tomas Groth
Subject: [Gnash-commit] gnash ChangeLog backend/render_handler_ogl.cpp ...
Date: Sat, 13 Jan 2007 20:06:18 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Tomas Groth <tgc>       07/01/13 20:06:18

Modified files:
        .              : ChangeLog 
        backend        : render_handler_ogl.cpp 
        libbase        : Makefile.am 
        server         : Makefile.am 
        server/asobj   : Makefile.am NetConnection.cpp NetConnection.h 
                         NetStream.h NetStreamFfmpeg.cpp 
                         NetStreamFfmpeg.h 
Added files:
        libbase        : gstgnashsrc.c gstgnashsrc.h 
        server/asobj   : NetStreamGst.cpp NetStreamGst.h 

Log message:
        * backend/render_handler_ogl.cpp: No need to flip the frame twice.
        * libbase/Makefile.am, libbase/gstgnashsrc.{c,h}: Added 
gstgnashsrc.{c,h}
          for feeding gstreamer through callbacks.
        * server/Makefile.am, server/asobj/Makefile.am, 
          server/asobj/NetStream.h, server/asobj/NetStreamGst.{cpp,h}: Added 
          NetStreamGst for decoding of external videofiles using Gstreamer.
        * server/asobj/NetConnection.{cpp,h}: Rewritten to use curl (based on 
          curl_adapter)
        * server/asobj/NetStreamFfmpeg.cpp: Use NetConnection instead of 
          StreamProvider. Fixed a 100%-CPU-use-bug. Stopped fliping the 
videoframe.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.2103&r2=1.2104
http://cvs.savannah.gnu.org/viewcvs/gnash/backend/render_handler_ogl.cpp?cvsroot=gnash&r1=1.62&r2=1.63
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/Makefile.am?cvsroot=gnash&r1=1.53&r2=1.54
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/gstgnashsrc.c?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/gstgnashsrc.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/Makefile.am?cvsroot=gnash&r1=1.98&r2=1.99
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/Makefile.am?cvsroot=gnash&r1=1.28&r2=1.29
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetConnection.cpp?cvsroot=gnash&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetConnection.h?cvsroot=gnash&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStream.h?cvsroot=gnash&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamFfmpeg.cpp?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamFfmpeg.h?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamGst.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamGst.h?cvsroot=gnash&rev=1.1

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.2103
retrieving revision 1.2104
diff -u -b -r1.2103 -r1.2104
--- ChangeLog   12 Jan 2007 14:38:55 -0000      1.2103
+++ ChangeLog   13 Jan 2007 20:06:17 -0000      1.2104
@@ -1,3 +1,16 @@
+2007-01-13 Tomas Groth Christensen <address@hidden>
+
+       * backend/render_handler_ogl.cpp: No need to flip the frame twice.
+       * libbase/Makefile.am, libbase/gstgnashsrc.{c,h}: Added 
gstgnashsrc.{c,h}
+         for feeding gstreamer through callbacks.
+       * server/Makefile.am, server/asobj/Makefile.am, 
+         server/asobj/NetStream.h, server/asobj/NetStreamGst.{cpp,h}: Added 
+         NetStreamGst for decoding of external videofiles using Gstreamer.
+       * server/asobj/NetConnection.{cpp,h}: Rewritten to use curl (based on 
+         curl_adapter)
+       * server/asobj/NetStreamFfmpeg.cpp: Use NetConnection instead of 
+         StreamProvider. Fixed a 100%-CPU-use-bug. Stopped fliping the 
videoframe.
+
 2007-01-12 Sandro Santilli <address@hidden>
 
        * testsuite/misc-ming.all/place_and_remove_object_insane_test.c:

Index: backend/render_handler_ogl.cpp
===================================================================
RCS file: /sources/gnash/gnash/backend/render_handler_ogl.cpp,v
retrieving revision 1.62
retrieving revision 1.63
diff -u -b -r1.62 -r1.63
--- backend/render_handler_ogl.cpp      25 Dec 2006 12:29:08 -0000      1.62
+++ backend/render_handler_ogl.cpp      13 Jan 2007 20:06:17 -0000      1.63
@@ -6,7 +6,7 @@
 // A render_handler that uses SDL & OpenGL
 
 
-/* $Id: render_handler_ogl.cpp,v 1.62 2006/12/25 12:29:08 tgc Exp $ */
+/* $Id: render_handler_ogl.cpp,v 1.63 2007/01/13 20:06:17 tgc Exp $ */
 
 //#include "gnash.h"
 #include "render_handler.h"
@@ -392,13 +392,13 @@
                float h_bounds = TWIPS_TO_PIXELS(c.m_y - a.m_y);
 
                unsigned char*   ptr = frame->m_data;
-#if GLYUV
-               GLenum rgb[3] = {GL_RED, GL_GREEN, GL_BLUE}; 
-
                float xpos = a.m_x < 0 ? 0.0f : a.m_x;  //hack
                float ypos = a.m_y < 0 ? 0.0f : a.m_y;  //hack
                glRasterPos2f(xpos, ypos);      //hack
 
+#if GLYUV
+               GLenum rgb[3] = {GL_RED, GL_GREEN, GL_BLUE}; 
+
                for (int i = 0; i < 3; ++i)
                {
                        float zx = w_bounds / (float) frame->planes[i].w;
@@ -415,15 +415,11 @@
                        ptr += frame->planes[i].size;
                }
 #else
-               float xpos = c.m_x < 0 ? 0.0f : c.m_x;  //hack
-               float ypos = c.m_y < 0 ? 0.0f : c.m_y;  //hack
-               glRasterPos2f(xpos, ypos);      //hack
-
                int height = frame->m_height;
                int width = frame->m_width;
                float zx = w_bounds / (float) width;
                float zy = h_bounds / (float) height;
-               glPixelZoom(zx,  zy);   // flip & zoom image
+               glPixelZoom(zx,  -zy);  // flip & zoom image
                glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, ptr);
 #endif
 

Index: libbase/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/libbase/Makefile.am,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -b -r1.53 -r1.54
--- libbase/Makefile.am 30 Nov 2006 22:11:50 -0000      1.53
+++ libbase/Makefile.am 13 Jan 2007 20:06:17 -0000      1.54
@@ -36,7 +36,8 @@
         $(ZLIB_CFLAGS) \
         $(JPEG_CFLAGS) \
        $(BOOST_CFLAGS) \
-       $(INCLTDL)
+       $(INCLTDL) \
+       $(NULL)
 
 # These headers get installed
 # include_HEADERS = log.h err.h proc.h serial.h xantrex.h outback.h
@@ -131,6 +132,13 @@
        Thread.h \
        URL.h
 
+if USE_SOUND_GST
+libgnashbase_la_SOURCES += gstgnashsrc.c
+noinst_HEADERS += gstgnashsrc.h
+libgnashbase_la_CPPFLAGS += $(GSTREAMER_CFLAGS)
+libgnashbase_la_LIBADD += $(GSTREAMER_LIBS) -lgstbase-0.10
+endif
+
 # libgnashbase_la_LDFLAGS = -export-dynamic
 libgnashbase_la_LDFLAGS = -avoid-version
 

Index: server/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/server/Makefile.am,v
retrieving revision 1.98
retrieving revision 1.99
diff -u -b -r1.98 -r1.99
--- server/Makefile.am  9 Jan 2007 23:18:59 -0000       1.98
+++ server/Makefile.am  13 Jan 2007 20:06:17 -0000      1.99
@@ -18,7 +18,7 @@
 # 
 #
 
-# $Id: Makefile.am,v 1.98 2007/01/09 23:18:59 strk Exp $
+# $Id: Makefile.am,v 1.99 2007/01/13 20:06:17 tgc Exp $
 
 AUTOMAKE_OPTIONS = 
 
@@ -147,6 +147,10 @@
        $(LIBXML_LIBS) \
        $(NULL)
 
+if USE_SOUND_GST
+AM_CPPFLAGS += $(GSTREAMER_CFLAGS)
+endif
+
 #libserver_la_LDFLAGS = -module -avoid-version -no-undefined
 #libserver_la_LIBDADD =  address@hidden@  # $(LIBLTDL)
 libgnashserver_la_LDFLAGS = -avoid-version

Index: server/asobj/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/Makefile.am,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -b -r1.28 -r1.29
--- server/asobj/Makefile.am    9 Jan 2007 15:14:20 -0000       1.28
+++ server/asobj/Makefile.am    13 Jan 2007 20:06:17 -0000      1.29
@@ -18,7 +18,7 @@
 # 
 #
 
-# $Id: Makefile.am,v 1.28 2007/01/09 15:14:20 rsavoye Exp $
+# $Id: Makefile.am,v 1.29 2007/01/13 20:06:17 tgc Exp $
 
 AUTOMAKE_OPTIONS = 
 
@@ -60,7 +60,6 @@
        Mouse.cpp       \
        NetConnection.cpp\
        NetStream.cpp   \
-       NetStreamFfmpeg.cpp \
        Number.cpp      \
        Object.cpp      \
        Selection.cpp   \
@@ -97,6 +96,7 @@
        NetConnection.h \
        NetStream.h     \
        NetStreamFfmpeg.h \
+       NetStreamGst.h \
        Number.h        \
        Object.h        \
        Selection.h     \
@@ -117,10 +117,17 @@
        $(top_builddir)/libbase/libgnashbase.la
 
 if USE_FFMPEG_ENGINE
+libgnashasobjs_la_SOURCES += NetStreamFfmpeg.cpp
 AM_CPPFLAGS += $(FFMPEG_CFLAGS)
 libgnashasobjs_la_LIBADD += $(FFMPEG_LIBS)
 endif
 
+if USE_SOUND_GST
+libgnashasobjs_la_SOURCES += NetStreamGst.cpp
+AM_CPPFLAGS += $(GSTREAMER_CFLAGS)
+libgnashasobjs_la_LIBADD += $(GSTREAMER_LIBS)
+endif
+
 libgnashasobjs_la_LDFLAGS = -avoid-version
 
 # Rebuild with GCC 4.x Mudflap support

Index: server/asobj/NetConnection.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetConnection.cpp,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- server/asobj/NetConnection.cpp      6 Dec 2006 10:58:34 -0000       1.13
+++ server/asobj/NetConnection.cpp      13 Jan 2007 20:06:17 -0000      1.14
@@ -14,9 +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: */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -29,6 +27,7 @@
 #include "fn_call.h"
 #include "rtmp.h"
 #include "log.h"
+#include "GnashException.h"
 
 using namespace std;
 using namespace amf;
@@ -39,31 +38,128 @@
 
 namespace gnash {
 
+#ifdef HAVE_CURL_CURL_H
+
 /// \class NetConnection
 /// \brief Opens a local connection through which you can play
 /// back video (FLV) files from an HTTP address or from the local file
-/// system.
+/// system, using curl.
 
-/// First introduced for swf v7
 
-/// protocol:[//host][:port]/appname/[instanceName]
+// Ensure libcurl is initialized
+static void ensure_libcurl_initialized()
+{
+       static bool initialized=0;
+       if ( ! initialized ) {
+               // TODO: handle an error here
+               curl_global_init(CURL_GLOBAL_ALL);
+               initialized=1;
+       }
+}
 
-/// For protocol, specify either rtmp or rtmpt. If rtmp is specified,
-/// Flash Player will create a persistent Communication Server. If
-/// rtmpt is specified, Flash Player will create an HTTP "tunneling"
-/// connection to the server. For more information on RTMP and RTMPT,
-/// see the description section below.
-//
-/// You can omit the host parameter if the Flash movie is served from
-/// the same host where Flash Communication Server is installed.
-/// If the instanceName parameter is omitted, Flash Player connects to
-/// the application's default instance (_definst_).
-/// By default, RTMP connections use port 1935, and RTMPT connections
-/// use port 80.
+/*static private*/
+int
+NetConnection::progress_callback(void *clientp, double dltotal, 
+               double dlnow, double /*ultotal*/, double /*ulnow*/)
+{
+
+       NetConnection* stream = (NetConnection*)clientp;
+       stream->totalSize = dltotal;
+       /*if (stream->callback && stream->callback_cache >= dltotal) {
+               stream->netStreamObj->startPlayback();
+               stream->callback = false;
+       }*/
+       printf("\tprogress callback, cached: %lf, totalsize: %lf\n", dlnow, 
dltotal);
+       return 0;
+}
+
+/*static private*/
+size_t
+NetConnection::recv(void *buf, size_t  size,  size_t  nmemb, 
+       void *userp)
+{
+
+       NetConnection* stream = (NetConnection*)userp;
+       return stream->cache(buf, size*nmemb);
+}
+
+       
+/*private*/
+size_t
+NetConnection::cache(void *from, size_t sz)
+{
+       // take note of current position
+       long curr_pos = ftell(_cache);
+
+       // seek to the end
+       fseek(_cache, 0, SEEK_END);
+
+       size_t wrote = fwrite(from, 1, sz, _cache);
+       if ( wrote < 1 )
+       {
+               char errmsg[256];
+       
+               snprintf(errmsg, 255,
+                       "writing to cache file: requested " SIZET_FMT ", wrote 
" SIZET_FMT " (%s)",
+                       sz, wrote, strerror(errno));
+               fprintf(stderr, "%s\n", errmsg);
+               throw gnash::GnashException(errmsg);
+       }
+
+       // reset position for next read
+       fseek(_cache, curr_pos, SEEK_SET);
+
+       return wrote;
+}
+
+/*public*/
+size_t
+NetConnection::tell()
+{
+       long ret =  ftell(_cache);
+
+       return ret;
+
+}
+
+/*private*/
+void
+NetConnection::fill_cache(off_t size)
+{
+       struct stat statbuf;
+
+       CURLMcode mcode;
+       while (_running)
+       {
+               do
+               {
+                       mcode=curl_multi_perform(_mhandle, &_running);
+               } while ( mcode == CURLM_CALL_MULTI_PERFORM );
+
+               if ( mcode != CURLM_OK )
+               {
+                       throw gnash::GnashException(curl_multi_strerror(mcode));
+               }
+
+               // we already have that much data
+               fstat(_cachefd, &statbuf);
+               if ( statbuf.st_size >= size ) 
+               {
+                       return;
+               }
+
+
+       }
+
+}
 NetConnection::NetConnection() {
 }
 
 NetConnection::~NetConnection() {
+       curl_multi_remove_handle(_mhandle, _handle);
+       curl_easy_cleanup(_handle);
+       curl_multi_cleanup(_mhandle);
+       fclose(_cache);
 }
 
 /// Open a connection to stream FLV files.
@@ -74,69 +170,146 @@
 /// the parameter, which therefor only connects to the localhost using
 /// RTMP. Newer Flash movies have a parameter to connect which is a
 /// URL string like rtmp://foobar.com/videos/bar.flv
-bool
-NetConnection::connect(const char *arg)
+/*public*/
+bool NetConnection::openConnection(const char* char_url, as_object* ns, bool 
local)
 {
-    GNASH_REPORT_FUNCTION;
-    
-    string::size_type first_colon;
-    string::size_type second_colon;
-    string::size_type single_slash;
-    string::size_type double_slash;
-
-    if (arg != 0) {
-        if (strcmp(arg, "null") == 0) {
-            log_warning("No URL specified!\n");
+       netStreamObj = ns;
+       _url = std::string(char_url);
+       _running = 1;
+       _cache = NULL;
+
+       localFile = local;
+
+       if (localFile) {
+               _cache = fopen(char_url, "rb");
+               if (_cache) {
+                       _cachefd = fileno(_cache);
+                       return true;
+               } else {
+                       _cachefd = -1;
             return false;
         }
-        _url = arg;
-        // protocol:[//host][:port]/appname/[instanceName]
-        first_colon = _url.find(':', 0);
-        second_colon = _url.find(':', first_colon + 1);
-        double_slash = _url.find("//", 0) + 2;
-        single_slash = _url.find("/", double_slash);
-        _protocol = _url.substr(0, first_colon);
-        if (second_colon != string::npos) {
-            _host = _url.substr(double_slash, second_colon - double_slash);
-            _portstr = _url.substr(second_colon + 1, single_slash - 
second_colon - 1);
-            _port = (short)strtol(_portstr.c_str(), NULL, 0);
-        } else {
-            _host = _url.substr(double_slash, single_slash - double_slash);
-            if (_protocol == "rtmp") {
-                _port = RTMP;
             }
-            if (_protocol == "http") {
-                _port = RTMPT;
+
+       ensure_libcurl_initialized();
+
+       _handle = curl_easy_init();
+       _mhandle = curl_multi_init();
+
+       /// later on we might want to accept a filename
+       /// in the constructor
+       _cache = tmpfile();
+       if ( ! _cache ) {
+               throw gnash::GnashException("Could not create temporary cache 
file");
             }
+       _cachefd = fileno(_cache);
+
+       CURLcode ccode;
+       CURLMcode mcode;
+
+       ccode = curl_easy_setopt(_handle, CURLOPT_USERAGENT, "Gnash-" VERSION);
+       if ( ccode != CURLE_OK ) {
+               throw gnash::GnashException(curl_easy_strerror(ccode));
         }
-        _path = _url.substr(single_slash, _url.size());
 
         
-        if (_portstr.size() == 0) {
-            log_msg("Loading FLV file from: %s://%s%s\n",
-                    _protocol.c_str(), _host.c_str(), _path.c_str());
-        } else {
-            log_msg("Loading FLV file from: %s://%s:%s%s\n",
-                    _protocol.c_str(), _host.c_str(),
-                    _portstr.c_str(), _path.c_str());
+/* from libcurl-tutorial(3)
+When using multiple threads you should set the CURLOPT_NOSIGNAL  option
+to TRUE for all handles. Everything will work fine except that timeouts
+are not honored during the DNS lookup - which you can  work  around  by
+*/
+
+       ccode = curl_easy_setopt(_handle, CURLOPT_NOSIGNAL, true);
+       if ( ccode != CURLE_OK ) {
+               throw gnash::GnashException(curl_easy_strerror(ccode));
         }
-    } else {
-        log_msg("Connecting to localhost\n");
+
+       // set url
+       ccode = curl_easy_setopt(_handle, CURLOPT_URL, char_url);
+       if ( ccode != CURLE_OK ) {
+               throw gnash::GnashException(curl_easy_strerror(ccode));
     }
 
-    RTMPproto proto;
+       // set write data and function
+       ccode = curl_easy_setopt(_handle, CURLOPT_WRITEDATA, this);
+       if ( ccode != CURLE_OK ) {
+               throw gnash::GnashException(curl_easy_strerror(ccode));
+       }
 
-    if (proto.createClient(_host.c_str(), _port)) {
-        proto.handShakeRequest();
-        proto.clientFinish();
-    } else {
-        dbglogfile << "ERROR: Couldn't connect to server!" << endl;
-        return false;
+       ccode = curl_easy_setopt(_handle, CURLOPT_WRITEFUNCTION,
+               NetConnection::recv);
+       if ( ccode != CURLE_OK ) {
+               throw gnash::GnashException(curl_easy_strerror(ccode));
+       }
+
+       ccode = curl_easy_setopt(_handle, CURLOPT_FOLLOWLOCATION, 1);
+       if ( ccode != CURLE_OK ) {
+               throw gnash::GnashException(curl_easy_strerror(ccode));
+       }
+
+       // set progress callback and function
+       ccode = curl_easy_setopt(_handle, CURLOPT_PROGRESSFUNCTION, 
+               NetConnection::progress_callback);
+       if ( ccode != CURLE_OK ) {
+               throw gnash::GnashException(curl_easy_strerror(ccode));
+       }
+
+       ccode = curl_easy_setopt(_handle, CURLOPT_PROGRESSDATA, this);
+       if ( ccode != CURLE_OK ) {
+               throw gnash::GnashException(curl_easy_strerror(ccode));
     }
 
+       ccode = curl_easy_setopt(_handle, CURLOPT_NOPROGRESS, false);
+       if ( ccode != CURLE_OK ) {
+               throw gnash::GnashException(curl_easy_strerror(ccode));
+       }
+
+       // CURLMcode ret = 
+       mcode = curl_multi_add_handle(_mhandle, _handle);
+       if ( mcode != CURLM_OK ) {
+               throw gnash::GnashException(curl_multi_strerror(mcode));
+       }
+       fill_cache(50000); // pre-cache 50 Kbytes
+
+}
+/*public*/
+bool
+NetConnection::eof()
+{
+       bool ret = ( ! _running && feof(_cache) );
+       
+       return ret;
+
+}
+/*public*/
+size_t
+NetConnection::read(void *dst, size_t bytes)
+{
+       if ( eof() ) return 0;
+
+       if (!localFile) fill_cache(tell()+bytes);
+
+       return fread(dst, 1, bytes, _cache);
+
+}
+
+/*public*/
+bool
+NetConnection::seek(size_t pos)
+{
+       if (!localFile) fill_cache(pos);
+
+       if ( fseek(_cache, pos, SEEK_SET) == -1 ) {
+               return false;
+       } else {
     return true;
+       }
+
 }
 
+
+#endif // HAVE_CURL_CURL_H
+
 /// \brief callback to instantiate a new NetConnection object.
 /// \param fn the parameters from the Flash movie
 /// \return nothing from the function call.
@@ -145,25 +318,17 @@
 netconnection_new(const fn_call& fn)
 {
     GNASH_REPORT_FUNCTION;
-//    log_msg("%s: %d args\n", __PRETTY_FUNCTION__, fn.nargs);
         
     netconnection_as_object *netconnection_obj = new netconnection_as_object;
 
     netconnection_obj->set_member("connect", &netconnection_connect);
-#ifdef ENABLE_TESTING
-    netconnection_obj->set_member("geturl",  &netconnection_geturl);
-    netconnection_obj->set_member("getprotocol",  &netconnection_getprotocol);
-    netconnection_obj->set_member("gethost", &netconnection_gethost);
-    netconnection_obj->set_member("getport", &netconnection_getport);
-    netconnection_obj->set_member("getpath", &netconnection_getpath);
-#endif
+
     fn.result->set_as_object(netconnection_obj);
 }
 
 void netconnection_connect(const fn_call& fn)
 {
     GNASH_REPORT_FUNCTION;
-//    log_msg("%s: %d args\n", __PRETTY_FUNCTION__, fn.nargs);
     
     string filespec;
     netconnection_as_object *ptr = (netconnection_as_object*)fn.this_ptr;
@@ -171,71 +336,12 @@
     assert(ptr);
     if (fn.nargs != 0) {
         filespec = fn.env->bottom(fn.first_arg_bottom_index).to_string();
-        ptr->obj.connect(filespec.c_str());
+//        ptr->obj.connect(filespec.c_str());
     } else {
-        ptr->obj.connect(0);
+//        ptr->obj.connect(0);
     }    
 }
 
-#ifdef ENABLE_TESTING
-// These are the callbacks used to define custom methods for our AS
-// classes. This way we can examine the private dats after calling a
-// method to see if it worked correctly.
-void netconnection_geturl(const fn_call& fn)
-{
-
-    netconnection_as_object *ptr = (netconnection_as_object*)fn.this_ptr;
-    assert(ptr);
-    fn.result->set_tu_string(ptr->obj.getURL().c_str());
-}
-
-void netconnection_getprotocol(const fn_call& fn)
-{
-    netconnection_as_object *ptr = (netconnection_as_object*)fn.this_ptr;
-    assert(ptr);
-    fn.result->set_tu_string(ptr->obj.getProtocol().c_str());
-}
-
-void netconnection_gethost(const fn_call& fn)
-{
-    netconnection_as_object *ptr = (netconnection_as_object*)fn.this_ptr;
-    assert(ptr);
-    fn.result->set_tu_string(ptr->obj.getHost().c_str());
-}
-
-void netconnection_getport(const fn_call& fn)
-{
-    netconnection_as_object *ptr = (netconnection_as_object*)fn.this_ptr;
-    assert(ptr);
-    fn.result->set_tu_string(ptr->obj.getPortStr().c_str());
-}
-
-void netconnection_getpath(const fn_call& fn)
-{
-    netconnection_as_object *ptr = (netconnection_as_object*)fn.this_ptr;
-    assert(ptr);
-    fn.result->set_tu_string(ptr->obj.getPath().c_str());
-}
-
-void netconnection_connected(const fn_call& fn)
-{
-    netconnection_as_object *ptr = (netconnection_as_object*)fn.this_ptr;
-    assert(ptr);
-    fn.result->set_bool(ptr->obj.connected());
-}
-void netconnection_getfilefd(const fn_call& fn)
-{
-    netconnection_as_object *ptr = (netconnection_as_object*)fn.this_ptr;
-    assert(ptr);
-    fn.result->set_int(ptr->obj.getFileFd());
-}
-void netconnection_getlistenfd(const fn_call& fn)
-{
-    netconnection_as_object *ptr = (netconnection_as_object*)fn.this_ptr;
-    assert(ptr);
-    fn.result->set_int(ptr->obj.getListenFd());
-}
-#endif
 
 } // end of gnash namespace
 

Index: server/asobj/NetConnection.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetConnection.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- server/asobj/NetConnection.h        20 Nov 2006 21:44:24 -0000      1.9
+++ server/asobj/NetConnection.h        13 Jan 2007 20:06:17 -0000      1.10
@@ -14,9 +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: */
 
 #ifndef __NETCONNECTION_H__
 #define __NETCONNECTION_H__
@@ -25,49 +23,122 @@
 #include "config.h"
 #endif
 
+#ifdef HAVE_CURL_CURL_H
+#include <curl/curl.h>
+#include <stdexcept>
+#include <cstdio>
+#include <cerrno>
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
 #include <string>
 
 // TODO: port to new AS architecture
 //
 #include "as_object.h" // for inheritance
 #include "fn_call.h"
-#include "network.h"
 
 namespace gnash {
-    
-class NetConnection : public Network {
+#ifdef HAVE_CURL_CURL_H
+class NetConnection {
 public:
+
     NetConnection();
     ~NetConnection();
-    bool connect(const char *arg);
- private:
-    std::string _app;
-    std::string _flashVer;
-    std::string _swfUrl;
-    std::string _tcUrl;
+
+       /// Opens the connection to char_url
+       bool openConnection(const char* char_url, as_object* ns, bool local);
+
+       /// Put read pointer at given position
+       bool seek(size_t pos);
+
+       /// Read 'bytes' bytes into the given buffer.
+       //
+       /// Return number of actually read bytes
+       ///
+       size_t read(void *dst, size_t bytes);
+
+       /// Return true if EOF has been reached
+       bool eof();
+
+       /// Report global position within the file
+       size_t tell();
+
+private:
+       // Use this file to cache data
+       FILE* _cache;
+
+       // _cache file descriptor
+       int _cachefd;
+
+       // we keep a copy here to be sure the char*
+       // is alive for the whole CurlStreamFile lifetime
+       // TODO: don't really do this :)
+       std::string _url;
+
+       // the libcurl easy handle
+       CURL *_handle;
+
+       // the libcurl multi handle
+       CURLM *_mhandle;
+
+       // transfer in progress
+       int _running;
+
+       // Attempt at filling the cache up to the given size.
+       // Will call libcurl routines to fetch data.
+       void fill_cache(off_t size);
+
+       // Append sz bytes to the cache
+       size_t cache(void *from, size_t sz);
+
+       void printInfo();
+
+       // Callback for libcurl, will be called
+       // by fill_cache() and will call cache() 
+       static size_t recv(void *buf, size_t  size, 
+               size_t  nmemb, void *userp);
+
+       // If the file is local
+       bool localFile;
+
+       // The NetStream object which handles the video playback
+       as_object* netStreamObj;
+
+       // Total filesize
+       double totalSize;
+
+       // Callback for libcurl, will be used to detect total filesize
+       static int progress_callback(void *clientp, double dltotal, 
+               double dlnow, double ultotal, double ulnow);
+
+
+};
+
+#else
+class NetConnection {
+public:
+       NetConnection() {};
+       ~NetConnection() {};
+       bool openConnection(const char* /*char_url*/, as_object* /*ns*/) { 
return false; };
 };
 
+#endif // HAVE_CURL_CURL_H
+
 class netconnection_as_object : public as_object
 {
 public:
     NetConnection obj;
+       /*void seek(int pos) { obj.seek(pos); }
+       void read(void* buf, int buf_size) { 
obj.read(static_cast<uint8_t*>(buf), buf_size); }
+       void openConnection(as_object* ns, const char* url) { 
obj.openConnection(url, ns); }
+       int getFD() { return obj.getFD(); }*/
 };
 
 DSOEXPORT void netconnection_new(const fn_call& fn);
 DSOEXPORT void netconnection_connect(const fn_call& fn);
 
-#ifdef ENABLE_TESTING 
-
-DSOEXPORT void netconnection_geturl(const fn_call& fn);
-DSOEXPORT void netconnection_getprotocol(const fn_call& fn);
-DSOEXPORT void netconnection_gethost(const fn_call& fn);
-DSOEXPORT void netconnection_getport(const fn_call& fn);
-DSOEXPORT void netconnection_getpath(const fn_call& fn);
-DSOEXPORT void netconnection_connected(const fn_call& fn);
-
-DSOEXPORT void netconnection_getfilefd(const fn_call& fn);
-DSOEXPORT void netconnection_getlistenfd(const fn_call& fn);
-#endif
 
 } // end of gnash namespace
 

Index: server/asobj/NetStream.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStream.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- server/asobj/NetStream.h    5 Dec 2006 14:26:10 -0000       1.15
+++ server/asobj/NetStream.h    13 Jan 2007 20:06:17 -0000      1.16
@@ -18,7 +18,7 @@
 //
 //
 
-/*  $Id: NetStream.h,v 1.15 2006/12/05 14:26:10 tgc Exp $ */
+/*  $Id: NetStream.h,v 1.16 2007/01/13 20:06:17 tgc Exp $ */
 
 #ifndef __NETSTREAM_H__
 #define __NETSTREAM_H__
@@ -32,7 +32,7 @@
 #include "impl.h"
 #include "video_stream_instance.h"
 #include "NetStreamFfmpeg.h"
-
+#include "NetStreamGst.h"
 
 namespace gnash {
   
@@ -44,7 +44,7 @@
        ~NetStreamBase(){}
        void close(){}
        void pause(int /*mode*/){}
-       int play(const char* /*source*/){ log_error("FFMPEG is needed to play 
video"); return 0; }
+       int play(const char* /*source*/){ log_error("FFMPEG or Gstreamer is 
needed to play video"); return 0; }
        void seek(unsigned int /*pos*/){}
        void setBufferTime(unsigned int /*pos*/){}
        void set_status(const char* /*code*/){}
@@ -62,7 +62,9 @@
 
 };
 
-#ifdef USE_FFMPEG
+#ifdef SOUND_GST
+class NetStream : public NetStreamGst {
+#elif defined(USE_FFMPEG)
 class NetStream : public NetStreamFfmpeg {
 #else
 class NetStream : public NetStreamBase {

Index: server/asobj/NetStreamFfmpeg.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamFfmpeg.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- server/asobj/NetStreamFfmpeg.cpp    12 Jan 2007 11:20:15 -0000      1.4
+++ server/asobj/NetStreamFfmpeg.cpp    13 Jan 2007 20:06:17 -0000      1.5
@@ -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.4 2007/01/12 11:20:15 bjacques Exp $ */
+/* $Id: NetStreamFfmpeg.cpp,v 1.5 2007/01/13 20:06:17 tgc Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -26,9 +26,10 @@
 #include "NetStreamFfmpeg.h"
 #include "fn_call.h"
 #include "NetStream.h"
-
+#include "URLAccessManager.h"
 #include "render.h"    
 #include "movie_root.h"
+#include "NetConnection.h"
 
 #include "URL.h"
 #include "tu_file.h"
@@ -136,7 +137,7 @@
                m_qaudio.pop();
        }
 
-       delete input;
+       //delete input;
 
 }
 
@@ -146,9 +147,11 @@
 
        NetStreamFfmpeg* ns = static_cast<NetStreamFfmpeg*>(opaque);
 
-       int ret = ns->input->read_bytes(static_cast<void*>(buf), buf_size);
+       netconnection_as_object* nc = 
static_cast<netconnection_as_object*>(ns->netCon);
+       size_t ret = nc->obj.read(static_cast<void*>(buf), buf_size);
        ns->inputPos += ret;
        return ret;
+
 }
 
 // ffmpeg callback function
@@ -156,22 +159,24 @@
 NetStreamFfmpeg::seekMedia(void *opaque, offset_t offset, int whence){
 
        NetStreamFfmpeg* ns = static_cast<NetStreamFfmpeg*>(opaque);
+       netconnection_as_object* nc = 
static_cast<netconnection_as_object*>(ns->netCon);
+
 
        // Offset is absolute new position in the file
        if (whence == SEEK_SET) {
-               ns->input->set_position(offset);
+               nc->obj.seek(offset);
                ns->inputPos = offset;
 
        // New position is offset + old position
        } else if (whence == SEEK_CUR) {
-               ns->input->set_position(ns->inputPos + offset);
+               nc->obj.seek(ns->inputPos + offset);
                ns->inputPos = ns->inputPos + offset;
 
        //      // New position is offset + end of file
        } else if (whence == SEEK_END) {
                // This is (most likely) a streamed file, so we can't seek to 
the end!
                // Instead we seek to 50.000 bytes... seems to work fine...
-               ns->input->set_position(50000);
+               nc->obj.seek(50000);
                ns->inputPos = 50000;
                
        }
@@ -205,19 +210,23 @@
 NetStreamFfmpeg::startPlayback(void* arg)
 {
        NetStreamFfmpeg* ns = static_cast<NetStreamFfmpeg*>(arg);
+       netconnection_as_object* nc = 
static_cast<netconnection_as_object*>(ns->netCon);
 
        URL uri(ns->url);
 
-       ns->input = ns->streamProvider.getStream(uri);
-       if (ns->input == NULL)
+       // Check if we're allowed to open url
+       if (URLAccessManager::allow(uri)) {
+
+               bool local = false;
+               if (uri.protocol() == "file")
        {
-           log_error("failed to open '%s'; can't create movie.\n", 
ns->url.c_str());
-           return 0;
+                       local = true;
        }
-       else if (ns->input->get_error())
-       {
-           log_error("streamProvider opener can't open '%s'\n", 
ns->url.c_str());
-           return 0;
+
+               // Pass stuff from/to the NetConnection object.
+               nc->obj.openConnection(ns->url.c_str(), ns->m_netstream_object, 
local);
+       } else {
+               log_warning("Gnash is not allowed to open movie url: %s", 
ns->url.c_str());
        }
 
        ns->inputPos = 0;
@@ -229,9 +238,6 @@
        av_register_all();
 
        // Open video file
-       // The last three parameters specify the file format, buffer size and 
format parameters;
-       // by simply specifying NULL or 0 we ask libavformat to auto-detect the 
format 
-       // and use a default buffer size
 
        // Probe the file to detect the format
        AVProbeData probe_data, *pd = &probe_data;
@@ -242,16 +248,19 @@
 
        AVInputFormat* inputFmt = av_probe_input_format(pd, 1);
 
+       // After the format probe, reset to the beginning of the file.
+       nc->obj.seek(0);
+
        // Setup the filereader/seeker mechanism. 7th argument (NULL) is the 
writer function,
        // which isn't needed.
        init_put_byte(&ns->ByteIOCxt, new uint8_t[500000], 500000, 0, ns, 
NetStreamFfmpeg::readPacket, NULL, NetStreamFfmpeg::seekMedia);
-       ns->ByteIOCxt.is_streamed = 0;
+       ns->ByteIOCxt.is_streamed = 1;
 
        ns->m_FormatCtx = av_alloc_format_context();
 
        // Open the stream. the 4th argument is the filename, which we ignore.
        if(av_open_input_stream(&ns->m_FormatCtx, &ns->ByteIOCxt, "", inputFmt, 
NULL) < 0){
-               log_error("Couldn't open file '%s'", ns->url.c_str());
+               log_error("Couldn't open file '%s' for decoding", 
ns->url.c_str());
                ns->set_status("NetStream.Play.StreamNotFound");
                return 0;
        }
@@ -426,12 +435,13 @@
                        }
                        else
                        {
-                               delay = int(video_clock - clock);
+                               delay = int((video_clock - clock)*1000000);
                        }
 
                        // Don't hog the CPU.
                        // Queues have filled, video frame have shown
                        // now it is possible and to have a rest
+
                        if (ns->m_unqueued_data && delay > 0)
                        {
                                usleep(delay);
@@ -512,7 +522,10 @@
 
                                        bool stereo = m_ACodecCtx->channels > 1 
? true : false;
                                        int samples = stereo ? frame_size >> 2 
: frame_size >> 1;
+
+                                       // This convertion only works for 5.5, 
11, 22 and 44 KHz. 32KHz causes problems.
                                        s->convert_raw_data(&adjusted_data, &n, 
ptr, samples, 2, m_ACodecCtx->sample_rate, stereo);
+
                                        raw_videodata_t* raw = new 
raw_videodata_t;
                                        raw->m_data = (uint8_t*) adjusted_data;
                                        raw->m_ptr = raw->m_data;
@@ -609,11 +622,9 @@
                                } else if (videoFrameFormat == render::RGB) {
                                        for(int line = 0; line < 
m_VCodecCtx->height; line++)
                                        {
-                                               int lineInv = 
m_VCodecCtx->height - line - 1; //the picture is y-inverted we have to flip 
lines
                                                for(int byte = 0; byte < 
(m_VCodecCtx->width*3); byte++)
                                                {
-                                               //printf("dst: %d, src: %d\n", 
byte + (lineInv*m_VCodecCtx->width*3), (line*m_Frame->linesize[0])+byte);
-                                                       video->m_data[byte + 
(lineInv*m_VCodecCtx->width*3)] = (unsigned char) 
*(m_Frame->data[0]+(line*m_Frame->linesize[0])+byte);
+                                                       video->m_data[byte + 
(line*m_VCodecCtx->width*3)] = (unsigned char) 
*(m_Frame->data[0]+(line*m_Frame->linesize[0])+byte);
                                                }
                                        }   
                                }

Index: server/asobj/NetStreamFfmpeg.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamFfmpeg.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- server/asobj/NetStreamFfmpeg.h      5 Dec 2006 14:26:10 -0000       1.1
+++ server/asobj/NetStreamFfmpeg.h      13 Jan 2007 20:06:17 -0000      1.2
@@ -14,9 +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: */
 
 #ifndef __NETSTREAMFFMPEG_H__
 #define __NETSTREAMFFMPEG_H__

Index: libbase/gstgnashsrc.c
===================================================================
RCS file: libbase/gstgnashsrc.c
diff -N libbase/gstgnashsrc.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libbase/gstgnashsrc.c       13 Jan 2007 20:06:17 -0000      1.1
@@ -0,0 +1,329 @@
+// 
+//   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 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
+// 
+// Based on the filesrc and fdsrc element in Gstreamer-core.
+//
+
+/* $id: */
+
+#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)
+{
+/*  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)
+{
+
+  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;
+
+  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)
+{
+  struct stat stat_results;
+  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);
+  struct stat stat_results;
+
+  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);
+
+  return TRUE;
+}
+

Index: libbase/gstgnashsrc.h
===================================================================
RCS file: libbase/gstgnashsrc.h
diff -N libbase/gstgnashsrc.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libbase/gstgnashsrc.h       13 Jan 2007 20:06:17 -0000      1.1
@@ -0,0 +1,97 @@
+// 
+//   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 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
+// 
+// Based on the filesrc and fdsrc element in Gstreamer-core
+//
+
+/* $id: */
+
+#ifndef __GST_GNASH_SRC_H__
+#define __GST_GNASH_SRC_H__
+
+#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
+
+static gboolean
+register_elements (GstPlugin *plugin)
+{
+  return gst_element_register (plugin, "gnashsrc", GST_RANK_NONE, 
GST_TYPE_GNASH_SRC);
+}
+
+static GstPluginDesc gnash_plugin_desc = {
+  0, // GST_VERSION_MAJOR
+  10, // GST_VERSION_MINOR
+  "gnashsrc",
+  "Use gnash as source via callbacks",
+  register_elements,
+  "0.0.1",
+  "LGPL",
+  "gnash",
+  "gnash",
+  "http://www.gnu.org/software/gnash/";,
+  GST_PADDING_INIT
+};
+
+#endif /* __GST_GNASH_SRC_H__ */

Index: server/asobj/NetStreamGst.cpp
===================================================================
RCS file: server/asobj/NetStreamGst.cpp
diff -N server/asobj/NetStreamGst.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ server/asobj/NetStreamGst.cpp       13 Jan 2007 20:06:17 -0000      1.1
@@ -0,0 +1,428 @@
+// 
+//   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 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: */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef SOUND_GST
+
+#include "log.h"
+#include "NetStreamGst.h"
+#include "fn_call.h"
+#include "NetStream.h"
+#include "URLAccessManager.h"
+#include "render.h"    
+#include "movie_root.h"
+#include "NetConnection.h"
+
+#include "gstgnashsrc.h"
+
+#include "URL.h"
+
+#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 {
+
+
+NetStreamGst::NetStreamGst():
+
+       m_go(false),
+       m_imageframe(NULL),
+       m_video_clock(0),
+       m_pause(false),
+       //m_unqueued_data(NULL),
+       inputPos(0),
+       videowidth(0),
+       videoheight(0)
+{
+}
+
+NetStreamGst::~NetStreamGst()
+{
+       close();
+}
+
+// called from avstreamer thread
+void NetStreamGst::set_status(const char* /*code*/)
+{
+       if (m_netstream_object)
+       {
+               //m_netstream_object->set_member("onStatus_Code", code);
+               //push_video_event(m_netstream_object);
+       }
+}
+
+void NetStreamGst::pause(int mode)
+{
+       if (mode == -1)
+       {
+               m_pause = ! m_pause;
+       }
+       else
+       {
+               m_pause = (mode == 0) ? true : false;
+       }
+       if (m_pause) gst_element_set_state (GST_ELEMENT (pipeline), 
GST_STATE_PAUSED);
+       else  gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
+}
+
+void NetStreamGst::close()
+{
+       if (m_go)
+       {
+               // terminate thread
+               m_go = false;
+
+               // wait till thread is complete before main continues
+               //pthread_join(m_thread, NULL);
+       }
+
+       gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
+       gst_object_unref (GST_OBJECT (pipeline));
+
+       if (m_imageframe) delete m_imageframe;
+
+       while (m_qvideo.size() > 0)
+       {
+               delete m_qvideo.front();
+               m_qvideo.pop();
+       }
+
+}
+
+
+int
+NetStreamGst::play(const char* c_url)
+{
+
+       // Is it already playing ?
+       if (m_go)
+       {
+               if (m_pause) {
+                       m_pause = false;
+                       gst_element_set_state (GST_ELEMENT (pipeline), 
GST_STATE_PLAYING);
+               }
+               return 0;
+       }
+
+       url += c_url;
+       m_go = true;
+
+       // To avoid blocking while connecting, we use a thread.
+       if (pthread_create(&startThread, NULL, NetStreamGst::startPlayback, 
this) != 0)
+       {
+               return 0;
+       };
+       return 0;
+}
+
+
+// Callback function used by Gstreamer to to attached audio and video streams
+// detected by decoderbin to either the video out or audio out elements.
+void
+NetStreamGst::callback_newpad (GstElement* /*decodebin*/, GstPad *pad, 
gboolean /*last*/, gpointer data)
+{
+
+       NetStreamGst* ns = static_cast<NetStreamGst*>(data);
+       GstCaps *caps;
+       GstStructure *str;
+       GstPad *audiopad, *videopad;
+
+       audiopad = gst_element_get_pad (ns->audioconv, "sink");
+       videopad = gst_element_get_pad (ns->colorspace, "sink");
+
+       // check media type
+       caps = gst_pad_get_caps (pad);
+       str = gst_caps_get_structure (caps, 0);
+       if (g_strrstr (gst_structure_get_name (str), "audio")) {
+               gst_object_unref (videopad);
+
+               // link'n'play
+               gst_pad_link (pad, audiopad);
+
+       } else if (g_strrstr (gst_structure_get_name (str), "video")) {
+               gst_object_unref (audiopad);
+               // Link'n'play
+               gst_pad_link (pad, videopad);
+       } else {
+               gst_object_unref (audiopad);
+               gst_object_unref (videopad);
+       }
+       gst_caps_unref (caps);
+       return;
+
+}
+
+// The callback function which unloads the decoded video frames unto the video
+// output imageframe.
+void 
+NetStreamGst::callback_output (GstElement* /*c*/, GstBuffer *buffer, GstPad* 
/*pad*/, gpointer user_data)
+{
+
+       NetStreamGst* ns = static_cast<NetStreamGst*>(user_data);
+
+       // If the video size has not yet been detected, detect them
+       if (ns->videowidth == 0 && ns->videoheight == 0) {
+               GstPad* videopad = gst_element_get_pad (ns->colorspace, "src");
+               GstCaps* caps = gst_pad_get_caps (videopad);
+               GstStructure* str = gst_caps_get_structure (caps, 0);
+
+               int height, width, ret, framerate1, framerate2;
+               ret = gst_structure_get_int (str, "width", &width);
+               ret &= gst_structure_get_int (str, "height", &height);
+               if (ret) {
+                       ns->videowidth = width;
+                       ns->videoheight = height;
+               }
+               ret = gst_structure_get_fraction (str, "framerate", 
&framerate1, &framerate2);
+               
+               // Setup the output videoframe
+               int videoFrameFormat = gnash::render::videoFrameFormat();
+               if (videoFrameFormat == render::YUV) {
+                       ns->m_imageframe = new image::yuv(width, height);
+               } else if (videoFrameFormat == render::RGB) {
+                       ns->m_imageframe = new image::rgb(width, height);
+               }
+       }
+
+       if (ns->m_imageframe) {
+//             ns->m_imageframe->update(GST_BUFFER_DATA(buffer));
+               if (gnash::render::videoFrameFormat() == render::YUV) {
+                       assert(0);
+
+               /*      image::yuv* yuvframe = 
static_cast<image::yuv*>(m_imageframe);
+                       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 {
+                       ns->m_imageframe->update(GST_BUFFER_DATA(buffer));
+               }
+
+       }
+
+}
+
+
+void*
+NetStreamGst::startPlayback(void* arg)
+{
+       NetStreamGst* ns = static_cast<NetStreamGst*>(arg);
+       netconnection_as_object* nc = 
static_cast<netconnection_as_object*>(ns->netCon);
+       URL uri(ns->url);
+
+       // Check if we're allowed to open url
+       if (URLAccessManager::allow(uri)) {
+               bool local = false;
+               if (uri.protocol() == "file")
+               {
+                       local = true;
+               }
+
+               // Pass stuff from/to the NetConnection object.
+               nc->obj.openConnection(ns->url.c_str(), ns->m_netstream_object, 
local);
+       } else {
+               log_warning("Gnash is not allowed to open movie url: %s", 
ns->url.c_str());
+               return 0;
+       }
+
+       ns->inputPos = 0;
+
+       // init GStreamer
+       gst_init (NULL, NULL);
+
+       // setup the GnashNC plugin
+       _gst_plugin_register_static (&gnash_plugin_desc);
+
+       // setup the pipeline
+       ns->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 the gstreamer adder ever gets fixed this should be connected to 
the
+       // adder in the soundhandler.
+#if !defined(__NetBSD__)
+       ns->audiosink = gst_element_factory_make ("autoaudiosink", NULL);
+       if (!ns->audiosink) ns->audiosink = gst_element_factory_make 
("alsasink", NULL);
+       if (!ns->audiosink) ns->audiosink = gst_element_factory_make 
("osssink", NULL);
+#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 0;
+       }
+       if (!ns->audiosink) {
+               gnash::log_error("The gstreamer audiosink element could not be 
created\n");
+               return 0;
+       }
+
+       // setup gnashnc source (our homegrown source element)
+       ns->source = gst_element_factory_make ("gnashsrc", NULL);
+       gnashsrc_callback* gc = new gnashsrc_callback;
+       gc->read = NetStreamGst::readPacket;
+       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);
+       g_signal_connect (ns->decoder, "new-decoded-pad", G_CALLBACK 
(NetStreamGst::callback_newpad), ns);
+
+       // setup the video colorspaceconverter converter
+       ns->colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
+
+       // Setup the capsfilter which demands either YUV or RGB videoframe 
format
+       ns->videocaps = gst_element_factory_make ("capsfilter", NULL);
+       GstCaps* caps;
+       if (gnash::render::videoFrameFormat() == render::YUV) {
+               caps = gst_caps_new_simple ("video/x-raw-yuv", NULL);
+       } else {
+               caps = gst_caps_new_simple ("video/x-raw-rgb", NULL);
+       }
+       g_object_set (G_OBJECT (ns->videocaps), "caps", caps, NULL);
+       gst_caps_unref (caps);
+
+       // Setup the videorate element which makes sure the frames are 
delivered on time.
+       ns->videorate = gst_element_factory_make ("videorate", NULL);
+
+       // Setup the videorate element which makes sure the frames are 
delivered on time.
+/*     ns->videoflip = gst_element_factory_make ("videoflip", NULL);
+       g_object_set (G_OBJECT (ns->videoflip), "method", 5, NULL);*/
+
+       // setup the videosink with callback
+       ns->videosink = gst_element_factory_make ("fakesink", NULL);
+       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->videoflip*/ || !ns->videocaps || !ns->videorate || 
!ns->videosink) {
+               gnash::log_error("Gstreamer element(s) for movie handling could 
not be created\n");
+               return 0;
+       }
+
+       // 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->videoflip,*/ 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->videoflip,*/ ns->colorspace, ns->videocaps, 
ns->videorate, ns->videosink, NULL);
+       
+       // start playing        
+       gst_element_set_state (ns->pipeline, GST_STATE_PLAYING);
+       return 0;
+}
+
+void
+NetStreamGst::setNetCon(as_object* nc){
+       netCon = nc;
+}
+
+image::image_base* NetStreamGst::get_video()
+{
+       return m_imageframe;
+}
+
+void
+NetStreamGst::seek()
+{
+    log_msg("%s:unimplemented \n", __FUNCTION__);
+}
+
+void
+NetStreamGst::setBufferTime()
+{
+    log_msg("%s:unimplemented \n", __FUNCTION__);
+}
+
+// Gstreamer callback function
+int 
+NetStreamGst::readPacket(void* opaque, char* buf, int buf_size){
+
+       NetStreamGst* ns = static_cast<NetStreamGst*>(opaque);
+
+       netconnection_as_object* nc = 
static_cast<netconnection_as_object*>(ns->netCon);
+       size_t ret = nc->obj.read(static_cast<void*>(buf), buf_size);
+       ns->inputPos += ret;
+
+       return ret;
+
+}
+
+// Gstreamer callback function
+int 
+NetStreamGst::seekMedia(void *opaque, int offset, int whence){
+
+       NetStreamGst* ns = static_cast<NetStreamGst*>(opaque);
+       netconnection_as_object* nc = 
static_cast<netconnection_as_object*>(ns->netCon);
+
+       bool ret;
+
+       // Offset is absolute new position in the file
+       if (whence == SEEK_SET) {
+               ret = nc->obj.seek(offset);
+               if (!ret) return -1;
+               ns->inputPos = offset;
+
+       // New position is offset + old position
+       } else if (whence == SEEK_CUR) {
+               ret = nc->obj.seek(ns->inputPos + offset);
+               if (!ret) return -1;
+               ns->inputPos = ns->inputPos + offset;
+
+       //      // New position is offset + end of file
+       } else if (whence == SEEK_END) {
+               // This is (most likely) a streamed file, so we can't seek to 
the end!
+               // Instead we seek to 50.000 bytes... seems to work fine...
+               ret = nc->obj.seek(50000);
+               ns->inputPos = 50000;
+       }
+       return ns->inputPos;
+}
+
+} // gnash namespcae
+
+#endif // SOUND_GST

Index: server/asobj/NetStreamGst.h
===================================================================
RCS file: server/asobj/NetStreamGst.h
diff -N server/asobj/NetStreamGst.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ server/asobj/NetStreamGst.h 13 Jan 2007 20:06:17 -0000      1.1
@@ -0,0 +1,234 @@
+// 
+//   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 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: */
+
+#ifndef __NETSTREAMGST_H__
+#define __NETSTREAMGST_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef SOUND_GST
+
+#include <queue>
+#include <pthread.h>
+#include "impl.h"
+#include "video_stream_instance.h"
+#include <gst/gst.h>
+#include "image.h"
+#include "StreamProvider.h"
+
+namespace gnash {
+  
+struct raw_videodata_t
+{
+       raw_videodata_t():
+       m_stream_index(-1),
+       m_size(0),
+       m_data(NULL),
+       m_ptr(NULL),
+       m_pts(0)
+       {
+       };
+
+       ~raw_videodata_t()
+       {
+               if (m_data)
+               {
+                       delete m_data;
+               }
+       };
+
+       int m_stream_index;
+       uint32_t m_size;
+       uint8_t* m_data;
+       uint8_t* m_ptr;
+       double m_pts;   // presentation timestamp in sec
+};
+
+template<class T>
+class multithread_queue
+{
+       public:
+
+       multithread_queue()
+               {
+                       pthread_mutex_init(&m_mutex, NULL);
+               };
+
+       ~multithread_queue()
+               {
+                       lock();
+                       while (m_queue.size() > 0)
+                       {
+                               T x = m_queue.front();
+                               m_queue.pop();
+                               delete x;
+                       }
+                       unlock();
+
+                       pthread_mutex_destroy(&m_mutex);
+               }
+
+               size_t size()
+               {
+                       lock();
+                       size_t n = m_queue.size();
+                       unlock();
+                       return n;
+               }
+
+               bool push(T member)
+               {
+                       bool rc = false;
+                       lock();
+                       if (m_queue.size() < 20)        // hack
+                       {
+                               m_queue.push(member);
+                               rc = true;
+                       }
+                       unlock();
+                       return rc;
+               }
+
+               T front()
+               {
+                       lock();
+                       T member = NULL;
+                       if (m_queue.size() > 0)
+                       {
+                               member = m_queue.front();
+                       }
+                       unlock();
+                       return member;
+               }
+
+               void pop()
+               {
+                       lock();
+                       if (m_queue.size() > 0)
+                       {
+                               m_queue.pop();
+                       }
+                       unlock();
+               }
+
+       private:
+
+               inline void lock()
+               {
+                       pthread_mutex_lock(&m_mutex);
+               }
+
+               inline void unlock()
+               {
+                       pthread_mutex_unlock(&m_mutex);
+               }
+
+               pthread_mutex_t m_mutex;
+               std::queue < T > m_queue;
+};
+
+class netstream_as_object;
+
+class NetStreamGst {
+public:
+       NetStreamGst();
+       ~NetStreamGst();
+       void close();
+       void pause(int mode);
+       int play(const char* source);
+       void seek();
+       void setBufferTime();
+       void set_status(const char* code);
+       void setNetCon(as_object* nc);
+
+       // Used for gstreamer data read and seek callbacks
+       static int readPacket(void* opaque, char* buf, int buf_size);
+       static int seekMedia(void *opaque, int offset, int whence);
+
+       image::image_base* get_video();
+
+       inline bool playing()
+       {
+               return m_go;
+       }
+
+       inline void set_parent(netstream_as_object* ns)
+       {
+               m_netstream_object = ns;
+       }
+
+       static void* startPlayback(void* arg);
+       //static void callback_input (GstElement* /*c*/, GstBuffer *buffer, 
GstPad* /*pad*/, gpointer user_data);
+       static void callback_output (GstElement* /*c*/, GstBuffer *buffer, 
GstPad* /*pad*/, gpointer user_data);
+       static void callback_newpad (GstElement *decodebin, GstPad *pad, 
gboolean last, gpointer data);
+private:
+
+       bool _bufferLength;
+       bool _bufferTime;
+       bool _bytesLoaded;
+       bool _bytesTotal;
+       bool _currentFps;
+       bool _onStatus;
+       bool _time;
+
+       // gstreamer pipeline objects
+       GstElement *pipeline;
+       GstElement *audiosink;
+       GstElement *videosink;
+       GstElement *source;
+       GstElement *decoder;
+       GstElement *volume;
+       GstElement *colorspace;
+       GstElement *videorate;
+       GstElement *videocaps;
+       GstElement *videoflip;
+       GstElement *audioconv;
+
+       // video info
+       int videowidth;
+       int videoheight;
+
+       volatile bool m_go;
+       unsigned int runtime;
+
+       image::image_base* m_imageframe;
+
+       double m_video_clock;
+
+       pthread_t m_thread;
+       pthread_t startThread;
+       multithread_queue <raw_videodata_t*> m_qvideo;
+       bool m_pause;
+//     double m_start_clock;
+       netstream_as_object* m_netstream_object;
+//     raw_videodata_t* m_unqueued_data;
+
+       as_object* netCon;
+       tu_file* input;
+       long inputPos;
+       StreamProvider streamProvider;
+       std::string url;
+};
+
+} // gnash namespace
+
+#endif // SOUND_GST
+
+#endif //  __NETSTREAMGST_H__




reply via email to

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