[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/trunk r9662: add tag interface to MediaPar
From: |
Sandro Santilli |
Subject: |
[Gnash-commit] /srv/bzr/gnash/trunk r9662: add tag interface to MediaParser; implement it in FLVParser and use from NetStreamFfmpeg |
Date: |
Wed, 03 Sep 2008 02:05:38 +0200 |
User-agent: |
Bazaar (1.5) |
------------------------------------------------------------
revno: 9662
committer: Sandro Santilli <address@hidden>
branch nick: trunk
timestamp: Wed 2008-09-03 02:05:38 +0200
message:
add tag interface to MediaParser; implement it in FLVParser and use from
NetStreamFfmpeg
modified:
libcore/Makefile.am
libcore/as_value.cpp
libcore/as_value.h
libcore/asobj/NetConnection.cpp
libcore/asobj/NetStreamFfmpeg.cpp
libmedia/FLVParser.cpp
libmedia/FLVParser.h
libmedia/MediaParser.cpp
libmedia/MediaParser.h
testsuite/misc-ming.all/NetStream-SquareTest.c
------------------------------------------------------------
revno: 9659.1.1
committer: Sandro Santilli <address@hidden>
branch nick: mybranch
timestamp: Tue 2008-09-02 18:26:29 +0200
message:
Add support for ECMA array (objects) to amf0 to as_value converter.
Fully qualify amf namespace.
modified:
libcore/asobj/NetConnection.cpp
------------------------------------------------------------
revno: 9659.1.2
committer: Sandro Santilli <address@hidden>
branch nick: mybranch
timestamp: Wed 2008-09-03 00:20:43 +0200
message:
add support for decoding bool amf0
modified:
libcore/asobj/NetConnection.cpp
------------------------------------------------------------
revno: 9659.1.3
committer: Sandro Santilli <address@hidden>
branch nick: mybranch
timestamp: Wed 2008-09-03 00:57:53 +0200
message:
Move AMF0 to as_value conversion from NetConnection to as_value;
add interface of MediaParser to process tags; implement tags processing
in FLVParser by executing custom methods; fixes NetStream-SquareTest
with ffmpeg.
modified:
libcore/Makefile.am
libcore/as_value.cpp
libcore/as_value.h
libcore/asobj/NetConnection.cpp
libcore/asobj/NetStreamFfmpeg.cpp
libmedia/FLVParser.cpp
libmedia/FLVParser.h
libmedia/MediaParser.cpp
libmedia/MediaParser.h
testsuite/misc-ming.all/NetStream-SquareTest.c
------------------------------------------------------------
revno: 9659.1.4
committer: Sandro Santilli <address@hidden>
branch nick: mybranch
timestamp: Wed 2008-09-03 01:15:48 +0200
message:
make FLV metatags access thread-safe
modified:
libmedia/FLVParser.cpp
libmedia/FLVParser.h
------------------------------------------------------------
revno: 9659.1.5
committer: Sandro Santilli <address@hidden>
branch nick: mybranch
timestamp: Wed 2008-09-03 01:28:53 +0200
message:
drop unneeded double decoding of FLV metatag
modified:
libmedia/FLVParser.cpp
------------------------------------------------------------
revno: 9659.1.6
committer: Sandro Santilli <address@hidden>
branch nick: mybranch
timestamp: Wed 2008-09-03 01:43:00 +0200
message:
hush amf parsing verbosity with compile-time macro
modified:
libcore/as_value.cpp
=== modified file 'libcore/Makefile.am'
--- a/libcore/Makefile.am 2008-08-18 23:53:04 +0000
+++ b/libcore/Makefile.am 2008-09-02 22:57:53 +0000
@@ -38,6 +38,7 @@
-I$(top_srcdir)/libcore/vm \
-I$(top_srcdir)/libbase \
-I$(top_srcdir)/libmedia \
+ -I$(top_srcdir)/libamf \
$(PTHREAD_CFLAGS) \
$(DMALLOC_CFLAGS) \
$(GLIB_CFLAGS) \
=== modified file 'libcore/as_value.cpp'
--- a/libcore/as_value.cpp 2008-09-01 18:11:06 +0000
+++ b/libcore/as_value.cpp 2008-09-02 23:43:00 +0000
@@ -32,6 +32,10 @@
#include "action.h" // for call_method0
#include "utility.h" // for typeName() and utility::isFinite
#include "namedStrings.h"
+#include "element.h" // for readAMF
+#include "amf.h" // for readAMF
+#include "array.h" // for readAMF
+#include "Object.h" // for readAMF
#include <cmath> // std::fmod
#include <boost/algorithm/string/case_conv.hpp>
@@ -50,6 +54,9 @@
// Define this macro to make soft references activity verbose
//#define GNASH_DEBUG_SOFT_REFERENCES
+// Define this macto to make AMF parsing verbose
+//#define GNASH_DEBUG_AMF_PARSING
+
namespace {
struct invalidHexDigit {};
@@ -1746,6 +1753,207 @@
return *this;
}
+
+static boost::uint16_t
+readNetworkShort(const boost::uint8_t* buf) {
+ boost::uint16_t s = buf[0] << 8 | buf[1];
+ return s;
+}
+
+static boost::uint16_t
+readNetworkLong(const boost::uint8_t* buf) {
+ boost::uint32_t s = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
+ return s;
+}
+
+// Pass pointer to buffer and pointer to end of buffer. Buffer is raw AMF
+// encoded data. Must start with a type byte unless third parameter is set.
+//
+// On success, sets the given as_value and returns true.
+// On error (premature end of buffer, etc.) returns false and leaves the given
+// as_value untouched.
+//
+// IF you pass a fourth parameter, it WILL NOT READ A TYPE BYTE, but use what
+// you passed instead.
+//
+// The l-value you pass as the first parameter (buffer start) is updated to
+// point just past the last byte parsed
+//
+// TODO restore first parameter on parse errors
+//
+static bool
+amf0_read_value(boost::uint8_t *&b, boost::uint8_t *end, as_value& ret, int
inType = -1)
+{
+ boost::uint16_t si;
+ boost::uint16_t li;
+ double dub;
+ int amf_type;
+
+ if(b > end) {
+ return false;
+ }
+ if(inType != -1) {
+ amf_type = inType;
+ } else {
+ if(b < end) {
+ amf_type = *b; b += 1;
+ } else {
+ return false;
+ }
+ }
+
+ switch(amf_type) {
+ case amf::Element::BOOLEAN_AMF0:
+ {
+ bool val = *b; b += 1;
+#ifdef GNASH_DEBUG_AMF_PARSING
+ log_debug("amf0 read bool: %d", val);
+#endif
+ ret.set_bool(val);
+ return true;
+ }
+ case amf::Element::NUMBER_AMF0:
+ if(b + 8 > end) {
+ log_error(_("AMF0 read: premature end of input
reading Number type"));
+ return false;
+ }
+ dub = *(reinterpret_cast<double*>(b)); b += 8;
+ amf::swapBytes(&dub, 8);
+#ifdef GNASH_DEBUG_AMF_PARSING
+ log_debug("amf0 read double: %e", dub);
+#endif
+ ret.set_double(dub);
+ return true;
+ case amf::Element::STRING_AMF0:
+ if(b + 2 > end) {
+ log_error(_("AMF0 read: premature end of input
reading String type"));
+ return false;
+ }
+ si = readNetworkShort(b); b += 2;
+ if(b + si > end) {
+ log_error(_("AMF0 read: premature end of input
reading String type"));
+ return false;
+ }
+
+ {
+ std::string str(reinterpret_cast<char *>(b),
si); b += si;
+#ifdef GNASH_DEBUG_AMF_PARSING
+ log_debug("amf0 read string: %s", str);
+#endif
+ ret.set_string(str);
+ return true;
+
+ }
+ break;
+ case amf::Element::STRICT_ARRAY_AMF0:
+ {
+ boost::intrusive_ptr<as_array_object> array(new
as_array_object());
+ li = readNetworkLong(b); b += 4;
+#ifdef GNASH_DEBUG_AMF_PARSING
+ log_debug("amf0 starting read of array with %i
elements", li);
+#endif
+ as_value arrayElement;
+ for(int i = 0; i < li; ++i)
+ {
+ if ( ! amf0_read_value(b, end,
arrayElement) )
+ {
+ return false;
+ }
+ array->push(arrayElement);
+ }
+
+ ret.set_as_object(array);
+ return true;
+ }
+ case amf::Element::ECMA_ARRAY_AMF0:
+ {
+ boost::intrusive_ptr<as_object> obj(new
as_object(getObjectInterface()));
+ li = readNetworkLong(b); b += 4;
+#ifdef GNASH_DEBUG_AMF_PARSING
+ log_debug("amf0 starting read of object with %i
elements", li);
+#endif
+ as_value objectElement;
+ VM& vm = VM::get(); // TODO: get VM from outside
+ string_table& st = vm.getStringTable();
+ for(int i = 0; i < li; ++i)
+ {
+ boost::uint16_t strlen =
readNetworkShort(b); b+=2;
+ std::string name((char*)b, strlen);
+#ifdef GNASH_DEBUG_AMF_PARSING
+ log_debug("amf0 Object prop name is
%s", name);
+#endif
+ b += strlen;
+ if ( ! amf0_read_value(b, end,
objectElement) )
+ {
+ return false;
+ }
+ obj->set_member(st.find(name),
objectElement);
+ }
+
+ ret.set_as_object(obj);
+ return true;
+ }
+ case amf::Element::OBJECT_AMF0:
+ {
+ // TODO: need this?
boost::intrusive_ptr<as_object> obj(new as_object(getObjectInterface()));
+ boost::intrusive_ptr<as_object> obj(new
as_object());
+#ifdef GNASH_DEBUG_AMF_PARSING
+ log_debug("amf0 starting read of object");
+#endif
+ as_value tmp;
+ std::string keyString;
+ for(;;)
+ {
+ if ( ! amf0_read_value(b, end, tmp,
amf::Element::STRING_AMF0) )
+ {
+ return false;
+ }
+ keyString = tmp.to_string();
+
+ if ( keyString.empty() )
+ {
+ if(b < end) {
+ b += 1; // AMF0 has a
redundant "object end" byte
+ } else {
+ log_error("AMF buffer
terminated just before object end byte. continueing anyway.");
+ }
+ ret.set_as_object(obj);
+ return true;
+ }
+
+ if ( ! amf0_read_value(b, end, tmp) )
+ {
+ return false;
+ }
+ obj->init_member(keyString, tmp);
+ }
+ }
+ case amf::Element::UNDEFINED_AMF0:
+ {
+ ret.set_undefined();
+ return true;
+ }
+ case amf::Element::NULL_AMF0:
+ {
+ ret.set_null();
+ return true;
+ }
+ // TODO define other types (function, sprite, etc)
+ default:
+ log_unimpl("AMF0 to as_value: unsupported type: %i",
amf_type);
+ return false;
+ }
+
+ // this function was called with a zero-length buffer
+ return false;
+}
+
+bool
+as_value::readAMF0(boost::uint8_t *&b, boost::uint8_t *end, int inType)
+{
+ return amf0_read_value(b, end, *this, inType);
+}
+
} // namespace gnash
=== modified file 'libcore/as_value.h'
--- a/libcore/as_value.h 2008-08-29 08:59:12 +0000
+++ b/libcore/as_value.h 2008-09-02 22:57:53 +0000
@@ -176,6 +176,25 @@
/// Construct a NULL or AS_FUNCTION value
as_value(as_function* func);
+ /// Read AMF0 data from the given buffer
+ //
+ /// Pass pointer to buffer and pointer to end of buffer. Buffer is raw
AMF
+ /// encoded data. Must start with a type byte unless third parameter is
set.
+ ///
+ /// On success, sets the given as_value and returns true.
+ /// On error (premature end of buffer, etc.) returns false and leaves
the given
+ /// as_value untouched.
+ ///
+ /// IF you pass a fourth parameter, it WILL NOT READ A TYPE BYTE, but
use what
+ /// you passed instead.
+ ///
+ /// The l-value you pass as the first parameter (buffer start) is
updated to
+ /// point just past the last byte parsed
+ ///
+ /// TODO restore first parameter on parse errors
+ ///
+ bool readAMF0(boost::uint8_t *&b, boost::uint8_t *end, int inType = -1);
+
/// Convert numeric value to string value, following ECMA-262
specification
//
/// TODO: move here some of the good comments found in the function
definition.
=== modified file 'libcore/asobj/NetConnection.cpp'
--- a/libcore/asobj/NetConnection.cpp 2008-08-29 08:45:10 +0000
+++ b/libcore/asobj/NetConnection.cpp 2008-09-02 22:57:53 +0000
@@ -25,6 +25,7 @@
#include <iostream>
#include <string>
#include <boost/scoped_ptr.hpp>
+#include <arpa/inet.h> // for htons
#include "NetConnection.h"
#include "log.h"
@@ -39,13 +40,13 @@
// for NetConnection.call()
#include "VM.h"
-#include "array.h"
+//#include "array.h"
#include "amf.h"
#include "SimpleBuffer.h"
#include "timers.h"
#include "namedStrings.h"
-using namespace amf;
+//using namespace amf;
namespace gnash {
@@ -192,156 +193,18 @@
return as_value();
}
-boost::uint16_t
+static boost::uint16_t
readNetworkShort(const boost::uint8_t* buf) {
boost::uint16_t s = buf[0] << 8 | buf[1];
return s;
}
-boost::uint16_t
+static boost::uint16_t
readNetworkLong(const boost::uint8_t* buf) {
boost::uint32_t s = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
return s;
}
-// Pass pointer to buffer and pointer to end of buffer. Buffer is raw AMF
-// encoded data. Must start with a type byte unless third parameter is set.
-//
-// On success, sets the given as_value and returns true.
-// On error (premature end of buffer, etc.) returns false and leaves the given
-// as_value untouched.
-//
-// IF you pass a fourth parameter, it WILL NOT READ A TYPE BYTE, but use what
-// you passed instead.
-//
-// The l-value you pass as the first parameter (buffer start) is updated to
-// point just past the last byte parsed
-//
-// TODO restore first parameter on parse errors
-//
-static bool
-amf0_read_value(boost::uint8_t *&b, boost::uint8_t *end, as_value& ret, int
inType = -1)
-{
- boost::uint16_t si;
- boost::uint16_t li;
- double dub;
- int amf_type;
-
- if(b > end) {
- return false;
- }
- if(inType != -1) {
- amf_type = inType;
- } else {
- if(b < end) {
- amf_type = *b; b += 1;
- } else {
- return false;
- }
- }
-
- switch(amf_type) {
- case Element::NUMBER_AMF0:
- if(b + 8 > end) {
- log_error(_("NetConnection.call(): server sent
us a number which goes past the end of the data sent"));
- return false;
- }
- dub = *(reinterpret_cast<double*>(b)); b += 8;
- swapBytes(&dub, 8);
- log_debug("nc read double: %e", dub);
- ret.set_double(dub);
- return true;
- case Element::STRING_AMF0:
- if(b + 2 > end) {
- log_error(_("NetConnection.call(): server sent
us a string which goes past the end of the data sent"));
- return false;
- }
- si = readNetworkShort(b); b += 2;
- if(b + si > end) {
- log_error(_("NetConnection.call(): server sent
us a string which goes past the end of the data sent"));
- return false;
- }
-
- {
- std::string str(reinterpret_cast<char *>(b),
si); b += si;
- log_debug("nc read string: %s", str);
- ret.set_string(str);
- return true;
-
- }
- break;
- case Element::STRICT_ARRAY_AMF0:
- {
- boost::intrusive_ptr<as_array_object> array(new
as_array_object());
- li = readNetworkLong(b); b += 4;
- log_debug("nc starting read of array with %i
elements", li);
- as_value arrayElement;
- for(int i = 0; i < li; ++i)
- {
- if ( ! amf0_read_value(b, end,
arrayElement) )
- {
- return false;
- }
- array->push(arrayElement);
- }
-
- ret.set_as_object(array);
- return true;
- }
- case Element::OBJECT_AMF0:
- {
- // need this? boost::intrusive_ptr<as_object>
obj(new as_object(getObjectInterface()));
- boost::intrusive_ptr<as_object> obj(new
as_object());
- log_debug("nc starting read of object");
- as_value tmp;
- std::string keyString;
- for(;;)
- {
- if ( ! amf0_read_value(b, end, tmp,
Element::STRING_AMF0) )
- {
- return false;
- }
- keyString = tmp.to_string();
-
- if ( keyString.empty() )
- {
- if(b < end) {
- b += 1; // AMF0 has a
redundant "object end" byte
- } else {
- log_error("AMF buffer
terminated just before object end byte. continueing anyway.");
- }
- ret.set_as_object(obj);
- return true;
- }
-
- if ( ! amf0_read_value(b, end, tmp) )
- {
- return false;
- }
- obj->init_member(keyString, tmp);
- }
- }
- case Element::UNDEFINED_AMF0:
- {
- ret.set_undefined();
- return true;
- }
- case Element::NULL_AMF0:
- {
- ret.set_null();
- return true;
- }
- // TODO define other types (function, sprite, etc)
- default:
- log_unimpl("NetConnection.call(): server sent us a
value of unsupported type: %i", amf_type);
- return false;
- }
-
- // this function was called with a zero-length buffer
- return false;
-}
-
-
/// Queue of remoting calls
//
/// This class in made to handle data and do defered processing for
@@ -479,7 +342,7 @@
break;
}
std::string
headerName((char*)b, si); // end-b);
- //if(
!amf0_read_value(b, end, tmp) )
+ //if( !tmp.readAMF0(b,
end) )
//{
// headers_ok = 0;
// break;
@@ -491,7 +354,7 @@
break;
}
b += 5; // skip past
bool and length long
- if( !amf0_read_value(b,
end, tmp) )
+ if( !tmp.readAMF0(b,
end) )
{
headers_ok = 0;
break;
@@ -549,7 +412,7 @@
log_debug("about to parse amf value");
// this updates
b to point to the next unparsed byte
as_value
reply_as_value;
- if ( !
amf0_read_value(b, end, reply_as_value) )
+ if ( !
reply_as_value.readAMF0(b, end) )
{
log_error("parse amf failed");
// this
will happen if we get
@@ -746,14 +609,14 @@
// encode array of arguments to remote method
- buf->appendByte(Element::STRICT_ARRAY_AMF0);
+ buf->appendByte(amf::Element::STRICT_ARRAY_AMF0);
buf->appendNetworkLong(fn.nargs - 2);
if (fn.nargs > 2) {
for (unsigned int i = 2; i < fn.nargs; ++i) {
if (fn.arg(i).is_string()) {
- buf->appendByte(Element::STRING_AMF0);
+ buf->appendByte(amf::Element::STRING_AMF0);
std::string str = fn.arg(i).to_string();
buf->appendNetworkShort(str.size());
buf->append(str.c_str(), str.size());
@@ -765,8 +628,8 @@
else if(fn.arg(i).is_number()) {
double d = fn.arg(i).to_number();
- buf->appendByte(Element::NUMBER_AMF0);
- swapBytes(&d, 8); // this actually only swapps
on little-endian machines
+ buf->appendByte(amf::Element::NUMBER_AMF0);
+ amf::swapBytes(&d, 8); // this actually only
swapps on little-endian machines
buf->append(&d, 8);
// FIXME implement this
//} else if(fn.arg(i).is_object()) {
@@ -776,7 +639,7 @@
else {
log_error(_("NetConnection.call(): unknown
argument type"));
- buf->appendByte(Element::UNDEFINED_AMF0);
+ buf->appendByte(amf::Element::UNDEFINED_AMF0);
}
}
}
=== modified file 'libcore/asobj/NetStreamFfmpeg.cpp'
--- a/libcore/asobj/NetStreamFfmpeg.cpp 2008-09-01 13:10:41 +0000
+++ b/libcore/asobj/NetStreamFfmpeg.cpp 2008-09-02 22:57:53 +0000
@@ -995,6 +995,9 @@
// Refill audio buffer to consume all samples
// up to current playhead
refreshAudioBuffer();
+
+ // Process media tags
+ m_parser->processTags(_playHead.getPosition(), this, getVM());
}
boost::int32_t
=== modified file 'libmedia/FLVParser.cpp'
--- a/libmedia/FLVParser.cpp 2008-09-02 09:37:42 +0000
+++ b/libmedia/FLVParser.cpp 2008-09-02 23:28:53 +0000
@@ -26,6 +26,12 @@
#include "utility.h"
#include "GnashException.h"
#include "IOChannel.h"
+#include "SimpleBuffer.h"
+
+#include "as_object.h"
+#include "array.h"
+#include "element.h"
+#include "VM.h"
#include <string>
#include <iosfwd>
@@ -60,7 +66,10 @@
FLVParser::~FLVParser()
{
- // nothing to do here, all done in base class now
+ for (MetaTags::iterator i=_metaTags.begin(), e=_metaTags.end(); i!=e;
++i)
+ {
+ delete *i;
+ }
}
@@ -447,18 +456,18 @@
else if (tag[0] == FLV_META_TAG)
{
// Extract information from the meta tag
- boost::scoped_array<unsigned char> metaTag ( new unsigned
char[bodyLength] );
- size_t actuallyRead = _stream->read(metaTag.get(), bodyLength);
+ std::auto_ptr<SimpleBuffer> metaTag(new
SimpleBuffer(bodyLength));
+ size_t actuallyRead = _stream->read(metaTag->data(),
bodyLength);
if ( actuallyRead < bodyLength )
{
log_error("FLVParser::parseNextTag: can't read metaTag
(%d) body (needed %d bytes, only got %d)",
FLV_META_TAG, bodyLength, actuallyRead);
return false;
}
- amf::Flv flv;
- std::auto_ptr<amf::Element> el (
flv.decodeMetaData(metaTag.get(), actuallyRead) );
- log_unimpl("FLV MetaTag handling. Data: %s", *el);
- //el->dump();
+ metaTag->resize(actuallyRead);
+
+ boost::mutex::scoped_lock lock(_metaTagsMutex);
+ _metaTags.push_back(new MetaTag(timestamp, metaTag));
}
else
{
@@ -574,6 +583,59 @@
return frame;
}
+void
+FLVParser::processTags(boost::uint64_t ts, as_object* thisPtr, VM& vm)
+{
+ 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;
+ if ( ! arg.readAMF0(ptr, endptr) )
+ {
+ log_error("Could not convert FLV metatag to as_value");
+ return;
+ }
+
+ thisPtr->callMethod(funcKey, arg);
+}
+
} // end of gnash::media namespace
} // end of gnash namespace
=== modified file 'libmedia/FLVParser.h'
--- a/libmedia/FLVParser.h 2008-09-02 10:00:19 +0000
+++ b/libmedia/FLVParser.h 2008-09-02 23:15:48 +0000
@@ -25,6 +25,7 @@
#include "dsodefs.h"
#include "MediaParser.h" // for inheritance
+#include "SimpleBuffer.h" // for MetaTag destructor
#include <vector>
#include <memory>
@@ -32,6 +33,12 @@
#include <boost/thread/mutex.hpp>
+// Forward declarations
+namespace gnash {
+ class as_object;
+ class VM;
+}
+
namespace gnash {
namespace media {
@@ -77,6 +84,8 @@
return _indexingCompleted;
}
+ virtual void processTags(boost::uint64_t ts, as_object* thisPtr, VM&
env);
+
private:
/// Parses next tag from the file
@@ -132,6 +141,25 @@
CuePointsMap _cuePoints;
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;
};
} // end of gnash::media namespace
=== modified file 'libmedia/MediaParser.cpp'
--- a/libmedia/MediaParser.cpp 2008-09-02 10:11:27 +0000
+++ b/libmedia/MediaParser.cpp 2008-09-02 22:57:53 +0000
@@ -359,6 +359,12 @@
}
}
+
+void
+MediaParser::processTags(boost::uint64_t /*ts*/, as_object* /*thisPtr*/, VM&
/*env*/)
+{
+}
+
std::ostream& operator << (std::ostream& os, const VideoInfo& vi)
{
os << "codec:" << vi.codec << " (type " << vi.type << ") - "
=== modified file 'libmedia/MediaParser.h'
--- a/libmedia/MediaParser.h 2008-09-02 10:11:27 +0000
+++ b/libmedia/MediaParser.h 2008-09-02 22:57:53 +0000
@@ -38,6 +38,12 @@
#define LOAD_MEDIA_IN_A_SEPARATE_THREAD 1
+// Forward declarations
+namespace gnash {
+ class as_object;
+ class VM;
+}
+
namespace gnash {
namespace media {
@@ -390,6 +396,8 @@
///
virtual bool parseNextChunk()=0;
+ virtual void processTags(boost::uint64_t ts, as_object* thisPtr, VM&
env);
+
protected:
/// Start the parser thread
=== modified file 'testsuite/misc-ming.all/NetStream-SquareTest.c'
--- a/testsuite/misc-ming.all/NetStream-SquareTest.c 2008-06-17 13:04:17
+0000
+++ b/testsuite/misc-ming.all/NetStream-SquareTest.c 2008-09-02 22:57:53
+0000
@@ -506,7 +506,7 @@
// and would succeed in composition checking in second
call.
" if ( _root.metadataNotified > 1 ) return;"
- " xcheck(_root.startNotified, 'onMetaData should be notified
after Play.Start');"
+ " check(_root.startNotified, 'onMetaData should be notified
after Play.Start');"
" check_equals(arguments.length, 1, 'single argument');"
" check(info instanceof Object, 'onMetaData argument should be
instanceof Object');"
@@ -515,7 +515,7 @@
" for (e in info) { "
" enu.push(e);"
" }"
- " xcheck_equals(enu.length, 11);" // gnash contains 2 more
+ " check_equals(enu.length, 11);" // gnash contains 2 more
"\n"
@@ -609,10 +609,10 @@
SWFMovie_nextFrame(mo);
- xcheck_equals(mo, "metadataNotified", "1");
+ check_equals(mo, "metadataNotified", "1");
check_equals(mo, "stopNotified", "2");
check_equals(mo, "startNotified", "1");
- SWFMovie_add(mo, (SWFBlock)newSWFAction("totals(119); stop();"));
+ SWFMovie_add(mo, (SWFBlock)newSWFAction("totals(140); stop();"));
SWFMovie_nextFrame(mo);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] /srv/bzr/gnash/trunk r9662: add tag interface to MediaParser; implement it in FLVParser and use from NetStreamFfmpeg,
Sandro Santilli <=