diff --git a/README.md b/README.md
index aeae5b7d6..fcc9967cf 100755
--- a/README.md
+++ b/README.md
@@ -45,6 +45,7 @@ url: rtmp://127.0.0.1:1935/live/livestream
* nginx v1.5.0: 139524 lines
### History
+* v0.3, 2013-10-28, support librtmp without extended-timestamp in 0xCX chunk packet.
* v0.3, 2013-10-27, support cache last gop for client fast startup.
* v0.2, 2013-10-25, v0.2 released. 10125 lines.
* v0.2, 2013-10-25, support flash publish.
diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp
index 25effe6a7..af05a23ff 100755
--- a/trunk/src/core/srs_core.hpp
+++ b/trunk/src/core/srs_core.hpp
@@ -62,13 +62,18 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
} \
(void)0
+// current release version
+#define RTMP_SIG_SRS_VERSION "0.2"
// server info.
#define RTMP_SIG_SRS_KEY "srs"
+#define RTMP_SIG_SRS_ROLE "origin server"
#define RTMP_SIG_SRS_NAME RTMP_SIG_SRS_KEY"(simple rtmp server)"
-#define RTMP_SIG_SRS_URL "https://github.com/winlinvip/simple-rtmp-server"
+#define RTMP_SIG_SRS_URL "https://"RTMP_SIG_SRS_URL_SHORT
+#define RTMP_SIG_SRS_URL_SHORT "github.com/winlinvip/simple-rtmp-server"
#define RTMP_SIG_SRS_WEB "http://blog.csdn.net/win_lin"
#define RTMP_SIG_SRS_EMAIL "winterserver@126.com"
-#define RTMP_SIG_SRS_VERSION "0.1"
+#define RTMP_SIG_SRS_LICENSE "The MIT License (MIT)"
+#define RTMP_SIG_SRS_COPYRIGHT "Copyright (c) 2013 winlin"
// compare
#define srs_min(a, b) ((a < b)? a : b)
diff --git a/trunk/src/core/srs_core_client.cpp b/trunk/src/core/srs_core_client.cpp
index 7cceb2367..1c64d04e9 100755
--- a/trunk/src/core/srs_core_client.cpp
+++ b/trunk/src/core/srs_core_client.cpp
@@ -63,8 +63,8 @@ int SrsClient::do_cycle()
}
srs_verbose("get peer ip success. ip=%s", ip);
- rtmp->set_recv_timeout(SRS_SEND_TIMEOUT_MS);
- rtmp->set_send_timeout(SRS_SEND_TIMEOUT_MS);
+ rtmp->set_recv_timeout(SRS_SEND_TIMEOUT_MS * 1000);
+ rtmp->set_send_timeout(SRS_SEND_TIMEOUT_MS * 1000);
if ((ret = rtmp->handshake()) != ERROR_SUCCESS) {
srs_error("rtmp handshake failed. ret=%d", ret);
@@ -185,7 +185,7 @@ int SrsClient::streaming_play(SrsSource* source)
SrsAutoFree(SrsConsumer, consumer, false);
srs_verbose("consumer created success.");
- rtmp->set_recv_timeout(SRS_PULSE_TIMEOUT_MS);
+ rtmp->set_recv_timeout(SRS_PULSE_TIMEOUT_MS * 1000);
int64_t report_time = 0;
int64_t reported_time = 0;
diff --git a/trunk/src/core/srs_core_protocol.cpp b/trunk/src/core/srs_core_protocol.cpp
index f42db4a24..e0e44d3f0 100755
--- a/trunk/src/core/srs_core_protocol.cpp
+++ b/trunk/src/core/srs_core_protocol.cpp
@@ -249,6 +249,9 @@ messages.
/****************************************************************************
*****************************************************************************
****************************************************************************/
+// when got a messae header, increase recv timeout to got an entire message.
+#define SRS_MIN_RECV_TIMEOUT_US 3000
+
SrsProtocol::AckWindowSize::AckWindowSize()
{
ack_window_size = acked_size = 0;
@@ -278,14 +281,19 @@ SrsProtocol::~SrsProtocol()
srs_freep(skt);
}
-void SrsProtocol::set_recv_timeout(int timeout_ms)
+void SrsProtocol::set_recv_timeout(int64_t timeout_us)
{
- return skt->set_recv_timeout(timeout_ms);
+ return skt->set_recv_timeout(timeout_us);
}
-void SrsProtocol::set_send_timeout(int timeout_ms)
+int64_t SrsProtocol::get_recv_timeout()
{
- return skt->set_send_timeout(timeout_ms);
+ return skt->get_recv_timeout();
+}
+
+void SrsProtocol::set_send_timeout(int64_t timeout_us)
+{
+ return skt->set_send_timeout(timeout_us);
}
int SrsProtocol::recv_message(SrsCommonMessage** pmsg)
@@ -602,17 +610,31 @@ int SrsProtocol::recv_interlaced_message(SrsCommonMessage** pmsg)
}
return ret;
}
- srs_info("read basic header success. fmt=%d, cid=%d, bh_size=%d", fmt, cid, bh_size);
+ srs_verbose("read basic header success. fmt=%d, cid=%d, bh_size=%d", fmt, cid, bh_size);
+
+ // once we got the chunk message header,
+ // that is there is a real message in cache,
+ // increase the timeout to got it.
+ // For example, in the play loop, we set timeout to 100ms,
+ // when we got a chunk header, we should increase the timeout,
+ // or we maybe timeout and disconnect the client.
+ int64_t timeout_us = skt->get_recv_timeout();
+ if (timeout_us != (int64_t)ST_UTIME_NO_TIMEOUT) {
+ int64_t pkt_timeout_us = srs_max(timeout_us, SRS_MIN_RECV_TIMEOUT_US);
+ skt->set_recv_timeout(pkt_timeout_us);
+ srs_verbose("change recv timeout_us "
+ "from %"PRId64" to %"PRId64"", timeout_us, pkt_timeout_us);
+ }
// get the cached chunk stream.
SrsChunkStream* chunk = NULL;
if (chunk_streams.find(cid) == chunk_streams.end()) {
chunk = chunk_streams[cid] = new SrsChunkStream(cid);
- srs_info("cache new chunk stream: fmt=%d, cid=%d", fmt, cid);
+ srs_verbose("cache new chunk stream: fmt=%d, cid=%d", fmt, cid);
} else {
chunk = chunk_streams[cid];
- srs_info("cached chunk stream: fmt=%d, cid=%d, size=%d, message(type=%d, size=%d, time=%d, sid=%d)",
+ srs_verbose("cached chunk stream: fmt=%d, cid=%d, size=%d, message(type=%d, size=%d, time=%d, sid=%d)",
chunk->fmt, chunk->cid, (chunk->msg? chunk->msg->size : 0), chunk->header.message_type, chunk->header.payload_length,
chunk->header.timestamp, chunk->header.stream_id);
}
@@ -625,7 +647,7 @@ int SrsProtocol::recv_interlaced_message(SrsCommonMessage** pmsg)
}
return ret;
}
- srs_info("read message header success. "
+ srs_verbose("read message header success. "
"fmt=%d, mh_size=%d, ext_time=%d, size=%d, message(type=%d, size=%d, time=%d, sid=%d)",
fmt, mh_size, chunk->extended_timestamp, (chunk->msg? chunk->msg->size : 0), chunk->header.message_type,
chunk->header.payload_length, chunk->header.timestamp, chunk->header.stream_id);
@@ -640,9 +662,15 @@ int SrsProtocol::recv_interlaced_message(SrsCommonMessage** pmsg)
return ret;
}
+ // reset the recv timeout
+ if (timeout_us != (int64_t)ST_UTIME_NO_TIMEOUT) {
+ skt->set_recv_timeout(timeout_us);
+ srs_verbose("reset recv timeout_us to %"PRId64"", timeout_us);
+ }
+
// not got an entire RTMP message, try next chunk.
if (!msg) {
- srs_info("get partial message success. chunk_payload_size=%d, size=%d, message(type=%d, size=%d, time=%d, sid=%d)",
+ srs_verbose("get partial message success. chunk_payload_size=%d, size=%d, message(type=%d, size=%d, time=%d, sid=%d)",
payload_size, (msg? msg->size : (chunk->msg? chunk->msg->size : 0)), chunk->header.message_type, chunk->header.payload_length,
chunk->header.timestamp, chunk->header.stream_id);
return ret;
diff --git a/trunk/src/core/srs_core_protocol.hpp b/trunk/src/core/srs_core_protocol.hpp
index 5628762a6..601bb9c9c 100755
--- a/trunk/src/core/srs_core_protocol.hpp
+++ b/trunk/src/core/srs_core_protocol.hpp
@@ -104,11 +104,12 @@ public:
virtual ~SrsProtocol();
public:
/**
- * set the timeout in ms.
+ * set the timeout in us.
* if timeout, recv/send message return ERROR_SOCKET_TIMEOUT.
*/
- virtual void set_recv_timeout(int timeout_ms);
- virtual void set_send_timeout(int timeout_ms);
+ virtual void set_recv_timeout(int64_t timeout_us);
+ virtual int64_t get_recv_timeout();
+ virtual void set_send_timeout(int64_t timeout_us);
/**
* recv a message with raw/undecoded payload from peer.
* the payload is not decoded, use srs_rtmp_expect_message if requires
diff --git a/trunk/src/core/srs_core_rtmp.cpp b/trunk/src/core/srs_core_rtmp.cpp
index e8a4e8fa8..ec72bde60 100755
--- a/trunk/src/core/srs_core_rtmp.cpp
+++ b/trunk/src/core/srs_core_rtmp.cpp
@@ -149,14 +149,19 @@ SrsRtmp::~SrsRtmp()
srs_freep(complex_handshake);
}
-void SrsRtmp::set_recv_timeout(int timeout_ms)
+void SrsRtmp::set_recv_timeout(int64_t timeout_us)
{
- return protocol->set_recv_timeout(timeout_ms);
+ return protocol->set_recv_timeout(timeout_us);
}
-void SrsRtmp::set_send_timeout(int timeout_ms)
+int64_t SrsRtmp::get_recv_timeout()
{
- return protocol->set_send_timeout(timeout_ms);
+ return protocol->get_recv_timeout();
+}
+
+void SrsRtmp::set_send_timeout(int64_t timeout_us)
+{
+ return protocol->set_send_timeout(timeout_us);
}
int SrsRtmp::recv_message(SrsCommonMessage** pmsg)
@@ -176,7 +181,6 @@ int SrsRtmp::handshake()
ssize_t nsize;
SrsSocket skt(stfd);
- // TODO: complex handshake for h264/aac codec.
char* c0c1 = new char[1537];
SrsAutoFree(char, c0c1, true);
if ((ret = skt.read_fully(c0c1, 1537, &nsize)) != ERROR_SUCCESS) {
@@ -325,10 +329,15 @@ int SrsRtmp::response_connect_app(SrsRequest* req)
SrsASrsAmf0EcmaArray* data = new SrsASrsAmf0EcmaArray();
pkt->info->set("data", data);
- data->set("version", new SrsAmf0String(RTMP_SIG_FMS_VER));
- data->set("server", new SrsAmf0String(RTMP_SIG_SRS_NAME));
+ data->set("srs_version", new SrsAmf0String(RTMP_SIG_FMS_VER));
+ data->set("srs_server", new SrsAmf0String(RTMP_SIG_SRS_NAME));
+ data->set("srs_license", new SrsAmf0String(RTMP_SIG_SRS_LICENSE));
+ data->set("srs_role", new SrsAmf0String(RTMP_SIG_SRS_ROLE));
data->set("srs_url", new SrsAmf0String(RTMP_SIG_SRS_URL));
data->set("srs_version", new SrsAmf0String(RTMP_SIG_SRS_VERSION));
+ data->set("srs_site", new SrsAmf0String(RTMP_SIG_SRS_WEB));
+ data->set("srs_email", new SrsAmf0String(RTMP_SIG_SRS_EMAIL));
+ data->set("srs_copyright", new SrsAmf0String(RTMP_SIG_SRS_COPYRIGHT));
msg->set_packet(pkt, 0);
diff --git a/trunk/src/core/srs_core_rtmp.hpp b/trunk/src/core/srs_core_rtmp.hpp
index e9608392f..670f88fad 100755
--- a/trunk/src/core/srs_core_rtmp.hpp
+++ b/trunk/src/core/srs_core_rtmp.hpp
@@ -105,8 +105,9 @@ public:
SrsRtmp(st_netfd_t client_stfd);
virtual ~SrsRtmp();
public:
- virtual void set_recv_timeout(int timeout_ms);
- virtual void set_send_timeout(int timeout_ms);
+ virtual void set_recv_timeout(int64_t timeout_us);
+ virtual int64_t get_recv_timeout();
+ virtual void set_send_timeout(int64_t timeout_us);
virtual int recv_message(SrsCommonMessage** pmsg);
virtual int send_message(ISrsMessage* msg);
public:
diff --git a/trunk/src/core/srs_core_socket.cpp b/trunk/src/core/srs_core_socket.cpp
index 5f540baf0..46c11361d 100755
--- a/trunk/src/core/srs_core_socket.cpp
+++ b/trunk/src/core/srs_core_socket.cpp
@@ -36,14 +36,19 @@ SrsSocket::~SrsSocket()
{
}
-void SrsSocket::set_recv_timeout(int timeout_ms)
+void SrsSocket::set_recv_timeout(int64_t timeout_us)
{
- recv_timeout = timeout_ms * 1000;
+ recv_timeout = timeout_us;
}
-void SrsSocket::set_send_timeout(int timeout_ms)
+int64_t SrsSocket::get_recv_timeout()
{
- send_timeout = timeout_ms * 1000;
+ return recv_timeout;
+}
+
+void SrsSocket::set_send_timeout(int64_t timeout_us)
+{
+ send_timeout = timeout_us;
}
int64_t SrsSocket::get_recv_bytes()
diff --git a/trunk/src/core/srs_core_socket.hpp b/trunk/src/core/srs_core_socket.hpp
index 320487a03..e7495f74c 100755
--- a/trunk/src/core/srs_core_socket.hpp
+++ b/trunk/src/core/srs_core_socket.hpp
@@ -48,8 +48,9 @@ public:
SrsSocket(st_netfd_t client_stfd);
virtual ~SrsSocket();
public:
- virtual void set_recv_timeout(int timeout_ms);
- virtual void set_send_timeout(int timeout_ms);
+ virtual void set_recv_timeout(int64_t timeout_us);
+ virtual int64_t get_recv_timeout();
+ virtual void set_send_timeout(int64_t timeout_us);
virtual int64_t get_recv_bytes();
virtual int64_t get_send_bytes();
public:
diff --git a/trunk/src/core/srs_core_source.cpp b/trunk/src/core/srs_core_source.cpp
index 22a4da2eb..e9940e082 100755
--- a/trunk/src/core/srs_core_source.cpp
+++ b/trunk/src/core/srs_core_source.cpp
@@ -179,8 +179,8 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata
{
int ret = ERROR_SUCCESS;
- metadata->metadata->set("server",
- new SrsAmf0String(RTMP_SIG_SRS_NAME""RTMP_SIG_SRS_VERSION));
+ metadata->metadata->set("server", new SrsAmf0String(
+ RTMP_SIG_SRS_KEY" "RTMP_SIG_SRS_VERSION" ("RTMP_SIG_SRS_URL_SHORT")"));
// encode the metadata to payload
int size = metadata->get_payload_length();