[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/trunk r9618: merge from rtmp branch.
From: |
rob |
Subject: |
[Gnash-commit] /srv/bzr/gnash/trunk r9618: merge from rtmp branch. |
Date: |
Mon, 18 Aug 2008 17:53:04 -0600 |
User-agent: |
Bazaar (1.5) |
------------------------------------------------------------
revno: 9618
committer: address@hidden
branch nick: trunk
timestamp: Mon 2008-08-18 17:53:04 -0600
message:
merge from rtmp branch.
added:
utilities/rtmpget.cpp
modified:
libamf/flv.cpp
testsuite/libamf.all/test_flv.cpp
------------------------------------------------------------
revno: 9483.1.104
committer: address@hidden
branch nick: rtmp
timestamp: Mon 2008-08-18 17:35:08 -0600
message:
Fix all valgrind errors on all platforms.
removed:
utilities/rtmpget.cpp
added:
macros/nspr.m4
macros/xpcom.m4
plugin/xpcom/
plugin/xpcom/GnashComponent.cpp
plugin/xpcom/GnashComponent.h
plugin/xpcom/GnashComponentModule.cpp
plugin/xpcom/Makefile.am
plugin/xpcom/iGnashComponent.idl
testsuite/media/greyscale.png
testsuite/media/indexed.png
utilities/rtmpget.cpp
modified:
.bzrignore
Makefile.am
configure.ac
libamf/flv.cpp
libnet/cque.cpp
libnet/cque.h
libnet/network.cpp
libnet/network.h
libnet/rtmp.cpp
libnet/rtmp.h
libnet/rtmp_client.cpp
libnet/rtmp_msg.cpp
libnet/rtmp_msg.h
libnet/rtmp_server.cpp
libnet/rtmp_server.h
packaging/deb.am
packaging/install-gnash.sh
packaging/snapshot.am
packaging/xpi.am
packaging/xpi/install.rdf
plugin/Makefile.am
testsuite/libamf.all/test_flv.cpp
testsuite/libnet.all/Makefile.am
testsuite/libnet.all/test_rtmp.cpp
testsuite/misc-ming.all/Makefile.am
testsuite/misc-ming.all/loadImageTest.c
testsuite/misc-swfc.all/matrix_accuracy_test1.sc
testsuite/swfdec/PASSING
utilities/Makefile.am
=== modified file 'libamf/flv.cpp'
--- a/libamf/flv.cpp 2008-08-15 19:17:28 +0000
+++ b/libamf/flv.cpp 2008-08-18 23:35:08 +0000
@@ -21,6 +21,7 @@
#include "gnashconfig.h"
#endif
+#include <boost/detail/endian.hpp>
#include <string>
#include <vector>
#include <cmath>
@@ -141,39 +142,29 @@
AMF amf;
Network::byte_t *ptr = buf;
Network::byte_t *tooFar = ptr + size;
- char *name = 0;
// Extract the onMetaData object name
// In disk files, I always see the 0x2 type field for
// a string, but not always in streaming, at least according to
- // Gnash's libmedia/FLVParser code. So if we see the begining
- // of "onMetaData", then just grab the length without the type
- // field.
- if ((*ptr == 0) && (*(ptr+2) == 'o')) {
- boost::uint16_t length;
- length = ntohs((*(boost::uint16_t *)ptr) & 0xffff);
- name = new char(length+1);
- memset(name, 0, length+1);
- ptr += sizeof(boost::uint16_t);
- std::copy(name, name + length, ptr);
- ptr += length;
- } else {
- Element *objname = amf.extractAMF(ptr, tooFar);
- if (objname == 0) {
- log_error("Failed to get the onMetaData string");
- return 0;
- }
- ptr += objname->getLength() + AMF_HEADER_SIZE;
- name = const_cast<char *>(objname->to_string());
- }
+ // Gnash's libmedia/FLVParser code. Since this is always
+ if (*ptr == Element::STRING_AMF0) {
+ ptr++;
+ }
+
+ boost::uint16_t length;
+ length = ntohs((*(boost::uint16_t *)ptr) & 0xffff);
+ if (length >= SANE_STR_SIZE) {
+ log_error("%d bytes for a string is over the safe limit of %d",
+ length, SANE_STR_SIZE);
+ }
+ ptr += sizeof(boost::uint16_t);
+ std::string name(reinterpret_cast<const char *>(ptr), length);
+ ptr += length;
// Extract the properties for this metadata object.
Element *el = amf.extractAMF(ptr, tooFar);
ptr += amf.totalsize();
-
- if (name) {
- el->setName(name);
- }
+ el->setName(name.c_str(), length);
return el;
}
@@ -284,10 +275,13 @@
{
// GNASH_REPORT_FUNCTION;
boost::uint32_t bodysize = 0;
+#ifdef BOOST_BIG_ENDIAN
+ bodysize = *(reinterpret_cast<boost::uint32_t *>(num)) >> 8;
+#else
bodysize = *(reinterpret_cast<boost::uint32_t *>(num)) << 8;
-
bodysize = ntohl(bodysize);
-
+#endif
+
return bodysize;
}
=== modified file 'testsuite/libamf.all/test_flv.cpp'
--- a/testsuite/libamf.all/test_flv.cpp 2008-08-16 19:21:36 +0000
+++ b/testsuite/libamf.all/test_flv.cpp 2008-08-18 23:35:08 +0000
@@ -196,7 +196,7 @@
}
}
delete hex1;
-
+
Buffer *enc1 = flv.encodeHeader(Flv::FLV_AUDIO | Flv::FLV_VIDEO);
Network::byte_t *ptr = enc1->reference();
if ((enc1->size() == sizeof(Flv::flv_header_t))
@@ -207,7 +207,8 @@
} else {
runtest.fail("Encoded FLV header");
}
-
+ delete enc1;
+
// Test converting 3 byte "integers" to a real 4 byte one. The
// 0xf on each end should be ignore to be correct.
Buffer *hex2 = hex2mem("0f 00 00 a4 0f");
@@ -220,20 +221,16 @@
}
delete hex2;
- if (notest) {
- runtest.unresolved("Decoded FLV MetaData header");
+ Buffer *hex3 = hex2mem("12 00 00 a4 00 00 00 00 00 00 00");
+ Flv::flv_tag_t *tag3 = flv.decodeTagHeader(hex3);
+ if ((tag3->type == Flv::TAG_METADATA)
+ && (flv.convert24(tag3->bodysize) == 164)) {
+ runtest.pass("Decoded FLV MetaData header");
} else {
- Buffer *hex3 = hex2mem("12 00 00 a4 00 00 00 00 00 00 00");
- Flv::flv_tag_t *tag3 = flv.decodeTagHeader(hex3);
- if ((tag3->type == Flv::TAG_METADATA)
- && (flv.convert24(tag3->bodysize) == 164)) {
- runtest.pass("Decoded FLV MetaData header");
- } else {
- runtest.fail("Decoded FLV MetaData header");
- }
- delete tag3;
- delete hex3;
+ runtest.fail("Decoded FLV MetaData header");
}
+ delete tag3;
+ delete hex3;
}
void
=== added file 'utilities/rtmpget.cpp'
--- a/utilities/rtmpget.cpp 1970-01-01 00:00:00 +0000
+++ b/utilities/rtmpget.cpp 2008-08-18 23:35:08 +0000
@@ -0,0 +1,506 @@
+// rtmpget.cpp: RTMP file downloader utility
+//
+// Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include <string>
+#include <iostream>
+#include <sstream>
+#include <signal.h>
+#include <vector>
+#include <sys/mman.h>
+#include <cerrno>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <gettext.h>
+
+// classes internal to Gnash
+#include "gnash.h"
+#include "network.h"
+#include "log.h"
+#include "http.h"
+#include "limits.h"
+#include "netstats.h"
+#include "statistics.h"
+#include "gmemory.h"
+#include "arg_parser.h"
+#include "amf.h"
+#include "rtmp.h"
+#include "rtmp_client.h"
+#include "rtmp_msg.h"
+#include "buffer.h"
+#include "network.h"
+#include "element.h"
+#include "URL.h"
+
+// classes internal to Cygnal
+#include "buffer.h"
+#include "handler.h"
+
+#ifdef ENABLE_NLS
+#include <locale.h>
+#endif
+
+#include <boost/date_time/gregorian/gregorian.hpp>
+#include <boost/date_time/time_zone_base.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/bind.hpp>
+
+using gnash::log_debug;
+using namespace std;
+using namespace gnash;
+using namespace amf;
+
+static void usage();
+static void version_and_copyright();
+static void cntrlc_handler(int sig);
+
+void connection_handler(Handler::thread_params_t *args);
+void admin_handler(Handler::thread_params_t *args);
+
+LogFile& dbglogfile = LogFile::getDefaultInstance();
+
+// The rcfile is loaded and parsed here:
+RcInitFile& rcfile = RcInitFile::getDefaultInstance();
+
+// Toggles very verbose debugging info from the network Network class
+static bool netdebug = false;
+
+static struct sigaction act;
+
+std::vector<std::string> infiles;
+
+// The next few global variables have to be global because Boost
+// threads don't take arguments. Since these are set in main() before
+// any of the threads are started, and it's value should never change,
+// it's safe to use these without a mutex, as all threads share the
+// same read-only value.
+
+// end of globals
+
+int
+main(int argc, char *argv[])
+{
+ // Initialize national language support
+#ifdef ENABLE_NLS
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+#endif
+
+ // If no command line arguments have been supplied, do nothing but
+ // print the usage message.
+ if (argc < 2) {
+ usage();
+ exit(0);
+ }
+
+ const Arg_parser::Option opts[] =
+ {
+ { 'h', "help", Arg_parser::no },
+ { 'V', "version", Arg_parser::no },
+ { 'p', "port-offset", Arg_parser::yes },
+ { 'v', "verbose", Arg_parser::no },
+ { 'd', "dump", Arg_parser::no },
+ { 'a', "app", Arg_parser::yes },
+ { 'p', "path", Arg_parser::yes },
+ { 'f', "filename", Arg_parser::yes },
+ { 't', "tcurl", Arg_parser::yes },
+ { 's', "swfurl", Arg_parser::yes },
+ { 'u', "url", Arg_parser::yes },
+ { 'n', "netdebug", Arg_parser::no }
+ };
+
+ Arg_parser parser(argc, argv, opts);
+ if( ! parser.error().empty() )
+ {
+ cout << parser.error() << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ // Set the log file name before trying to write to
+ // it, or we might get two.
+ dbglogfile.setLogFilename("rtmpget-dbg.log");
+
+ if (rcfile.verbosityLevel() > 0) {
+ dbglogfile.setVerbosity(rcfile.verbosityLevel());
+ }
+
+ RTMPClient client;
+ short port = 0;
+ string protocol; // the network protocol, rtmp or http
+ string app; // the application name
+ string path; // the path to the file on the server
+ string query; // any queries for the host
+ string filename; // the filename to play
+ string tcUrl; // the tcUrl field
+ string swfUrl; // the swfUrl field
+ string pageUrl; // the pageUrl field
+ string hostname; // the hostname of the server
+
+ // Handle command line arguments
+ for( int i = 0; i < parser.arguments(); ++i ) {
+ const int code = parser.code(i);
+ try {
+ switch( code ) {
+ case 'h':
+ version_and_copyright();
+ usage();
+ exit(0);
+ case 'V':
+ version_and_copyright();
+ exit(0);
+ case 'v':
+ dbglogfile.setVerbosity();
+ log_debug (_("Verbose output turned on"));
+ break;
+ case 'a':
+ app = parser.argument(i);
+ break;
+ case 'p':
+ path = parser.argument(i);
+ break;
+ case 't':
+ tcUrl = parser.argument(i);
+ break;
+ case 's':
+ swfUrl = parser.argument(i);
+ break;
+ case 'f':
+ filename = parser.argument(i);
+ break;
+ case 'n':
+ netdebug = true;
+ break;
+ case 'd':
+ rcfile.dump();
+ exit(0);
+ break;
+ case 0:
+ infiles.push_back(parser.argument(i));
+ break;
+ default:
+ log_error (_("Extraneous argument: %s"),
parser.argument(i).c_str());
+ }
+ }
+
+ catch (Arg_parser::ArgParserException &e) {
+ cerr << _("Error parsing command line options: ") << e.what() <<
endl;
+ cerr << _("This is a Gnash bug.") << endl;
+ }
+ }
+
+ if (infiles.empty()) {
+ cerr << _("Error: no input file was specified. Exiting.") << endl;
+ usage();
+ return EXIT_FAILURE;
+ }
+
+ string url = infiles[0];
+ string portstr;
+
+ // Trap ^C (SIGINT) so we can kill all the threads
+ act.sa_handler = cntrlc_handler;
+ sigaction (SIGINT, &act, NULL);
+
+ // Take a standard URL apart.
+ string::size_type start = url.find(':', 0);
+ if (start != string::npos) {
+ protocol = url.substr(0, start);
+ start += 3; // skip past the "://" part after the protocol
+ }
+ string::size_type end = url.find('/', start);
+ if (end != string::npos) {
+ string::size_type pos = url.find(':', start);
+ if (pos != string::npos) {
+ hostname = url.substr(start, pos - start);
+ portstr = url.substr(pos + 1, (end - pos) - 1);
+ port = strtol(portstr.c_str(), NULL, 0) & 0xffff;
+ } else {
+ hostname = url.substr(start, end - start);
+ if ((protocol == "http") || (protocol == "rtmpt")) {
+ port = RTMPT_PORT;
+ }
+ if (protocol == "rtmp") {
+ port = RTMP_PORT;
+ }
+ }
+ start = end;
+ }
+ end = url.rfind('/');
+ if (end != string::npos) {
+ path = url.substr(start + 1, end - start - 1);
+ start = end;
+ filename = url.substr(end + 1);
+ }
+
+ start = path.find('?', 0);
+ if (start != string::npos) {
+ end = path.find('/', 0);
+ query = path.substr(0, end);
+ app = query;
+ path = path.substr(end, path.size());
+ } else {
+ app = path;
+ }
+
+ if (tcUrl.empty()) {
+ tcUrl = protocol + "://" + hostname;
+ if (!portstr.empty()) {
+ tcUrl += ":" + portstr;
+ }
+ if (!query.empty()) {
+ tcUrl += "/" + query;
+ } else {
+ tcUrl += "/" + path;
+ }
+ }
+
+ if (app.empty()) {
+ // Get the application name
+ app = path;
+
+ if (!query.empty()) {
+ app = path;
+ app += "?" + query;
+ }
+ }
+
+ if (swfUrl.empty()) {
+ swfUrl = "mediaplayer.swf";
+ }
+ if (pageUrl.empty()) {
+ pageUrl = "http://gnashdev.org";
+ }
+
+ if (netdebug) {
+ cerr << "URL is " << url << endl;
+ cerr << "Protocol is " << protocol << endl;
+ cerr << "Host is " << hostname << endl;
+ cerr << "Port is " << port << endl;
+ cerr << "Path is " << path << endl;
+ cerr << "Filename is " << filename << endl;
+ cerr << "App is " << app << endl;
+ cerr << "Query is " << query << endl;
+ cerr << "tcUrl is " << tcUrl << endl;
+ cerr << "swfUrl is " << swfUrl << endl;
+ cerr << "pageUrl is " << pageUrl << endl;
+ }
+
+ client.toggleDebug(netdebug);
+ if (client.createClient(hostname, port) == false) {
+ log_error("Can't connect to RTMP server %s", hostname);
+ exit(-1);
+ }
+
+ client.handShakeRequest();
+
+ client.clientFinish();
+
+ // Make a buffer to hold the handshake data.
+ Buffer buf(1537);
+ RTMP::rtmp_head_t *rthead = 0;
+ int ret = 0;
+ log_debug("Sending NetConnection Connect message,");
+ Buffer *buf2 = client.encodeConnect(app.c_str(), swfUrl.c_str(),
tcUrl.c_str(), 615, 124, 1, pageUrl.c_str());
+// Buffer *buf2 =
client.encodeConnect("video/2006/sekt/gate06/tablan_valentin",
"mediaplayer.swf",
"rtmp://velblod.videolectures.net/video/2006/sekt/gate06/tablan_valentin", 615,
124, 1, "http://gnashdev.org");
+// Buffer *buf2 = client.encodeConnect("oflaDemo",
"http://192.168.1.70/software/gnash/tests/ofla_demo.swf",
"rtmp://localhost/oflaDemo/stream", 615, 124, 1,
"http://192.168.1.70/software/gnash/tests/index.html");
+ buf2->resize(buf2->size() - 6); // FIXME: encodeConnect returns the wrong
size for the buffer!
+ size_t total_size = buf2->size();
+ RTMPMsg *msg1 = client.sendRecvMsg(0x3, RTMP::HEADER_12, total_size,
+ RTMP::INVOKE, RTMPMsg::FROM_CLIENT,
+ buf2);
+ if (msg1) {
+ msg1->dump();
+ if (msg1->getStatus() == RTMPMsg::NC_CONNECT_SUCCESS) {
+ log_debug("Sent NetConnection Connect message sucessfully");
+ } else {
+ log_error("Couldn't send NetConnection Connect message,");
+// exit(-1);
+ }
+ }
+
+ // make the createStream for ID 3 encoded object
+ log_debug("Sending NetStream::createStream message,");
+ Buffer *buf3 = client.encodeStream(0x2);
+// buf3->dump();
+ total_size = buf3->size();
+ RTMPMsg *msg2 = client.sendRecvMsg(0x3, RTMP::HEADER_12, total_size,
+ RTMP::INVOKE, RTMPMsg::FROM_CLIENT,
+ buf3);
+ double streamID = 0.0;
+ if (msg2) {
+ msg2->dump();
+ log_debug("Sent NetStream::createStream message successfully.");
+ std::vector<amf::Element *> hell = msg2->getElements();
+ if (hell.size() > 0) {
+ streamID = hell[0]->to_number();
+ } else {
+ if (msg2->getMethodName() == "close") {
+ log_debug("Got close packet!!! Exiting...");
+ exit(0);
+ }
+ streamID = 0.0;
+ }
+ } else {
+ log_error("Couldn't send NetStream::createStream message,");
+// exit(-1);
+ }
+ int id = int(streamID);
+ log_debug("Stream ID returned from createStream is: %d", id);
+
+ // make the NetStream::play() operations for ID 2 encoded object
+// log_debug("Sending NetStream play message,");
+ Buffer *buf4 = client.encodeStreamOp(0, RTMP::STREAM_PLAY, false,
filename.c_str());
+// Buffer *buf4 = client.encodeStreamOp(0, RTMP::STREAM_PLAY, false,
"gate06_tablan_bcueu_01");
+// log_debug("TRACE: buf4: %s", hexify(buf4->reference(), buf4->size(),
true));
+ total_size = buf4->size();
+ RTMPMsg *msg3 = client.sendRecvMsg(0x8, RTMP::HEADER_12, total_size,
+ RTMP::INVOKE, RTMPMsg::FROM_CLIENT,
buf4);
+ if (msg3) {
+ msg3->dump();
+ if (msg3->getStatus() == RTMPMsg::NS_PLAY_START) {
+ log_debug("Sent NetStream::play message sucessfully.");
+ } else {
+ log_error("Couldn't send NetStream::play message,");
+// exit(-1);
+ }
+ }
+
+ int loop = 20;
+ do {
+ Buffer *msgs = client.recvMsg(1); // use a 1 second timeout
+ if (msgs == 0) {
+ log_error("Never got any data!");
+ exit(-1);
+ }
+ RTMP::queues_t *que = client.split(msgs);
+ if (que == 0) {
+ log_error("Never got any messages!");
+ exit(-1);
+ }
+
+#if 0
+ deque<CQue *>::iterator it;
+ for (it = que->begin(); it != que->end(); it++) {
+ CQue *q = *(it);
+ q->dump();
+ }
+#endif
+ while (que->size()) {
+ cerr << "QUE SIZE: " << que->size() << endl;
+ Buffer *ptr = que->front()->pop();
+ if ((ptr->size() >= 0) && (ptr->size() <= 0xffff)) {
+ que->pop_front(); // delete the item from the queue
+ RTMP::rtmp_head_t *rthead = client.decodeHeader(ptr);
+ msg2 = client.processMsg(ptr);
+ if (msg2 == 0) {
+// log_error("Couldn't process the RTMP message!");
+ continue;
+ }
+ } else {
+ log_error("Buffer size (%d) out of range at %d", ptr->size(),
__LINE__);
+ break;
+ }
+ }
+ } while(loop--);
+
+// std::vector<amf::Element *> hell = msg2->getElements();
+// std::vector<amf::Element *> props = hell[0]->getProperties();
+
+// cerr << "HELL Elements: " << hell.size() << endl;
+// cerr << "HELL Properties: " << props.size() << endl;
+
+// // cerr << props[0]->getName() << endl;
+// // cerr << props[0]->to_string() << endl;
+// cerr << props[0]->getName() << endl;
+// // cerr << props[0]->to_number() << endl;
+// cerr << props[1]->getName() << ": " << props[1]->to_string() << endl;
+// cerr << props[2]->getName() << ": " << props[3]->to_string() << endl;
+// cerr << props[3]->getName() << ": " << props[3]->to_string() << endl;
+
+// Element *eell = hell[0]->findProperty("level");
+// if (eell) {
+// eell->dump();
+// }
+// *eell = hell[0]->findProperty("code");
+// if (eell) {
+// eell->dump();
+// }
+
+#if 0
+ // Write the packet to disk so we can anaylze it with other tools
+ int fd = open("outbuf.raw",O_WRONLY|O_CREAT, S_IRWXU);
+ if (fd == -1) {
+ perror("open");
+ }
+ cout << "Writing packet to disk: \"outbuf.raw\"" << endl;
+// write(fd, out, 12);
+// write(fd, outbuf.begin(), amf_obj.totalsize());
+ write(fd, buf2->reference(), buf2->size());
+ write(fd, buf3->reference(), buf3->size());
+ close(fd);
+#endif
+}
+
+// Trap Control-C so we can cleanly exit
+static void
+cntrlc_handler (int /*sig*/)
+{
+ log_debug(_("Got an interrupt"));
+
+ exit(-1);
+}
+
+static void
+version_and_copyright()
+{
+ cout << "rtmpget " << VERSION << endl
+ << endl
+ << _("Copyright (C) 2008 Free Software Foundation, Inc.\n"
+ "Cygnal comes with NO WARRANTY, to the extent permitted by law.\n"
+ "You may redistribute copies of Cygnal under the terms of the GNU
General\n"
+ "Public License. For more information, see the file named COPYING.\n")
+ << endl;
+}
+
+
+static void
+usage()
+{
+ cout << _("rtmpget -- a file downloaded that uses RTMP.") << endl
+ << endl
+ << _("Usage: rtmpget [options...]") << endl
+ << _(" -h, --help Print this help and exit") << endl
+ << _(" -V, --version Print version information and exit") <<
endl
+ << _(" -v, --verbose Output verbose debug info") << endl
+ << _(" -n, --netdebug Verbose networking debug info") << endl
+ << _(" -d, --dump display init file to terminal") << endl
+ << endl;
+}
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] /srv/bzr/gnash/trunk r9618: merge from rtmp branch.,
rob <=