winlin

fix bug #45, support duration for live. change to 0.9.62

@@ -54,6 +54,7 @@ class SrsPithyPrint @@ -54,6 +54,7 @@ class SrsPithyPrint
54 private: 54 private:
55 int client_id; 55 int client_id;
56 int stage_id; 56 int stage_id;
  57 + // in ms.
57 int64_t age; 58 int64_t age;
58 int64_t printed_age; 59 int64_t printed_age;
59 public: 60 public:
@@ -254,13 +254,13 @@ int SrsRtmpConn::stream_service_cycle() @@ -254,13 +254,13 @@ int SrsRtmpConn::stream_service_cycle()
254 int ret = ERROR_SUCCESS; 254 int ret = ERROR_SUCCESS;
255 255
256 SrsRtmpConnType type; 256 SrsRtmpConnType type;
257 - if ((ret = rtmp->identify_client(res->stream_id, type, req->stream)) != ERROR_SUCCESS) { 257 + if ((ret = rtmp->identify_client(res->stream_id, type, req->stream, req->duration)) != ERROR_SUCCESS) {
258 srs_error("identify client failed. ret=%d", ret); 258 srs_error("identify client failed. ret=%d", ret);
259 return ret; 259 return ret;
260 } 260 }
261 req->strip(); 261 req->strip();
262 - srs_trace("identify client success. type=%s, stream_name=%s",  
263 - srs_client_type_string(type).c_str(), req->stream.c_str()); 262 + srs_trace("identify client success. type=%s, stream_name=%s, duration=%.2f",
  263 + srs_client_type_string(type).c_str(), req->stream.c_str(), req->duration);
264 264
265 // client is identified, set the timeout to service timeout. 265 // client is identified, set the timeout to service timeout.
266 rtmp->set_recv_timeout(SRS_RECV_TIMEOUT_US); 266 rtmp->set_recv_timeout(SRS_RECV_TIMEOUT_US);
@@ -417,6 +417,15 @@ int SrsRtmpConn::playing(SrsSource* source) @@ -417,6 +417,15 @@ int SrsRtmpConn::playing(SrsSource* source)
417 while (true) { 417 while (true) {
418 pithy_print.elapse(SRS_PULSE_TIMEOUT_US / 1000); 418 pithy_print.elapse(SRS_PULSE_TIMEOUT_US / 1000);
419 419
  420 + // if duration specified, and exceed it, stop play live.
  421 + // @see: https://github.com/winlinvip/simple-rtmp-server/issues/45
  422 + // TODO: maybe the duration should use the stream duration.
  423 + if (req->duration > 0 && pithy_print.get_age() >= (int64_t)req->duration) {
  424 + ret = ERROR_RTMP_DURATION_EXCEED;
  425 + srs_trace("stop live for duration exceed. ret=%d", ret);
  426 + return ret;
  427 + }
  428 +
420 // switch to other st-threads. 429 // switch to other st-threads.
421 st_usleep(0); 430 st_usleep(0);
422 431
@@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 // current release version 31 // current release version
32 #define VERSION_MAJOR "0" 32 #define VERSION_MAJOR "0"
33 #define VERSION_MINOR "9" 33 #define VERSION_MINOR "9"
34 -#define VERSION_REVISION "61" 34 +#define VERSION_REVISION "62"
35 #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION 35 #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
36 // server info. 36 // server info.
37 #define RTMP_SIG_SRS_KEY "srs" 37 #define RTMP_SIG_SRS_KEY "srs"
@@ -75,6 +75,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -75,6 +75,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
75 // 1. srs is ok, ignore and turn to simple handshake. 75 // 1. srs is ok, ignore and turn to simple handshake.
76 // 2. srs-librtmp return error, to terminate the program. 76 // 2. srs-librtmp return error, to terminate the program.
77 #define ERROR_RTMP_HS_SSL_REQUIRE 318 77 #define ERROR_RTMP_HS_SSL_REQUIRE 318
  78 +#define ERROR_RTMP_DURATION_EXCEED 319
78 79
79 #define ERROR_SYSTEM_STREAM_INIT 400 80 #define ERROR_SYSTEM_STREAM_INIT 400
80 #define ERROR_SYSTEM_PACKET_INVALID 401 81 #define ERROR_SYSTEM_PACKET_INVALID 401
@@ -74,6 +74,7 @@ using namespace std; @@ -74,6 +74,7 @@ using namespace std;
74 SrsRequest::SrsRequest() 74 SrsRequest::SrsRequest()
75 { 75 {
76 objectEncoding = RTMP_SIG_AMF0_VER; 76 objectEncoding = RTMP_SIG_AMF0_VER;
  77 + duration = -1;
77 } 78 }
78 79
79 SrsRequest::~SrsRequest() 80 SrsRequest::~SrsRequest()
@@ -94,6 +95,7 @@ SrsRequest* SrsRequest::copy() @@ -94,6 +95,7 @@ SrsRequest* SrsRequest::copy()
94 cp->swfUrl = swfUrl; 95 cp->swfUrl = swfUrl;
95 cp->tcUrl = tcUrl; 96 cp->tcUrl = tcUrl;
96 cp->vhost = vhost; 97 cp->vhost = vhost;
  98 + cp->duration = duration;
97 99
98 return cp; 100 return cp;
99 } 101 }
@@ -940,7 +942,7 @@ int SrsRtmpServer::on_bw_done() @@ -940,7 +942,7 @@ int SrsRtmpServer::on_bw_done()
940 return ret; 942 return ret;
941 } 943 }
942 944
943 -int SrsRtmpServer::identify_client(int stream_id, SrsRtmpConnType& type, string& stream_name) 945 +int SrsRtmpServer::identify_client(int stream_id, SrsRtmpConnType& type, string& stream_name, double& duration)
944 { 946 {
945 type = SrsRtmpConnUnknown; 947 type = SrsRtmpConnUnknown;
946 int ret = ERROR_SUCCESS; 948 int ret = ERROR_SUCCESS;
@@ -968,7 +970,7 @@ int SrsRtmpServer::identify_client(int stream_id, SrsRtmpConnType& type, string& @@ -968,7 +970,7 @@ int SrsRtmpServer::identify_client(int stream_id, SrsRtmpConnType& type, string&
968 SrsPacket* pkt = msg->get_packet(); 970 SrsPacket* pkt = msg->get_packet();
969 if (dynamic_cast<SrsCreateStreamPacket*>(pkt)) { 971 if (dynamic_cast<SrsCreateStreamPacket*>(pkt)) {
970 srs_info("identify client by create stream, play or flash publish."); 972 srs_info("identify client by create stream, play or flash publish.");
971 - return identify_create_stream_client(dynamic_cast<SrsCreateStreamPacket*>(pkt), stream_id, type, stream_name); 973 + return identify_create_stream_client(dynamic_cast<SrsCreateStreamPacket*>(pkt), stream_id, type, stream_name, duration);
972 } 974 }
973 if (dynamic_cast<SrsFMLEStartPacket*>(pkt)) { 975 if (dynamic_cast<SrsFMLEStartPacket*>(pkt)) {
974 srs_info("identify client by releaseStream, fmle publish."); 976 srs_info("identify client by releaseStream, fmle publish.");
@@ -976,7 +978,7 @@ int SrsRtmpServer::identify_client(int stream_id, SrsRtmpConnType& type, string& @@ -976,7 +978,7 @@ int SrsRtmpServer::identify_client(int stream_id, SrsRtmpConnType& type, string&
976 } 978 }
977 if (dynamic_cast<SrsPlayPacket*>(pkt)) { 979 if (dynamic_cast<SrsPlayPacket*>(pkt)) {
978 srs_info("level0 identify client by play."); 980 srs_info("level0 identify client by play.");
979 - return identify_play_client(dynamic_cast<SrsPlayPacket*>(pkt), type, stream_name); 981 + return identify_play_client(dynamic_cast<SrsPlayPacket*>(pkt), type, stream_name, duration);
980 } 982 }
981 983
982 srs_trace("ignore AMF0/AMF3 command message."); 984 srs_trace("ignore AMF0/AMF3 command message.");
@@ -1373,7 +1375,7 @@ int SrsRtmpServer::start_flash_publish(int stream_id) @@ -1373,7 +1375,7 @@ int SrsRtmpServer::start_flash_publish(int stream_id)
1373 return ret; 1375 return ret;
1374 } 1376 }
1375 1377
1376 -int SrsRtmpServer::identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsRtmpConnType& type, string& stream_name) 1378 +int SrsRtmpServer::identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsRtmpConnType& type, string& stream_name, double& duration)
1377 { 1379 {
1378 int ret = ERROR_SUCCESS; 1380 int ret = ERROR_SUCCESS;
1379 1381
@@ -1413,7 +1415,7 @@ int SrsRtmpServer::identify_create_stream_client(SrsCreateStreamPacket* req, int @@ -1413,7 +1415,7 @@ int SrsRtmpServer::identify_create_stream_client(SrsCreateStreamPacket* req, int
1413 SrsPacket* pkt = msg->get_packet(); 1415 SrsPacket* pkt = msg->get_packet();
1414 if (dynamic_cast<SrsPlayPacket*>(pkt)) { 1416 if (dynamic_cast<SrsPlayPacket*>(pkt)) {
1415 srs_info("level1 identify client by play."); 1417 srs_info("level1 identify client by play.");
1416 - return identify_play_client(dynamic_cast<SrsPlayPacket*>(pkt), type, stream_name); 1418 + return identify_play_client(dynamic_cast<SrsPlayPacket*>(pkt), type, stream_name, duration);
1417 } 1419 }
1418 if (dynamic_cast<SrsPublishPacket*>(pkt)) { 1420 if (dynamic_cast<SrsPublishPacket*>(pkt)) {
1419 srs_info("identify client by publish, falsh publish."); 1421 srs_info("identify client by publish, falsh publish.");
@@ -1460,14 +1462,15 @@ int SrsRtmpServer::identify_flash_publish_client(SrsPublishPacket* req, SrsRtmpC @@ -1460,14 +1462,15 @@ int SrsRtmpServer::identify_flash_publish_client(SrsPublishPacket* req, SrsRtmpC
1460 return ret; 1462 return ret;
1461 } 1463 }
1462 1464
1463 -int SrsRtmpServer::identify_play_client(SrsPlayPacket* req, SrsRtmpConnType& type, string& stream_name) 1465 +int SrsRtmpServer::identify_play_client(SrsPlayPacket* req, SrsRtmpConnType& type, string& stream_name, double& duration)
1464 { 1466 {
1465 int ret = ERROR_SUCCESS; 1467 int ret = ERROR_SUCCESS;
1466 1468
1467 type = SrsRtmpConnPlay; 1469 type = SrsRtmpConnPlay;
1468 stream_name = req->stream_name; 1470 stream_name = req->stream_name;
  1471 + duration = req->duration;
1469 1472
1470 - srs_trace("identity client type=play, stream_name=%s", stream_name.c_str()); 1473 + srs_trace("identity client type=play, stream_name=%s, duration=%.2f", stream_name.c_str(), duration);
1471 1474
1472 return ret; 1475 return ret;
1473 } 1476 }
@@ -67,6 +67,12 @@ public: @@ -67,6 +67,12 @@ public:
67 std::string app; 67 std::string app;
68 std::string stream; 68 std::string stream;
69 69
  70 + // for play live stream,
  71 + // used to specified the stop when exceed the duration.
  72 + // @see https://github.com/winlinvip/simple-rtmp-server/issues/45
  73 + // in ms.
  74 + double duration;
  75 +
70 SrsRequest(); 76 SrsRequest();
71 virtual ~SrsRequest(); 77 virtual ~SrsRequest();
72 78
@@ -222,8 +228,10 @@ public: @@ -222,8 +228,10 @@ public:
222 * @stream_id, client will createStream to play or publish by flash, 228 * @stream_id, client will createStream to play or publish by flash,
223 * the stream_id used to response the createStream request. 229 * the stream_id used to response the createStream request.
224 * @type, output the client type. 230 * @type, output the client type.
  231 + * @stream_name, output the client publish/play stream name. @see: SrsRequest.stream
  232 + * @duration, output the play client duration. @see: SrsRequest.duration
225 */ 233 */
226 - virtual int identify_client(int stream_id, SrsRtmpConnType& type, std::string& stream_name); 234 + virtual int identify_client(int stream_id, SrsRtmpConnType& type, std::string& stream_name, double& duration);
227 /** 235 /**
228 * set the chunk size when client type identified. 236 * set the chunk size when client type identified.
229 */ 237 */
@@ -267,11 +275,11 @@ public: @@ -267,11 +275,11 @@ public:
267 */ 275 */
268 virtual int start_flash_publish(int stream_id); 276 virtual int start_flash_publish(int stream_id);
269 private: 277 private:
270 - virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsRtmpConnType& type, std::string& stream_name); 278 + virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsRtmpConnType& type, std::string& stream_name, double& duration);
271 virtual int identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsRtmpConnType& type, std::string& stream_name); 279 virtual int identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsRtmpConnType& type, std::string& stream_name);
272 virtual int identify_flash_publish_client(SrsPublishPacket* req, SrsRtmpConnType& type, std::string& stream_name); 280 virtual int identify_flash_publish_client(SrsPublishPacket* req, SrsRtmpConnType& type, std::string& stream_name);
273 private: 281 private:
274 - virtual int identify_play_client(SrsPlayPacket* req, SrsRtmpConnType& type, std::string& stream_name); 282 + virtual int identify_play_client(SrsPlayPacket* req, SrsRtmpConnType& type, std::string& stream_name, double& duration);
275 }; 283 };
276 284
277 #endif 285 #endif