正在显示
19 个修改的文件
包含
179 行增加
和
30 行删除
| @@ -453,6 +453,7 @@ Supported operating systems and hardware: | @@ -453,6 +453,7 @@ Supported operating systems and hardware: | ||
| 453 | [CN](https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_SrsLibrtmp#publish-audio-raw-stream), | 453 | [CN](https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_SrsLibrtmp#publish-audio-raw-stream), |
| 454 | [EN](https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_SrsLibrtmp#publish-audio-raw-stream) | 454 | [EN](https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_SrsLibrtmp#publish-audio-raw-stream) |
| 455 | ) by srs-librtmp. | 455 | ) by srs-librtmp. |
| 456 | +1. Support 0.1s+ latency, read [#257](https://github.com/winlinvip/simple-rtmp-server/issues/257). | ||
| 456 | 1. [no-plan] Support <500ms latency, FRSC(Fast RTMP-compatible Stream Channel tech). | 457 | 1. [no-plan] Support <500ms latency, FRSC(Fast RTMP-compatible Stream Channel tech). |
| 457 | 1. [no-plan] Support RTMP 302 redirect [#92](https://github.com/winlinvip/simple-rtmp-server/issues/92). | 458 | 1. [no-plan] Support RTMP 302 redirect [#92](https://github.com/winlinvip/simple-rtmp-server/issues/92). |
| 458 | 1. [no-plan] Support multiple processes, for both origin and edge | 459 | 1. [no-plan] Support multiple processes, for both origin and edge |
| @@ -486,6 +487,7 @@ Supported operating systems and hardware: | @@ -486,6 +487,7 @@ Supported operating systems and hardware: | ||
| 486 | * 2013-10-17, Created.<br/> | 487 | * 2013-10-17, Created.<br/> |
| 487 | 488 | ||
| 488 | ## History | 489 | ## History |
| 490 | +* v2.0, 2014-12-12, fix [#257](https://github.com/winlinvip/simple-rtmp-server/issues/257), support 0.1s+ latency. 2.0.70 | ||
| 489 | * v2.0, 2014-12-08, update wiki for mr([EN](https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_LowLatency#merged-read), [CN](https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_LowLatency#merged-read)) and mw([EN](https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_LowLatency#merged-write), [CN](https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_LowLatency#merged-write)). | 491 | * v2.0, 2014-12-08, update wiki for mr([EN](https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_LowLatency#merged-read), [CN](https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_LowLatency#merged-read)) and mw([EN](https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_LowLatency#merged-write), [CN](https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_LowLatency#merged-write)). |
| 490 | * v2.0, 2014-12-07, fix [#251](https://github.com/winlinvip/simple-rtmp-server/issues/251), 10k+ clients, use queue cond wait and fast vector. 2.0.67 | 492 | * v2.0, 2014-12-07, fix [#251](https://github.com/winlinvip/simple-rtmp-server/issues/251), 10k+ clients, use queue cond wait and fast vector. 2.0.67 |
| 491 | * v2.0, 2014-12-05, fix [#251](https://github.com/winlinvip/simple-rtmp-server/issues/251), 9k+ clients, use fast cache for msgs queue. 2.0.57 | 493 | * v2.0, 2014-12-05, fix [#251](https://github.com/winlinvip/simple-rtmp-server/issues/251), 9k+ clients, use fast cache for msgs queue. 2.0.57 |
| @@ -145,6 +145,13 @@ vhost __defaultVhost__ { | @@ -145,6 +145,13 @@ vhost __defaultVhost__ { | ||
| 145 | # the MR(merged-read) setting for publisher. | 145 | # the MR(merged-read) setting for publisher. |
| 146 | # the MW(merged-write) settings for player. | 146 | # the MW(merged-write) settings for player. |
| 147 | vhost mrw.srs.com { | 147 | vhost mrw.srs.com { |
| 148 | + # whether enable min delay mode for vhost. | ||
| 149 | + # for min latence mode: | ||
| 150 | + # 1. disable the mr for vhost. | ||
| 151 | + # 2. use timeout for cond wait for consumer queue. | ||
| 152 | + # @see https://github.com/winlinvip/simple-rtmp-server/issues/257 | ||
| 153 | + # default: on | ||
| 154 | + min_latency off; | ||
| 148 | # about MR, read https://github.com/winlinvip/simple-rtmp-server/issues/241 | 155 | # about MR, read https://github.com/winlinvip/simple-rtmp-server/issues/241 |
| 149 | mr { | 156 | mr { |
| 150 | # whether enable the MR(merged-read) | 157 | # whether enable the MR(merged-read) |
| @@ -440,6 +447,12 @@ vhost debug.srs.com { | @@ -440,6 +447,12 @@ vhost debug.srs.com { | ||
| 440 | 447 | ||
| 441 | # the vhost for min delay, donot cache any stream. | 448 | # the vhost for min delay, donot cache any stream. |
| 442 | vhost min.delay.com { | 449 | vhost min.delay.com { |
| 450 | + # @see vhost mrw.srs.com for detail. | ||
| 451 | + min_latency on; | ||
| 452 | + mr { | ||
| 453 | + enabled off; | ||
| 454 | + } | ||
| 455 | + mw_latency 100; | ||
| 443 | # whether cache the last gop. | 456 | # whether cache the last gop. |
| 444 | # if on, cache the last gop and dispatch to client, | 457 | # if on, cache the last gop and dispatch to client, |
| 445 | # to enabled fast startup for client, client play immediately. | 458 | # to enabled fast startup for client, client play immediately. |
| 1 | # the config for srs to delivery realtime RTMP stream | 1 | # the config for srs to delivery realtime RTMP stream |
| 2 | -# @see https://github.com/winlinvip/simple-rtmp-server/wiki/v1_CN_SampleRealtime | 2 | +# @see https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_SampleRealtime |
| 3 | # @see full.conf for detail config. | 3 | # @see full.conf for detail config. |
| 4 | 4 | ||
| 5 | listen 1935; | 5 | listen 1935; |
| @@ -7,6 +7,7 @@ max_connections 1000; | @@ -7,6 +7,7 @@ max_connections 1000; | ||
| 7 | vhost __defaultVhost__ { | 7 | vhost __defaultVhost__ { |
| 8 | gop_cache off; | 8 | gop_cache off; |
| 9 | queue_length 10; | 9 | queue_length 10; |
| 10 | + min_latency on; | ||
| 10 | mr { | 11 | mr { |
| 11 | enabled off; | 12 | enabled off; |
| 12 | } | 13 | } |
| @@ -22,7 +22,7 @@ function SrsPlayer(container, width, height, private_object) { | @@ -22,7 +22,7 @@ function SrsPlayer(container, width, height, private_object) { | ||
| 22 | this.height = height; | 22 | this.height = height; |
| 23 | this.id = SrsPlayer.__id++; | 23 | this.id = SrsPlayer.__id++; |
| 24 | this.stream_url = null; | 24 | this.stream_url = null; |
| 25 | - this.buffer_time = 0.8; // default to 0.8 | 25 | + this.buffer_time = 0.3; // default to 0.3 |
| 26 | this.volume = 1.0; // default to 100% | 26 | this.volume = 1.0; // default to 100% |
| 27 | this.callbackObj = null; | 27 | this.callbackObj = null; |
| 28 | 28 |
trunk/research/players/srs_player.html
100644 → 100755
| @@ -96,7 +96,7 @@ | @@ -96,7 +96,7 @@ | ||
| 96 | 96 | ||
| 97 | srs_player = new SrsPlayer("player_id", srs_get_player_width(), srs_get_player_height()); | 97 | srs_player = new SrsPlayer("player_id", srs_get_player_width(), srs_get_player_height()); |
| 98 | srs_player.on_player_ready = function() { | 98 | srs_player.on_player_ready = function() { |
| 99 | - select_buffer_time("#btn_bt_0_8", 0.8); | 99 | + select_buffer_time("#btn_bt_0_1", 0.1); |
| 100 | this.play(url); | 100 | this.play(url); |
| 101 | }; | 101 | }; |
| 102 | srs_player.on_player_metadata = function(metadata) { | 102 | srs_player.on_player_metadata = function(metadata) { |
| @@ -231,6 +231,15 @@ | @@ -231,6 +231,15 @@ | ||
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | if (true) { | 233 | if (true) { |
| 234 | + $("#btn_bt_0_1").click(function(){ | ||
| 235 | + select_buffer_time("#btn_bt_0_1", 0.1); | ||
| 236 | + }); | ||
| 237 | + $("#btn_bt_0_2").click(function(){ | ||
| 238 | + select_buffer_time("#btn_bt_0_2", 0.2); | ||
| 239 | + }); | ||
| 240 | + $("#btn_bt_0_3").click(function(){ | ||
| 241 | + select_buffer_time("#btn_bt_0_3", 0.3); | ||
| 242 | + }); | ||
| 234 | $("#btn_bt_0_5").click(function(){ | 243 | $("#btn_bt_0_5").click(function(){ |
| 235 | select_buffer_time("#btn_bt_0_5", 0.5); | 244 | select_buffer_time("#btn_bt_0_5", 0.5); |
| 236 | }); | 245 | }); |
| @@ -504,6 +513,9 @@ | @@ -504,6 +513,9 @@ | ||
| 504 | <div class="btn-group dropup"> | 513 | <div class="btn-group dropup"> |
| 505 | <button class="btn dropdown-toggle" data-toggle="dropdown">缓冲区<span class="caret"></span></button> | 514 | <button class="btn dropdown-toggle" data-toggle="dropdown">缓冲区<span class="caret"></span></button> |
| 506 | <ul class="dropdown-menu"> | 515 | <ul class="dropdown-menu"> |
| 516 | + <li><a id="btn_bt_0_1" href="#">0.1秒(实时)</a></li> | ||
| 517 | + <li><a id="btn_bt_0_2" href="#">0.2秒(实时)</a></li> | ||
| 518 | + <li><a id="btn_bt_0_3" href="#">0.3秒(实时)</a></li> | ||
| 507 | <li><a id="btn_bt_0_5" href="#">0.5秒(实时)</a></li> | 519 | <li><a id="btn_bt_0_5" href="#">0.5秒(实时)</a></li> |
| 508 | <li><a id="btn_bt_0_8" href="#">0.8秒(会议)</a></li> | 520 | <li><a id="btn_bt_0_8" href="#">0.8秒(会议)</a></li> |
| 509 | <li><a id="btn_bt_1" href="#">1秒(低延迟)</a></li> | 521 | <li><a id="btn_bt_1" href="#">1秒(低延迟)</a></li> |
| @@ -852,6 +852,17 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root) | @@ -852,6 +852,17 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root) | ||
| 852 | } | 852 | } |
| 853 | srs_trace("vhost %s reload mw success.", vhost.c_str()); | 853 | srs_trace("vhost %s reload mw success.", vhost.c_str()); |
| 854 | } | 854 | } |
| 855 | + // min_latency, only one per vhost | ||
| 856 | + if (!srs_directive_equals(new_vhost->get("min_latency"), old_vhost->get("min_latency"))) { | ||
| 857 | + for (it = subscribes.begin(); it != subscribes.end(); ++it) { | ||
| 858 | + ISrsReloadHandler* subscribe = *it; | ||
| 859 | + if ((ret = subscribe->on_reload_vhost_realtime(vhost)) != ERROR_SUCCESS) { | ||
| 860 | + srs_error("vhost %s notify subscribes min_latency failed. ret=%d", vhost.c_str(), ret); | ||
| 861 | + return ret; | ||
| 862 | + } | ||
| 863 | + } | ||
| 864 | + srs_trace("vhost %s reload min_latency success.", vhost.c_str()); | ||
| 865 | + } | ||
| 855 | // http, only one per vhost. | 866 | // http, only one per vhost. |
| 856 | if (!srs_directive_equals(new_vhost->get("http"), old_vhost->get("http"))) { | 867 | if (!srs_directive_equals(new_vhost->get("http"), old_vhost->get("http"))) { |
| 857 | for (it = subscribes.begin(); it != subscribes.end(); ++it) { | 868 | for (it = subscribes.begin(); it != subscribes.end(); ++it) { |
| @@ -1350,7 +1361,7 @@ int SrsConfig::check_config() | @@ -1350,7 +1361,7 @@ int SrsConfig::check_config() | ||
| 1350 | && n != "time_jitter" | 1361 | && n != "time_jitter" |
| 1351 | && n != "atc" && n != "atc_auto" | 1362 | && n != "atc" && n != "atc_auto" |
| 1352 | && n != "debug_srs_upnode" | 1363 | && n != "debug_srs_upnode" |
| 1353 | - && n != "mr" && n != "mw_latency" | 1364 | + && n != "mr" && n != "mw_latency" && n != "min_latency" |
| 1354 | ) { | 1365 | ) { |
| 1355 | ret = ERROR_SYSTEM_CONFIG_INVALID; | 1366 | ret = ERROR_SYSTEM_CONFIG_INVALID; |
| 1356 | srs_error("unsupported vhost directive %s, ret=%d", n.c_str(), ret); | 1367 | srs_error("unsupported vhost directive %s, ret=%d", n.c_str(), ret); |
| @@ -2125,7 +2136,6 @@ int SrsConfig::get_chunk_size(string vhost) | @@ -2125,7 +2136,6 @@ int SrsConfig::get_chunk_size(string vhost) | ||
| 2125 | 2136 | ||
| 2126 | bool SrsConfig::get_mr_enabled(string vhost) | 2137 | bool SrsConfig::get_mr_enabled(string vhost) |
| 2127 | { | 2138 | { |
| 2128 | - | ||
| 2129 | SrsConfDirective* conf = get_vhost(vhost); | 2139 | SrsConfDirective* conf = get_vhost(vhost); |
| 2130 | 2140 | ||
| 2131 | if (!conf) { | 2141 | if (!conf) { |
| @@ -2147,7 +2157,6 @@ bool SrsConfig::get_mr_enabled(string vhost) | @@ -2147,7 +2157,6 @@ bool SrsConfig::get_mr_enabled(string vhost) | ||
| 2147 | 2157 | ||
| 2148 | int SrsConfig::get_mr_sleep_ms(string vhost) | 2158 | int SrsConfig::get_mr_sleep_ms(string vhost) |
| 2149 | { | 2159 | { |
| 2150 | - | ||
| 2151 | SrsConfDirective* conf = get_vhost(vhost); | 2160 | SrsConfDirective* conf = get_vhost(vhost); |
| 2152 | 2161 | ||
| 2153 | if (!conf) { | 2162 | if (!conf) { |
| @@ -2169,7 +2178,6 @@ int SrsConfig::get_mr_sleep_ms(string vhost) | @@ -2169,7 +2178,6 @@ int SrsConfig::get_mr_sleep_ms(string vhost) | ||
| 2169 | 2178 | ||
| 2170 | int SrsConfig::get_mw_sleep_ms(string vhost) | 2179 | int SrsConfig::get_mw_sleep_ms(string vhost) |
| 2171 | { | 2180 | { |
| 2172 | - | ||
| 2173 | SrsConfDirective* conf = get_vhost(vhost); | 2181 | SrsConfDirective* conf = get_vhost(vhost); |
| 2174 | 2182 | ||
| 2175 | if (!conf) { | 2183 | if (!conf) { |
| @@ -2184,6 +2192,22 @@ int SrsConfig::get_mw_sleep_ms(string vhost) | @@ -2184,6 +2192,22 @@ int SrsConfig::get_mw_sleep_ms(string vhost) | ||
| 2184 | return ::atoi(conf->arg0().c_str()); | 2192 | return ::atoi(conf->arg0().c_str()); |
| 2185 | } | 2193 | } |
| 2186 | 2194 | ||
| 2195 | +bool SrsConfig::get_realtime_enabled(string vhost) | ||
| 2196 | +{ | ||
| 2197 | + SrsConfDirective* conf = get_vhost(vhost); | ||
| 2198 | + | ||
| 2199 | + if (!conf) { | ||
| 2200 | + return SRS_PERF_MIN_LATENCY_ENABLED; | ||
| 2201 | + } | ||
| 2202 | + | ||
| 2203 | + conf = conf->get("min_latency"); | ||
| 2204 | + if (!conf || conf->arg0() != "off") { | ||
| 2205 | + return SRS_PERF_MIN_LATENCY_ENABLED; | ||
| 2206 | + } | ||
| 2207 | + | ||
| 2208 | + return false; | ||
| 2209 | +} | ||
| 2210 | + | ||
| 2187 | int SrsConfig::get_global_chunk_size() | 2211 | int SrsConfig::get_global_chunk_size() |
| 2188 | { | 2212 | { |
| 2189 | SrsConfDirective* conf = root->get("chunk_size"); | 2213 | SrsConfDirective* conf = root->get("chunk_size"); |
| @@ -545,6 +545,12 @@ public: | @@ -545,6 +545,12 @@ public: | ||
| 545 | */ | 545 | */ |
| 546 | // TODO: FIXME: add utest for mw config. | 546 | // TODO: FIXME: add utest for mw config. |
| 547 | virtual int get_mw_sleep_ms(std::string vhost); | 547 | virtual int get_mw_sleep_ms(std::string vhost); |
| 548 | + /** | ||
| 549 | + * whether min latency mode enabled. | ||
| 550 | + * @param vhost, the vhost to get the min_latency. | ||
| 551 | + */ | ||
| 552 | + // TODO: FIXME: add utest for min_latency. | ||
| 553 | + virtual bool get_realtime_enabled(std::string vhost); | ||
| 548 | private: | 554 | private: |
| 549 | /** | 555 | /** |
| 550 | * get the global chunk size. | 556 | * get the global chunk size. |
| @@ -251,6 +251,8 @@ SrsPublishRecvThread::SrsPublishRecvThread( | @@ -251,6 +251,8 @@ SrsPublishRecvThread::SrsPublishRecvThread( | ||
| 251 | mr = _srs_config->get_mr_enabled(req->vhost); | 251 | mr = _srs_config->get_mr_enabled(req->vhost); |
| 252 | mr_sleep = _srs_config->get_mr_sleep_ms(req->vhost); | 252 | mr_sleep = _srs_config->get_mr_sleep_ms(req->vhost); |
| 253 | 253 | ||
| 254 | + realtime = _srs_config->get_realtime_enabled(req->vhost); | ||
| 255 | + | ||
| 254 | _srs_config->subscribe(this); | 256 | _srs_config->subscribe(this); |
| 255 | } | 257 | } |
| 256 | 258 | ||
| @@ -340,6 +342,10 @@ int SrsPublishRecvThread::handle(SrsCommonMessage* msg) | @@ -340,6 +342,10 @@ int SrsPublishRecvThread::handle(SrsCommonMessage* msg) | ||
| 340 | int ret = ERROR_SUCCESS; | 342 | int ret = ERROR_SUCCESS; |
| 341 | 343 | ||
| 342 | _nb_msgs++; | 344 | _nb_msgs++; |
| 345 | + | ||
| 346 | + // log to show the time of recv thread. | ||
| 347 | + srs_verbose("recv thread now=%"PRId64"us, got msg time=%"PRId64"ms, size=%d", | ||
| 348 | + srs_update_system_time_ms(), msg->header.timestamp, msg->size); | ||
| 343 | 349 | ||
| 344 | // the rtmp connection will handle this message | 350 | // the rtmp connection will handle this message |
| 345 | ret = _conn->handle_publish_message(_source, msg, _is_fmle, _is_edge); | 351 | ret = _conn->handle_publish_message(_source, msg, _is_fmle, _is_edge); |
| @@ -363,7 +369,7 @@ void SrsPublishRecvThread::on_recv_error(int ret) | @@ -363,7 +369,7 @@ void SrsPublishRecvThread::on_recv_error(int ret) | ||
| 363 | #ifdef SRS_PERF_MERGED_READ | 369 | #ifdef SRS_PERF_MERGED_READ |
| 364 | void SrsPublishRecvThread::on_read(ssize_t nread) | 370 | void SrsPublishRecvThread::on_read(ssize_t nread) |
| 365 | { | 371 | { |
| 366 | - if (!mr) { | 372 | + if (!mr || realtime) { |
| 367 | return; | 373 | return; |
| 368 | } | 374 | } |
| 369 | 375 | ||
| @@ -386,6 +392,10 @@ void SrsPublishRecvThread::on_read(ssize_t nread) | @@ -386,6 +392,10 @@ void SrsPublishRecvThread::on_read(ssize_t nread) | ||
| 386 | int SrsPublishRecvThread::on_reload_vhost_mr(string vhost) | 392 | int SrsPublishRecvThread::on_reload_vhost_mr(string vhost) |
| 387 | { | 393 | { |
| 388 | int ret = ERROR_SUCCESS; | 394 | int ret = ERROR_SUCCESS; |
| 395 | + | ||
| 396 | + if (req->vhost != vhost) { | ||
| 397 | + return ret; | ||
| 398 | + } | ||
| 389 | 399 | ||
| 390 | // the mr settings, | 400 | // the mr settings, |
| 391 | // @see https://github.com/winlinvip/simple-rtmp-server/issues/241 | 401 | // @see https://github.com/winlinvip/simple-rtmp-server/issues/241 |
| @@ -419,6 +429,21 @@ int SrsPublishRecvThread::on_reload_vhost_mr(string vhost) | @@ -419,6 +429,21 @@ int SrsPublishRecvThread::on_reload_vhost_mr(string vhost) | ||
| 419 | return ret; | 429 | return ret; |
| 420 | } | 430 | } |
| 421 | 431 | ||
| 432 | +int SrsPublishRecvThread::on_reload_vhost_realtime(string vhost) | ||
| 433 | +{ | ||
| 434 | + int ret = ERROR_SUCCESS; | ||
| 435 | + | ||
| 436 | + if (req->vhost != vhost) { | ||
| 437 | + return ret; | ||
| 438 | + } | ||
| 439 | + | ||
| 440 | + bool realtime_enabled = _srs_config->get_realtime_enabled(req->vhost); | ||
| 441 | + srs_trace("realtime changed %d=>%d", realtime, realtime_enabled); | ||
| 442 | + realtime = realtime_enabled; | ||
| 443 | + | ||
| 444 | + return ret; | ||
| 445 | +} | ||
| 446 | + | ||
| 422 | void SrsPublishRecvThread::set_socket_buffer(int sleep_ms) | 447 | void SrsPublishRecvThread::set_socket_buffer(int sleep_ms) |
| 423 | { | 448 | { |
| 424 | // the bytes: | 449 | // the bytes: |
| @@ -446,8 +471,9 @@ void SrsPublishRecvThread::set_socket_buffer(int sleep_ms) | @@ -446,8 +471,9 @@ void SrsPublishRecvThread::set_socket_buffer(int sleep_ms) | ||
| 446 | } | 471 | } |
| 447 | getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &nb_rbuf, &sock_buf_size); | 472 | getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &nb_rbuf, &sock_buf_size); |
| 448 | 473 | ||
| 449 | - srs_trace("mr change sleep %d=>%d, erbuf=%d, rbuf %d=>%d, sbytes=%d", | ||
| 450 | - mr_sleep, sleep_ms, socket_buffer_size, onb_rbuf, nb_rbuf, SRS_MR_SMALL_BYTES); | 474 | + srs_trace("mr change sleep %d=>%d, erbuf=%d, rbuf %d=>%d, sbytes=%d, realtime=%d", |
| 475 | + mr_sleep, sleep_ms, socket_buffer_size, onb_rbuf, nb_rbuf, | ||
| 476 | + SRS_MR_SMALL_BYTES, realtime); | ||
| 451 | 477 | ||
| 452 | rtmp->set_recv_buffer(nb_rbuf); | 478 | rtmp->set_recv_buffer(nb_rbuf); |
| 453 | } | 479 | } |
| @@ -153,6 +153,9 @@ private: | @@ -153,6 +153,9 @@ private: | ||
| 153 | bool mr; | 153 | bool mr; |
| 154 | int mr_fd; | 154 | int mr_fd; |
| 155 | int mr_sleep; | 155 | int mr_sleep; |
| 156 | + // for realtime | ||
| 157 | + // @see https://github.com/winlinvip/simple-rtmp-server/issues/257 | ||
| 158 | + bool realtime; | ||
| 156 | // the recv thread error code. | 159 | // the recv thread error code. |
| 157 | int recv_error_code; | 160 | int recv_error_code; |
| 158 | SrsRtmpConn* _conn; | 161 | SrsRtmpConn* _conn; |
| @@ -193,6 +196,7 @@ public: | @@ -193,6 +196,7 @@ public: | ||
| 193 | // interface ISrsReloadHandler | 196 | // interface ISrsReloadHandler |
| 194 | public: | 197 | public: |
| 195 | virtual int on_reload_vhost_mr(std::string vhost); | 198 | virtual int on_reload_vhost_mr(std::string vhost); |
| 199 | + virtual int on_reload_vhost_realtime(std::string vhost); | ||
| 196 | private: | 200 | private: |
| 197 | virtual void set_socket_buffer(int sleep_ms); | 201 | virtual void set_socket_buffer(int sleep_ms); |
| 198 | }; | 202 | }; |
| @@ -150,6 +150,11 @@ int ISrsReloadHandler::on_reload_vhost_mw(string /*vhost*/) | @@ -150,6 +150,11 @@ int ISrsReloadHandler::on_reload_vhost_mw(string /*vhost*/) | ||
| 150 | return ERROR_SUCCESS; | 150 | return ERROR_SUCCESS; |
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | +int ISrsReloadHandler::on_reload_vhost_realtime(string /*vhost*/) | ||
| 154 | +{ | ||
| 155 | + return ERROR_SUCCESS; | ||
| 156 | +} | ||
| 157 | + | ||
| 153 | int ISrsReloadHandler::on_reload_vhost_chunk_size(string /*vhost*/) | 158 | int ISrsReloadHandler::on_reload_vhost_chunk_size(string /*vhost*/) |
| 154 | { | 159 | { |
| 155 | return ERROR_SUCCESS; | 160 | return ERROR_SUCCESS; |
| @@ -67,6 +67,7 @@ public: | @@ -67,6 +67,7 @@ public: | ||
| 67 | virtual int on_reload_vhost_dvr(std::string vhost); | 67 | virtual int on_reload_vhost_dvr(std::string vhost); |
| 68 | virtual int on_reload_vhost_mr(std::string vhost); | 68 | virtual int on_reload_vhost_mr(std::string vhost); |
| 69 | virtual int on_reload_vhost_mw(std::string vhost); | 69 | virtual int on_reload_vhost_mw(std::string vhost); |
| 70 | + virtual int on_reload_vhost_realtime(std::string vhost); | ||
| 70 | virtual int on_reload_vhost_chunk_size(std::string vhost); | 71 | virtual int on_reload_vhost_chunk_size(std::string vhost); |
| 71 | virtual int on_reload_vhost_transcode(std::string vhost); | 72 | virtual int on_reload_vhost_transcode(std::string vhost); |
| 72 | virtual int on_reload_ingest_removed(std::string vhost, std::string ingest_id); | 73 | virtual int on_reload_ingest_removed(std::string vhost, std::string ingest_id); |
| @@ -50,6 +50,7 @@ using namespace std; | @@ -50,6 +50,7 @@ using namespace std; | ||
| 50 | #include <srs_protocol_amf0.hpp> | 50 | #include <srs_protocol_amf0.hpp> |
| 51 | #include <srs_app_recv_thread.hpp> | 51 | #include <srs_app_recv_thread.hpp> |
| 52 | #include <srs_core_performance.hpp> | 52 | #include <srs_core_performance.hpp> |
| 53 | +#include <srs_kernel_utility.hpp> | ||
| 53 | 54 | ||
| 54 | // when stream is busy, for example, streaming is already | 55 | // when stream is busy, for example, streaming is already |
| 55 | // publishing, when a new client to request to publish, | 56 | // publishing, when a new client to request to publish, |
| @@ -86,6 +87,7 @@ SrsRtmpConn::SrsRtmpConn(SrsServer* srs_server, st_netfd_t client_stfd) | @@ -86,6 +87,7 @@ SrsRtmpConn::SrsRtmpConn(SrsServer* srs_server, st_netfd_t client_stfd) | ||
| 86 | 87 | ||
| 87 | mw_sleep = SRS_PERF_MW_SLEEP; | 88 | mw_sleep = SRS_PERF_MW_SLEEP; |
| 88 | mw_enabled = false; | 89 | mw_enabled = false; |
| 90 | + realtime = SRS_PERF_MIN_LATENCY_ENABLED; | ||
| 89 | 91 | ||
| 90 | _srs_config->subscribe(this); | 92 | _srs_config->subscribe(this); |
| 91 | } | 93 | } |
| @@ -212,14 +214,35 @@ int SrsRtmpConn::on_reload_vhost_removed(string vhost) | @@ -212,14 +214,35 @@ int SrsRtmpConn::on_reload_vhost_removed(string vhost) | ||
| 212 | return ret; | 214 | return ret; |
| 213 | } | 215 | } |
| 214 | 216 | ||
| 215 | -int SrsRtmpConn::on_reload_vhost_mw(string /*vhost*/) | 217 | +int SrsRtmpConn::on_reload_vhost_mw(string vhost) |
| 216 | { | 218 | { |
| 219 | + int ret = ERROR_SUCCESS; | ||
| 220 | + | ||
| 221 | + if (req->vhost != vhost) { | ||
| 222 | + return ret; | ||
| 223 | + } | ||
| 224 | + | ||
| 217 | int sleep_ms = _srs_config->get_mw_sleep_ms(req->vhost); | 225 | int sleep_ms = _srs_config->get_mw_sleep_ms(req->vhost); |
| 218 | 226 | ||
| 219 | // when mw_sleep changed, resize the socket send buffer. | 227 | // when mw_sleep changed, resize the socket send buffer. |
| 220 | change_mw_sleep(sleep_ms); | 228 | change_mw_sleep(sleep_ms); |
| 221 | 229 | ||
| 222 | - return ERROR_SUCCESS; | 230 | + return ret; |
| 231 | +} | ||
| 232 | + | ||
| 233 | +int SrsRtmpConn::on_reload_vhost_realtime(string vhost) | ||
| 234 | +{ | ||
| 235 | + int ret = ERROR_SUCCESS; | ||
| 236 | + | ||
| 237 | + if (req->vhost != vhost) { | ||
| 238 | + return ret; | ||
| 239 | + } | ||
| 240 | + | ||
| 241 | + bool realtime_enabled = _srs_config->get_realtime_enabled(req->vhost); | ||
| 242 | + srs_trace("realtime changed %d=>%d", realtime, realtime_enabled); | ||
| 243 | + realtime = realtime_enabled; | ||
| 244 | + | ||
| 245 | + return ret; | ||
| 223 | } | 246 | } |
| 224 | 247 | ||
| 225 | int64_t SrsRtmpConn::get_send_bytes_delta() | 248 | int64_t SrsRtmpConn::get_send_bytes_delta() |
| @@ -570,6 +593,7 @@ int SrsRtmpConn::do_playing(SrsSource* source, SrsQueueRecvThread* trd) | @@ -570,6 +593,7 @@ int SrsRtmpConn::do_playing(SrsSource* source, SrsQueueRecvThread* trd) | ||
| 570 | // when mw_sleep changed, resize the socket send buffer. | 593 | // when mw_sleep changed, resize the socket send buffer. |
| 571 | mw_enabled = true; | 594 | mw_enabled = true; |
| 572 | change_mw_sleep(_srs_config->get_mw_sleep_ms(req->vhost)); | 595 | change_mw_sleep(_srs_config->get_mw_sleep_ms(req->vhost)); |
| 596 | + realtime = _srs_config->get_realtime_enabled(req->vhost); | ||
| 573 | 597 | ||
| 574 | while (true) { | 598 | while (true) { |
| 575 | // to use isolate thread to recv, can improve about 33% performance. | 599 | // to use isolate thread to recv, can improve about 33% performance. |
| @@ -599,9 +623,15 @@ int SrsRtmpConn::do_playing(SrsSource* source, SrsQueueRecvThread* trd) | @@ -599,9 +623,15 @@ int SrsRtmpConn::do_playing(SrsSource* source, SrsQueueRecvThread* trd) | ||
| 599 | pithy_print.elapse(); | 623 | pithy_print.elapse(); |
| 600 | 624 | ||
| 601 | #ifdef SRS_PERF_QUEUE_COND_WAIT | 625 | #ifdef SRS_PERF_QUEUE_COND_WAIT |
| 626 | + // for send wait time debug | ||
| 627 | + srs_verbose("send thread now=%"PRId64"us, wait %dms", srs_update_system_time_ms(), mw_sleep); | ||
| 628 | + | ||
| 602 | // wait for message to incoming. | 629 | // wait for message to incoming. |
| 603 | // @see https://github.com/winlinvip/simple-rtmp-server/issues/251 | 630 | // @see https://github.com/winlinvip/simple-rtmp-server/issues/251 |
| 604 | - consumer->wait(SRS_PERF_MW_MIN_MSGS, mw_sleep); | 631 | + consumer->wait(SRS_PERF_MW_MIN_MSGS, mw_sleep, realtime); |
| 632 | + | ||
| 633 | + // for send wait time debug | ||
| 634 | + srs_verbose("send thread now=%"PRId64"us wakeup", srs_update_system_time_ms()); | ||
| 605 | #endif | 635 | #endif |
| 606 | 636 | ||
| 607 | // get messages from consumer. | 637 | // get messages from consumer. |
| @@ -613,10 +643,12 @@ int SrsRtmpConn::do_playing(SrsSource* source, SrsQueueRecvThread* trd) | @@ -613,10 +643,12 @@ int SrsRtmpConn::do_playing(SrsSource* source, SrsQueueRecvThread* trd) | ||
| 613 | } | 643 | } |
| 614 | 644 | ||
| 615 | #ifdef SRS_PERF_QUEUE_COND_WAIT | 645 | #ifdef SRS_PERF_QUEUE_COND_WAIT |
| 616 | - // we use wait to get messages, so the count must be positive. | ||
| 617 | - srs_assert(count > 0); | ||
| 618 | - srs_info("mw wait %dms and got %d msgs %"PRId64"-%"PRId64"ms", | ||
| 619 | - mw_sleep, count, msgs.msgs[0]->timestamp, msgs.msgs[count - 1]->timestamp); | 646 | + // we use wait timeout to get messages, |
| 647 | + // for min latency event no message incoming, | ||
| 648 | + // so the count maybe zero. | ||
| 649 | + srs_verbose("mw wait %dms and got %d msgs %"PRId64"-%"PRId64"ms", mw_sleep, count, | ||
| 650 | + (count > 0? msgs.msgs[0]->timestamp : 0), | ||
| 651 | + (count > 0? msgs.msgs[count - 1]->timestamp : 0)); | ||
| 620 | #else | 652 | #else |
| 621 | if (count <= 0) { | 653 | if (count <= 0) { |
| 622 | srs_info("mw sleep %dms for no msg", mw_sleep); | 654 | srs_info("mw sleep %dms for no msg", mw_sleep); |
| @@ -1037,12 +1069,12 @@ void SrsRtmpConn::change_mw_sleep(int sleep_ms) | @@ -1037,12 +1069,12 @@ void SrsRtmpConn::change_mw_sleep(int sleep_ms) | ||
| 1037 | } | 1069 | } |
| 1038 | getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &nb_sbuf, &sock_buf_size); | 1070 | getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &nb_sbuf, &sock_buf_size); |
| 1039 | 1071 | ||
| 1040 | - srs_trace("mw changed sleep %d=>%d, max_msgs=%d, esbuf=%d, sbuf %d=>%d", | 1072 | + srs_trace("mw changed sleep %d=>%d, max_msgs=%d, esbuf=%d, sbuf %d=>%d, realtime=%d", |
| 1041 | mw_sleep, sleep_ms, SRS_PERF_MW_MSGS, socket_buffer_size, | 1073 | mw_sleep, sleep_ms, SRS_PERF_MW_MSGS, socket_buffer_size, |
| 1042 | - onb_sbuf, nb_sbuf); | 1074 | + onb_sbuf, nb_sbuf, realtime); |
| 1043 | #else | 1075 | #else |
| 1044 | - srs_trace("mw changed sleep %d=>%d, max_msgs=%d, sbuf %d", | ||
| 1045 | - mw_sleep, sleep_ms, SRS_PERF_MW_MSGS, onb_sbuf); | 1076 | + srs_trace("mw changed sleep %d=>%d, max_msgs=%d, sbuf %d, realtime=%d", |
| 1077 | + mw_sleep, sleep_ms, SRS_PERF_MW_MSGS, onb_sbuf, realtime); | ||
| 1046 | #endif | 1078 | #endif |
| 1047 | 1079 | ||
| 1048 | mw_sleep = sleep_ms; | 1080 | mw_sleep = sleep_ms; |
| @@ -75,6 +75,9 @@ private: | @@ -75,6 +75,9 @@ private: | ||
| 75 | int mw_sleep; | 75 | int mw_sleep; |
| 76 | // the MR(merged-write) only enabled for play. | 76 | // the MR(merged-write) only enabled for play. |
| 77 | int mw_enabled; | 77 | int mw_enabled; |
| 78 | + // for realtime | ||
| 79 | + // @see https://github.com/winlinvip/simple-rtmp-server/issues/257 | ||
| 80 | + bool realtime; | ||
| 78 | public: | 81 | public: |
| 79 | SrsRtmpConn(SrsServer* srs_server, st_netfd_t client_stfd); | 82 | SrsRtmpConn(SrsServer* srs_server, st_netfd_t client_stfd); |
| 80 | virtual ~SrsRtmpConn(); | 83 | virtual ~SrsRtmpConn(); |
| @@ -86,6 +89,7 @@ protected: | @@ -86,6 +89,7 @@ protected: | ||
| 86 | public: | 89 | public: |
| 87 | virtual int on_reload_vhost_removed(std::string vhost); | 90 | virtual int on_reload_vhost_removed(std::string vhost); |
| 88 | virtual int on_reload_vhost_mw(std::string vhost); | 91 | virtual int on_reload_vhost_mw(std::string vhost); |
| 92 | + virtual int on_reload_vhost_realtime(std::string vhost); | ||
| 89 | // interface IKbpsDelta | 93 | // interface IKbpsDelta |
| 90 | public: | 94 | public: |
| 91 | virtual int64_t get_send_bytes_delta(); | 95 | virtual int64_t get_send_bytes_delta(); |
| @@ -493,7 +493,7 @@ int SrsConsumer::dump_packets(SrsMessageArray* msgs, int& count) | @@ -493,7 +493,7 @@ int SrsConsumer::dump_packets(SrsMessageArray* msgs, int& count) | ||
| 493 | } | 493 | } |
| 494 | 494 | ||
| 495 | #ifdef SRS_PERF_QUEUE_COND_WAIT | 495 | #ifdef SRS_PERF_QUEUE_COND_WAIT |
| 496 | -void SrsConsumer::wait(int nb_msgs, int duration) | 496 | +void SrsConsumer::wait(int nb_msgs, int duration, bool realtime) |
| 497 | { | 497 | { |
| 498 | mw_min_msgs = nb_msgs; | 498 | mw_min_msgs = nb_msgs; |
| 499 | mw_duration = duration; | 499 | mw_duration = duration; |
| @@ -508,8 +508,15 @@ void SrsConsumer::wait(int nb_msgs, int duration) | @@ -508,8 +508,15 @@ void SrsConsumer::wait(int nb_msgs, int duration) | ||
| 508 | 508 | ||
| 509 | // the enqueue will notify this cond. | 509 | // the enqueue will notify this cond. |
| 510 | mw_waiting = true; | 510 | mw_waiting = true; |
| 511 | - // wait for msgs to incoming. | ||
| 512 | - st_cond_wait(mw_wait); | 511 | + |
| 512 | + // use timeout wait for realtime mode. | ||
| 513 | + // @see https://github.com/winlinvip/simple-rtmp-server/issues/257 | ||
| 514 | + if (realtime) { | ||
| 515 | + st_cond_timedwait(mw_wait, duration * 1000); | ||
| 516 | + } else { | ||
| 517 | + // use cond block wait for high performance mode. | ||
| 518 | + st_cond_wait(mw_wait); | ||
| 519 | + } | ||
| 513 | } | 520 | } |
| 514 | #endif | 521 | #endif |
| 515 | 522 |
| @@ -245,8 +245,9 @@ public: | @@ -245,8 +245,9 @@ public: | ||
| 245 | * wait for messages incomming, atleast nb_msgs and in duration. | 245 | * wait for messages incomming, atleast nb_msgs and in duration. |
| 246 | * @param nb_msgs the messages count to wait. | 246 | * @param nb_msgs the messages count to wait. |
| 247 | * @param duration the messgae duration to wait. | 247 | * @param duration the messgae duration to wait. |
| 248 | + * @param realtime whether use realtime mode. | ||
| 248 | */ | 249 | */ |
| 249 | - virtual void wait(int nb_msgs, int duration); | 250 | + virtual void wait(int nb_msgs, int duration, bool realtime); |
| 250 | #endif | 251 | #endif |
| 251 | /** | 252 | /** |
| 252 | * when client send the pause message. | 253 | * when client send the pause message. |
| @@ -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 2 | 32 | #define VERSION_MAJOR 2 |
| 33 | #define VERSION_MINOR 0 | 33 | #define VERSION_MINOR 0 |
| 34 | -#define VERSION_REVISION 69 | 34 | +#define VERSION_REVISION 70 |
| 35 | // server info. | 35 | // server info. |
| 36 | #define RTMP_SIG_SRS_KEY "SRS" | 36 | #define RTMP_SIG_SRS_KEY "SRS" |
| 37 | #define RTMP_SIG_SRS_ROLE "origin/edge server" | 37 | #define RTMP_SIG_SRS_ROLE "origin/edge server" |
| @@ -128,6 +128,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -128,6 +128,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 128 | #ifdef SRS_PERF_QUEUE_COND_WAIT | 128 | #ifdef SRS_PERF_QUEUE_COND_WAIT |
| 129 | #define SRS_PERF_MW_MIN_MSGS 8 | 129 | #define SRS_PERF_MW_MIN_MSGS 8 |
| 130 | #endif | 130 | #endif |
| 131 | +/** | ||
| 132 | +* the default value of vhost for | ||
| 133 | +* SRS whether use the min latency mode. | ||
| 134 | +* for min latence mode: | ||
| 135 | +* 1. disable the mr for vhost. | ||
| 136 | +* 2. use timeout for cond wait for consumer queue. | ||
| 137 | +* @see https://github.com/winlinvip/simple-rtmp-server/issues/257 | ||
| 138 | +*/ | ||
| 139 | +#define SRS_PERF_MIN_LATENCY_ENABLED true | ||
| 131 | 140 | ||
| 132 | /** | 141 | /** |
| 133 | * how many chunk stream to cache, [0, N]. | 142 | * how many chunk stream to cache, [0, N]. |
| @@ -61,13 +61,13 @@ int64_t srs_get_system_startup_time_ms() | @@ -61,13 +61,13 @@ int64_t srs_get_system_startup_time_ms() | ||
| 61 | 61 | ||
| 62 | return _srs_system_time_startup_time / 1000; | 62 | return _srs_system_time_startup_time / 1000; |
| 63 | } | 63 | } |
| 64 | -void srs_update_system_time_ms() | 64 | +int64_t srs_update_system_time_ms() |
| 65 | { | 65 | { |
| 66 | timeval now; | 66 | timeval now; |
| 67 | 67 | ||
| 68 | if (gettimeofday(&now, NULL) < 0) { | 68 | if (gettimeofday(&now, NULL) < 0) { |
| 69 | srs_warn("gettimeofday failed, ignore"); | 69 | srs_warn("gettimeofday failed, ignore"); |
| 70 | - return; | 70 | + return -1; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | // @see: https://github.com/winlinvip/simple-rtmp-server/issues/35 | 73 | // @see: https://github.com/winlinvip/simple-rtmp-server/issues/35 |
| @@ -83,7 +83,7 @@ void srs_update_system_time_ms() | @@ -83,7 +83,7 @@ void srs_update_system_time_ms() | ||
| 83 | if (_srs_system_time_us_cache <= 0) { | 83 | if (_srs_system_time_us_cache <= 0) { |
| 84 | _srs_system_time_us_cache = now_us; | 84 | _srs_system_time_us_cache = now_us; |
| 85 | _srs_system_time_startup_time = now_us; | 85 | _srs_system_time_startup_time = now_us; |
| 86 | - return; | 86 | + return _srs_system_time_us_cache; |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | // use relative time. | 89 | // use relative time. |
| @@ -99,6 +99,8 @@ void srs_update_system_time_ms() | @@ -99,6 +99,8 @@ void srs_update_system_time_ms() | ||
| 99 | _srs_system_time_us_cache = now_us; | 99 | _srs_system_time_us_cache = now_us; |
| 100 | srs_info("system time updated, startup=%"PRId64"us, now=%"PRId64"us", | 100 | srs_info("system time updated, startup=%"PRId64"us, now=%"PRId64"us", |
| 101 | _srs_system_time_startup_time, _srs_system_time_us_cache); | 101 | _srs_system_time_startup_time, _srs_system_time_us_cache); |
| 102 | + | ||
| 103 | + return _srs_system_time_us_cache; | ||
| 102 | } | 104 | } |
| 103 | 105 | ||
| 104 | string srs_dns_resolve(string host) | 106 | string srs_dns_resolve(string host) |
| @@ -40,7 +40,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -40,7 +40,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 40 | extern int64_t srs_get_system_time_ms(); | 40 | extern int64_t srs_get_system_time_ms(); |
| 41 | extern int64_t srs_get_system_startup_time_ms(); | 41 | extern int64_t srs_get_system_startup_time_ms(); |
| 42 | // the deamon st-thread will update it. | 42 | // the deamon st-thread will update it. |
| 43 | -extern void srs_update_system_time_ms(); | 43 | +extern int64_t srs_update_system_time_ms(); |
| 44 | 44 | ||
| 45 | // dns resolve utility, return the resolved ip address. | 45 | // dns resolve utility, return the resolved ip address. |
| 46 | extern std::string srs_dns_resolve(std::string host); | 46 | extern std::string srs_dns_resolve(std::string host); |
-
请 注册 或 登录 后发表评论