gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] /srv/bzr/gnash/trunk r10503: Remove libmedia dependency o


From: Benjamin Wolsey
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r10503: Remove libmedia dependency on libcore. Fix metadata handling crash
Date: Sat, 03 Jan 2009 17:45:59 +0100
User-agent: Bazaar (1.5)

------------------------------------------------------------
revno: 10503
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Sat 2009-01-03 17:45:59 +0100
message:
  Remove libmedia dependency on libcore. Fix metadata handling crash
  (bug #22868). Minor modifications, with documentation, to libmedia interface
  and removal of VM functionality to libcore.
modified:
  libcore/as_value.cpp
  libcore/as_value.h
  libcore/asobj/Date_as.cpp
  libcore/asobj/Date_as.h
  libcore/asobj/NetConnection_as.cpp
  libcore/asobj/NetStream_as.cpp
  libcore/asobj/SharedObject_as.cpp
  libcore/parser/action_buffer.h
  libmedia/AudioDecoderNellymoser.cpp
  libmedia/FLVParser.cpp
  libmedia/FLVParser.h
  libmedia/Makefile.am
  libmedia/MediaHandler.cpp
  libmedia/MediaHandler.h
  libmedia/MediaParser.cpp
  libmedia/MediaParser.h
  libmedia/ffmpeg/MediaHandlerFfmpeg.cpp
  libmedia/ffmpeg/MediaParserFfmpeg.cpp
  libmedia/gst/MediaHandlerGst.cpp
    ------------------------------------------------------------
    revno: 10502.1.1
    committer: Benjamin Wolsey <address@hidden>
    branch nick: test
    timestamp: Fri 2009-01-02 16:37:21 +0100
    message:
      Minor cleanups.
    modified:
      libcore/as_value.cpp
    ------------------------------------------------------------
    revno: 10502.1.2
    committer: Benjamin Wolsey <address@hidden>
    branch nick: test
    timestamp: Fri 2009-01-02 17:08:00 +0100
    message:
      Drop stuff.
    modified:
      libcore/parser/action_buffer.h
    ------------------------------------------------------------
    revno: 10502.1.3
    committer: Benjamin Wolsey <address@hidden>
    branch nick: test
    timestamp: Sat 2009-01-03 09:45:20 +0100
    message:
      Rearrange header.
    modified:
      libmedia/FLVParser.h
    ------------------------------------------------------------
    revno: 10502.1.4
    committer: Benjamin Wolsey <address@hidden>
    branch nick: test
    timestamp: Sat 2009-01-03 10:37:30 +0100
    message:
      Line breaks.
    modified:
      libcore/asobj/NetStream_as.cpp
    ------------------------------------------------------------
    revno: 10502.1.5
    committer: Benjamin Wolsey <address@hidden>
    branch nick: test
    timestamp: Sat 2009-01-03 10:54:35 +0100
    message:
      Have isFLV throw an IOException when not enough bytes are available for
      reading. Add exception specification, document and catch it. Throw 
      MediaException not GnashException on other libmedia errors.
      
      Split long lines.
    modified:
      libmedia/FLVParser.cpp
      libmedia/FLVParser.h
      libmedia/MediaHandler.cpp
      libmedia/MediaHandler.h
      libmedia/ffmpeg/MediaHandlerFfmpeg.cpp
      libmedia/ffmpeg/MediaParserFfmpeg.cpp
      libmedia/gst/MediaHandlerGst.cpp
    ------------------------------------------------------------
    revno: 10502.1.6
    committer: Benjamin Wolsey <address@hidden>
    branch nick: test
    timestamp: Sat 2009-01-03 16:01:27 +0100
    message:
      Replace MetaTag struct with a simple multimap of timestamp to buffer. 
Transfer
      tags to NetStream_as before executing, and move execution to libcore 
instead
      of libmedia. This removes libmedia's dependency on libcore for this 
purpose,
      and more importantly fixes a crash when a metadata function triggers the
      destruction of the FLVParser.
      
      Make readAMF0 const correct, update all callers.
      
      Register Date prototype with VM using addStatic, which fixes a crash in
      AMF parsing (Date construction).
      
      Don't use the VM's RNG in AudioDecoderNellymoser. It's not thread-safe, 
and
      creates an unnecessary dependency.
      
      Remove libmedia's dependency on libcore for win32 (should now build 
without).
    modified:
      libcore/as_value.cpp
      libcore/as_value.h
      libcore/asobj/Date_as.cpp
      libcore/asobj/Date_as.h
      libcore/asobj/NetConnection_as.cpp
      libcore/asobj/NetStream_as.cpp
      libcore/asobj/SharedObject_as.cpp
      libmedia/AudioDecoderNellymoser.cpp
      libmedia/FLVParser.cpp
      libmedia/FLVParser.h
      libmedia/Makefile.am
      libmedia/MediaParser.cpp
      libmedia/MediaParser.h
    ------------------------------------------------------------
    revno: 10502.1.7
    committer: Benjamin Wolsey <address@hidden>
    branch nick: test
    timestamp: Sat 2009-01-03 16:29:43 +0100
    message:
      Dox, quieten debugging.
    modified:
      libcore/as_value.cpp
      libcore/asobj/NetStream_as.cpp
      libmedia/FLVParser.h
      libmedia/MediaParser.h
    ------------------------------------------------------------
    revno: 10502.1.8
    committer: Benjamin Wolsey <address@hidden>
    branch nick: test
    timestamp: Sat 2009-01-03 17:34:08 +0100
    message:
      Move typedefs to MediaParser class.
    modified:
      libcore/asobj/NetStream_as.cpp
      libmedia/MediaParser.h
=== modified file 'libcore/as_value.cpp'
--- a/libcore/as_value.cpp      2009-01-02 12:48:38 +0000
+++ b/libcore/as_value.cpp      2009-01-03 15:29:43 +0000
@@ -58,7 +58,7 @@
 // Define this macro to make soft references activity verbose
 //#define GNASH_DEBUG_SOFT_REFERENCES
 
-// Define this macto to make AMF parsing verbose
+// Define this macro to make AMF parsing verbose
 //#define GNASH_DEBUG_AMF_DESERIALIZE
 
 // Define this macto to make AMF writing verbose
@@ -437,13 +437,6 @@
                hint = STRING;
        }
 
-#if 0
-       else if ( m_type == MOVIECLIP && swfVersion > 5 )
-       {
-               throw ActionTypeError();
-       }
-#endif
-
        return convert_to_primitive(hint);
 }
 
@@ -452,7 +445,6 @@
 as_value::to_primitive(AsType hint) const
 {
        if ( m_type != OBJECT && m_type != AS_FUNCTION ) return *this; 
-       //if ( ! is_object() ) return *this; // include MOVIECLIP !!
 
 #if GNASH_DEBUG_CONVERSION_TO_PRIMITIVE
        log_debug("to_primitive(%s)", hint==NUMBER ? "NUMBER" : "STRING");
@@ -490,12 +482,10 @@
        {
                assert(hint==STRING);
 
-#if 1
                if ( m_type == MOVIECLIP )
                {
                        return as_value(getCharacterProxy().getTarget());
                }
-#endif
 
                if ( m_type == OBJECT ) obj = getObj().get();
                else obj = getFun().get();
@@ -516,17 +506,18 @@
                        return as_value(obj->get_text_value());
                }
 
-               if ( (!obj->get_member(NSV::PROP_TO_STRING, &method)) || 
(!method.is_function()) ) // ECMA says ! is_object()
+               if ( (!obj->get_member(NSV::PROP_TO_STRING, &method)) ||
+                (!method.is_function()) ) // ECMA says ! is_object()
                {
 #if GNASH_DEBUG_CONVERSION_TO_PRIMITIVE
                        log_debug(" toString not found");
 #endif
-                       if ( (!obj->get_member(NSV::PROP_VALUE_OF, &method)) || 
(!method.is_function()) ) // ECMA says ! is_object()
+                       if ( (!obj->get_member(NSV::PROP_VALUE_OF, &method)) ||
+                    (!method.is_function()) ) // ECMA says ! is_object()
                        {
 #if GNASH_DEBUG_CONVERSION_TO_PRIMITIVE
                                log_debug(" valueOf not found");
 #endif
-                               //return as_value(obj->get_text_value());
                                throw ActionTypeError();
                        }
                }
@@ -575,7 +566,8 @@
                if ( m_type == OBJECT ) obj = getObj().get();
                else obj = getFun().get();
 
-               if ( (!obj->get_member(NSV::PROP_VALUE_OF, &method)) || 
(!method.is_object()) ) // ECMA says ! is_object()
+               if ( (!obj->get_member(NSV::PROP_VALUE_OF, &method)) ||
+                (!method.is_object()) ) // ECMA says ! is_object()
                {
 #if GNASH_DEBUG_CONVERSION_TO_PRIMITIVE
                        log_debug(" valueOf not found");
@@ -619,12 +611,14 @@
                        return *this;
                }
 
-               if ( (!obj->get_member(NSV::PROP_TO_STRING, &method)) || 
(!method.is_function()) ) // ECMA says ! is_object()
+               if ( (!obj->get_member(NSV::PROP_TO_STRING, &method)) || 
+                (!method.is_function()) ) // ECMA says ! is_object()
                {
 #if GNASH_DEBUG_CONVERSION_TO_PRIMITIVE
                        log_debug(" toString not found");
 #endif
-                       if ( (!obj->get_member(NSV::PROP_VALUE_OF, &method)) || 
(!method.is_function()) ) // ECMA says ! is_object()
+                       if ( (!obj->get_member(NSV::PROP_VALUE_OF, &method)) || 
+                    (!method.is_function()) ) // ECMA says ! is_object()
                        {
 #if GNASH_DEBUG_CONVERSION_TO_PRIMITIVE
                                log_debug(" valueOf not found");
@@ -654,7 +648,6 @@
 double
 as_value::to_number() const
 {
-    // TODO:  split in to_number_# (version based)
 
     int swfversion = VM::get().getSWFVersion();
 
@@ -2110,7 +2103,7 @@
 // TODO restore first parameter on parse errors
 //
 static bool
-amf0_read_value(boost::uint8_t *&b, boost::uint8_t *end, 
+amf0_read_value(const boost::uint8_t *&b, const boost::uint8_t *end, 
         as_value& ret, int inType, std::vector<as_object*>& objRefs, VM& vm)
 {
        int amf_type;
@@ -2176,7 +2169,7 @@
                        }
 
                        {
-                               std::string str(reinterpret_cast<char *>(b), 
si); b += si;
+                               std::string str(reinterpret_cast<const 
char*>(b), si); b += si;
 #ifdef GNASH_DEBUG_AMF_DESERIALIZE
                                log_debug("amf0 read string: %s", str);
 #endif
@@ -2202,7 +2195,7 @@
                        }
 
                        {
-                               std::string str(reinterpret_cast<char *>(b), 
si); b += si;
+                               std::string str(reinterpret_cast<const 
char*>(b), si); b += si;
 #ifdef GNASH_DEBUG_AMF_DESERIALIZE
                                log_debug("amf0 read long string: %s", str);
 #endif
@@ -2284,7 +2277,7 @@
                         break;
                     }
 
-                                       std::string 
name(reinterpret_cast<char*>(b), strlen);
+                                       std::string name(reinterpret_cast<const 
char*>(b), strlen);
 
 #ifdef GNASH_DEBUG_AMF_DESERIALIZE
                                        log_debug("amf0 ECMA_ARRAY prop name is 
%s", name);
@@ -2381,7 +2374,8 @@
                case amf::Element::DATE_AMF0:
         {
                        if (b + 8 > end) {
-                               log_error(_("AMF0 read: premature end of input 
reading Date type"));
+                               log_error(_("AMF0 read: premature end of input 
reading Date "
+                            "type"));
                                return false;
                        }
                        double dub;
@@ -2396,10 +2390,12 @@
                        ret.set_as_object(obj);
 
                        if (b + 2 > end) {
-                               log_error(_("AMF0 read: premature end of input 
reading timezone from Date type"));
+                               log_error(_("AMF0 read: premature end of input 
reading "
+                            "timezone from Date type"));
                                return false;
                        }
-            LOG_ONCE(log_unimpl("Timezone info from AMF0 encoded Date object 
ignored"));
+            LOG_ONCE(log_unimpl("Timezone info from AMF0 encoded Date object "
+                        "ignored"));
             b+=2;
 
                        return true;
@@ -2418,7 +2414,8 @@
 }
 
 bool
-as_value::readAMF0(boost::uint8_t *&b, boost::uint8_t *end, int inType, 
std::vector<as_object*>& objRefs, VM& vm)
+as_value::readAMF0(const boost::uint8_t *&b, const boost::uint8_t *end,
+        int inType, std::vector<as_object*>& objRefs, VM& vm)
 {
        return amf0_read_value(b, end, *this, inType, objRefs, vm);
 }
@@ -2575,7 +2572,7 @@
             log_debug(_("writeAMF0: serializing number '%g'"), d);
 #endif
             buf.appendByte(amf::Element::NUMBER_AMF0);
-            amf::swapBytes(&d, 8); // this actually only swapps on 
little-endian machines
+            amf::swapBytes(&d, 8); // this actually only swaps on 
little-endian machines
             buf.append(&d, 8);
             return true;
         }

=== modified file 'libcore/as_value.h'
--- a/libcore/as_value.h        2008-12-16 12:20:22 +0000
+++ b/libcore/as_value.h        2009-01-03 15:01:27 +0000
@@ -224,7 +224,8 @@
        /// @param vm
     ///     Virtual machine to use for initialization of the values 
(string_table)
        ///
-       DSOEXPORT bool readAMF0(boost::uint8_t *&b, boost::uint8_t *end, int 
inType,
+       DSOEXPORT bool readAMF0(const boost::uint8_t*& b,
+            const boost::uint8_t* const end, int inType,
             std::vector<as_object*>& objRefs, VM& vm);
 
     /// Serialize value in AMF0 format.

=== modified file 'libcore/asobj/Date_as.cpp'
--- a/libcore/asobj/Date_as.cpp 2008-12-31 12:53:47 +0000
+++ b/libcore/asobj/Date_as.cpp 2009-01-03 15:01:27 +0000
@@ -163,7 +163,7 @@
 Date_as::Date_as(double value)
     :
     as_object(getDateInterface()),
-    _value(value)
+    _timeValue(value)
 {
 }
 
@@ -179,7 +179,7 @@
                                    "Thu", "Fri", "Sat" };
   
     /// NaN and infinities all print as "Invalid Date"
-    if (isNaN(_value) || isInf(_value)) {
+    if (isNaN(_timeValue) || isInf(_timeValue)) {
         return "Invalid Date";
     }
   
@@ -187,7 +187,7 @@
     GnashTime gt;
     // Time zone offset (including DST) as hours and minutes east of GMT
 
-    localTime(_value, gt);
+    localTime(_timeValue, gt);
 
     int offsetHours = gt.timeZoneOffset / 60;
     int offsetMinutes = gt.timeZoneOffset % 60;    
@@ -393,6 +393,7 @@
     if ( !o )
     {
         o = new as_object(getObjectInterface());
+        VM::get().addStatic(o.get());
         attachDateInterface(*o);
     }
     return o.get();
@@ -486,7 +487,8 @@
         // due to shortcomings in the timezoneoffset calculation, but should
         // be internally consistent.
         double localTime = makeTimeValue(gt);
-        date = new Date_as(localTime - clocktime::getTimeZoneOffset(localTime) 
* 60000);
+        date = new Date_as(
+                localTime - clocktime::getTimeZoneOffset(localTime) * 60000);
     }
     
     return as_value(date.get());

=== modified file 'libcore/asobj/Date_as.h'
--- a/libcore/asobj/Date_as.h   2008-12-31 12:53:47 +0000
+++ b/libcore/asobj/Date_as.h   2009-01-03 15:01:27 +0000
@@ -30,9 +30,9 @@
 
     explicit Date_as(double value = clocktime::getTicks());
 
-    void setTimeValue(const double& value) { _value = value; }
+    void setTimeValue(const double& value) { _timeValue = value; }
 
-    double getTimeValue() const { return _value; }
+    double getTimeValue() const { return _timeValue; }
 
     static void registerNative(as_object& global);
 
@@ -44,7 +44,7 @@
 
 private:
 
-    double _value;
+    double _timeValue;
 
 };
 

=== modified file 'libcore/asobj/NetConnection_as.cpp'
--- a/libcore/asobj/NetConnection_as.cpp        2008-12-20 16:06:27 +0000
+++ b/libcore/asobj/NetConnection_as.cpp        2009-01-03 15:01:27 +0000
@@ -394,8 +394,8 @@
 #endif
                 boost::int16_t si;
                 boost::uint16_t li;
-                boost::uint8_t *b = reply.data() + reply_start;
-                boost::uint8_t *end = reply.data() + reply.size();
+                const boost::uint8_t *b = reply.data() + reply_start;
+                const boost::uint8_t *end = reply.data() + reply.size();
 
                 // parse header
                 b += 2; // skip version indicator and client id
@@ -477,13 +477,19 @@
                             int ns = 1; // next slash position
                             while (ns<si-1 && *(b+ns) != '/') ++ns;
                             if ( ns >= si-1 ) {
-                                std::string msg(reinterpret_cast<char*>(b), 
si);
-                                log_error("NetConnection::call(): invalid 
reply message name (%s)", msg);
+                                std::string msg(
+                                        reinterpret_cast<const char*>(b), si);
+                                log_error("NetConnection::call(): invalid "
+                                        "reply message name (%s)", msg);
                                 break;
                             }
 
-                            std::string id(reinterpret_cast<char*>(b), ns);
-                            std::string 
methodName(reinterpret_cast<char*>(b+ns+1), si-ns-1);
+                            std::string id(reinterpret_cast<const char*>(b),
+                                    ns);
+
+                            std::string methodName(
+                                    reinterpret_cast<const char*>(b+ns+1),
+                                    si-ns-1);
 
                             b += si;
 

=== modified file 'libcore/asobj/NetStream_as.cpp'
--- a/libcore/asobj/NetStream_as.cpp    2008-12-15 08:08:03 +0000
+++ b/libcore/asobj/NetStream_as.cpp    2009-01-03 16:34:08 +0000
@@ -45,7 +45,15 @@
 #include "StreamProvider.h"
 #include "sound_handler.h"
 
-#include <boost/algorithm/string/case_conv.hpp> // for PROPNAME
+// For ntohs in amf conversion. FIXME: do this somewhere
+// more appropriate. There's AMF code scattered all over the place.
+#if !defined(HAVE_WINSOCK_H) || defined(__OS2__)
+# include <sys/types.h>
+# include <arpa/inet.h>
+#else
+# include <windows.h>
+# include <io.h>
+#endif
 
 // Define the following macro to have status notification handling debugged
 //#define GNASH_DEBUG_STATUS
@@ -74,6 +82,9 @@
 
     as_object* getNetStreamInterface();
     void attachNetStreamInterface(as_object& o);
+    
+    // TODO: see where this can be done more centrally.
+    void executeTag(const SimpleBuffer& _buffer, as_object* thisPtr, VM& vm);
 }
 
 /// Contruct a NetStream object.
@@ -333,7 +344,9 @@
 as_value
 NetStream_as::advanceWrapper(const fn_call& fn)
 {
-        boost::intrusive_ptr<NetStream_as> ptr = 
ensureType<NetStream_as>(fn.this_ptr);
+        boost::intrusive_ptr<NetStream_as> ptr =
+            ensureType<NetStream_as>(fn.this_ptr);
+
         ptr->advance();
         return as_value();
 }
@@ -531,7 +544,7 @@
 
     inputPos = 0;
 
-    if ( ! _mediaHandler )
+    if (!_mediaHandler)
     {
         LOG_ONCE( log_error(_("No Media handler registered, can't "
             "parse NetStream input")) );
@@ -1256,6 +1269,7 @@
     return _videoDecoder->width();
 }
 
+
 void
 NetStream_as::advance()
 {
@@ -1284,7 +1298,7 @@
     // Check decoding status 
     if ( decodingStatus() == DEC_DECODING && bufferLen == 0 )
     {
-        if ( ! parsingComplete )
+        if (!parsingComplete)
         {
 #ifdef GNASH_DEBUG_DECODING
             log_debug("%p.advance: buffer empty while decoding,"
@@ -1321,7 +1335,8 @@
             // The very first video frame we want to provide
             // as soon as possible (if not paused),
             // reguardless bufferLength...
-            if ( ! m_imageframe.get() && _playHead.getState() != 
PlayHead::PLAY_PAUSED )
+            if (!m_imageframe.get() && 
+                    _playHead.getState() != PlayHead::PLAY_PAUSED)
             {
                 log_debug("refreshing video frame for the first time");
                 refreshVideoFrame(true);
@@ -1331,9 +1346,9 @@
         }
 
 #ifdef GNASH_DEBUG_DECODING
-        log_debug("%p.advance: buffer full (or parsing completed), resuming 
playback clock"
-            " - position=%d, buffer=%d/%d",
-            this, _playHead.getPosition(), bufferLen, m_bufferTime);
+        log_debug("%p.advance: buffer full (or parsing completed), "
+                "resuming playback clock - position=%d, buffer=%d/%d",
+                this, _playHead.getPosition(), bufferLen, m_bufferTime);
 #endif // GNASH_DEBUG_DECODING
 
         setStatus(bufferFull);
@@ -1349,12 +1364,20 @@
     // up to current playhead
     refreshAudioBuffer();
 
-    // Advance PlayeHead position if current one was consumed
+    // Advance PlayHead position if current one was consumed
     // by all available consumers
     _playHead.advanceIfConsumed();
 
-    // Process media tags
-    m_parser->processTags(_playHead.getPosition(), this, getVM());
+    media::MediaParser::OrderedMetaTags tags;
+
+    m_parser->fetchMetaTags(tags, _playHead.getPosition());
+
+    if (tags.empty()) return;
+
+    for (media::MediaParser::OrderedMetaTags::iterator i = tags.begin(),
+            e = tags.end(); i != e; ++i) {
+        executeTag(**i, this, getVM());
+    }
 }
 
 boost::int32_t
@@ -1363,11 +1386,13 @@
     return _playHead.getPosition();
 }
 
-void NetStream_as::pausePlayback()
+void
+NetStream_as::pausePlayback()
 {
     GNASH_REPORT_FUNCTION;
 
-    PlayHead::PlaybackStatus oldStatus = 
_playHead.setState(PlayHead::PLAY_PAUSED);
+    PlayHead::PlaybackStatus oldStatus = 
+        _playHead.setState(PlayHead::PLAY_PAUSED);
 
     // Disconnect the soundhandler if we were playing before
     if ( oldStatus == PlayHead::PLAY_PLAYING )
@@ -1376,11 +1401,13 @@
     }
 }
 
-void NetStream_as::unpausePlayback()
+void
+NetStream_as::unpausePlayback()
 {
     GNASH_REPORT_FUNCTION;
 
-    PlayHead::PlaybackStatus oldStatus = 
_playHead.setState(PlayHead::PLAY_PLAYING);
+    PlayHead::PlaybackStatus oldStatus = 
+        _playHead.setState(PlayHead::PLAY_PLAYING);
 
     // Re-connect to the soundhandler if we were paused before
     if ( oldStatus == PlayHead::PLAY_PAUSED )
@@ -1441,10 +1468,12 @@
     }
 
     try {
-        _auxStreamer = 
_soundHandler->attach_aux_streamer(BufferedAudioStreamer::fetchWrapper,
-            (void*)this);
-    } catch (SoundException& e) {
-        log_error("Could not attach NetStream aux streamer to sound handler: 
%s", e.what());
+        _auxStreamer = _soundHandler->attach_aux_streamer(
+                BufferedAudioStreamer::fetchWrapper, (void*)this);
+    }
+    catch (SoundException& e) {
+        log_error("Could not attach NetStream aux streamer to sound handler: "
+                "%s", e.what());
     }
 }
 
@@ -1463,9 +1492,12 @@
 
 // audio callback, possibly running in a separate thread
 unsigned int
-BufferedAudioStreamer::fetchWrapper(void *owner, boost::int16_t* samples, 
unsigned int nSamples, bool& eof)
+BufferedAudioStreamer::fetchWrapper(void *owner, boost::int16_t* samples,
+        unsigned int nSamples, bool& eof)
 {
-    BufferedAudioStreamer* streamer = 
static_cast<BufferedAudioStreamer*>(owner);
+    BufferedAudioStreamer* streamer =
+        static_cast<BufferedAudioStreamer*>(owner);
+
     return streamer->fetch(samples, nSamples, eof);
 }
 
@@ -1903,5 +1935,43 @@
     return o.get();
 }
 
+void
+executeTag(const SimpleBuffer& _buffer, as_object* thisPtr, VM& vm)
+{
+       const boost::uint8_t* ptr = _buffer.data();
+       const boost::uint8_t* endptr = ptr + _buffer.size();
+
+       if ( ptr + 2 > endptr ) {
+               log_error("Premature end of AMF in NetStream metatag");
+               return;
+       }
+       boost::uint16_t length = ntohs((*(boost::uint16_t *)ptr) & 0xffff);
+       ptr += 2;
+
+       if ( ptr + length > endptr ) {
+               log_error("Premature end of AMF in NetStream metatag");
+               return;
+       }
+
+       std::string funcName(reinterpret_cast<const char*>(ptr), length); 
+       ptr += length;
+
+       log_debug("funcName: %s", funcName);
+
+       string_table& st = vm.getStringTable();
+       string_table::key funcKey = st.find(funcName);
+
+       as_value arg;
+       std::vector<as_object*> objRefs;
+       if ( ! arg.readAMF0(ptr, endptr, -1, objRefs, vm) )
+       {
+               log_error("Could not convert FLV metatag to as_value, but will 
try "
+                "passing it anyway. It's an %s", arg);
+       }
+
+       log_debug("Calling %s(%s)", funcName, arg);
+       thisPtr->callMethod(funcKey, arg);
+}
+
 } // anonymous namespace
 } // gnash namespace

=== modified file 'libcore/asobj/SharedObject_as.cpp'
--- a/libcore/asobj/SharedObject_as.cpp 2009-01-02 12:00:13 +0000
+++ b/libcore/asobj/SharedObject_as.cpp 2009-01-03 15:01:27 +0000
@@ -953,20 +953,20 @@
     }
 
     boost::scoped_array<boost::uint8_t> sbuf(new boost::uint8_t[st.st_size]);
-    boost::uint8_t *buf = sbuf.get();
-    boost::uint8_t *end = buf + st.st_size;
+    const boost::uint8_t *buf = sbuf.get();
+    const boost::uint8_t *end = buf + st.st_size;
 
     try
     {
         std::ifstream ifs(filespec.c_str(), std::ios::binary);
-        ifs.read(reinterpret_cast<char *>(buf), st.st_size);
+        ifs.read(reinterpret_cast<char*>(sbuf.get()), st.st_size);
 
         // TODO check initial bytes, and print warnings if they are fishy
 
         buf += 16; // skip const-length headers
 
         // skip past name   TODO add sanity check
-        buf += ntohs(*(reinterpret_cast<boost::uint16_t*>(buf)));
+        buf += ntohs(*(reinterpret_cast<const boost::uint16_t*>(buf)));
         buf += 2;
         
         buf += 4; // skip past padding
@@ -986,7 +986,7 @@
                     "byte %s", buf - sbuf.get());
             // read property name
             boost::uint16_t len = 
-                ntohs(*(reinterpret_cast<boost::uint16_t*>(buf)));
+                ntohs(*(reinterpret_cast<const boost::uint16_t*>(buf)));
             buf += 2;
 
             if( buf + len >= end )
@@ -998,7 +998,7 @@
                 log_error("SharedObject::readSOL: empty property name");
                 break;
             }
-            std::string prop_name(reinterpret_cast<char*>(buf), len);
+            std::string prop_name(reinterpret_cast<const char*>(buf), len);
             buf += len;
 
             // read value

=== modified file 'libcore/parser/action_buffer.h'
--- a/libcore/parser/action_buffer.h    2008-11-19 16:51:17 +0000
+++ b/libcore/parser/action_buffer.h    2009-01-02 16:08:00 +0000
@@ -64,11 +64,6 @@
        ///
        void read(SWFStream& in, unsigned long endPos);
 
-       bool is_null() const
-       {
-               return (m_buffer.size() < 1 || m_buffer[0] == 0);
-       }
-
        size_t size() const { return m_buffer.size(); }
 
        boost::uint8_t operator[] (size_t off) const
@@ -98,52 +93,6 @@
                return reinterpret_cast<const char*>(&m_buffer[pc]);
        }
 
-       /// Get a variable length 32-bit integer from the stream.
-       /// Store its length in the passed boost::uint8_t.
-       boost::uint32_t read_V32(size_t pc, boost::uint8_t& length) const
-       {
-           const size_t buflen = m_buffer.size();
-           const std::string err = _("Attempt to read outside action buffer");
-           
-           if (pc >= buflen) throw ActionParserException(err);
-
-               boost::uint32_t res = m_buffer[pc];
-               if (!(res & 0x00000080))
-               {
-                       length = 1;
-                       return res;
-               }
-
-           if (pc + 1 >= buflen) throw ActionParserException(err);
-               res = (res & 0x0000007F) | (m_buffer[pc + 1] << 7);
-               if (!(res & 0x00004000))
-               {
-                       length = 2;
-                       return res;
-               }
-
-           if (pc + 2 >= buflen) throw ActionParserException(err);
-               res = (res & 0x00003FFF) | (m_buffer[pc + 2] << 14);
-               if (!(res & 0x00200000))
-               {
-                       length = 3;
-                       return res;
-               }
-
-           if (pc + 3 >= buflen) throw ActionParserException(err);
-               res = (res & 0x001FFFFF) | (m_buffer[pc + 3] << 21);
-               if (!(res & 0x10000000))
-               {
-                       length = 4;
-                       return res;
-               }
-
-           if (pc + 4 >= buflen) throw ActionParserException(err);
-               res = (res & 0x0FFFFFFF) | (m_buffer[pc + 4] << 28);
-               length = 5;
-               return res;
-       }
-
     /// Get a pointer to the current instruction within the code
        const unsigned char* getFramePointer(size_t pc) const
        {

=== modified file 'libmedia/AudioDecoderNellymoser.cpp'
--- a/libmedia/AudioDecoderNellymoser.cpp       2008-10-29 22:32:10 +0000
+++ b/libmedia/AudioDecoderNellymoser.cpp       2009-01-03 15:01:27 +0000
@@ -50,10 +50,9 @@
 #include "SoundInfo.h"
 #include "log.h"
 
-#include "VM.h" // for randonNumberGenerator
-
 #include <ctime>
 #include <cmath>
+#include <boost/random.hpp>
 
 namespace gnash {
 namespace media {
@@ -648,10 +647,13 @@
 gimme_random()
 {
        using namespace boost;
-       VM::RNG& rnd = VM::get().randomNumberGenerator();
+       
+    typedef boost::mt11213b RNG;
+
+    static RNG rnd;
 
        uniform_int<> dist(0, std::numeric_limits<int>::max());
-       variate_generator<VM::RNG&, uniform_int<> > uni(rnd, dist);
+       variate_generator<RNG, uniform_int<> > uni(rnd, dist);
 
        return uni();
 }

=== modified file 'libmedia/FLVParser.cpp'
--- a/libmedia/FLVParser.cpp    2008-12-27 19:02:45 +0000
+++ b/libmedia/FLVParser.cpp    2009-01-03 15:01:27 +0000
@@ -28,19 +28,10 @@
 #include "IOChannel.h"
 #include "SimpleBuffer.h"
 
-#include "as_object.h"
 #include "element.h"
-#include "VM.h"
 
 #include <string>
 #include <iosfwd>
-#if !defined(HAVE_WINSOCK_H) || defined(__OS2__)
-# include <sys/types.h>
-# include <arpa/inet.h>
-#else
-# include <windows.h>
-# include <io.h>
-#endif
 
 
 #define PADDING_BYTES 64
@@ -67,6 +58,21 @@
 namespace gnash {
 namespace media {
 
+namespace {
+
+/// Functor for use when transforming a map into a vector of mapped values.
+template<typename T>
+struct SecondElement
+{
+    typedef typename T::second_type result_type;
+
+    const result_type& operator()(const T& pair) const
+    {
+        return pair.second;
+    }
+};
+
+}
 
 const boost::uint16_t FLVParser::FLVAudioTag::flv_audio_rates [] = {5500, 
11000, 22050, 44100};
 
@@ -82,19 +88,16 @@
        _cuePoints(),
        _indexingCompleted(false)
 {
-       if ( ! parseHeader() ) 
-               throw GnashException("FLVParser couldn't parse header from 
input");
+       if (!parseHeader()) {
+               throw MediaException("FLVParser couldn't parse header from 
input");
+    }
+
        startParserThread();
 }
 
 FLVParser::~FLVParser()
 {
        stopParserThread();
-
-       for (MetaTags::iterator i=_metaTags.begin(), e=_metaTags.end(); i!=e; 
++i)
-       {
-               delete *i;
-       }
 }
 
 
@@ -102,7 +105,6 @@
 bool
 FLVParser::seek(boost::uint32_t& time)
 {
-       //GNASH_REPORT_FUNCTION;
 
        boost::mutex::scoped_lock streamLock(_streamMutex);
        // we might obtain this lock while the parser is pushing the last
@@ -115,8 +117,6 @@
        // while the parser was pushing to queue
        _seekRequest = true;
 
-
-
        if ( _cuePoints.empty() )
        {
                log_debug("No known cue points yet, can't seek");
@@ -131,7 +131,8 @@
        }
 
        long lowerBoundPosition = it->second;
-       log_debug("Seek requested to time %d triggered seek to cue point at 
position %d and time %d", time, it->second, it->first);
+       log_debug("Seek requested to time %d triggered seek to cue point at "
+            "position %d and time %d", time, it->second, it->first);
        time = it->first;
        _lastParsedPosition=lowerBoundPosition; 
        _parsingComplete=false; // or NetStream will send the Play.Stop event...
@@ -201,7 +202,9 @@
        std::auto_ptr<EncodedAudioFrame> frame;
 
        if ( ! _audio ) {
-               log_error(_("Unexpected audio tag found at offset %d FLV stream 
advertising no audio in header. We'll warn only once for each FLV, expecting 
any further audio tag."), thisTagPos);
+               log_error(_("Unexpected audio tag found at offset %d FLV stream 
"
+                    "advertising no audio in header. We'll warn only once for "
+                    "each FLV, expecting any further audio tag."), thisTagPos);
                _audio = true; // TOCHECK: is this safe ?
        }
 
@@ -223,7 +226,8 @@
        // audio format has been noted, so we do that now
        if ( !_audioInfo.get() )
        {
-               _audioInfo.reset( new AudioInfo(audiotag.codec, 
audiotag.samplerate, audiotag.samplesize, audiotag.stereo, 0, FLASH) );
+               _audioInfo.reset(new AudioInfo(audiotag.codec, 
audiotag.samplerate,
+                    audiotag.samplesize, audiotag.stereo, 0, FLASH) );
                if (header) {
                        boost::uint8_t* newbuf = new 
boost::uint8_t[frame->dataSize];
                        memcpy(newbuf, frame->data.get(), frame->dataSize);
@@ -245,7 +249,9 @@
 FLVParser::parseVideoTag(const FLVTag& flvtag, const FLVVideoTag& videotag, 
boost::uint32_t thisTagPos)
 {
        if ( ! _video ) {
-               log_error(_("Unexpected video tag found at offset %d of FLV 
stream advertising no video in header. We'll warn only once per FLV, expecting 
any further video tag."), thisTagPos);
+               log_error(_("Unexpected video tag found at offset %d of FLV 
stream "
+                    "advertising no video in header. We'll warn only once per "
+                    "FLV, expecting any further video tag."), thisTagPos);
                _video = true; // TOCHECK: is this safe ?
        }
 
@@ -306,14 +312,10 @@
 }
 
 
-
-
-
 // would be called by parser thread
-bool FLVParser::parseNextTag(bool index_only)
+bool
+FLVParser::parseNextTag(bool index_only)
 {
-       //GNASH_REPORT_FUNCTION;
-
        // lock the stream while reading from it, so actionscript
        // won't mess with the parser on seek  or on getBytesLoaded
        boost::mutex::scoped_lock streamLock(_streamMutex);
@@ -351,20 +353,22 @@
        if ( actuallyRead < 12 )
        {
                if ( actuallyRead )
-                       log_error("FLVParser::parseNextTag: can't read tag info 
(needed 12 bytes, only got %d)", actuallyRead);
+                       log_error("FLVParser::parseNextTag: can't read tag info 
"
+                    "(needed 12 bytes, only got %d)", actuallyRead);
                // else { assert(_stream->eof(); } ?
 
                completed = true;
 
-                // update bytes loaded
-                boost::mutex::scoped_lock lock(_bytesLoadedMutex);
+        // update bytes loaded
+        boost::mutex::scoped_lock lock(_bytesLoadedMutex);
                _bytesLoaded = _stream->tell(); 
                return false;
        }
 
        FLVTag flvtag(chunk);
 
-        position += 15 + flvtag.body_size; // may be _lastParsedPosition OR 
_nextPosToIndex
+    // May be _lastParsedPosition OR _nextPosToIndex
+    position += 15 + flvtag.body_size; 
 
        bool doIndex = (_lastParsedPosition+4 > _nextPosToIndex) || index_only;
        if ( _lastParsedPosition > _nextPosToIndex )
@@ -463,19 +467,21 @@
                }
 
                boost::mutex::scoped_lock lock(_metaTagsMutex);
-               _metaTags.push_back(new MetaTag(flvtag.timestamp, metaTag));
+               _metaTags.insert(std::make_pair(flvtag.timestamp, 
metaTag.release()));
        }
        else
        {
-               log_error(_("FLVParser::parseNextTag: unknown FLV tag type 
%d"), (int)chunk[0]);
+               log_error(_("FLVParser::parseNextTag: unknown FLV tag type %d"),
+                (int)chunk[0]);
                return false;
        }
 
        _stream->read(chunk, 4);
-       boost::uint32_t prevtagsize = chunk[0] << 24 | chunk[1] << 16 | 
chunk[2] << 8 | chunk[3];
+       boost::uint32_t prevtagsize = chunk[0] << 24 | chunk[1] << 16 |
+        chunk[2] << 8 | chunk[3];
        if (prevtagsize != flvtag.body_size + 11) {
-               log_error(_("Corrupt FLV: previous tag size record (%1%) 
unexpected (actual size: %2%)"), 
-                         prevtagsize, flvtag.body_size + 11);
+               log_error(_("Corrupt FLV: previous tag size record (%1%) 
unexpected "
+                    "(actual size: %2%)"), prevtagsize, flvtag.body_size + 11);
        }
 
        return true;
@@ -497,7 +503,7 @@
 
        _lastParsedPosition = _bytesLoaded = _nextPosToIndex = 9;
 
-       if (!std::equal(header, header+3, "FLV")) {
+       if (!std::equal(header, header + 3, "FLV")) {
                return false;
        }
 
@@ -513,7 +519,8 @@
        return true;
 }
 
-inline boost::uint32_t FLVParser::getUInt24(boost::uint8_t* in)
+inline boost::uint32_t
+FLVParser::getUInt24(boost::uint8_t* in)
 {
        // The bits are in big endian order
        return (in[0] << 16) | (in[1] << 8) | in[2];
@@ -537,18 +544,21 @@
        frame->dataSize = dataSize;
        frame->timestamp = timestamp;
 
-       unsigned long int chunkSize = smallestMultipleContaining(READ_CHUNKS, 
dataSize+PADDING_BYTES);
-
-       frame->data.reset( new boost::uint8_t[chunkSize] );
-       size_t bytesread = _stream->read(frame->data.get(), dataSize);
+       const size_t chunkSize = smallestMultipleContaining(READ_CHUNKS,
+            dataSize + PADDING_BYTES);
+
+       frame->data.reset(new boost::uint8_t[chunkSize]);
+
+       const size_t bytesread = _stream->read(frame->data.get(), dataSize);
        if ( bytesread < dataSize )
        {
-               log_error("FLVParser::readAudioFrame: could only read %d/%d 
bytes", bytesread, dataSize);
+               log_error("FLVParser::readAudioFrame: could only read %d/%d 
bytes",
+                bytesread, dataSize);
        }
 
-       unsigned long int padding = chunkSize-dataSize;
+       const size_t padding = chunkSize - dataSize;
        assert(padding);
-       memset(frame->data.get() + bytesread, 0, padding);
+    std::fill_n(frame->data.get() + bytesread, padding, 0);
 
        return frame;
 }
@@ -560,76 +570,37 @@
 {
        std::auto_ptr<EncodedVideoFrame> frame;
 
-       unsigned long int chunkSize = smallestMultipleContaining(READ_CHUNKS, 
dataSize+PADDING_BYTES);
+       const size_t chunkSize = smallestMultipleContaining(READ_CHUNKS,
+            dataSize + PADDING_BYTES);
 
        boost::uint8_t* data = new boost::uint8_t[chunkSize];
        size_t bytesread = _stream->read(data, dataSize);
 
-       unsigned long int padding = chunkSize-dataSize;
+       const size_t padding = chunkSize - dataSize;
        assert(padding);
-       memset(data + bytesread, 0, padding);
+    std::fill_n(data + bytesread, padding, 0);
 
        // We won't need frameNum, so will set to zero...
        // TODO: fix this ?
        // NOTE: ownership of 'data' is transferred here
 
-       frame.reset( new EncodedVideoFrame(data, dataSize, 0, timestamp) );
+       frame.reset(new EncodedVideoFrame(data, dataSize, 0, timestamp));
        return frame;
 }
 
+
 void
-FLVParser::processTags(boost::uint64_t ts, as_object* thisPtr, VM& vm)
+FLVParser::fetchMetaTags(OrderedMetaTags& tags, boost::uint64_t ts)
 {
        boost::mutex::scoped_lock lock(_metaTagsMutex);
-       while (!_metaTags.empty())
-       {
-               if ( _metaTags.front()->timestamp() > ts ) break;
-
-               std::auto_ptr<MetaTag> tag ( _metaTags.front() );
-               _metaTags.pop_front();
-               tag->execute(thisPtr, vm);
-               
-       }
-}
-
-void
-FLVParser::MetaTag::execute(as_object* thisPtr, VM& vm)
-{
-       boost::uint8_t* ptr = _buffer->data();
-       boost::uint8_t* endptr = ptr+_buffer->size();
-
-       //log_debug("FLV meta: %s", hexify(ptr, 32, 0));
-       //log_debug("FLV meta: %s", hexify(ptr, 32, 1));
-
-       if ( ptr + 2 > endptr ) {
-               log_error("Premature end of AMF in FLV metatag");
-               return;
-       }
-       boost::uint16_t length = ntohs((*(boost::uint16_t *)ptr) & 0xffff);
-       ptr+=2;
-
-       if ( ptr + length > endptr ) {
-               log_error("Premature end of AMF in FLV metatag");
-               return;
-       }
-       std::string funcName((char*)ptr, length); // TODO: check for OOB !
-       ptr += length;
-
-       log_debug("funcName: %s", funcName);
-
-       string_table& st = vm.getStringTable();
-       string_table::key funcKey = st.find(funcName);
-
-       as_value arg;
-       std::vector<as_object*> objRefs;
-       if ( ! arg.readAMF0(ptr, endptr, -1, objRefs, vm) )
-       {
-               log_error("Could not convert FLV metatag to as_value, but will 
try passing it anyway. It's an %s", arg);
-               //return;
-       }
-
-       log_debug("Calling %s(%s)", funcName, arg);
-       thisPtr->callMethod(funcKey, arg);
+       if (!_metaTags.empty())
+       {
+        MetaTags::iterator it = _metaTags.upper_bound(ts);
+        std::transform(_metaTags.begin(), it, std::back_inserter(tags),
+                SecondElement<MetaTags::value_type>());
+        _metaTags.erase(_metaTags.begin(), it);
+       
+       }
 }
 
 } // end of gnash::media namespace

=== modified file 'libmedia/FLVParser.h'
--- a/libmedia/FLVParser.h      2008-10-27 12:03:47 +0000
+++ b/libmedia/FLVParser.h      2009-01-03 15:29:43 +0000
@@ -20,29 +20,23 @@
 
 // Information about the FLV format can be found at http://osflash.org/flv
 
-#ifndef __FLVPARSER_H__
-#define __FLVPARSER_H__
+#ifndef GNASH_FLVPARSER_H
+#define GNASH_FLVPARSER_H
 
 #include "dsodefs.h"
 #include "MediaParser.h" // for inheritance
-#include "SimpleBuffer.h" // for MetaTag destructor
+#include "SimpleBuffer.h" 
 
+#include <set>
 #include <vector>
 #include <memory>
 #include <map>
 
 #include <boost/thread/mutex.hpp>
 
-// Forward declarations
-namespace gnash {
-       class as_object;
-       class VM;
-}
-
 namespace gnash {
 namespace media {
 
-
 /// Extra video info found in some FLV embedded streams
 //
 /// This is basically composed by an header for the audio stream
@@ -94,11 +88,11 @@
     /// @todo take a SimpleBuffer by auto_ptr
     ///
     ExtraAudioInfoFlv(boost::uint8_t* extradata, size_t datasize)
-                :
-                data(extradata),
-                size(datasize)
-        {
-        }
+        :
+        data(extradata),
+        size(datasize)
+    {
+    }
 
     /// Audio stream header
     boost::scoped_array<boost::uint8_t> data;
@@ -111,6 +105,50 @@
 class DSOEXPORT FLVParser : public MediaParser
 {
 
+public:
+
+       /// \brief
+       /// Create an FLV parser reading input from
+       /// the given IOChannel
+       //
+       /// @param lt
+       ///     IOChannel to use for input.
+       ///     Ownership transferred.
+       ///
+       FLVParser(std::auto_ptr<IOChannel> lt);
+
+       /// Kills the parser...
+       ~FLVParser();
+
+       // see dox in MediaParser.h
+       virtual bool seek(boost::uint32_t&);
+
+       // see dox in MediaParser.h
+       virtual bool parseNextChunk();
+
+       // see dox in MediaParser.h
+       boost::uint64_t getBytesLoaded() const;
+
+       // see dox in MediaParser.h
+       bool indexingCompleted() const
+       {
+               return _indexingCompleted;
+       }
+
+    /// Retrieve any parsed metadata tags up to a specified timestamp.
+    //
+    /// This copies pointers to a SimpleBuffer of AMF data from _metaTags,
+    /// then removes those pointers from the MetaTags map. Any metadata later
+    /// than the timestamp is kept until fetchMetaTags is called again (or 
+    /// the dtor is called).
+    //
+    /// @param ts   The latest timestamp to retrieve metadata for.
+    /// @param tags This is filled with shared pointers to metatags in
+    ///             timestamp order. Ownership of the data is shared. It
+    ///             is destroyed automatically along with the last owner.
+    //
+    virtual void fetchMetaTags(OrderedMetaTags& tags, boost::uint64_t ts);
+
 private:
 
        enum tagType
@@ -123,9 +161,10 @@
        struct FLVTag : public boost::noncopyable
        {
                FLVTag(boost::uint8_t* stream)
-               : type(stream[0]),
-                 body_size(getUInt24(stream+1)),
-                 timestamp(getUInt24(stream+4) | (stream[7] << 24) )
+                   :
+            type(stream[0]),
+            body_size(getUInt24(stream+1)),
+            timestamp(getUInt24(stream+4) | (stream[7] << 24) )
                {}
 
                /// Equals tagType
@@ -137,10 +176,11 @@
        struct FLVAudioTag : public boost::noncopyable
        {
                FLVAudioTag(const boost::uint8_t& byte)
-               : codec( (byte & 0xf0) >> 4 ),
-                 samplerate( flv_audio_rates[(byte & 0x0C) >> 2] ),
-                 samplesize( 1 + ((byte & 0x02) >> 1)),
-                 stereo( (byte & 0x01) )
+                   :
+            codec( (byte & 0xf0) >> 4 ),
+                   samplerate( flv_audio_rates[(byte & 0x0C) >> 2] ),
+                   samplesize( 1 + ((byte & 0x02) >> 1)),
+                   stereo( (byte & 0x01) )
                {
                }
 
@@ -153,9 +193,12 @@
                boost::uint8_t samplesize;
 
                bool stereo;
-       private:
-               static const boost::uint16_t flv_audio_rates[];
-       };
+
+    private:
+       
+        static const boost::uint16_t flv_audio_rates[];
+       
+    };
 
        enum frameType
        {
@@ -167,8 +210,9 @@
        struct FLVVideoTag : public boost::noncopyable
        {
                FLVVideoTag(const boost::uint8_t& byte)
-               : frametype( (byte & 0xf0) >> 4 ),
-                 codec( byte & 0x0f )
+            :
+            frametype( (byte & 0xf0) >> 4 ),
+                   codec( byte & 0x0f )
                {}
 
                /// Equals frameType
@@ -177,40 +221,6 @@
                boost::uint8_t codec;
        };
 
-public:
-
-       /// \brief
-       /// Create an FLV parser reading input from
-       /// the given IOChannel
-       //
-       /// @param lt
-       ///     IOChannel to use for input.
-       ///     Ownership transferred.
-       ///
-       FLVParser(std::auto_ptr<IOChannel> lt);
-
-       /// Kills the parser...
-       ~FLVParser();
-
-       // see dox in MediaParser.h
-       virtual bool seek(boost::uint32_t&);
-
-       // see dox in MediaParser.h
-       virtual bool parseNextChunk();
-
-       // see dox in MediaParser.h
-       boost::uint64_t getBytesLoaded() const;
-
-       // see dox in MediaParser.h
-       bool indexingCompleted() const
-       {
-               return _indexingCompleted;
-       }
-
-       virtual void processTags(boost::uint64_t ts, as_object* thisPtr, VM& 
env);
-
-private:
-
        /// Parses next tag from the file
        //
        /// Returns true if something was parsed, false otherwise.
@@ -218,11 +228,16 @@
        ///
        bool parseNextTag(bool index_only);
 
-       std::auto_ptr<EncodedAudioFrame> parseAudioTag(const FLVTag& flvtag, 
const FLVAudioTag& audiotag, boost::uint32_t thisTagPos);
-       std::auto_ptr<EncodedVideoFrame> parseVideoTag(const FLVTag& flvtag, 
const FLVVideoTag& videotag, boost::uint32_t thisTagPos);
+       std::auto_ptr<EncodedAudioFrame> parseAudioTag(const FLVTag& flvtag,
+            const FLVAudioTag& audiotag, boost::uint32_t thisTagPos);
+       
+    std::auto_ptr<EncodedVideoFrame> parseVideoTag(const FLVTag& flvtag,
+            const FLVVideoTag& videotag, boost::uint32_t thisTagPos);
 
        void indexAudioTag(const FLVTag& tag, boost::uint32_t thisTagPos);
-       void indexVideoTag(const FLVTag& tag, const FLVVideoTag& videotag, 
boost::uint32_t thisTagPos);
+       
+    void indexVideoTag(const FLVTag& tag, const FLVVideoTag& videotag,
+            boost::uint32_t thisTagPos);
 
        /// Parses the header of the file
        bool parseHeader();
@@ -259,9 +274,11 @@
        /// Audio stream is present
        bool _video;
 
-       std::auto_ptr<EncodedAudioFrame> readAudioFrame(boost::uint32_t 
dataSize, boost::uint32_t timestamp);
+       std::auto_ptr<EncodedAudioFrame>
+        readAudioFrame(boost::uint32_t dataSize, boost::uint32_t timestamp);
 
-       std::auto_ptr<EncodedVideoFrame> readVideoFrame(boost::uint32_t 
dataSize, boost::uint32_t timestamp);
+       std::auto_ptr<EncodedVideoFrame>
+        readVideoFrame(boost::uint32_t dataSize, boost::uint32_t timestamp);
 
        /// Position in input stream for each cue point
        /// first: timestamp
@@ -271,27 +288,12 @@
 
        bool _indexingCompleted;
 
-       class MetaTag {
-       public:
-               MetaTag(boost::uint64_t t, std::auto_ptr<SimpleBuffer> b)
-                       :
-                       _timestamp(t),
-                       _buffer(b)
-               {}
-
-               void execute(as_object* thisPtr, VM& env);
-               boost::uint64_t timestamp() const { return _timestamp; }
-       private:
-               boost::uint64_t _timestamp;
-               std::auto_ptr<SimpleBuffer> _buffer;
-       };
-
-       typedef std::deque<MetaTag*> MetaTags;
-       MetaTags _metaTags;
-       boost::mutex _metaTagsMutex;
+    MetaTags _metaTags;
+
+    boost::mutex _metaTagsMutex;
 };
 
 } // end of gnash::media namespace
 } // end of gnash namespace
 
-#endif // __FLVPARSER_H__
+#endif 

=== modified file 'libmedia/Makefile.am'
--- a/libmedia/Makefile.am      2008-11-12 15:29:13 +0000
+++ b/libmedia/Makefile.am      2009-01-03 15:01:27 +0000
@@ -32,11 +32,8 @@
 libgnashmedia_la_CPPFLAGS = \
        -I$(top_srcdir)/libamf  \
        -I$(top_srcdir)/libnet \
-       -I$(top_srcdir)/backend \
        -I$(top_srcdir)/libbase \
        -I$(top_srcdir)/libcore \
-       -I$(top_srcdir)/libcore/vm \
-       -I$(top_srcdir)/libcore/parser \
        $(PTHREAD_CFLAGS) \
        $(DMALLOC_CFLAGS) \
        $(OPENGL_CFLAGS) \
@@ -170,8 +167,7 @@
 if WIN32
   libgnashmedia_la_LDFLAGS += -no-undefined
   libgnashmedia_la_LIBADD += \
-       $(top_builddir)/libbase/libgnashbase.la \
-       $(top_builddir)/libcore/libgnashcore.la \
+       $(top_builddir)/libbase/libgnashbase.la
        -lintl
 endif
 

=== modified file 'libmedia/MediaHandler.cpp'
--- a/libmedia/MediaHandler.cpp 2008-11-27 13:05:09 +0000
+++ b/libmedia/MediaHandler.cpp 2009-01-03 09:54:35 +0000
@@ -38,9 +38,8 @@
 
 std::auto_ptr<MediaHandler> MediaHandler::_handler;
 
-/* public static */
 bool
-MediaHandler::isFLV(IOChannel& stream)
+MediaHandler::isFLV(IOChannel& stream) throw (IOException)
 {
        char head[4] = {0, 0, 0, 0};
        stream.seek(0);
@@ -49,11 +48,11 @@
 
        if (actuallyRead < 3)
        {
-               log_error(_("MediaHandler::isFLV: Could not read 3 bytes from 
input stream"));
-               return false;
+               throw IOException(_("MediaHandler::isFLV: Could not read 3 
bytes "
+                    "from input stream"));
        }
 
-       if (std::string(head) != "FLV") return false;
+    if (!std::equal(head, head + 3, "FLV")) return false;
        return true;
 }
 
@@ -62,12 +61,18 @@
 {
        std::auto_ptr<MediaParser> parser;
 
-       if ( ! isFLV(*stream) )
-       {
-               log_error(_("MediaHandler::createMediaParser: only FLV input is 
"
-                    "supported by this MediaHandler"));
-               return parser;
-       }
+    try {
+        if (!isFLV(*stream))
+        {
+            log_error(_("MediaHandler::createMediaParser: only FLV input is "
+                        "supported by this MediaHandler"));
+            return parser;
+        }
+    }
+    catch (IOException& m) {
+        log_error(_("Exception while reading from stream: %s"), m.what());
+        return parser;
+    }
 
        parser.reset( new FLVParser(stream) );
        assert(! stream.get() ); // TODO: when ownership will be transferred...

=== modified file 'libmedia/MediaHandler.h'
--- a/libmedia/MediaHandler.h   2008-10-28 19:26:42 +0000
+++ b/libmedia/MediaHandler.h   2009-01-03 09:54:35 +0000
@@ -130,7 +130,9 @@
     std::auto_ptr<AudioDecoder> createFlashAudioDecoder(const AudioInfo& info);
 
        /// Return true if input stream is an FLV
-       bool isFLV(IOChannel& stream);
+    //
+    /// If this cannot read the necessary 3 bytes, it throws an IOException.
+       bool isFLV(IOChannel& stream) throw (IOException);
 
        MediaHandler() {}
 

=== modified file 'libmedia/MediaParser.cpp'
--- a/libmedia/MediaParser.cpp  2008-10-22 21:11:11 +0000
+++ b/libmedia/MediaParser.cpp  2009-01-03 15:01:27 +0000
@@ -20,9 +20,9 @@
 
 #include "MediaParser.h"
 #include "log.h"
+#include "GnashSleep.h" // for usleep.
 
 #include <boost/bind.hpp>
-#include "GnashSleep.h" // for usleep.
 
 // Define this to get debugging output from MediaParser
 //#define GNASH_DEBUG_MEDIAPARSER
@@ -380,11 +380,13 @@
 
 
 void
-MediaParser::processTags(boost::uint64_t /*ts*/, as_object* /*thisPtr*/, VM& 
/*env*/)
+MediaParser::fetchMetaTags(OrderedMetaTags& /*tags*/, boost::uint64_t /*ts*/)
 {
 }
 
-std::ostream& operator << (std::ostream& os, const VideoInfo& vi)
+
+std::ostream&
+operator<< (std::ostream& os, const VideoInfo& vi)
 {
        os << "codec:" << vi.codec << " (type " << vi.type << ") - "
           << "size:" << vi.width << "x" << vi.height << " - "

=== modified file 'libmedia/MediaParser.h'
--- a/libmedia/MediaParser.h    2008-12-03 23:36:26 +0000
+++ b/libmedia/MediaParser.h    2009-01-03 16:34:08 +0000
@@ -26,6 +26,7 @@
 
 #include "IOChannel.h" // for inlines
 #include "dsodefs.h" // DSOEXPORT
+#include "SimpleBuffer.h"
 
 #include <boost/scoped_array.hpp>
 #include <boost/thread/thread.hpp>
@@ -38,15 +39,10 @@
 #define LOAD_MEDIA_IN_A_SEPARATE_THREAD 1
 
 
-// Forward declarations
-namespace gnash {
-       class as_object;
-       class VM;
-}
-
 namespace gnash {
 namespace media {
 
+
 /// Video frame types
 enum videoFrameType
 {
@@ -435,7 +431,14 @@
 {
 public:
 
-       MediaParser(std::auto_ptr<IOChannel> stream);
+    /// A container for executable MetaTags contained in media streams.
+    //
+    /// Presently only known in FLV.
+    typedef std::multimap<boost::uint64_t, boost::shared_ptr<SimpleBuffer> >
+        MetaTags;
+    
+    typedef std::vector<MetaTags::mapped_type> OrderedMetaTags;
+        MediaParser(std::auto_ptr<IOChannel> stream);
 
        // Classes with virtual methods (virtual classes)
        // must have a virtual destructor, or the destructors
@@ -570,7 +573,16 @@
        ///
        virtual bool parseNextChunk()=0;
 
-       virtual void processTags(boost::uint64_t ts, as_object* thisPtr, VM& 
env);
+    /// Retrieve any parsed metadata tags up to a specified timestamp.
+    //
+    /// @param ts   The latest timestamp to retrieve metadata for.
+    /// @param tags This is filled with shared pointers to metatags in
+    ///             timestamp order. Ownership of the data is shared. It
+    ///             is destroyed automatically along with the last owner.
+    //
+    /// Metadata is currently only parsed from FLV streams. The default
+    /// is a no-op.
+    virtual void fetchMetaTags(OrderedMetaTags& tags, boost::uint64_t ts);
 
 protected:
 

=== modified file 'libmedia/ffmpeg/MediaHandlerFfmpeg.cpp'
--- a/libmedia/ffmpeg/MediaHandlerFfmpeg.cpp    2008-10-28 19:29:24 +0000
+++ b/libmedia/ffmpeg/MediaHandlerFfmpeg.cpp    2009-01-03 09:54:35 +0000
@@ -37,23 +37,22 @@
 {
        std::auto_ptr<MediaParser> parser;
 
-       if ( isFLV(*stream) )
-       {
-               parser.reset( new FLVParser(stream) );
-       }
-       else
-       {
-               try
-               {
+    try {
+        if (isFLV(*stream))
+        {
+            parser.reset(new FLVParser(stream));
+        }
+        else
+        {
                        parser.reset(new MediaParserFfmpeg(stream));
                }
-               catch (GnashException& ex)
-               {
-                       log_error("Could not create FFMPEG based media parser 
for "
-                    "input stream: %s", ex.what());
-                       assert(!parser.get());
-               }
-       }
+    }
+    catch (GnashException& ex)
+    {
+        log_error("Could not create FFMPEG based media parser for "
+                "input stream: %s", ex.what());
+        assert(!parser.get());
+    }
 
        return parser;
 }

=== modified file 'libmedia/ffmpeg/MediaParserFfmpeg.cpp'
--- a/libmedia/ffmpeg/MediaParserFfmpeg.cpp     2008-12-19 20:17:52 +0000
+++ b/libmedia/ffmpeg/MediaParserFfmpeg.cpp     2009-01-03 09:54:35 +0000
@@ -69,8 +69,9 @@
 
        if (actuallyRead < 1)
        {
-               throw IOException(_("MediaParserFfmpeg could not read probe 
data from input"));
-               return NULL;
+               throw IOException(_("MediaParserFfmpeg could not read probe 
data "
+                    "from input"));
+               return 0;
        }
 
        probe_data.buf_size = actuallyRead; // right ?
@@ -324,7 +325,8 @@
        _inputFmt = probeStream();
        if ( ! _inputFmt )
        {
-               throw GnashException("MediaParserFfmpeg couldn't figure out 
input format");
+               throw MediaException("MediaParserFfmpeg couldn't figure out 
input "
+                "format");
        }
 
        _formatCtx = av_alloc_format_context();

=== modified file 'libmedia/gst/MediaHandlerGst.cpp'
--- a/libmedia/gst/MediaHandlerGst.cpp  2008-11-26 08:25:29 +0000
+++ b/libmedia/gst/MediaHandlerGst.cpp  2009-01-03 09:54:35 +0000
@@ -43,23 +43,23 @@
 {
        std::auto_ptr<MediaParser> parser;
 
-       if ( isFLV(*stream) )
-       {
-               parser.reset( new FLVParser(stream) );
-       }
-       else
-       {
-               try
-               {
+    try
+    {
+        if (isFLV(*stream))
+        {
+            parser.reset(new FLVParser(stream));
+        }
+        else
+        {
                        parser.reset(new MediaParserGst(stream));
                }
-               catch (GnashException& ex)
-               {
-                       log_error("Could not create Gstreamer based media 
parser for "
-                    "input stream: %s", ex.what());
-                       assert(!parser.get());
-               }
-       }
+    }
+    catch (GnashException& ex)
+    {
+        log_error("Could not create Gstreamer based media parser for "
+                "input stream: %s", ex.what());
+        assert(!parser.get());
+    }
 
        return parser;
 }


reply via email to

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