gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] gnash libamf/amf.cpp libamf/element.cpp libnet/...


From: Rob Savoye
Subject: [Gnash-commit] gnash libamf/amf.cpp libamf/element.cpp libnet/...
Date: Fri, 06 Jun 2008 14:21:34 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Rob Savoye <rsavoye>    08/06/06 14:21:33

Modified files:
        libamf         : amf.cpp element.cpp 
        libnet         : rtmp.h rtmp_client.cpp rtmp_client.h 
        testsuite/libnet.all: test_rtmp.cpp 
        .              : ChangeLog 

Log message:
                * libamf/amf.cpp: Add support for NULL objects.
                * libamf/element.cpp: Set the boolean data correctly, it was
                offset by one byte. Make a NULL object.
                * libnet/rtmp.h: Add Stream operations, play, stop, pause, seek,
                publish.
                * libnet/rtmp_client.{h,cpp}: Build NetStream operation packets.
                * testsuite/libnet.all/test_rtmp.cpp: Test NetStream operations
                packets for the client side.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/amf.cpp?cvsroot=gnash&r1=1.80&r2=1.81
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/element.cpp?cvsroot=gnash&r1=1.26&r2=1.27
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp.h?cvsroot=gnash&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp_client.cpp?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp_client.h?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/libnet.all/test_rtmp.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.6835&r2=1.6836

Patches:
Index: libamf/amf.cpp
===================================================================
RCS file: /sources/gnash/gnash/libamf/amf.cpp,v
retrieving revision 1.80
retrieving revision 1.81
diff -u -b -r1.80 -r1.81
--- libamf/amf.cpp      17 May 2008 20:10:36 -0000      1.80
+++ libamf/amf.cpp      6 Jun 2008 14:21:31 -0000       1.81
@@ -193,7 +193,6 @@
 /// @return a binary AMF packet in big endian format (header,data) which
 /// needs to be deleted[] after being used.
 ///
-/// Although a boolean is one byte in size.
 Buffer *
 AMF::encodeBoolean(bool flag)
 {
@@ -201,9 +200,6 @@
     // Encode a boolean value. 0 for false, 1 for true
     Buffer *buf = new Buffer(2);
     buf->append(Element::BOOLEAN_AMF0);
-// Hum, AMF3 ???
-//     boost::uint16_t x = flag;
-//     swapBytes(&x, 2);
     buf->append(flag);
     
     return buf;
@@ -312,8 +308,10 @@
 {
 //    GNASH_REPORT_FUNCTION;
 
-    log_unimpl("NULL AMF object not supported yet");
-    return 0;
+    Buffer *buf = new Buffer(1);
+    buf->append(Element::NULL_AMF0);
+    
+    return buf;
 }
 
 /// Encode an XML object
@@ -514,6 +512,10 @@
     } else {
        outsize = el->getNameSize() + AMF_VAR_HEADER_SIZE;
     }
+    // A NULL object is a single byte
+    if (el->getType() == Element::NULL_AMF0) {
+       outsize = 1;
+    }
     buf = new Buffer(outsize);
     buf->clear();              // FIXME: temporary, makes buffers cleaner in 
gdb.
     // If the name field is set, it's a "property", followed by the data

Index: libamf/element.cpp
===================================================================
RCS file: /sources/gnash/gnash/libamf/element.cpp,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -b -r1.26 -r1.27
--- libamf/element.cpp  16 May 2008 03:46:21 -0000      1.26
+++ libamf/element.cpp  6 Jun 2008 14:21:32 -0000       1.27
@@ -597,7 +597,8 @@
 //    GNASH_REPORT_FUNCTION;
     _type = Element::BOOLEAN_AMF0;
     check_buffer(sizeof(bool));
-    _buffer->append(flag);
+    *(_buffer->reference()) = flag;
+
     return *this;
 }
 
@@ -638,13 +639,12 @@
     return makeUndefined();
 }
 
+// a NULL amf Object consists of a single byte, which is the type
 Element &
 Element::makeNull()
 {
 //    GNASH_REPORT_FUNCTION;
     _type = Element::NULL_AMF0;
-    check_buffer(sizeof(Network::byte_t));
-    *(_buffer->reference()) = 0;
     return *this;
 }
 

Index: libnet/rtmp.h
===================================================================
RCS file: /sources/gnash/gnash/libnet/rtmp.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- libnet/rtmp.h       16 May 2008 03:46:26 -0000      1.9
+++ libnet/rtmp.h       6 Jun 2008 14:21:32 -0000       1.10
@@ -126,6 +126,13 @@
        PING_CLIENT = 0x6,      // Ping the client from the server
        PONG_CLIENT = 0x7       // pong reply from client to server
     } rtmp_ping_e;
+    typedef enum {
+       STREAM_PLAY,            // play the existing stream
+       STREAM_PAUSE,           // pause the existing stream
+       STREAM_PUBLISH,         // publish the existing stream
+       STREAM_STOP,            // stop the existing stream
+       STREAM_SEEK             // seek in the existing stream
+    } rtmp_op_e;
     typedef struct {
        rtmp_ping_e type;       // the type of the ping message
        boost::uint16_t target; // all Ping message data fields

Index: libnet/rtmp_client.cpp
===================================================================
RCS file: /sources/gnash/gnash/libnet/rtmp_client.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- libnet/rtmp_client.cpp      16 May 2008 03:46:27 -0000      1.1
+++ libnet/rtmp_client.cpp      6 Jun 2008 14:21:32 -0000       1.2
@@ -79,16 +79,16 @@
     
     AMF amf_obj;
 
-    Element *connect = new Element;
-    connect->makeString("connect");
+    Element connect;
+    connect.makeString("connect");
 
-    Element *connum = new Element;
+    Element connum;
 //     const char *connumStr = "00 00 00 00 00 00 f0 3f";
 //     Buffer *connumBuf = hex2mem(connumStr);
     // update the counter for the number of connections. This number is used 
heavily
     // in RTMP to help keep communications clear when there are multiple 
streams.
     _connections++;
-    connum->makeNumber(_connections);
+    connum.makeNumber(_connections);
     
     // Make the top level object
     Element obj;
@@ -148,8 +148,8 @@
 //                                      RTMP::INVOKE, RTMP::FROM_CLIENT);
 //     const char *rtmpStr = "03 00 00 04 00 01 1f 14 00 00 00 00";
 //     Buffer *rtmpBuf = hex2mem(rtmpStr);
-    Buffer *conobj = connect->encode();
-    Buffer *numobj = connum->encode();
+    Buffer *conobj = connect.encode();
+    Buffer *numobj = connum.encode();
     Buffer *encobj = obj.encode();
 
     Buffer *buf = new Buffer(conobj->size() + numobj->size() + encobj->size());
@@ -158,6 +158,8 @@
     buf->append(numobj);
     buf->append(encobj);
 
+    // Now that we have an encoded buffer, nuke the Element
+    
     return buf;
 }
 
@@ -165,19 +167,37 @@
 // 65 53 74 72 65 61 6d 00 40 08 00 00 00 00 00 00  address@hidden
 // 05                                                    .               
 amf::Buffer *
-RTMPClient::encodeStream(double /* id */)
+RTMPClient::encodeStream(double id)
 {
     GNASH_REPORT_FUNCTION;
     
     struct timespec now;
     clock_gettime (CLOCK_REALTIME, &now);
     
-//     log_debug("Buffer %x (%d) stayed in queue for %f seconds",
-//           (void *)_ptr, _nbytes,
-//           (float)((now.tv_sec - _stamp.tv_sec) + ((now.tv_nsec - 
_stamp.tv_nsec)/1e9)));
+    Element str = new Element;
+    str.makeString("createStream");
+    Buffer *strobj = str.encode();
+    if (!strobj) {
+       return 0;
+    }
 
-    log_unimpl(__PRETTY_FUNCTION__);
+    Element num = new Element;
+    num.makeNumber(id);
+    Buffer *numobj = num.encode();
+    if (!numobj) {
     return 0;
+    }
+
+    Buffer *buf = new Buffer(strobj->size() + numobj->size());
+    if (!buf) {
+       return 0;
+    }
+    buf->append(strobj);
+    buf->append(numobj);
+
+    delete strobj;
+    delete numobj;
+    return buf;
 }
 
 // 127.0.0.1:38167 -> 127.0.0.1:1935 [AP]
@@ -187,11 +207,133 @@
 // 69 6f 2e 66 6c 76 c2 00 03 00 00 00 01 00 00 27  io.flv.........'
 // 10
 amf::Buffer *
-RTMPClient::encodePublish()
+RTMPClient::encodeStreamOp(double id, rtmp_op_e op, bool flag)
+{
+//    GNASH_REPORT_FUNCTION;
+    return encodeStreamOp(id, op, flag, "", 0);
+}    
+
+amf::Buffer *
+RTMPClient::encodeStreamOp(double id, rtmp_op_e op, bool flag, double pos)
+{
+//    GNASH_REPORT_FUNCTION;
+    return encodeStreamOp(id, op, flag, "", pos);
+}    
+
+amf::Buffer *
+RTMPClient::encodeStreamOp(double id, rtmp_op_e op, bool flag, const 
std::string &name)
+{
+//    GNASH_REPORT_FUNCTION;
+    return encodeStreamOp(id, op, flag, name, 0);
+}
+
+// A seek packet is the operation name "seek", followed by the
+// stream ID, then a NULL object, followed by the location to seek to.
+//
+// A pause packet is the operation name "pause", followed by the stream ID,
+// then a NULL object, a boolean (always true from what I can tell), and then
+// a location, which appears to always be 0.
+amf::Buffer *
+RTMPClient::encodeStreamOp(double id, rtmp_op_e op, bool flag, const 
std::string &name, double pos)
 {
     GNASH_REPORT_FUNCTION;
-    log_unimpl(__PRETTY_FUNCTION__);
+
+    // Set the operations command name
+    Element str;
+    switch (op) {
+      case STREAM_PLAY:                // play the existing stream
+         str.makeString("play");
+         break;
+      case STREAM_PAUSE:       // pause the existing stream
+         str.makeString("pause");
+         break;
+      case STREAM_PUBLISH:     // publish the existing stream
+         str.makeString("publish");
+         break;
+      case STREAM_STOP:                // stop the existing stream
+         str.makeString("stop");
+         break;
+      case STREAM_SEEK:                // seek in the existing stream
+         str.makeString("seek");
+         break;
+      default:
     return 0;
+    };
+
+    Buffer *strobj = str.encode();
+    if (!strobj) {
+       return 0;
+    }
+
+    // Set the stream ID, which follows the command
+    Element strid;
+    strid.makeNumber(id);
+    Buffer *stridobj = strid.encode();
+    if (!stridobj) {
+       return 0;
+    }
+
+    // Set the NULL object element that follows the stream ID
+    Element null;
+    null.makeNull();
+    Buffer *nullobj = null.encode();    
+    if (!nullobj) {
+       return 0;
+    }
+
+    // Set the BOOLEAN object element that is the last field in the packet
+    Element boolean;
+    boolean.makeBoolean(flag);
+    Buffer *boolobj = boolean.encode();    
+    if (!boolobj) {
+       return 0;
+    }
+    
+    // Calculate the packet size, rather than use the default as we want to
+    // to be concious of the memory usage. The command name and the optional
+    // file name are the only two dynamically sized fields.
+    size_t pktsize = strobj->size() + name.size();
+    // Add 2 bytes for the Boolean, and 16 bytes for the two doubles, which are
+    // 8 bytes apiece.
+    pktsize += (sizeof(double) * 2) + 2;
+//    Buffer *buf = new Buffer(pktsize);
+    Buffer *buf = new Buffer;
+    
+    if (!buf) {
+       return 0;
+    }
+    buf->append(strobj);
+    delete strobj;
+    buf->append(stridobj);
+    delete stridobj;    
+    buf->append(nullobj);
+    delete nullobj;
+    // Seek doesn't use the boolean flag
+    if (op != STREAM_SEEK) {
+       buf->append(boolobj);
+    }
+    delete boolobj;
+
+    // The play command has an optional field, which is the name of the file
+    // used for the stream. A Play command without this name set play an
+    // existing stream that is already open.
+    if (!name.empty()) {
+       buf->append(name);
+    }
+    
+    // The seek command also may have an optional location to seek to
+    if ((op == STREAM_PAUSE) || (op == STREAM_SEEK)) {
+       Element seek;
+       seek.makeNumber(pos);
+       Buffer *posobj = seek.encode();
+       if (!posobj) {
+           return 0;
+       }
+       buf->append(posobj);
+       delete posobj;
+    }
+
+    return buf;
 }    
 
 // A request for a handshake is initiated by sending a byte with a

Index: libnet/rtmp_client.h
===================================================================
RCS file: /sources/gnash/gnash/libnet/rtmp_client.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- libnet/rtmp_client.h        16 May 2008 03:46:27 -0000      1.1
+++ libnet/rtmp_client.h        6 Jun 2008 14:21:32 -0000       1.2
@@ -51,8 +51,10 @@
                               const char *pageUrl);
     // Create the second object sent to the server, which is 
NetStream():;NetStream()
     amf::Buffer *encodeStream(double id);
-
-    amf::Buffer *encodePublish();
+    amf::Buffer *encodeStreamOp(double id, rtmp_op_e op, bool flag);
+    amf::Buffer *encodeStreamOp(double id, rtmp_op_e op, bool flag, double 
pos);
+    amf::Buffer *encodeStreamOp(double id, rtmp_op_e op, bool flag, const 
std::string &name);
+    amf::Buffer *encodeStreamOp(double id, rtmp_op_e op, bool flag, const 
std::string &name, double pos);
     
     void dump();
   private:

Index: testsuite/libnet.all/test_rtmp.cpp
===================================================================
RCS file: /sources/gnash/gnash/testsuite/libnet.all/test_rtmp.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- testsuite/libnet.all/test_rtmp.cpp  16 May 2008 03:46:38 -0000      1.2
+++ testsuite/libnet.all/test_rtmp.cpp  6 Jun 2008 14:21:32 -0000       1.3
@@ -68,6 +68,7 @@
 static void test_types();
 static void test_results();
 static void test_system();
+static void test_client();
 
 LogFile& dbglogfile = LogFile::getDefaultInstance();
 
@@ -113,6 +114,7 @@
         ch |= hex2digit(*ptr++);
         buf->append(ch);
     }
+
     return buf;
 }
 
@@ -173,6 +175,7 @@
     test_header();
     test_system();
     test_results();
+    test_client();
 //    test_types();
 }
 
@@ -184,14 +187,9 @@
     RTMPClient client;
     RTMPServer server;
 
-    
-//    const char *x1 = "00 00 00 00 00 00";
     Buffer *buf1 = hex2mem("00 00 00 00 00 00");  // clear buffer message
-//    const char *x2 = "00 06 cf 03 04 c3";
     Buffer *buf2 = hex2mem("00 06 cf 03 04 c3"); // ping client from server
-//    const char *x3 = "00 07 cf 03 04 c3";
     Buffer *buf3 = hex2mem("00 07 cf 03 04 c3"); // Pong, reply from client
-//    const char *x4 = "00 00 00 00 00 01";
     Buffer *buf4 = hex2mem("00 00 00 00 00 01"); // clear buffer message
     
     RTMP::rtmp_ping_t *ping1 = client.decodePing(buf1);
@@ -459,6 +457,79 @@
     const char *x = "06 00 d2 04 00 00 00 00";
     Buffer *buf1 = hex2mem(x);
     
+    delete buf1;
+}
+
+void
+test_client()
+{
+    GNASH_REPORT_FUNCTION;
+    RTMPClient rtmp;
+
+    Buffer *buf1 = hex2mem("02 00 04 70 6c 61 79 00 00 00 00 00 00 00 00 00 05 
01 00");
+    Buffer *buf2 = rtmp.encodeStreamOp(0, RTMP::STREAM_PLAY, false);
+    if ((memcmp(buf1->reference(), buf2->reference(), buf1->size()) == 0)) {
+        runtest.pass("Encoded RTMPClient::encodeStreamOp(RTMP::STREAM_PLAY)");
+    } else {
+        runtest.fail("Encoded RTMPClient::encodeStreamOp(RTMP::STREAM_PLAY)");
+    }
+    delete buf1;
+    delete buf2;
+
+    buf1 = hex2mem("02 00 05 70 61 75 73 65 00 00 00 00 00 00 00 00 00 05 01 
01 00 00 00 00 00 00 00 00 00");
+    buf2 = rtmp.encodeStreamOp(0, RTMP::STREAM_PAUSE, true, 0);
+    if ((memcmp(buf1->reference(), buf2->reference(), buf1->size()) == 0)) {
+        runtest.pass("Encoded RTMPClient::encodeStreamOp(RTMP::STREAM_PAUSE)");
+    } else {
+        runtest.fail("Encoded RTMPClient::encodeStreamOp(RTMP::STREAM_PAUSE)");
+    }
+    delete buf1;
+    delete buf2;
+
+    buf1 = hex2mem("02 00 04 73 74 6f 70 00 00 00 00 00 00 00 00 00 05 01 00");
+    buf2 = rtmp.encodeStreamOp(0, RTMP::STREAM_STOP, false);
+    if ((memcmp(buf1->reference(), buf2->reference(), buf1->size()) == 0)) {
+        runtest.pass("Encoded RTMPClient::encodeStreamOp(RTMP::STREAM_STOP)");
+    } else {
+        runtest.fail("Encoded RTMPClient::encodeStreamOp(RTMP::STREAM_STOP)");
+    }
+    delete buf1;
+    delete buf2;
+
+#if 0
+    buf1 = hex2mem("02 00 07 70 75 62 6c 69 73 68 00 00 00 00 00 00 00 00 00 
05 02 00 06 73 74 72 65 61 6d 02 00 04 6c 69 76 65 0d 00 02 ba 00 00 1a 14 02 
00 00 00 02 00");
+    buf2 = rtmp.encodeStreamOp(0, RTMP::STREAM_PUBLISH, false);
+    cerr << hexify(buf1->begin(), buf1->size(), false) << endl;
+    cerr << hexify(buf2->begin(), buf1->size(), false) << endl;
+    if ((memcmp(buf1->reference(), buf2->reference(), buf1->size()) == 0)) {
+        runtest.pass("Encoded 
RTMPClient::encodeStreamOp(RTMP::STREAM_PUBLISH)");
+    } else {
+        runtest.fail("Encoded 
RTMPClient::encodeStreamOp(RTMP::STREAM_PUBLISH)");
+    }
+    delete buf1;
+    delete buf2;
+#endif
+    
+    buf1 = hex2mem("02 00 04 73 65 65 6b 00 00 00 00 00 00 00 00 00 05 00 00 
00 00 00 00 00 00 00");
+    buf2 = rtmp.encodeStreamOp(0, RTMP::STREAM_SEEK, false);
+    if ((memcmp(buf1->reference(), buf2->reference(), buf1->size()) == 0)) {
+        runtest.pass("Encoded RTMPClient::encodeStream(RTMP::SEEK)");
+    } else {
+        runtest.fail("Encoded RTMPClient::encodeStream(RTMP::SEEK)");
+    }
+    delete buf1;
+    delete buf2;
+
+    buf1 = hex2mem("02 00 04 73 65 65 6b 00 00 00 00 00 00 00 00 00 05 00 40 
c7 70 00 00 00 00 00");
+    buf2 = rtmp.encodeStreamOp(0, RTMP::STREAM_SEEK, false, 12000);
+    if ((memcmp(buf1->reference(), buf2->reference(), buf1->size()) == 0)) {
+        runtest.pass("Encoded RTMPClient::encodeStream(RTMP::SEEK, double)");
+    } else {
+        runtest.fail("Encoded RTMPClient::encodeStream(RTMP::SEEK, double)");
+    }
+    delete buf1;
+    delete buf2;
+
 }
 
 static void

Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.6835
retrieving revision 1.6836
diff -u -b -r1.6835 -r1.6836
--- ChangeLog   6 Jun 2008 10:51:39 -0000       1.6835
+++ ChangeLog   6 Jun 2008 14:21:33 -0000       1.6836
@@ -1,3 +1,14 @@
+2008-06-06  Rob Savoye  <address@hidden>
+
+       * libamf/amf.cpp: Add support for NULL objects.
+       * libamf/element.cpp: Set the boolean data correctly, it was
+       offset by one byte. Make a NULL object.
+       * libnet/rtmp.h: Add Stream operations, play, stop, pause, seek,
+       publish.
+       * libnet/rtmp_client.{h,cpp}: Build NetStream operation packets.
+       * testsuite/libnet.all/test_rtmp.cpp: Test NetStream operations
+       packets for the client side.
+
 2008-06-06 Benjamin Wolsey <address@hidden>
 
        * libbase/utility.h: include gnashconfig.h, fix some old-style casts,




reply via email to

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