gnash-commit
[Top][All Lists]
Advanced

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

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


From: Tomas Groth
Subject: [Gnash-commit] gnash ChangeLog backend/sound_handler_sdl.cpp s...
Date: Tue, 23 Jan 2007 16:41:28 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Tomas Groth <tgc>       07/01/23 16:41:28

Modified files:
        .              : ChangeLog 
        backend        : sound_handler_sdl.cpp 
        server/asobj   : Global.cpp NetConnection.h NetStream.cpp 
                         NetStream.h NetStreamFfmpeg.cpp 
                         NetStreamFfmpeg.h NetStreamGst.cpp 
                         NetStreamGst.h 

Log message:
        * backend/sound_handler_sdl.cpp: Also resample if samplerate is correct
          but number of channels is not (mono => stereo).
        * server/asobj/Global.cpp: Initialize NetStream using the new method.
        * server/asobj/NetConnection.h: Now compiles without Curl.
        * server/asobj/NetStream.{cpp,h}: Initialize NetStream using the new 
method.
          Implemented the time-property.
        * server/asobj/NetStreamFfmpeg.{cpp,h}: Switched from pthreads to boost.
          Hopefully fixed a thread-join-bug (#18571).
          Use ffmpeg/libavcodec's audio resampler since gnashs own resampler 
only
          supports a limited samplerates.
          Implemented seek() and time().
        * server/asobj/NetStreamGst.{cpp,h}: Implemented seek() and time().

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.2155&r2=1.2156
http://cvs.savannah.gnu.org/viewcvs/gnash/backend/sound_handler_sdl.cpp?cvsroot=gnash&r1=1.43&r2=1.44
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/Global.cpp?cvsroot=gnash&r1=1.33&r2=1.34
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetConnection.h?cvsroot=gnash&r1=1.12&r2=1.13
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStream.cpp?cvsroot=gnash&r1=1.22&r2=1.23
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStream.h?cvsroot=gnash&r1=1.17&r2=1.18
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamFfmpeg.cpp?cvsroot=gnash&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamFfmpeg.h?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamGst.cpp?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamGst.h?cvsroot=gnash&r1=1.3&r2=1.4

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.2155
retrieving revision 1.2156
diff -u -b -r1.2155 -r1.2156
--- ChangeLog   23 Jan 2007 12:40:21 -0000      1.2155
+++ ChangeLog   23 Jan 2007 16:41:27 -0000      1.2156
@@ -1,3 +1,18 @@
+2007-01-23 Tomas Groth Christensen <address@hidden>
+
+       * backend/sound_handler_sdl.cpp: Also resample if samplerate is correct
+         but number of channels is not (mono => stereo).
+       * server/asobj/Global.cpp: Initialize NetStream using the new method.
+       * server/asobj/NetConnection.h: Now compiles without Curl.
+       * server/asobj/NetStream.{cpp,h}: Initialize NetStream using the new 
method.
+         Implemented the time-property.
+       * server/asobj/NetStreamFfmpeg.{cpp,h}: Switched from pthreads to boost.
+         Hopefully fixed a thread-join-bug (#18571).
+         Use ffmpeg/libavcodec's audio resampler since gnashs own resampler 
only
+         supports a limited samplerates.
+         Implemented seek() and time().
+       * server/asobj/NetStreamGst.{cpp,h}: Implemented seek() and time().
+
 2007-01-23 Sandro Santilli <address@hidden>
 
        * testsuite/actionscript.all/: Inheritance.as, MovieClip.as:

Index: backend/sound_handler_sdl.cpp
===================================================================
RCS file: /sources/gnash/gnash/backend/sound_handler_sdl.cpp,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -b -r1.43 -r1.44
--- backend/sound_handler_sdl.cpp       18 Jan 2007 11:53:37 -0000      1.43
+++ backend/sound_handler_sdl.cpp       23 Jan 2007 16:41:27 -0000      1.44
@@ -18,7 +18,7 @@
 // Based on sound_handler_sdl.cpp by Thatcher Ulrich http://tulrich.com 2003
 // which has been donated to the Public Domain.
 
-// $Id: sound_handler_sdl.cpp,v 1.43 2007/01/18 11:53:37 tgc Exp $
+// $Id: sound_handler_sdl.cpp,v 1.44 2007/01/23 16:41:27 tgc Exp $
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -942,8 +942,8 @@
                                        }
 #endif
 
-                                       // If we need to convert samplerate...
-                                       if (outsize > 0 && 
sounddata->sample_rate != handler->audioSpec.freq) {
+                                       // If we need to convert samplerate 
or/and from mono to stereo...
+                                       if (outsize > 0 && 
(sounddata->sample_rate != handler->audioSpec.freq || !sounddata->stereo)) {
 
                                                int16_t* adjusted_data = 0;
                                                int     adjusted_size = 0;

Index: server/asobj/Global.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/Global.cpp,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -b -r1.33 -r1.34
--- server/asobj/Global.cpp     18 Jan 2007 22:53:21 -0000      1.33
+++ server/asobj/Global.cpp     23 Jan 2007 16:41:27 -0000      1.34
@@ -18,7 +18,7 @@
 
 // Implementation of the Global ActionScript Object
 
-/* $Id: Global.cpp,v 1.33 2007/01/18 22:53:21 strk Exp $ */
+/* $Id: Global.cpp,v 1.34 2007/01/23 16:41:27 tgc Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -497,7 +497,7 @@
        //-----------------------
 
        init_member("NetConnection", as_value(netconnection_new));
-       init_member("NetStream", as_value(netstream_new));
+       netstream_class_init(*this);
        contextmenu_class_init(*this);
        moviecliploader_class_init(*this);
        // sephiroth.it refers this to be introduced in SWF7

Index: server/asobj/NetConnection.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetConnection.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- server/asobj/NetConnection.h        18 Jan 2007 11:53:37 -0000      1.12
+++ server/asobj/NetConnection.h        23 Jan 2007 16:41:27 -0000      1.13
@@ -14,7 +14,7 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-/* $Id: NetConnection.h,v 1.12 2007/01/18 11:53:37 tgc Exp $ */
+/* $Id: NetConnection.h,v 1.13 2007/01/23 16:41:27 tgc Exp $ */
 
 #ifndef __NETCONNECTION_H__
 #define __NETCONNECTION_H__
@@ -121,7 +121,9 @@
 public:
        NetConnection() {};
        ~NetConnection() {};
-       bool openConnection(const char* /*char_url*/, as_object* /*ns*/) { 
return false; };
+       bool openConnection(const char* /*char_url*/, as_object* /*ns*/, bool 
/* local */) { return false; };
+       bool seek(size_t /*pos*/) { return 0; }
+       size_t read(void* /*dst*/, size_t /*bytes*/) { return false; }
 };
 
 #endif // HAVE_CURL_CURL_H
@@ -130,10 +132,6 @@
 {
 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);

Index: server/asobj/NetStream.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStream.cpp,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -b -r1.22 -r1.23
--- server/asobj/NetStream.cpp  18 Jan 2007 22:53:21 -0000      1.22
+++ server/asobj/NetStream.cpp  23 Jan 2007 16:41:27 -0000      1.23
@@ -18,7 +18,7 @@
 //
 //
 
-/* $Id: NetStream.cpp,v 1.22 2007/01/18 22:53:21 strk Exp $ */
+/* $Id: NetStream.cpp,v 1.23 2007/01/23 16:41:27 tgc Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -27,31 +27,37 @@
 #include "log.h"
 #include "NetStream.h"
 #include "fn_call.h"
+#include "builtin_function.h"
 
 #include "movie_root.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 {
  
-void
-netstream_new(const fn_call& fn)
+static void netstream_new(const fn_call& fn);
+static void netstream_close(const fn_call& fn);
+static void netstream_pause(const fn_call& fn);
+static void netstream_play(const fn_call& fn);
+static void netstream_seek(const fn_call& fn);
+static void netstream_setbuffertime(const fn_call& fn);
+static void netstream_time(const fn_call& fn);
+static as_object* getNetStreamInterface();
+
+netstream_as_object::netstream_as_object()
+       :
+       as_object(getNetStreamInterface())
 {
-    netstream_as_object *netstream_obj = new netstream_as_object;
+       obj.set_parent(this);
+}
+
+netstream_as_object::~netstream_as_object()
+{
+}
 
-    // FIXME: rely on inheritance
-    netstream_obj->init_member("close", &netstream_close);
-    netstream_obj->init_member("pause", &netstream_pause);
-    netstream_obj->init_member("play", &netstream_play);
-    netstream_obj->init_member("seek", &netstream_seek);
-    netstream_obj->init_member("setBufferTime", &netstream_setbuffertime);
+static void
+netstream_new(const fn_call& fn)
+{
 
-    fn.result->set_as_object(netstream_obj);
+       netstream_as_object *netstream_obj = new netstream_as_object;
 
        if (fn.nargs > 0)
        {
@@ -67,17 +73,19 @@
                        );
                }
        }
+       fn.result->set_as_object(netstream_obj);
 
 }
 
-void netstream_close(const fn_call& fn)
+
+static void netstream_close(const fn_call& fn)
 {
        assert(dynamic_cast<netstream_as_object*>(fn.this_ptr));
        netstream_as_object* ns = 
static_cast<netstream_as_object*>(fn.this_ptr);
        ns->obj.close();
 }
 
-void netstream_pause(const fn_call& fn)
+static void netstream_pause(const fn_call& fn)
 {
        assert(dynamic_cast<netstream_as_object*>(fn.this_ptr));
        netstream_as_object* ns = 
static_cast<netstream_as_object*>(fn.this_ptr);
@@ -91,7 +99,7 @@
        ns->obj.pause(mode);    // toggle mode
 }
 
-void netstream_play(const fn_call& fn)
+static void netstream_play(const fn_call& fn)
 {
        assert(dynamic_cast<netstream_as_object*>(fn.this_ptr));
        netstream_as_object* ns = 
static_cast<netstream_as_object*>(fn.this_ptr);
@@ -108,12 +116,95 @@
        };
 }
 
-void netstream_seek(const fn_call& /*fn*/) {
-    log_msg("%s:unimplemented \n", __FUNCTION__);
+static void netstream_seek(const fn_call& fn) {
+       assert(dynamic_cast<netstream_as_object*>(fn.this_ptr));
+       netstream_as_object* ns = 
static_cast<netstream_as_object*>(fn.this_ptr);
+
+       double time = 0;
+       if (fn.nargs > 0)
+       {
+               time = fn.arg(0).to_number();
+       }
+       ns->obj.seek(time);
+
 }
-void netstream_setbuffertime(const fn_call& /*fn*/) {
+static void netstream_setbuffertime(const fn_call& /*fn*/) {
     log_msg("%s:unimplemented \n", __FUNCTION__);
 }
 
+// Both a getter and a (do-nothing) setter for time
+static void
+netstream_time(const fn_call& fn)
+{
+
+       assert(dynamic_cast<netstream_as_object*>(fn.this_ptr));
+       netstream_as_object* ns = 
static_cast<netstream_as_object*>(fn.this_ptr);
+
+       if ( fn.nargs == 0 )
+       {
+               fn.result->set_double((double)ns->obj.time());
+       }
+       else
+       {
+               IF_VERBOSE_ASCODING_ERRORS(
+                       log_aserror("Tried to set read-only property 
NetStream.time");
+               );
+       }
+}
+
+void
+attachNetStreamInterface(as_object& o)
+{
+
+       o.init_member("close", &netstream_close);
+       o.init_member("pause", &netstream_pause);
+       o.init_member("play", &netstream_play);
+       o.init_member("seek", &netstream_seek);
+       o.init_member("setBufferTime", &netstream_setbuffertime);
+
+
+    // Properties
+
+    boost::intrusive_ptr<builtin_function> gettersetter;
+
+    gettersetter = new builtin_function(&netstream_time, NULL);
+    o.init_property("time", *gettersetter, *gettersetter);
+
+}
+
+static as_object*
+getNetStreamInterface()
+{
+
+       static boost::intrusive_ptr<as_object> o;
+       if ( o == NULL )
+       {
+               o = new as_object();
+               attachNetStreamInterface(*o);
+       }
+
+       return o.get();
+}
+
+// extern (used by Global.cpp)
+void netstream_class_init(as_object& global)
+{
+
+       // This is going to be the global NetStream "class"/"function"
+       static boost::intrusive_ptr<builtin_function> cl;
+
+       if ( cl == NULL )
+       {
+               cl=new builtin_function(&netstream_new, 
getNetStreamInterface());
+               // replicate all interface to class, to be able to access
+               // all methods as static functions
+               attachNetStreamInterface(*cl);
+                    
+       }
+
+       // Register _global.String
+       global.init_member("NetStream", cl.get());
+
+}
 } // end of gnash namespace
 

Index: server/asobj/NetStream.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStream.h,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -b -r1.17 -r1.18
--- server/asobj/NetStream.h    18 Jan 2007 22:53:21 -0000      1.17
+++ server/asobj/NetStream.h    23 Jan 2007 16:41:28 -0000      1.18
@@ -18,7 +18,7 @@
 //
 //
 
-/*  $Id: NetStream.h,v 1.17 2007/01/18 22:53:21 strk Exp $ */
+/*  $Id: NetStream.h,v 1.18 2007/01/23 16:41:28 tgc Exp $ */
 
 #ifndef __NETSTREAM_H__
 #define __NETSTREAM_H__
@@ -45,11 +45,12 @@
        void close(){}
        void pause(int /*mode*/){}
        int play(const char* /*source*/){ log_error("FFMPEG or Gstreamer is 
needed to play video"); return 0; }
-       void seek(unsigned int /*pos*/){}
+       void seek(double /*pos*/){}
        void setBufferTime(unsigned int /*pos*/){}
        void set_status(const char* /*code*/){}
        void setNetCon(as_object* /*nc*/) {}
        image::image_base* get_video(){ return NULL; }
+       long time() { return 0; }
 
        inline void set_parent(netstream_as_object* /*ns*/)
        {
@@ -77,25 +78,16 @@
 {
        public:
        
-       netstream_as_object()
-       {
-               obj.set_parent(this);
-       }
+       netstream_as_object();
 
-       ~netstream_as_object()
-       {
-       }
+       ~netstream_as_object();
 
        NetStream obj;
 
 };
 
-void netstream_new(const fn_call& fn);
-void netstream_close(const fn_call& fn);
-void netstream_pause(const fn_call& fn);
-void netstream_play(const fn_call& fn);
-void netstream_seek(const fn_call& fn);
-void netstream_setbuffertime(const fn_call& fn);
+// Initialize the global NetStream class
+void netstream_class_init(as_object& global);
 
 } // end of gnash namespace
 

Index: server/asobj/NetStreamFfmpeg.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamFfmpeg.cpp,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- server/asobj/NetStreamFfmpeg.cpp    18 Jan 2007 22:53:21 -0000      1.7
+++ server/asobj/NetStreamFfmpeg.cpp    23 Jan 2007 16:41:28 -0000      1.8
@@ -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.7 2007/01/18 22:53:21 strk Exp $ */
+/* $Id: NetStreamFfmpeg.cpp,v 1.8 2007/01/23 16:41:28 tgc Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -54,6 +54,7 @@
        m_ACodecCtx(NULL),
        m_FormatCtx(NULL),
        m_Frame(NULL),
+       m_Resample(NULL),
 
        m_go(false),
        m_imageframe(NULL),
@@ -99,7 +100,11 @@
                m_go = false;
 
                // wait till thread is complete before main continues
-               pthread_join(m_thread, NULL);
+               m_thread->join();
+               if (m_thread) delete m_thread;
+       }
+       if (startThread) {
+               delete startThread;
        }
 
        // When closing gnash before playback is finished, the soundhandler 
@@ -119,9 +124,15 @@
        if (m_ACodecCtx) avcodec_close(m_ACodecCtx);
        m_ACodecCtx = NULL;
 
+       if (m_FormatCtx) {
        m_FormatCtx->iformat->flags = AVFMT_NOFILE;
-       if (m_FormatCtx) av_close_input_file(m_FormatCtx);
+               av_close_input_file(m_FormatCtx);
        m_FormatCtx = NULL;
+       }
+
+       if (m_Resample) {
+               audio_resample_close (m_Resample);
+       }
 
        if (m_imageframe) delete m_imageframe;
 
@@ -137,8 +148,6 @@
                m_qaudio.pop();
        }
 
-       //delete input;
-
 }
 
 // ffmpeg callback function
@@ -199,17 +208,19 @@
        m_go = true;
 
        // To avoid blocking while connecting, we use a thread.
-       if (pthread_create(&startThread, NULL, NetStreamFfmpeg::startPlayback, 
this) != 0)
-       {
-               return 0;
-       };
+       startThread = new 
boost::thread(boost::bind(NetStreamFfmpeg::startPlayback, this));
+
+       // This starts the decoding thread
+       lock = new boost::mutex::scoped_lock(start_mutex);
+       m_thread = new boost::thread(boost::bind(NetStreamFfmpeg::av_streamer, 
this)); 
+
        return 0;
 }
 
-void*
-NetStreamFfmpeg::startPlayback(void* arg)
+void
+NetStreamFfmpeg::startPlayback(NetStreamFfmpeg* ns)
 {
-       NetStreamFfmpeg* ns = static_cast<NetStreamFfmpeg*>(arg);
+
        netconnection_as_object* nc = 
static_cast<netconnection_as_object*>(ns->netCon);
 
        URL uri(ns->url);
@@ -262,7 +273,7 @@
        if(av_open_input_stream(&ns->m_FormatCtx, &ns->ByteIOCxt, "", inputFmt, 
NULL) < 0){
                log_error("Couldn't open file '%s' for decoding", 
ns->url.c_str());
                ns->set_status("NetStream.Play.StreamNotFound");
-               return 0;
+               return;
        }
 
        // Next, we need to retrieve information about the streams contained in 
the file
@@ -271,7 +282,7 @@
        if (ret < 0)
        {
                log_error("Couldn't find stream information from '%s', error 
code: %d", ns->url.c_str(), ret);
-               return 0;
+               return;
        }
 
 //     m_FormatCtx->pb.eof_reached = 0;
@@ -280,7 +291,7 @@
        // Find the first video & audio stream
        ns->m_video_index = -1;
        ns->m_audio_index = -1;
-       for (int i = 0; i < ns->m_FormatCtx->nb_streams; i++)
+       for (unsigned int i = 0; i < ns->m_FormatCtx->nb_streams; i++)
        {
                AVCodecContext* enc = ns->m_FormatCtx->streams[i]->codec; 
 
@@ -311,7 +322,7 @@
        if (ns->m_video_index < 0)
        {
                log_error("Didn't find a video stream from '%s'", 
ns->url.c_str());
-               return 0;
+               return;
        }
 
        // Get a pointer to the codec context for the video stream
@@ -323,7 +334,7 @@
        {
                ns->m_VCodecCtx = NULL;
                log_error("Decoder not found");
-               return 0;
+               return;
        }
 
        // Open codec
@@ -355,14 +366,14 @@
            if(pACodec == NULL)
                {
                        log_error("No available AUDIO decoder to process MPEG 
file: '%s'", ns->url.c_str());
-                       return 0;
+                       return;
                }
         
                // Open codec
                if (avcodec_open(ns->m_ACodecCtx, pACodec) < 0)
                {
                        log_error("Could not open AUDIO codec");
-                       return 0;
+                       return;
                }
 
                s->attach_aux_streamer(audio_streamer, (void*) ns);
@@ -371,11 +382,9 @@
 
        ns->m_pause = false;
 
-       if (pthread_create(&ns->m_thread, NULL, NetStreamFfmpeg::av_streamer, 
ns) != 0)
-       {
-               return 0;
-       };
-       return 0;
+       // By deleting this lock we allow the av_streamer-thread to start its 
work
+       delete ns->lock;
+       return;
 }
 
 void
@@ -384,9 +393,11 @@
 }
 
 // decoder thread
-void* NetStreamFfmpeg::av_streamer(void* arg)
+void NetStreamFfmpeg::av_streamer(NetStreamFfmpeg* ns)
 {
-       NetStreamFfmpeg* ns = static_cast<NetStreamFfmpeg*>(arg);
+
+       boost::mutex::scoped_lock  lock(ns->start_mutex);
+
        ns->set_status("NetStream.Play.Start");
 
        raw_videodata_t* video = NULL;
@@ -397,6 +408,7 @@
        ns->m_start_clock = tu_timer::ticks_to_seconds(tu_timer::get_ticks());
        ns->m_go = true;
        ns->m_unqueued_data = NULL;
+
        while (ns->m_go)
        {
                if (ns->m_pause)
@@ -449,8 +461,7 @@
                }
        }
        ns->set_status("NetStream.Play.Stop");
-       pthread_exit(0);
-       return 0;
+
 }
 
 // audio callback is running in sound handler thread
@@ -458,6 +469,8 @@
 {
        NetStreamFfmpeg* ns = static_cast<NetStreamFfmpeg*>(owner);
 
+       boost::mutex::scoped_lock  lock(ns->decoding_mutex);
+
        while (len > 0 && ns->m_qaudio.size() > 0)
        {
                raw_videodata_t* samples = ns->m_qaudio.front();
@@ -479,6 +492,8 @@
 
 bool NetStreamFfmpeg::read_frame()
 {
+       boost::mutex::scoped_lock  lock(decoding_mutex);
+
 //     raw_videodata_t* ret = NULL;
        if (m_unqueued_data)
        {
@@ -517,19 +532,22 @@
                                if (avcodec_decode_audio(m_ACodecCtx, 
(int16_t*) ptr, &frame_size, packet.data, packet.size) >= 0)
                                {
 
-                                       int16_t*        adjusted_data = 0;
-                                       int n = 0;
-
                                        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);
+                                       // Resampeling using ffmpegs 
(libavcodecs) resampler
+                                       if (!m_Resample) {
+                                               // arguments: (output channels, 
input channels, output rate, input rate)
+                                               m_Resample = 
audio_resample_init (2, m_ACodecCtx->channels, 44100, m_ACodecCtx->sample_rate);
+                                       }
+                                       // The size of this is a guess, we 
don't know yet... Lets hope it's big enough
+                                       int16_t* output_data = new 
int16_t[frame_size * 2];
+                                       samples = audio_resample (m_Resample, 
output_data, (int16_t*)ptr, samples);
 
                                        raw_videodata_t* raw = new 
raw_videodata_t;
-                                       raw->m_data = (uint8_t*) adjusted_data;
+                                       raw->m_data = (uint8_t*) output_data;
                                        raw->m_ptr = raw->m_data;
-                                       raw->m_size = n;
+                                       raw->m_size = samples * 2 * 2; // 2 for 
stereo and 2 for samplesize = 2 bytes
                                        raw->m_stream_index = m_audio_index;
 
                                        m_unqueued_data = m_qaudio.push(raw) ? 
NULL : raw;
@@ -637,6 +655,7 @@
        }
        else
        {
+               log_warning("Problems decoding frame");
                return false;
        }
 
@@ -649,9 +668,58 @@
 }
 
 void
-NetStreamFfmpeg::seek()
+NetStreamFfmpeg::seek(double pos)
 {
-    log_msg("%s:unimplemented \n", __FUNCTION__);
+       boost::mutex::scoped_lock  lock(decoding_mutex);
+
+       // Seek to new position
+       double timebase = 
(double)m_FormatCtx->streams[m_video_index]->time_base.num / 
(double)m_FormatCtx->streams[m_video_index]->time_base.den;
+
+       long newpos = (long)(pos / timebase);
+
+       if (av_seek_frame(m_FormatCtx, m_video_index, newpos, 0) < 0) {
+               log_warning("seeking failed");
+               return;
+       }
+
+       // This is kindof hackish and ugly :-(
+       if (newpos == 0) {
+               m_video_clock = 0;
+               m_start_clock = 
tu_timer::ticks_to_seconds(tu_timer::get_ticks());
+       } else {
+
+               AVPacket Packet;
+               av_init_packet(&Packet);
+               double newtime = 0;
+               while (newtime == 0) {
+                       if ( av_read_frame(m_FormatCtx, &Packet) < 0) {
+                               av_seek_frame(m_FormatCtx, -1, 
0,AVSEEK_FLAG_BACKWARD);
+                               av_free_packet(&Packet);
+                               return;
+                       }
+
+                       newtime = timebase * 
(double)m_FormatCtx->streams[m_video_index]->cur_dts;
+               }
+
+               av_free_packet(&Packet);
+               av_seek_frame(m_FormatCtx, m_video_index, newpos, 0);
+
+               m_start_clock +=  m_video_clock - newtime;
+
+               m_video_clock = newtime;
+       }
+       // Flush the queues
+       while (m_qvideo.size() > 0)
+       {
+               delete m_qvideo.front();
+               m_qvideo.pop();
+       }
+
+       while (m_qaudio.size() > 0)
+       {
+               delete m_qaudio.front();
+               m_qaudio.pop();
+       }
 }
 
 void
@@ -660,6 +728,17 @@
     log_msg("%s:unimplemented \n", __FUNCTION__);
 }
 
+long
+NetStreamFfmpeg::time()
+{
+       if (m_FormatCtx && m_FormatCtx->nb_streams > 0) {
+               double time = (double)m_FormatCtx->streams[0]->time_base.num / 
(double)m_FormatCtx->streams[0]->time_base.den * 
(double)m_FormatCtx->streams[0]->cur_dts;
+       return (long) time;
+       } else {
+               return 0;
+       }
+}
+
 } // gnash namespcae
 
 #endif // USE_FFMPEG

Index: server/asobj/NetStreamFfmpeg.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamFfmpeg.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- server/asobj/NetStreamFfmpeg.h      18 Jan 2007 11:53:37 -0000      1.3
+++ server/asobj/NetStreamFfmpeg.h      23 Jan 2007 16:41:28 -0000      1.4
@@ -14,7 +14,7 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-/* $Id: NetStreamFfmpeg.h,v 1.3 2007/01/18 11:53:37 tgc Exp $ */
+/* $Id: NetStreamFfmpeg.h,v 1.4 2007/01/23 16:41:28 tgc Exp $ */
 
 #ifndef __NETSTREAMFFMPEG_H__
 #define __NETSTREAMFFMPEG_H__
@@ -26,7 +26,11 @@
 #ifdef USE_FFMPEG
 
 #include <queue>
-#include <pthread.h>
+//#include <pthread.h>
+#include <boost/thread/thread.hpp>
+#include <boost/bind.hpp> 
+#include <boost/thread/mutex.hpp>
+
 #include "impl.h"
 #include "video_stream_instance.h"
 #include <ffmpeg/avformat.h>
@@ -153,10 +157,11 @@
        void close();
        void pause(int mode);
        int play(const char* source);
-       void seek();
+       void seek(double pos);
        void setBufferTime();
        void set_status(const char* code);
        void setNetCon(as_object* nc);
+       long time();
 
        // Used for ffmpeg data read and seek callbacks
        static int readPacket(void* opaque, uint8_t* buf, int buf_size);
@@ -181,8 +186,8 @@
                return time.num / (double) time.den;
        }
 
-       static void* startPlayback(void* arg);
-       static void* av_streamer(void* arg);
+       static void startPlayback(NetStreamFfmpeg* ns);
+       static void av_streamer(NetStreamFfmpeg* ns);
        static void audio_streamer(void *udata, uint8 *stream, int len);
 
 private:
@@ -210,6 +215,8 @@
 
        AVFrame* m_Frame;
 
+       ReSampleContext *m_Resample;
+
        volatile bool m_go;
        unsigned int runtime;
 
@@ -217,8 +224,14 @@
 
        double m_video_clock;
 
-       pthread_t m_thread;
-       pthread_t startThread;
+//     pthread_t m_thread;
+//     pthread_t startThread;
+       boost::thread *m_thread;
+       boost::thread *startThread;
+       boost::mutex decoding_mutex;
+       boost::mutex start_mutex;
+       boost::mutex::scoped_lock *lock;
+
        multithread_queue <raw_videodata_t*> m_qaudio;
        multithread_queue <raw_videodata_t*> m_qvideo;
        bool m_pause;

Index: server/asobj/NetStreamGst.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamGst.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- server/asobj/NetStreamGst.cpp       18 Jan 2007 22:53:21 -0000      1.4
+++ server/asobj/NetStreamGst.cpp       23 Jan 2007 16:41:28 -0000      1.5
@@ -35,26 +35,29 @@
 
 #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():
 
+       pipeline(NULL),
+       audiosink(NULL),
+       videosink(NULL),
+       source(NULL),
+       decoder(NULL),
+       volume(NULL),
+       colorspace(NULL),
+       videorate(NULL),
+       videocaps(NULL),
+       videoflip(NULL),
+       audioconv(NULL),
        m_go(false),
        m_imageframe(NULL),
        m_pause(false),
        inputPos(0),
        videowidth(0),
        videoheight(0)
+
 {
 }
 
@@ -317,27 +320,23 @@
        // 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) {
+       if (!ns->source || !ns->audioconv || !ns->volume || !ns->decoder || 
!ns->colorspace || !ns->videocaps || !ns->videorate || !ns->videosink) {
                gnash::log_error("Gstreamer element(s) for movie handling could 
not be created\n");
                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);
+       gst_bin_add_many (GST_BIN (ns->pipeline), ns->source, ns->decoder, 
ns->audiosink, ns->audioconv, ns->colorspace, ns->videosink, ns->videorate, 
ns->videocaps, ns->volume, NULL);
 
        // 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);
+       gst_element_link_many(ns->colorspace, ns->videocaps, ns->videorate, 
ns->videosink, NULL);
        
        // start playing        
        gst_element_set_state (ns->pipeline, GST_STATE_PLAYING);
@@ -355,9 +354,12 @@
 }
 
 void
-NetStreamGst::seek()
+NetStreamGst::seek(double pos)
 {
-    log_msg("%s:unimplemented \n", __FUNCTION__);
+
+       if (!gst_element_seek_simple(pipeline, GST_FORMAT_TIME, 
GST_SEEK_FLAG_KEY_UNIT, GST_SECOND * static_cast<long>(pos))) {
+               log_warning("seek failed");
+       }
 }
 
 void
@@ -366,6 +368,29 @@
     log_msg("%s:unimplemented \n", __FUNCTION__);
 }
 
+long
+NetStreamGst::time()
+{
+
+       if (!pipeline) return 0;
+
+       GstFormat fmt = GST_FORMAT_TIME;
+       long pos;
+       GstStateChangeReturn ret;
+       GstState current, pending;
+
+       ret = gst_element_get_state (GST_ELEMENT (pipeline), &current, 
&pending, 0);
+//     fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not changing state async");
+//     fail_unless (current == GST_STATE_READY, "bad current state");
+//     fail_unless (pending == GST_STATE_PLAYING, "bad pending state");
+
+       if (current != GST_STATE_NULL && gst_element_query_position (pipeline, 
&fmt, &pos)) {
+               return pos;
+       } else {
+               return 0;
+       }
+}
+
 // Gstreamer callback function
 int 
 NetStreamGst::readPacket(void* opaque, char* buf, int buf_size){

Index: server/asobj/NetStreamGst.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamGst.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- server/asobj/NetStreamGst.h 15 Jan 2007 20:58:53 -0000      1.3
+++ server/asobj/NetStreamGst.h 23 Jan 2007 16:41:28 -0000      1.4
@@ -42,10 +42,11 @@
        void close();
        void pause(int mode);
        int play(const char* source);
-       void seek();
+       void seek(double pos);
        void setBufferTime();
        void set_status(const char* code);
        void setNetCon(as_object* nc);
+       long time();
 
        // Used for gstreamer data read and seek callbacks
        static int readPacket(void* opaque, char* buf, int buf_size);




reply via email to

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