diff --git a/trunk/research/players/srs_reuse_conn/.actionScriptProperties b/trunk/research/players/srs_reuse_conn/.actionScriptProperties
new file mode 100755
index 000000000..ea33e282e
--- /dev/null
+++ b/trunk/research/players/srs_reuse_conn/.actionScriptProperties
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/trunk/research/players/srs_reuse_conn/.project b/trunk/research/players/srs_reuse_conn/.project
new file mode 100755
index 000000000..11dc3f9c2
--- /dev/null
+++ b/trunk/research/players/srs_reuse_conn/.project
@@ -0,0 +1,17 @@
+
+
+ srs_reuse_conn
+
+
+
+
+
+ com.adobe.flexbuilder.project.flexbuilder
+
+
+
+
+
+ com.adobe.flexbuilder.project.actionscriptnature
+
+
diff --git a/trunk/research/players/srs_reuse_conn/.settings/org.eclipse.core.resources.prefs b/trunk/research/players/srs_reuse_conn/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..0fc6bb311
--- /dev/null
+++ b/trunk/research/players/srs_reuse_conn/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Sat Nov 22 18:40:22 CST 2014
+eclipse.preferences.version=1
+encoding/=utf-8
diff --git a/trunk/research/players/srs_reuse_conn/FlashCS5UI.swc b/trunk/research/players/srs_reuse_conn/FlashCS5UI.swc
new file mode 100644
index 000000000..ea19d9d5c
Binary files /dev/null and b/trunk/research/players/srs_reuse_conn/FlashCS5UI.swc differ
diff --git a/trunk/research/players/srs_reuse_conn/release/srs_reuse_conn.swf b/trunk/research/players/srs_reuse_conn/release/srs_reuse_conn.swf
new file mode 100644
index 000000000..c07272016
Binary files /dev/null and b/trunk/research/players/srs_reuse_conn/release/srs_reuse_conn.swf differ
diff --git a/trunk/research/players/srs_reuse_conn/src/srs_reuse_conn.as b/trunk/research/players/srs_reuse_conn/src/srs_reuse_conn.as
new file mode 100644
index 000000000..c534b647b
--- /dev/null
+++ b/trunk/research/players/srs_reuse_conn/src/srs_reuse_conn.as
@@ -0,0 +1,123 @@
+package
+{
+ import fl.controls.Button;
+ import fl.controls.TextInput;
+
+ import flash.display.Sprite;
+ import flash.display.StageAlign;
+ import flash.display.StageScaleMode;
+ import flash.events.Event;
+ import flash.events.MouseEvent;
+ import flash.events.NetStatusEvent;
+ import flash.media.Video;
+ import flash.net.NetConnection;
+ import flash.net.NetStream;
+
+ [SWF(backgroundColor="0xEEEEEE",frameRate="30",width="1024",height="576")]
+ public class srs_reuse_conn extends Sprite
+ {
+ public function srs_reuse_conn()
+ {
+ if (stage) {
+ onAddedToStage(null);
+ } else {
+ addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
+ }
+ }
+
+ private function onAddedToStage(evt:Event):void
+ {
+ stage.align = StageAlign.TOP_LEFT;
+ stage.scaleMode = StageScaleMode.NO_SCALE;
+
+ var txtUrl:TextInput = new TextInput();
+ var btnConn:Button = new Button();
+ var btnPlay:Button = new Button();
+
+ txtUrl.x = 10;
+ txtUrl.y = 10;
+ txtUrl.width = 400;
+ txtUrl.text = "rtmp://dev/live/livestream";
+ addChild(txtUrl);
+
+ btnConn.label = "Connect";
+ btnConn.x = txtUrl.x + txtUrl.width + 10;
+ btnConn.y = txtUrl.y;
+ btnConn.width = 100;
+ addChild(btnConn);
+
+ btnPlay.label = "Play";
+ btnPlay.x = btnConn.x + btnConn.width + 10;
+ btnPlay.y = btnConn.y;
+ btnPlay.width = 100;
+ addChild(btnPlay);
+
+ var video:Video = new Video();
+ video.x = txtUrl.x;
+ video.y = txtUrl.y + txtUrl.height + 10;
+ addChild(video);
+
+ var conn:NetConnection = null;
+ var stream:NetStream = null;
+
+ var tcUrl:Function = function():String {
+ var url:String = txtUrl.text;
+ return url.substr(0, url.lastIndexOf("/"));
+ }
+ var streamName:Function = function():String {
+ var url:String = txtUrl.text;
+ return url.substr(tcUrl().length + 1);
+ }
+
+ var closeConnection:Function = function():void {
+ if (stream) {
+ stream.close();
+ stream = null;
+ }
+ if (conn) {
+ conn.close();
+ conn = null;
+ }
+ btnConn.label = "Connect";
+ btnPlay.visible = false;
+ };
+
+ btnPlay.visible = false;
+ btnConn.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void {
+ if (btnConn.label == "Connect") {
+ conn = new NetConnection();
+ conn.client = {
+ onBWDone: function():void{}
+ };
+ conn.addEventListener(NetStatusEvent.NET_STATUS, function(ne:NetStatusEvent):void {
+ if (ne.info.code == "NetConnection.Connect.Success") {
+ btnPlay.visible = true;
+ } else if (ne.info.code == "NetConnection.Connect.Closed") {
+ closeConnection();
+ }
+ trace(ne.info.code);
+ });
+ conn.connect(tcUrl());
+ btnConn.label = "Close";
+ } else {
+ closeConnection();
+ }
+ });
+ btnPlay.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void {
+ if (stream) {
+ stream.close();
+ stream = null;
+ }
+ stream = new NetStream(conn);
+ stream.client = {
+ onMetaData: function(metadata:Object):void {
+ video.width = metadata.width;
+ video.height = metadata.height;
+ }
+ };
+ video.attachNetStream(stream);
+ stream.play(streamName());
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/trunk/src/app/srs_app_recv_thread.cpp b/trunk/src/app/srs_app_recv_thread.cpp
index 21e6cd316..0134af8de 100644
--- a/trunk/src/app/srs_app_recv_thread.cpp
+++ b/trunk/src/app/srs_app_recv_thread.cpp
@@ -54,6 +54,11 @@ bool SrsRecvThread::empty()
return queue.empty();
}
+int SrsRecvThread::size()
+{
+ return (int)queue.size();
+}
+
SrsMessage* SrsRecvThread::pump()
{
srs_assert(!queue.empty());
@@ -79,6 +84,15 @@ int SrsRecvThread::cycle()
{
int ret = ERROR_SUCCESS;
+ // we only recv one message and then process it,
+ // for the message may cause the thread to stop,
+ // when stop, the thread is freed, so the messages
+ // are dropped.
+ if (!queue.empty()) {
+ st_usleep(SRS_CONSTS_RTMP_PULSE_TIMEOUT_US);
+ return ret;
+ }
+
SrsMessage* msg = NULL;
if ((ret = rtmp->recv_message(&msg)) != ERROR_SUCCESS) {
@@ -93,6 +107,10 @@ int SrsRecvThread::cycle()
}
srs_verbose("play loop recv message. ret=%d", ret);
+ // put into queue, the send thread will get and process it,
+ // @see SrsRtmpConn::process_play_control_msg
+ queue.push_back(msg);
+
return ret;
}
diff --git a/trunk/src/app/srs_app_recv_thread.hpp b/trunk/src/app/srs_app_recv_thread.hpp
index dd8886e15..640decd1c 100644
--- a/trunk/src/app/srs_app_recv_thread.hpp
+++ b/trunk/src/app/srs_app_recv_thread.hpp
@@ -54,6 +54,7 @@ public:
virtual ~SrsRecvThread();
public:
virtual bool empty();
+ virtual int size();
virtual SrsMessage* pump();
public:
virtual int start();
diff --git a/trunk/src/app/srs_app_rtmp_conn.cpp b/trunk/src/app/srs_app_rtmp_conn.cpp
index 0d3d6a393..f280490e4 100644
--- a/trunk/src/app/srs_app_rtmp_conn.cpp
+++ b/trunk/src/app/srs_app_rtmp_conn.cpp
@@ -514,6 +514,11 @@ int SrsRtmpConn::playing(SrsSource* source)
// stop isolate recv thread
trd.stop();
+ // warn for the message is dropped.
+ if (!trd.empty()) {
+ srs_warn("drop the received %d messages", trd.size());
+ }
+
return ret;
}
@@ -549,7 +554,7 @@ int SrsRtmpConn::do_playing(SrsSource* source, SrsRecvThread* trd)
// @see: https://github.com/winlinvip/simple-rtmp-server/issues/217
while (!trd->empty()) {
SrsMessage* msg = trd->pump();
- srs_warn("pump client message to process.");
+ srs_verbose("pump client message to process.");
if ((ret = process_play_control_msg(consumer, msg)) != ERROR_SUCCESS) {
if (!srs_is_system_control_error(ret)) {