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)) {