[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/rtmp r9606: add support for decoding multi
From: |
rob |
Subject: |
[Gnash-commit] /srv/bzr/gnash/rtmp r9606: add support for decoding multiple RTMP messages. |
Date: |
Wed, 27 Aug 2008 19:24:04 -0600 |
User-agent: |
Bazaar (1.5) |
------------------------------------------------------------
revno: 9606
committer: address@hidden
branch nick: rtmp
timestamp: Wed 2008-08-27 19:24:04 -0600
message:
add support for decoding multiple RTMP messages.
modified:
libnet/rtmp.cpp
libnet/rtmp.h
=== modified file 'libnet/rtmp.cpp'
--- a/libnet/rtmp.cpp 2008-08-26 22:49:14 +0000
+++ b/libnet/rtmp.cpp 2008-08-28 01:24:04 +0000
@@ -21,10 +21,10 @@
#include "gnashconfig.h"
#endif
-#include <boost/detail/endian.hpp>
#include <iostream>
#include <string>
#include <map>
+#include <vector>
#if ! (defined(_WIN32) || defined(WIN32))
# include <netinet/in.h>
@@ -33,6 +33,7 @@
#include "log.h"
#include "amf.h"
#include "rtmp.h"
+#include "cque.h"
#include "network.h"
#include "element.h"
#include "handler.h"
@@ -46,6 +47,8 @@
namespace gnash
{
+CQue incoming;
+
extern map<int, Handler *> handlers;
const char *content_str[] = {
@@ -170,26 +173,28 @@
}
RTMP::RTMP()
- : _handshake(0), _handler(0)
+ : _handshake(0),
+ _handler(0),
+ _chunksize(RTMP_VIDEO_PACKET_SIZE),
+ _timeout(1)
{
// GNASH_REPORT_FUNCTION;
-// _inbytes = 0;
-// _outbytes = 0;
-
-// _body = new unsigned char(RTMP_BODY_SIZE+1);
-// memset(_body, 0, RTMP_BODY_SIZE+1);
+// _queues.resize(MAX_AMF_INDEXES);
+// for (size_t i=0; i<MAX_AMF_INDEXES; i++) {
+// string name = "channel #";
+// for (size_t i=0; i<10; i++) {
+// name[9] = i+'0';
+// _queues[i].setName(name.c_str());
+// }
}
RTMP::~RTMP()
{
// GNASH_REPORT_FUNCTION;
- _variables.clear();
- if (_handshake) {
- delete _handshake;
- }
- if (_handler) {
- delete _handler;
- }
+ _properties.clear();
+ delete _handshake;
+ delete _handler;
+
// delete _body;
}
@@ -197,23 +202,23 @@
RTMP::addProperty(amf::Element *el)
{
// GNASH_REPORT_FUNCTION;
- _variables[el->getName()] = el;
+ _properties[el->getName()] = el;
}
void
RTMP::addProperty(char *name, amf::Element *el)
{
// GNASH_REPORT_FUNCTION;
- _variables[name] = el;
+ _properties[name] = el;
}
amf::Element *
RTMP::getProperty(const std::string &name)
{
// GNASH_REPORT_FUNCTION;
-// return _variables[name.c_str()];
+// return _properties[name.c_str()];
map<const char *, amf::Element *>::iterator it;
- for (it = _variables.begin(); it != _variables.end(); it++) {
+ for (it = _properties.begin(); it != _properties.end(); it++) {
const char *title = it->first;
amf::Element *el = it->second;
if (name == title) {
@@ -227,7 +232,7 @@
RTMP::rtmp_head_t *
RTMP::decodeHeader(Buffer *buf)
{
- GNASH_REPORT_FUNCTION;
+// GNASH_REPORT_FUNCTION;
return decodeHeader(buf->reference());
}
@@ -265,15 +270,39 @@
}
if (_header.head_size >= 8) {
- char c = *(reinterpret_cast<char *>(tmpptr));
- _header.type = static_cast<content_types_e>(c);
+ Network::byte_t byte = *tmpptr;
+ _header.type = (content_types_e)byte;
tmpptr++;
- log_debug(_("The type is: %s"), content_str[_header.type]);
+ if (_header.type <= RTMP::INVOKE ) {
+ log_debug(_("The type is: %s"), content_str[_header.type]);
+ } else {
+ log_debug(_("The type is: 0x%x"), _header.type);
+ }
}
+
+// switch(_header.type) {
+// case CHUNK_SIZE:
+// case BYTES_READ:
+// case PING:
+// case SERVER:
+// case CLIENT:
+// case VIDEO_DATA:
+// case NOTIFY:
+// case SHARED_OBJ:
+// case INVOKE:
+// _packet_size = RTMP_VIDEO_PACKET_SIZE;
+// break;
+// case AUDIO_DATA:
+// _packet_size = RTMP_AUDIO_PACKET_SIZE;
+// break;
+// default:
+// log_error (_("ERROR: Unidentified AMF header data type 0x%x"),
_type);
+// break;
+// };
if (_header.head_size == 12) {
_header.src_dest = *(reinterpret_cast<RTMPMsg::rtmp_source_e
*>(tmpptr));
- tmpptr += sizeof(boost::uint32_t);
+ tmpptr += sizeof(unsigned int);
log_debug(_("The source/destination is: %x"), _header.src_dest);
}
@@ -346,13 +375,24 @@
// Add the size of the message if the header size is 8 or more.
// and add the type of the object if the header size is 8 or more.
if ((head_size == HEADER_8) || (head_size == HEADER_12)) {
-// RTMP uses a 3 byte length field, which is the total size of the packet
- boost::uint32_t length = total_size << 8;
- swapBytes(&length, 4);
- memcpy(ptr, &length, 3);
- ptr += 3;
-
- // Add the type
+ int length = total_size;
+ Network::byte_t *lenptr = reinterpret_cast<Network::byte_t *>(&length);
+//#ifndef BOOST_BIG_ENDIAN
+// swapBytes(&length, 4);
+ *ptr++ = *(lenptr + 2);
+ *ptr++ = *(lenptr + 1);
+ *ptr++ = *lenptr;
+// *(lenptr + 3) = *(lenptr);
+// memcpy(ptr, lenptr, 3);
+// #else
+// #ifdef BOOST_BIG_ENDIAN
+// memcpy(ptr, &length, 3);
+// #else
+// #error "No Endianess specified!"
+// #endif
+//#endif
+// swapBytes(&length, 4);
+// ptr += 3;
*ptr = type;
ptr++;
}
@@ -377,6 +417,7 @@
Network::byte_t *tooFar = ptr+buf->size();
AMF amf;
+//
address@hidden@\000\000\000\000\000\000\003\000\003app\002\000#software/gnash/tests/1153948634.flv\000\bflashVer\002\000\fLNX
6,0,82,0\000\006swfUrl\002\000\035file:///file|address@hidden://localhost/software/gnash/tests/1153948634
amf_index = *buf->reference() & RTMP_INDEX_MASK;
headersize = headerSize(*buf->reference());
log_debug (_("The Header size is: %d"), headersize);
@@ -450,9 +491,9 @@
void
RTMP::dump()
{
- cerr << "RTMP packet contains " << _variables.size() << " variables." <<
endl;
+ cerr << "RTMP packet contains " << _properties.size() << " variables." <<
endl;
map<const char *, amf::Element *>::iterator it;
- for (it = _variables.begin(); it != _variables.end(); it++) {
+ for (it = _properties.begin(); it != _properties.end(); it++) {
// const char *name = it->first;
amf::Element *el = it->second;
el->dump();
@@ -509,7 +550,6 @@
return ping;
}
-
RTMP::rtmp_ping_t *
RTMP::decodePing(amf::Buffer *buf)
{
@@ -576,7 +616,11 @@
// at the minimum.
Element *streamid = amf_obj.extractAMF(ptr, tooFar);
if (streamid) {
- ptr += streamid->getLength() + 2;
+ // Most onStatus messages have the stream ID, but the Data Start
onStatus
+ // message is basically just a marker that an FLV file is coming next.
+ if (streamid->getType() == Element::NUMBER_AMF0) {
+ ptr += streamid->getLength() + 2;
+ }
} else {
log_error("Stream ID field of RTMP Message corrupted!");
return 0;
@@ -585,12 +629,14 @@
// This will need to be deleted manually later after usage, it is not
// automatically deallocated.
RTMPMsg *msg = new RTMPMsg;
+// memset(msg, 0, sizeof(RTMPMsg));
msg->setMethodName(name->to_string());
double swapped = streamid->to_number();
+// swapBytes(&swapped, amf::AMF0_NUMBER_SIZE);
msg->setStreamID(swapped);
- if ((msg->getMethodName() == "_result") || (msg->getMethodName() ==
"error")) {
+ if ((msg->getMethodName() == "_result") || (msg->getMethodName() ==
"_error") || (msg->getMethodName() == "onStatus")) {
status = true;
}
@@ -763,19 +809,19 @@
// interval. (128 bytes for video data). Each message main contain
// multiple packets.
bool
-RTMP::sendMsg(amf::Buffer *buf)
+RTMP::sendMsg(amf::Buffer *data)
{
GNASH_REPORT_FUNCTION;
size_t partial = RTMP_VIDEO_PACKET_SIZE;
size_t nbytes = 0;
Network::byte_t header = 0xc3;
-
- while (nbytes <= buf->size()) {
- if ((buf->size() - nbytes) < static_cast<signed
int>(RTMP_VIDEO_PACKET_SIZE)) {
- partial = buf->size() - nbytes;
+
+ while (nbytes <= data->size()) {
+ if ((data->size() - nbytes) < static_cast<signed
int>(RTMP_VIDEO_PACKET_SIZE)) {
+ partial = data->size() - nbytes;
}
- writeNet(buf->reference() + nbytes, partial);
+ writeNet(data->reference() + nbytes, partial);
if (partial == static_cast<signed int>(RTMP_VIDEO_PACKET_SIZE)) {
writeNet(&header, 1);
}
@@ -785,7 +831,7 @@
}
// Send a Msg, and expect a response back of some kind.
-amf::Element *
+RTMPMsg *
RTMP::sendRecvMsg(int amf_index, rtmp_headersize_e head_size,
size_t total_size, content_types_e type,
RTMPMsg::rtmp_source_e routing, amf::Buffer *bufin)
@@ -794,78 +840,293 @@
// size_t total_size = buf2->size() - 6; // FIXME: why drop 6 bytes ?
Buffer *head = encodeHeader(amf_index, head_size, total_size,
type, routing);
+// int ret = 0;
int ret = writeNet(head);
// if (netDebug()) {
-// cerr << __FUNCTION__ << ": " <<__LINE__ << ": " <<
hexify(head->reference(), headerSize(head_size), false) << endl;
+// head->dump();
+// bufin->dump();
// }
-
+ delete head;
ret = sendMsg(bufin);
- if (netDebug()) {
- cerr << __FUNCTION__ << ": " << __LINE__ << ": " <<
hexify(head->reference(), headerSize(head_size), false) <<
hexify(bufin->reference(), ret, true) << endl;
- }
-
- Buffer buf;
- ret = readNet(&buf, 5);
- if (ret < 0) {
- log_error("Never got any data!");
+
+ RTMP::rtmp_head_t *rthead = 0;
+ RTMPMsg *msg = 0;
+ Buffer *buf = 0;
+ Network::byte_t *ptr = 0;
+
+
+ buf = recvMsg(1); // use a 1 second timeout
+ if (buf == 0) {
return 0;
}
- if ((ret == 1) && (*buf.reference() == 0xff)) {
- log_error("Got an error from the server sending object of type %s",
- content_str[type]);
- ret = readNet(&buf, 5);
- if (ret < 0) {
- log_error("Never got any data!");
+ RTMP::queues_t *que = split(buf);
+// CQue *que = split(buf);
+ while (que->size()) {
+// ptr = que->pop();
+ cerr << "QUE SIZE: " << que->size() << endl;
+ ptr = que->front()->pop()->reference();
+ que->pop_front();
+// ptr = buf->reference();
+ rthead = decodeHeader(ptr);
+
+ if (rthead) {
+ if (rthead->head_size == 1) {
+ log_debug("Response header: %s", hexify(ptr, 7, false));
+ } else {
+ log_debug("Response header: %s", hexify(ptr, rthead->head_size,
false));
+ }
+ if (rthead->type <= RTMP::FLV_DATA) {
+ log_error("Processing message of type %s!",
content_str[rthead->type]);
+ }
+
+ switch (rthead->type) {
+ case CHUNK_SIZE:
+ log_debug("Got CHUNK_SIZE packet!!!");
+ _chunksize = ntohl(*reinterpret_cast<boost::uint32_t *>(ptr +
rthead->head_size));
+ log_debug("Setting packet chunk size to %d.", _chunksize);
+// decodeChunkSize();
+ break;
+ case BYTES_READ:
+ log_debug("Got Bytes Read packet!!!");
+// decodeBytesRead();
+ break;
+ case PING:
+ {
+ RTMP::rtmp_ping_t *ping = decodePing(ptr);
+ log_debug("FIXME: Ping type is: %d, ignored for now",
ping->type);
+ switch (ping->type) {
+ case PING_CLEAR:
+ break;
+ case PING_PLAY:
+ break;
+ case PING_TIME:
+ break;
+ case PING_RESET:
+ break;
+ case PING_CLIENT:
+ break;
+ case PONG_CLIENT:
+ break;
+ default:
+ break;
+ };
+ break;
+ }
+ case SERVER:
+ {
+ log_debug("Got SERVER packet!!!");
+ Buffer server_data(rthead->bodysize);
+ server_data.copy(ptr + rthead->head_size, rthead->bodysize);
+// decodeServer();
+ break;
+ }
+ case CLIENT:
+ {
+ log_debug("Got CLIENT packet!!!");
+ Buffer client_data(rthead->bodysize);
+ client_data.copy(ptr + rthead->head_size, rthead->bodysize);
+// decodeClient();
+ break;
+ }
+ case VIDEO_DATA:
+ {
+ log_debug("Got VIDEO packets!!!");
+ Buffer *frame = 0;
+ do {
+ frame = recvMsg(1); // use a 1 second timeout
+ if (frame) {
+ _queues[rthead->channel].push(frame);
+ }
+// decodeVideoData();
+ } while (frame);
+ _queues->dump();
+ break;
+ }
+ case NOTIFY:
+// decodeNotify();
+ break;
+ case SHARED_OBJ:
+ log_debug("Got Shared Object packet!!!");
+// decodeSharedObj();
+ break;
+ case INVOKE:
+ msg = decodeMsgBody(ptr + rthead->head_size,
rthead->bodysize);
+// msg->dump();
+ if (msg) {
+ log_debug("%s: Msg status is: %d: %s, name is %s, size is
%d", __FUNCTION__,
+ msg->getStatus(), status_str[msg->getStatus()],
+ msg->getMethodName(), msg->size());
+ if (msg->getMethodName() == "onBWDone") {
+ log_debug("Got onBWDone packet!!!");
+ continue;
+ }
+ delete buf;
+ return msg;
+ } else {
+ log_error("Couldn't decode message body for type %s!",
+ content_str[rthead->type]);
+ }
+// decodeInvoke();
+ break;
+ case AUDIO_DATA:
+// decodeAudioData();
+ break;
+ default:
+ break;
+ } // end of switch
+ }
+// if (_queues[rthead->channel] != 0) {
+// _queues[rthead->channel].push(chunk);
+// }
+// ptr += rthead->head_size + rthead->bodysize;
+ };
+
+ return msg;
+}
+
+// Receive a message, which is a series of AMF elements, seperated
+// by a one byte header at regular byte intervals. (128 bytes for
+// video data by default). Each message main contain multiple packets.
+amf::Buffer *
+RTMP::recvMsg()
+{
+ GNASH_REPORT_FUNCTION;
+ return recvMsg(_timeout);
+}
+
+// Read big chunks of NETBUFSIZE, which is the default for a Buffer as it's
+// more efficient. As these reads may cross packet boundaries, and they may
+// also include the RTMP header every _chunksize bytes, this raw data will
+// need to be processed later on.
+amf::Buffer *
+RTMP::recvMsg(int timeout)
+{
+ GNASH_REPORT_FUNCTION;
+
+ int ret = 0;
+ bool nopacket = true;
+
+ Buffer *buf = 0;
+ buf = new Buffer;
+ while (nopacket) {
+ ret = readNet(buf, timeout);
+ if (ret <= 0) {
+ log_error("Never got any data at line %d", __LINE__);
+ delete buf;
return 0;
}
- if ((ret == 1) && (*buf.reference() == 0xff)) {
- cerr << __FUNCTION__ << ": " << __LINE__ << ": " <<
- hexify(buf.reference(), buf.size(), false) << endl;
- log_error("Got an error from the server sending object of type %s",
- content_str[type]);
-// exit(-1);
- }
- }
-
- RTMP::rtmp_head_t *rthead = decodeHeader(&buf);
-
- RTMPMsg *msg;
- if (rthead) {
- if (rthead->head_size == 1) {
- log_debug("Response header: %s", hexify(buf.reference(),
- 7, false));
- } else {
- log_debug("Response header: %s", hexify(buf.reference(),
- rthead->head_size, false));
- }
- if (rthead->type == RTMP::PING) {
- RTMP::rtmp_ping_t *ping = decodePing(buf.reference());
- log_debug("FIXME: Ping type is: %d, ignored for now", ping->type);
- } else if (rthead->type != RTMP::PING) {
- msg = decodeMsgBody(buf.reference() + rthead->head_size,
rthead->bodysize);
- if (msg) {
- log_debug("%s: Msg status is: %d: %s", __FUNCTION__,
- msg->getStatus(), status_str[msg->getStatus()]);
- } else {
- log_error("Couldn't decode message body for type %s!",
- content_str[rthead->type]);
- }
- } else {
- log_error("Couldn't decode message header for type %s!",
- content_str[type]);
- }
- }
-
-
-// Element *el = new Element;
-// el.
-
- if (rthead->bodysize < ret) {
- log_debug("more bytes left to read ! %d", (rthead->bodysize < ret));
- }
-
- return 0;
-}
+ if ((ret == 1) && (*(buf->reference()) == 0xff)) {
+ log_debug("Got an empty packet from the server at line %d",
__LINE__);
+ continue;
+ }
+ nopacket = false;
+ }
+ buf->resize(ret);
+// if (netDebug()) {
+// buf->dump();
+// }
+
+ return buf;
+}
+
+
+// Split a large buffer into multiple smaller ones of the default chunksize
+// of 128 bytes. We read network data in big chunks because it's more
efficient,
+// but RTMP uses a weird scheme of a standard header, and then every chunksize
+// bytes another 1 byte RTMP header. The header itself is not part of the byte
+// count.
+RTMP::queues_t *
+RTMP::split(Buffer *buf)
+{
+ return split(buf, _chunksize);
+}
+
+RTMP::queues_t *
+RTMP::split(Buffer *buf, size_t chunksize)
+{
+ GNASH_REPORT_FUNCTION;
+
+ if (buf == 0) {
+ log_error("Buffer pointer is invalid.");
+ }
+
+ // split the buffer at the chunksize boundary
+ Network::byte_t *ptr = 0;
+ rtmp_head_t *rthead = 0;
+ size_t pktsize = 0;
+ size_t nbytes = 0;
+
+ ptr = buf->reference();
+ Buffer *chunk = 0;
+ while ((ptr - buf->reference()) < buf->size()) {
+ rthead = decodeHeader(ptr);
+ // Make sure the header size is in range
+ if (rthead->head_size <= RTMP_MAX_HEADER_SIZE) {
+ // Any packet with a size greater than 1 is a new header, so create
+ // a new Buffer to hold all the data.
+ if ((rthead->head_size > 1)) {
+ // This is a queue of channels with active messages
+ _channels.push_back(&_queues[rthead->channel]);
+// cerr << "New packet for channel #" << rthead->channel << " of
size "
+// << (rthead->head_size + rthead->bodysize) << endl;
+ chunk = new Buffer(rthead->bodysize + rthead->head_size);
+ chunk->clear(); // FIXME: temporary debug only, should be
unnecessary
+ _queues[rthead->channel].push(chunk);
+ } else {
+ // Use the existing Buffer for this pkt
+ chunk = _queues[rthead->channel].peek();
+ }
+ // Many RTMP messages are smaller than the chunksize
+ if (chunk->size() <= chunksize) {
+ // a single byte header has no length field. As these are often
+ // used as continuation packets, the body size is the same as
the
+ // previous header with a length field.
+ if (rthead->head_size > 1) {
+ pktsize = chunk->size();
+ } else {
+ pktsize = rthead->head_size + rthead->bodysize -
chunk->size();
+ }
+ } else { // this RTMP message is larger than the chunksize
+ if (rthead->head_size > 1) {
+ pktsize = rthead->head_size + chunksize;
+ } else {
+ pktsize = rthead->head_size + (chunk->size() - chunksize);
+ }
+ }
+
+ // Range check the size of the packet
+ if (pktsize <= (chunksize + RTMP_MAX_HEADER_SIZE)) {
+ nbytes += pktsize;
+ // Skip the header for all but the first packet. The rest are
just to
+ // complete all the data up to the body size from the header.
+// cerr << _queues[rthead->channel].size() << " messages in queue
for channel "
+// << rthead->channel << endl;
+ if (rthead->head_size == 1) {
+// cerr << "FOLLOWING PACKET!" << " for channel " <<
rthead->channel << endl;
+// cerr << "Space Left in buffer for channel " <<
rthead->channel << " is: "
+// << chunk->spaceLeft() << endl;
+ ptr += rthead->head_size;
+ pktsize -= rthead->head_size;
+// } else {
+// cerr << "FIRST PACKET!" << " for channel " <<
rthead->channel << endl;
+ }
+ chunk->append(ptr, pktsize);
+// cerr << "Adding data to existing packet for channel #" <<
rthead->channel
+// << ", read " << nbytes << " bytes." << endl;
+ ptr += pktsize;
+ } else {
+ log_error("RTMP packet size is out of range! %d", pktsize);
+ break;
+ }
+ } else {
+ log_error("RTMP header size is out of range! %d",
rthead->head_size);
+ break;
+ }
+ }
+
+ return &_channels;
+}
+
} // end of gnash namespace
=== modified file 'libnet/rtmp.h'
--- a/libnet/rtmp.h 2008-08-14 04:24:41 +0000
+++ b/libnet/rtmp.h 2008-08-28 01:24:04 +0000
@@ -28,6 +28,7 @@
#include "network.h"
#include "buffer.h"
#include "rtmp_msg.h"
+#include "cque.h"
namespace gnash
{
@@ -74,6 +75,7 @@
class DSOEXPORT RTMP : public Network
{
public:
+ typedef std::deque<CQue *> queues_t;
typedef enum {
RAW=0x0,
ADPCM=0x01,
@@ -103,7 +105,8 @@
UNKNOWN3 = 0xa,
NOTIFY = 0x12,
SHARED_OBJ = 0x13,
- INVOKE = 0x14
+ INVOKE = 0x14,
+ FLV_DATA = 0x16
} content_types_e;
// typedef enum {
// CONNECT = 0x1,
@@ -230,7 +233,7 @@
int getPacketSize() { return _packet_size; };
int getMysteryWord() { return _mystery_word; };
- // Decode the an RTMP message
+ // Decode an RTMP message
RTMPMsg *decodeMsgBody(Network::byte_t *data, size_t size);
RTMPMsg *decodeMsgBody(amf::Buffer *buf);
@@ -266,27 +269,41 @@
// Receive a message, which is a series of AMF elements, seperated
// by a one byte header at regular byte intervals. (128 bytes for
- // video data). Each message main contain multiple packets.
+ // video data by default). Each message main contain multiple packets.
amf::Buffer *recvMsg();
+ amf::Buffer *recvMsg(int timeout);
// Send a message, usually a single ActionScript object. This message
// may be broken down into a series of packets on a regular byte
- // interval. (128 bytes for video data). Each message main contain
- // multiple packets.
- bool sendMsg(amf::Buffer *buf);
+ // interval. (128 bytes for video data by default). Each message main
+ // contain multiple packets.
+ bool sendMsg(amf::Buffer *data);
// Send a Msg, and expect a response back of some kind.
- amf::Element *sendRecvMsg(int amf_index, rtmp_headersize_e head_size,
+ RTMPMsg *sendRecvMsg(int amf_index, rtmp_headersize_e head_size,
size_t total_size, content_types_e type,
RTMPMsg::rtmp_source_e routing, amf::Buffer *buf);
+ // Split a large buffer into multiple smaller ones of the default chunksize
+ // of 128 bytes. We read network data in big chunks because it's more
efficient,
+ // but RTMP uses a weird scheme of a standard header, and then every
chunksize
+ // bytes another 1 byte RTMP header. The header itself is not part of the
byte
+ // count.
+ queues_t *split(amf::Buffer *buf);
+ queues_t *split(amf::Buffer *buf, size_t chunksize);
+
+ CQue &operator[] (size_t x) { return _queues[x]; }
void dump();
protected:
- std::map<const char *, amf::Element *> _variables;
+ std::map<const char *, amf::Element *> _properties;
amf::Buffer *_handshake;
Handler *_handler;
rtmp_head_t _header;
int _packet_size;
int _mystery_word;
+ size_t _chunksize;
+ int _timeout;
+ CQue _queues[MAX_AMF_INDEXES];
+ queues_t _channels;
};
} // end of gnash namespace
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] /srv/bzr/gnash/rtmp r9606: add support for decoding multiple RTMP messages.,
rob <=