[Top][All Lists]
[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__
- [Gnash-commit] gnash ChangeLog backend/render_handler_ogl.cpp ...,
Tomas Groth <=