+server support band check +every vhost can have it's own chunk size
正在显示
16 个修改的文件
包含
628 行增加
和
68 行删除
trunk/auto/build_ffmpeg.sh
100644 → 100755
| @@ -80,7 +80,7 @@ else | @@ -80,7 +80,7 @@ else | ||
| 80 | --yasmexe=${ff_yasm_bin} \ | 80 | --yasmexe=${ff_yasm_bin} \ |
| 81 | --prefix=${ff_release_dir} --cc= \ | 81 | --prefix=${ff_release_dir} --cc= \ |
| 82 | --enable-static --disable-shared --disable-debug \ | 82 | --enable-static --disable-shared --disable-debug \ |
| 83 | - --extra-cflags='-I${ffmpeg_exported_release_dir}/include' \ | 83 | + --extra-cflags='-I${ffmpeg_exported_release_dir}/include -I /usr/include/freetype2/' \ |
| 84 | --extra-ldflags='-L${ffmpeg_exported_release_dir}/lib -lm -ldl' \ | 84 | --extra-ldflags='-L${ffmpeg_exported_release_dir}/lib -lm -ldl' \ |
| 85 | --disable-ffplay --disable-ffprobe --disable-ffserver --disable-doc \ | 85 | --disable-ffplay --disable-ffprobe --disable-ffserver --disable-doc \ |
| 86 | --enable-postproc --enable-bzlib --enable-zlib --enable-parsers \ | 86 | --enable-postproc --enable-bzlib --enable-zlib --enable-parsers \ |
| 1 | # the listen ports, split by space. | 1 | # the listen ports, split by space. |
| 2 | listen 1935; | 2 | listen 1935; |
| 3 | -# the default chunk size is 128, max is 65536, | ||
| 4 | -# some client does not support chunk size change, | ||
| 5 | -# however, most clients supports it and it can improve | ||
| 6 | -# performance about 10%. | ||
| 7 | -# if not specified, set to 4096. | ||
| 8 | -chunk_size 65000; | ||
| 9 | # the logs dir. | 3 | # the logs dir. |
| 10 | # if enabled ffmpeg, each stracoding stream will create a log file. | 4 | # if enabled ffmpeg, each stracoding stream will create a log file. |
| 11 | # default: ./objs/logs | 5 | # default: ./objs/logs |
| @@ -19,6 +13,12 @@ max_connections 2000; | @@ -19,6 +13,12 @@ max_connections 2000; | ||
| 19 | # for which cannot identify the required vhost. | 13 | # for which cannot identify the required vhost. |
| 20 | # for default demo. | 14 | # for default demo. |
| 21 | vhost __defaultVhost__ { | 15 | vhost __defaultVhost__ { |
| 16 | + # the default chunk size is 128, max is 65536, | ||
| 17 | + # some client does not support chunk size change, | ||
| 18 | + # however, most clients supports it and it can improve | ||
| 19 | + # performance about 10%. | ||
| 20 | + # if not specified, set to 4096. | ||
| 21 | + chunk_size 65000; | ||
| 22 | enabled on; | 22 | enabled on; |
| 23 | gop_cache on; | 23 | gop_cache on; |
| 24 | hls on; | 24 | hls on; |
| @@ -79,6 +79,7 @@ vhost __defaultVhost__ { | @@ -79,6 +79,7 @@ vhost __defaultVhost__ { | ||
| 79 | } | 79 | } |
| 80 | # for development | 80 | # for development |
| 81 | vhost dev { | 81 | vhost dev { |
| 82 | + chunk_size 65000; | ||
| 82 | enabled on; | 83 | enabled on; |
| 83 | gop_cache on; | 84 | gop_cache on; |
| 84 | hls on; | 85 | hls on; |
| @@ -87,7 +88,7 @@ vhost dev { | @@ -87,7 +88,7 @@ vhost dev { | ||
| 87 | hls_window 30; | 88 | hls_window 30; |
| 88 | forward 127.0.0.1:19350; | 89 | forward 127.0.0.1:19350; |
| 89 | http_hooks { | 90 | http_hooks { |
| 90 | - enabled on; | 91 | + enabled off; |
| 91 | on_connect http://127.0.0.1:8085/api/v1/clients; | 92 | on_connect http://127.0.0.1:8085/api/v1/clients; |
| 92 | on_close http://127.0.0.1:8085/api/v1/clients; | 93 | on_close http://127.0.0.1:8085/api/v1/clients; |
| 93 | on_publish http://127.0.0.1:8085/api/v1/streams; | 94 | on_publish http://127.0.0.1:8085/api/v1/streams; |
| @@ -133,6 +134,20 @@ vhost dev { | @@ -133,6 +134,20 @@ vhost dev { | ||
| 133 | } | 134 | } |
| 134 | } | 135 | } |
| 135 | } | 136 | } |
| 137 | + | ||
| 138 | +vhost bandcheck.srs.com { | ||
| 139 | + chunk_size 65000; | ||
| 140 | + enabled on; | ||
| 141 | + # vhost for band width check | ||
| 142 | + bandcheck{ | ||
| 143 | + enabled on; | ||
| 144 | + key test kate; | ||
| 145 | + interval 30; | ||
| 146 | + max_play_kbps 45000; | ||
| 147 | + max_pub_kbps 25000; | ||
| 148 | + } | ||
| 149 | +} | ||
| 150 | + | ||
| 136 | # the http hook callback vhost, srs will invoke the hooks for specified events. | 151 | # the http hook callback vhost, srs will invoke the hooks for specified events. |
| 137 | vhost hooks.callback.vhost.com { | 152 | vhost hooks.callback.vhost.com { |
| 138 | http_hooks { | 153 | http_hooks { |
trunk/src/core/srs_core.cpp
100644 → 100755
| @@ -43,7 +43,7 @@ void srs_update_system_time_ms() | @@ -43,7 +43,7 @@ void srs_update_system_time_ms() | ||
| 43 | gettimeofday(&now, NULL); | 43 | gettimeofday(&now, NULL); |
| 44 | 44 | ||
| 45 | // we must convert the tv_sec/tv_usec to int64_t. | 45 | // we must convert the tv_sec/tv_usec to int64_t. |
| 46 | - _srs_system_time_us_cache = now.tv_sec * 1000 * 1000 + now.tv_usec; | 46 | + _srs_system_time_us_cache = ((int64_t)now.tv_sec) * 1000 * 1000 + (int64_t)now.tv_usec; |
| 47 | 47 | ||
| 48 | _srs_system_time_us_cache = srs_max(0, _srs_system_time_us_cache); | 48 | _srs_system_time_us_cache = srs_max(0, _srs_system_time_us_cache); |
| 49 | } | 49 | } |
| @@ -103,8 +103,8 @@ void srs_vhost_resolve(std::string& vhost, std::string& app) | @@ -103,8 +103,8 @@ void srs_vhost_resolve(std::string& vhost, std::string& app) | ||
| 103 | if ((pos = query.find("vhost?")) != std::string::npos | 103 | if ((pos = query.find("vhost?")) != std::string::npos |
| 104 | || (pos = query.find("vhost=")) != std::string::npos | 104 | || (pos = query.find("vhost=")) != std::string::npos |
| 105 | || (pos = query.find("Vhost?")) != std::string::npos | 105 | || (pos = query.find("Vhost?")) != std::string::npos |
| 106 | - || (pos = query.find("Vhost=")) != std::string::npos | ||
| 107 | - ) { | 106 | + || (pos = query.find("Vhost=")) != std::string::npos) |
| 107 | + { | ||
| 108 | query = query.substr(pos + 6); | 108 | query = query.substr(pos + 6); |
| 109 | if (!query.empty()) { | 109 | if (!query.empty()) { |
| 110 | vhost = query; | 110 | vhost = query; |
trunk/src/core/srs_core.hpp
100644 → 100755
trunk/src/core/srs_core_client.cpp
100644 → 100755
| @@ -130,6 +130,35 @@ int SrsClient::service_cycle() | @@ -130,6 +130,35 @@ int SrsClient::service_cycle() | ||
| 130 | } | 130 | } |
| 131 | srs_verbose("set peer bandwidth success"); | 131 | srs_verbose("set peer bandwidth success"); |
| 132 | 132 | ||
| 133 | + if(config->get_bw_check_enabled(req->vhost, req->bw_key)) | ||
| 134 | + { | ||
| 135 | + static int64_t last_check_time_ms = srs_get_system_time_ms(); | ||
| 136 | + int64_t interval_ms = 0; | ||
| 137 | + int play_kbps = 0; | ||
| 138 | + int pub_kbps = 0; | ||
| 139 | + config->get_bw_check_settings(req->vhost, interval_ms, play_kbps, pub_kbps); | ||
| 140 | + | ||
| 141 | + if((srs_get_system_time_ms() - last_check_time_ms) < interval_ms | ||
| 142 | + && last_check_time_ms != srs_get_system_time_ms()) | ||
| 143 | + { | ||
| 144 | + srs_trace("bandcheck interval less than limted interval. last time=%lld, current time=%lld" | ||
| 145 | + , last_check_time_ms, srs_get_system_time_ms()); | ||
| 146 | + return rtmp->response_connect_reject(req, "your bandcheck frequency is too high!"); | ||
| 147 | + } else { | ||
| 148 | + last_check_time_ms = srs_get_system_time_ms(); // update last check time | ||
| 149 | + char* local_ip = 0; | ||
| 150 | + if((ret = get_local_ip(local_ip)) != ERROR_SUCCESS){ | ||
| 151 | + srs_error("get local ip failed. ret = %d", ret); | ||
| 152 | + return ret; | ||
| 153 | + } | ||
| 154 | + if ((ret = rtmp->response_connect_app(req, local_ip)) != ERROR_SUCCESS) { | ||
| 155 | + srs_error("response connect app failed. ret=%d", ret); | ||
| 156 | + return ret; | ||
| 157 | + } | ||
| 158 | + return rtmp->start_bandwidth_check(play_kbps, pub_kbps); | ||
| 159 | + } | ||
| 160 | + } | ||
| 161 | + | ||
| 133 | if ((ret = rtmp->response_connect_app(req)) != ERROR_SUCCESS) { | 162 | if ((ret = rtmp->response_connect_app(req)) != ERROR_SUCCESS) { |
| 134 | srs_error("response connect app failed. ret=%d", ret); | 163 | srs_error("response connect app failed. ret=%d", ret); |
| 135 | return ret; | 164 | return ret; |
| @@ -147,11 +176,12 @@ int SrsClient::service_cycle() | @@ -147,11 +176,12 @@ int SrsClient::service_cycle() | ||
| 147 | srs_error("identify client failed. ret=%d", ret); | 176 | srs_error("identify client failed. ret=%d", ret); |
| 148 | return ret; | 177 | return ret; |
| 149 | } | 178 | } |
| 179 | + | ||
| 150 | req->strip(); | 180 | req->strip(); |
| 151 | srs_trace("identify client success. type=%d, stream_name=%s", type, req->stream.c_str()); | 181 | srs_trace("identify client success. type=%d, stream_name=%s", type, req->stream.c_str()); |
| 152 | 182 | ||
| 153 | int chunk_size = 4096; | 183 | int chunk_size = 4096; |
| 154 | - SrsConfDirective* conf = config->get_chunk_size(); | 184 | + SrsConfDirective* conf = config->get_chunk_size(req->vhost); |
| 155 | if (conf && !conf->arg0().empty()) { | 185 | if (conf && !conf->arg0().empty()) { |
| 156 | chunk_size = ::atoi(conf->arg0().c_str()); | 186 | chunk_size = ::atoi(conf->arg0().c_str()); |
| 157 | } | 187 | } |
| @@ -517,6 +547,40 @@ int SrsClient::get_peer_ip() | @@ -517,6 +547,40 @@ int SrsClient::get_peer_ip() | ||
| 517 | return ret; | 547 | return ret; |
| 518 | } | 548 | } |
| 519 | 549 | ||
| 550 | +int SrsClient::get_local_ip(char *&local_ip) | ||
| 551 | +{ | ||
| 552 | + int ret = ERROR_SUCCESS; | ||
| 553 | + | ||
| 554 | + int fd = st_netfd_fileno(stfd); | ||
| 555 | + | ||
| 556 | + // discovery client information | ||
| 557 | + sockaddr_in addr; | ||
| 558 | + socklen_t addrlen = sizeof(addr); | ||
| 559 | + if (getsockname(fd, (sockaddr*)&addr, &addrlen) == -1) { | ||
| 560 | + ret = ERROR_SOCKET_GET_LOCAL_IP; | ||
| 561 | + srs_error("discovery local ip information failed. ret=%d", ret); | ||
| 562 | + return ret; | ||
| 563 | + } | ||
| 564 | + srs_verbose("get local ip success."); | ||
| 565 | + | ||
| 566 | + // ip v4 or v6 | ||
| 567 | + char buf[INET6_ADDRSTRLEN]; | ||
| 568 | + memset(buf, 0, sizeof(buf)); | ||
| 569 | + | ||
| 570 | + if ((inet_ntop(addr.sin_family, &addr.sin_addr, buf, sizeof(buf))) == NULL) { | ||
| 571 | + ret = ERROR_SOCKET_GET_LOCAL_IP; | ||
| 572 | + srs_error("convert local ip information failed. ret=%d", ret); | ||
| 573 | + return ret; | ||
| 574 | + } | ||
| 575 | + | ||
| 576 | + local_ip = new char[strlen(buf) + 1]; | ||
| 577 | + strcpy(local_ip, buf); | ||
| 578 | + | ||
| 579 | + srs_verbose("get local ip of client ip=%s, fd=%d", buf, fd); | ||
| 580 | + | ||
| 581 | + return ret; | ||
| 582 | +} | ||
| 583 | + | ||
| 520 | int SrsClient::process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg) | 584 | int SrsClient::process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg) |
| 521 | { | 585 | { |
| 522 | int ret = ERROR_SUCCESS; | 586 | int ret = ERROR_SUCCESS; |
trunk/src/core/srs_core_client.hpp
100644 → 100755
| @@ -70,6 +70,7 @@ private: | @@ -70,6 +70,7 @@ private: | ||
| 70 | virtual int publish(SrsSource* source, bool is_fmle); | 70 | virtual int publish(SrsSource* source, bool is_fmle); |
| 71 | virtual int process_publish_message(SrsSource* source, SrsCommonMessage* msg, bool is_fmle); | 71 | virtual int process_publish_message(SrsSource* source, SrsCommonMessage* msg, bool is_fmle); |
| 72 | virtual int get_peer_ip(); | 72 | virtual int get_peer_ip(); |
| 73 | + virtual int get_local_ip(char *&local_ip); | ||
| 73 | virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg); | 74 | virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg); |
| 74 | private: | 75 | private: |
| 75 | virtual int on_connect(); | 76 | virtual int on_connect(); |
trunk/src/core/srs_core_config.cpp
100644 → 100755
| @@ -539,7 +539,7 @@ int SrsConfig::parse_options(int argc, char** argv) | @@ -539,7 +539,7 @@ int SrsConfig::parse_options(int argc, char** argv) | ||
| 539 | return parse_file(config_file.c_str()); | 539 | return parse_file(config_file.c_str()); |
| 540 | } | 540 | } |
| 541 | 541 | ||
| 542 | -SrsConfDirective* SrsConfig::get_vhost(std::string vhost) | 542 | +SrsConfDirective* SrsConfig::get_vhost(const std::string& vhost) |
| 543 | { | 543 | { |
| 544 | srs_assert(root); | 544 | srs_assert(root); |
| 545 | 545 | ||
| @@ -562,7 +562,7 @@ SrsConfDirective* SrsConfig::get_vhost(std::string vhost) | @@ -562,7 +562,7 @@ SrsConfDirective* SrsConfig::get_vhost(std::string vhost) | ||
| 562 | return NULL; | 562 | return NULL; |
| 563 | } | 563 | } |
| 564 | 564 | ||
| 565 | -SrsConfDirective* SrsConfig::get_vhost_on_connect(std::string vhost) | 565 | +SrsConfDirective* SrsConfig::get_vhost_on_connect(const std::string &vhost) |
| 566 | { | 566 | { |
| 567 | SrsConfDirective* conf = get_vhost(vhost); | 567 | SrsConfDirective* conf = get_vhost(vhost); |
| 568 | 568 | ||
| @@ -583,7 +583,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_connect(std::string vhost) | @@ -583,7 +583,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_connect(std::string vhost) | ||
| 583 | return conf->get("on_connect"); | 583 | return conf->get("on_connect"); |
| 584 | } | 584 | } |
| 585 | 585 | ||
| 586 | -SrsConfDirective* SrsConfig::get_vhost_on_close(std::string vhost) | 586 | +SrsConfDirective* SrsConfig::get_vhost_on_close(const std::string &vhost) |
| 587 | { | 587 | { |
| 588 | SrsConfDirective* conf = get_vhost(vhost); | 588 | SrsConfDirective* conf = get_vhost(vhost); |
| 589 | 589 | ||
| @@ -604,7 +604,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_close(std::string vhost) | @@ -604,7 +604,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_close(std::string vhost) | ||
| 604 | return conf->get("on_close"); | 604 | return conf->get("on_close"); |
| 605 | } | 605 | } |
| 606 | 606 | ||
| 607 | -SrsConfDirective* SrsConfig::get_vhost_on_publish(std::string vhost) | 607 | +SrsConfDirective* SrsConfig::get_vhost_on_publish(const std::string &vhost) |
| 608 | { | 608 | { |
| 609 | SrsConfDirective* conf = get_vhost(vhost); | 609 | SrsConfDirective* conf = get_vhost(vhost); |
| 610 | 610 | ||
| @@ -625,7 +625,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_publish(std::string vhost) | @@ -625,7 +625,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_publish(std::string vhost) | ||
| 625 | return conf->get("on_publish"); | 625 | return conf->get("on_publish"); |
| 626 | } | 626 | } |
| 627 | 627 | ||
| 628 | -SrsConfDirective* SrsConfig::get_vhost_on_unpublish(std::string vhost) | 628 | +SrsConfDirective* SrsConfig::get_vhost_on_unpublish(const std::string &vhost) |
| 629 | { | 629 | { |
| 630 | SrsConfDirective* conf = get_vhost(vhost); | 630 | SrsConfDirective* conf = get_vhost(vhost); |
| 631 | 631 | ||
| @@ -646,7 +646,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_unpublish(std::string vhost) | @@ -646,7 +646,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_unpublish(std::string vhost) | ||
| 646 | return conf->get("on_unpublish"); | 646 | return conf->get("on_unpublish"); |
| 647 | } | 647 | } |
| 648 | 648 | ||
| 649 | -SrsConfDirective* SrsConfig::get_vhost_on_play(std::string vhost) | 649 | +SrsConfDirective* SrsConfig::get_vhost_on_play(const std::string &vhost) |
| 650 | { | 650 | { |
| 651 | SrsConfDirective* conf = get_vhost(vhost); | 651 | SrsConfDirective* conf = get_vhost(vhost); |
| 652 | 652 | ||
| @@ -667,7 +667,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_play(std::string vhost) | @@ -667,7 +667,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_play(std::string vhost) | ||
| 667 | return conf->get("on_play"); | 667 | return conf->get("on_play"); |
| 668 | } | 668 | } |
| 669 | 669 | ||
| 670 | -SrsConfDirective* SrsConfig::get_vhost_on_stop(std::string vhost) | 670 | +SrsConfDirective* SrsConfig::get_vhost_on_stop(const std::string &vhost) |
| 671 | { | 671 | { |
| 672 | SrsConfDirective* conf = get_vhost(vhost); | 672 | SrsConfDirective* conf = get_vhost(vhost); |
| 673 | 673 | ||
| @@ -688,7 +688,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_stop(std::string vhost) | @@ -688,7 +688,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_stop(std::string vhost) | ||
| 688 | return conf->get("on_stop"); | 688 | return conf->get("on_stop"); |
| 689 | } | 689 | } |
| 690 | 690 | ||
| 691 | -bool SrsConfig::get_vhost_enabled(std::string vhost) | 691 | +bool SrsConfig::get_vhost_enabled(const std::string &vhost) |
| 692 | { | 692 | { |
| 693 | SrsConfDirective* vhost_conf = get_vhost(vhost); | 693 | SrsConfDirective* vhost_conf = get_vhost(vhost); |
| 694 | 694 | ||
| @@ -708,7 +708,7 @@ bool SrsConfig::get_vhost_enabled(std::string vhost) | @@ -708,7 +708,7 @@ bool SrsConfig::get_vhost_enabled(std::string vhost) | ||
| 708 | return true; | 708 | return true; |
| 709 | } | 709 | } |
| 710 | 710 | ||
| 711 | -SrsConfDirective* SrsConfig::get_transcode(std::string vhost, std::string scope) | 711 | +SrsConfDirective* SrsConfig::get_transcode(const std::string &vhost, const std::string &scope) |
| 712 | { | 712 | { |
| 713 | SrsConfDirective* conf = get_vhost(vhost); | 713 | SrsConfDirective* conf = get_vhost(vhost); |
| 714 | 714 | ||
| @@ -1059,7 +1059,7 @@ int SrsConfig::get_max_connections() | @@ -1059,7 +1059,7 @@ int SrsConfig::get_max_connections() | ||
| 1059 | return ::atoi(conf->arg0().c_str()); | 1059 | return ::atoi(conf->arg0().c_str()); |
| 1060 | } | 1060 | } |
| 1061 | 1061 | ||
| 1062 | -SrsConfDirective* SrsConfig::get_gop_cache(std::string vhost) | 1062 | +SrsConfDirective* SrsConfig::get_gop_cache(const std::string &vhost) |
| 1063 | { | 1063 | { |
| 1064 | SrsConfDirective* conf = get_vhost(vhost); | 1064 | SrsConfDirective* conf = get_vhost(vhost); |
| 1065 | 1065 | ||
| @@ -1070,7 +1070,7 @@ SrsConfDirective* SrsConfig::get_gop_cache(std::string vhost) | @@ -1070,7 +1070,7 @@ SrsConfDirective* SrsConfig::get_gop_cache(std::string vhost) | ||
| 1070 | return conf->get("gop_cache"); | 1070 | return conf->get("gop_cache"); |
| 1071 | } | 1071 | } |
| 1072 | 1072 | ||
| 1073 | -SrsConfDirective* SrsConfig::get_forward(std::string vhost) | 1073 | +SrsConfDirective* SrsConfig::get_forward(const std::string &vhost) |
| 1074 | { | 1074 | { |
| 1075 | SrsConfDirective* conf = get_vhost(vhost); | 1075 | SrsConfDirective* conf = get_vhost(vhost); |
| 1076 | 1076 | ||
| @@ -1081,7 +1081,7 @@ SrsConfDirective* SrsConfig::get_forward(std::string vhost) | @@ -1081,7 +1081,7 @@ SrsConfDirective* SrsConfig::get_forward(std::string vhost) | ||
| 1081 | return conf->get("forward"); | 1081 | return conf->get("forward"); |
| 1082 | } | 1082 | } |
| 1083 | 1083 | ||
| 1084 | -SrsConfDirective* SrsConfig::get_hls(std::string vhost) | 1084 | +SrsConfDirective* SrsConfig::get_hls(const std::string &vhost) |
| 1085 | { | 1085 | { |
| 1086 | SrsConfDirective* conf = get_vhost(vhost); | 1086 | SrsConfDirective* conf = get_vhost(vhost); |
| 1087 | 1087 | ||
| @@ -1092,7 +1092,7 @@ SrsConfDirective* SrsConfig::get_hls(std::string vhost) | @@ -1092,7 +1092,7 @@ SrsConfDirective* SrsConfig::get_hls(std::string vhost) | ||
| 1092 | return conf->get("hls"); | 1092 | return conf->get("hls"); |
| 1093 | } | 1093 | } |
| 1094 | 1094 | ||
| 1095 | -bool SrsConfig::get_hls_enabled(std::string vhost) | 1095 | +bool SrsConfig::get_hls_enabled(const std::string &vhost) |
| 1096 | { | 1096 | { |
| 1097 | SrsConfDirective* hls = get_hls(vhost); | 1097 | SrsConfDirective* hls = get_hls(vhost); |
| 1098 | 1098 | ||
| @@ -1107,7 +1107,7 @@ bool SrsConfig::get_hls_enabled(std::string vhost) | @@ -1107,7 +1107,7 @@ bool SrsConfig::get_hls_enabled(std::string vhost) | ||
| 1107 | return true; | 1107 | return true; |
| 1108 | } | 1108 | } |
| 1109 | 1109 | ||
| 1110 | -SrsConfDirective* SrsConfig::get_hls_path(std::string vhost) | 1110 | +SrsConfDirective* SrsConfig::get_hls_path(const std::string &vhost) |
| 1111 | { | 1111 | { |
| 1112 | SrsConfDirective* conf = get_vhost(vhost); | 1112 | SrsConfDirective* conf = get_vhost(vhost); |
| 1113 | 1113 | ||
| @@ -1118,7 +1118,7 @@ SrsConfDirective* SrsConfig::get_hls_path(std::string vhost) | @@ -1118,7 +1118,7 @@ SrsConfDirective* SrsConfig::get_hls_path(std::string vhost) | ||
| 1118 | return conf->get("hls_path"); | 1118 | return conf->get("hls_path"); |
| 1119 | } | 1119 | } |
| 1120 | 1120 | ||
| 1121 | -SrsConfDirective* SrsConfig::get_hls_fragment(std::string vhost) | 1121 | +SrsConfDirective* SrsConfig::get_hls_fragment(const std::string &vhost) |
| 1122 | { | 1122 | { |
| 1123 | SrsConfDirective* conf = get_vhost(vhost); | 1123 | SrsConfDirective* conf = get_vhost(vhost); |
| 1124 | 1124 | ||
| @@ -1129,7 +1129,7 @@ SrsConfDirective* SrsConfig::get_hls_fragment(std::string vhost) | @@ -1129,7 +1129,7 @@ SrsConfDirective* SrsConfig::get_hls_fragment(std::string vhost) | ||
| 1129 | return conf->get("hls_fragment"); | 1129 | return conf->get("hls_fragment"); |
| 1130 | } | 1130 | } |
| 1131 | 1131 | ||
| 1132 | -SrsConfDirective* SrsConfig::get_hls_window(std::string vhost) | 1132 | +SrsConfDirective* SrsConfig::get_hls_window(const std::string &vhost) |
| 1133 | { | 1133 | { |
| 1134 | SrsConfDirective* conf = get_vhost(vhost); | 1134 | SrsConfDirective* conf = get_vhost(vhost); |
| 1135 | 1135 | ||
| @@ -1140,7 +1140,7 @@ SrsConfDirective* SrsConfig::get_hls_window(std::string vhost) | @@ -1140,7 +1140,7 @@ SrsConfDirective* SrsConfig::get_hls_window(std::string vhost) | ||
| 1140 | return conf->get("hls_window"); | 1140 | return conf->get("hls_window"); |
| 1141 | } | 1141 | } |
| 1142 | 1142 | ||
| 1143 | -SrsConfDirective* SrsConfig::get_refer(std::string vhost) | 1143 | +SrsConfDirective* SrsConfig::get_refer(const std::string &vhost) |
| 1144 | { | 1144 | { |
| 1145 | SrsConfDirective* conf = get_vhost(vhost); | 1145 | SrsConfDirective* conf = get_vhost(vhost); |
| 1146 | 1146 | ||
| @@ -1151,7 +1151,7 @@ SrsConfDirective* SrsConfig::get_refer(std::string vhost) | @@ -1151,7 +1151,7 @@ SrsConfDirective* SrsConfig::get_refer(std::string vhost) | ||
| 1151 | return conf->get("refer"); | 1151 | return conf->get("refer"); |
| 1152 | } | 1152 | } |
| 1153 | 1153 | ||
| 1154 | -SrsConfDirective* SrsConfig::get_refer_play(std::string vhost) | 1154 | +SrsConfDirective* SrsConfig::get_refer_play(const std::string &vhost) |
| 1155 | { | 1155 | { |
| 1156 | SrsConfDirective* conf = get_vhost(vhost); | 1156 | SrsConfDirective* conf = get_vhost(vhost); |
| 1157 | 1157 | ||
| @@ -1162,7 +1162,7 @@ SrsConfDirective* SrsConfig::get_refer_play(std::string vhost) | @@ -1162,7 +1162,7 @@ SrsConfDirective* SrsConfig::get_refer_play(std::string vhost) | ||
| 1162 | return conf->get("refer_play"); | 1162 | return conf->get("refer_play"); |
| 1163 | } | 1163 | } |
| 1164 | 1164 | ||
| 1165 | -SrsConfDirective* SrsConfig::get_refer_publish(std::string vhost) | 1165 | +SrsConfDirective* SrsConfig::get_refer_publish(const std::string &vhost) |
| 1166 | { | 1166 | { |
| 1167 | SrsConfDirective* conf = get_vhost(vhost); | 1167 | SrsConfDirective* conf = get_vhost(vhost); |
| 1168 | 1168 | ||
| @@ -1178,9 +1178,15 @@ SrsConfDirective* SrsConfig::get_listen() | @@ -1178,9 +1178,15 @@ SrsConfDirective* SrsConfig::get_listen() | ||
| 1178 | return root->get("listen"); | 1178 | return root->get("listen"); |
| 1179 | } | 1179 | } |
| 1180 | 1180 | ||
| 1181 | -SrsConfDirective* SrsConfig::get_chunk_size() | 1181 | +SrsConfDirective* SrsConfig::get_chunk_size(const std::string &vhost) |
| 1182 | { | 1182 | { |
| 1183 | - return root->get("chunk_size"); | 1183 | + SrsConfDirective* conf = get_vhost(vhost); |
| 1184 | + | ||
| 1185 | + if (!conf) { | ||
| 1186 | + return NULL; | ||
| 1187 | + } | ||
| 1188 | + | ||
| 1189 | + return conf->get("chunk_size"); | ||
| 1184 | } | 1190 | } |
| 1185 | 1191 | ||
| 1186 | SrsConfDirective* SrsConfig::get_pithy_print_publish() | 1192 | SrsConfDirective* SrsConfig::get_pithy_print_publish() |
| @@ -1233,6 +1239,62 @@ SrsConfDirective* SrsConfig::get_pithy_print_play() | @@ -1233,6 +1239,62 @@ SrsConfDirective* SrsConfig::get_pithy_print_play() | ||
| 1233 | return pithy->get("play"); | 1239 | return pithy->get("play"); |
| 1234 | } | 1240 | } |
| 1235 | 1241 | ||
| 1242 | +bool SrsConfig::get_bw_check_enabled(const std::string &vhost, const std::string &key) | ||
| 1243 | +{ | ||
| 1244 | + SrsConfDirective* conf = get_vhost(vhost); | ||
| 1245 | + | ||
| 1246 | + if (!conf) { | ||
| 1247 | + return false; | ||
| 1248 | + } | ||
| 1249 | + | ||
| 1250 | + SrsConfDirective* bw_test = conf->get("bandcheck"); | ||
| 1251 | + if(!bw_test) | ||
| 1252 | + return false; | ||
| 1253 | + | ||
| 1254 | + SrsConfDirective* bw_enabled_conf = bw_test->get("enabled"); | ||
| 1255 | + if(bw_enabled_conf && bw_enabled_conf->arg0() == "on"){ | ||
| 1256 | + SrsConfDirective* bw_key = bw_test->get("key"); | ||
| 1257 | + if(!bw_key) return false; | ||
| 1258 | + | ||
| 1259 | + std::vector<std::string> &args = bw_key->args; | ||
| 1260 | + for(unsigned int i = 0; i < args.size(); ++i){ | ||
| 1261 | + if(args.at(i) == key) | ||
| 1262 | + return true; | ||
| 1263 | + } | ||
| 1264 | + } | ||
| 1265 | + | ||
| 1266 | + return false; | ||
| 1267 | +} | ||
| 1268 | + | ||
| 1269 | +void SrsConfig::get_bw_check_settings(const std::string &vhost, int64_t &interval_ms, int &play_kbps, int &pub_kbps) | ||
| 1270 | +{ | ||
| 1271 | + // set default value; | ||
| 1272 | + interval_ms = 30 * 1000; | ||
| 1273 | + play_kbps = 45000; | ||
| 1274 | + pub_kbps = 25000; | ||
| 1275 | + | ||
| 1276 | + SrsConfDirective* conf = get_vhost(vhost); | ||
| 1277 | + if (!conf) { | ||
| 1278 | + return; | ||
| 1279 | + } | ||
| 1280 | + | ||
| 1281 | + SrsConfDirective* bw_test = conf->get("bandcheck"); | ||
| 1282 | + if(!bw_test) | ||
| 1283 | + return; | ||
| 1284 | + | ||
| 1285 | + SrsConfDirective* interval_conf = bw_test->get("interval"); | ||
| 1286 | + if(interval_conf) | ||
| 1287 | + interval_ms = ::atoll(interval_conf->arg0().c_str()) * 1000; | ||
| 1288 | + | ||
| 1289 | + SrsConfDirective* play_conf = bw_test->get("max_play_kbps"); | ||
| 1290 | + if(play_conf) | ||
| 1291 | + play_kbps = ::atoi(play_conf->arg0().c_str()); | ||
| 1292 | + | ||
| 1293 | + SrsConfDirective* pub_conf = bw_test->get("max_pub_kbps"); | ||
| 1294 | + if(pub_conf) | ||
| 1295 | + pub_kbps = ::atoi(pub_conf->arg0().c_str()); | ||
| 1296 | +} | ||
| 1297 | + | ||
| 1236 | int SrsConfig::parse_file(const char* filename) | 1298 | int SrsConfig::parse_file(const char* filename) |
| 1237 | { | 1299 | { |
| 1238 | int ret = ERROR_SUCCESS; | 1300 | int ret = ERROR_SUCCESS; |
trunk/src/core/srs_core_config.hpp
100644 → 100755
| @@ -117,15 +117,15 @@ public: | @@ -117,15 +117,15 @@ public: | ||
| 117 | public: | 117 | public: |
| 118 | virtual int parse_options(int argc, char** argv); | 118 | virtual int parse_options(int argc, char** argv); |
| 119 | public: | 119 | public: |
| 120 | - virtual SrsConfDirective* get_vhost(std::string vhost); | ||
| 121 | - virtual bool get_vhost_enabled(std::string vhost); | ||
| 122 | - virtual SrsConfDirective* get_vhost_on_connect(std::string vhost); | ||
| 123 | - virtual SrsConfDirective* get_vhost_on_close(std::string vhost); | ||
| 124 | - virtual SrsConfDirective* get_vhost_on_publish(std::string vhost); | ||
| 125 | - virtual SrsConfDirective* get_vhost_on_unpublish(std::string vhost); | ||
| 126 | - virtual SrsConfDirective* get_vhost_on_play(std::string vhost); | ||
| 127 | - virtual SrsConfDirective* get_vhost_on_stop(std::string vhost); | ||
| 128 | - virtual SrsConfDirective* get_transcode(std::string vhost, std::string scope); | 120 | + virtual SrsConfDirective* get_vhost(const std::string &vhost); |
| 121 | + virtual bool get_vhost_enabled(const std::string& vhost); | ||
| 122 | + virtual SrsConfDirective* get_vhost_on_connect(const std::string& vhost); | ||
| 123 | + virtual SrsConfDirective* get_vhost_on_close(const std::string& vhost); | ||
| 124 | + virtual SrsConfDirective* get_vhost_on_publish(const std::string& vhost); | ||
| 125 | + virtual SrsConfDirective* get_vhost_on_unpublish(const std::string& vhost); | ||
| 126 | + virtual SrsConfDirective* get_vhost_on_play(const std::string& vhost); | ||
| 127 | + virtual SrsConfDirective* get_vhost_on_stop(const std::string& vhost); | ||
| 128 | + virtual SrsConfDirective* get_transcode(const std::string& vhost, const std::string& scope); | ||
| 129 | virtual bool get_transcode_enabled(SrsConfDirective* transcode); | 129 | virtual bool get_transcode_enabled(SrsConfDirective* transcode); |
| 130 | virtual std::string get_transcode_ffmpeg(SrsConfDirective* transcode); | 130 | virtual std::string get_transcode_ffmpeg(SrsConfDirective* transcode); |
| 131 | virtual void get_transcode_engines(SrsConfDirective* transcode, std::vector<SrsConfDirective*>& engines); | 131 | virtual void get_transcode_engines(SrsConfDirective* transcode, std::vector<SrsConfDirective*>& engines); |
| @@ -148,23 +148,25 @@ public: | @@ -148,23 +148,25 @@ public: | ||
| 148 | virtual std::string get_engine_output(SrsConfDirective* engine); | 148 | virtual std::string get_engine_output(SrsConfDirective* engine); |
| 149 | virtual std::string get_log_dir(); | 149 | virtual std::string get_log_dir(); |
| 150 | virtual int get_max_connections(); | 150 | virtual int get_max_connections(); |
| 151 | - virtual SrsConfDirective* get_gop_cache(std::string vhost); | ||
| 152 | - virtual SrsConfDirective* get_forward(std::string vhost); | ||
| 153 | - virtual SrsConfDirective* get_hls(std::string vhost); | ||
| 154 | - virtual bool get_hls_enabled(std::string vhost); | ||
| 155 | - virtual SrsConfDirective* get_hls_path(std::string vhost); | ||
| 156 | - virtual SrsConfDirective* get_hls_fragment(std::string vhost); | ||
| 157 | - virtual SrsConfDirective* get_hls_window(std::string vhost); | ||
| 158 | - virtual SrsConfDirective* get_refer(std::string vhost); | ||
| 159 | - virtual SrsConfDirective* get_refer_play(std::string vhost); | ||
| 160 | - virtual SrsConfDirective* get_refer_publish(std::string vhost); | 151 | + virtual SrsConfDirective* get_gop_cache(const std::string& vhost); |
| 152 | + virtual SrsConfDirective* get_forward(const std::string& vhost); | ||
| 153 | + virtual SrsConfDirective* get_hls(const std::string &vhost); | ||
| 154 | + virtual bool get_hls_enabled(const std::string& vhost); | ||
| 155 | + virtual SrsConfDirective* get_hls_path(const std::string& vhost); | ||
| 156 | + virtual SrsConfDirective* get_hls_fragment(const std::string& vhost); | ||
| 157 | + virtual SrsConfDirective* get_hls_window(const std::string& vhost); | ||
| 158 | + virtual SrsConfDirective* get_refer(const std::string& vhost); | ||
| 159 | + virtual SrsConfDirective* get_refer_play(const std::string& vhost); | ||
| 160 | + virtual SrsConfDirective* get_refer_publish(const std::string& vhost); | ||
| 161 | virtual SrsConfDirective* get_listen(); | 161 | virtual SrsConfDirective* get_listen(); |
| 162 | - virtual SrsConfDirective* get_chunk_size(); | 162 | + virtual SrsConfDirective* get_chunk_size(const std::string &vhost); |
| 163 | virtual SrsConfDirective* get_pithy_print_publish(); | 163 | virtual SrsConfDirective* get_pithy_print_publish(); |
| 164 | virtual SrsConfDirective* get_pithy_print_forwarder(); | 164 | virtual SrsConfDirective* get_pithy_print_forwarder(); |
| 165 | virtual SrsConfDirective* get_pithy_print_encoder(); | 165 | virtual SrsConfDirective* get_pithy_print_encoder(); |
| 166 | virtual SrsConfDirective* get_pithy_print_hls(); | 166 | virtual SrsConfDirective* get_pithy_print_hls(); |
| 167 | virtual SrsConfDirective* get_pithy_print_play(); | 167 | virtual SrsConfDirective* get_pithy_print_play(); |
| 168 | + virtual bool get_bw_check_enabled(const std::string &vhost, const std::string &key); | ||
| 169 | + virtual void get_bw_check_settings(const std::string &vhost, int64_t &interval_ms, int &play_kbps, int &pub_kbps); | ||
| 168 | private: | 170 | private: |
| 169 | virtual int parse_file(const char* filename); | 171 | virtual int parse_file(const char* filename); |
| 170 | virtual int parse_argv(int& i, char** argv); | 172 | virtual int parse_argv(int& i, char** argv); |
trunk/src/core/srs_core_error.hpp
100644 → 100755
| @@ -52,6 +52,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -52,6 +52,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 52 | #define ERROR_SOCKET_WRITE 209 | 52 | #define ERROR_SOCKET_WRITE 209 |
| 53 | #define ERROR_SOCKET_WAIT 210 | 53 | #define ERROR_SOCKET_WAIT 210 |
| 54 | #define ERROR_SOCKET_TIMEOUT 211 | 54 | #define ERROR_SOCKET_TIMEOUT 211 |
| 55 | +#define ERROR_SOCKET_GET_LOCAL_IP 222 | ||
| 55 | 56 | ||
| 56 | #define ERROR_RTMP_PLAIN_REQUIRED 300 | 57 | #define ERROR_RTMP_PLAIN_REQUIRED 300 |
| 57 | #define ERROR_RTMP_CHUNK_START 301 | 58 | #define ERROR_RTMP_CHUNK_START 301 |
trunk/src/core/srs_core_protocol.cpp
100644 → 100755
| @@ -1141,6 +1141,11 @@ bool SrsMessageHeader::is_user_control_message() | @@ -1141,6 +1141,11 @@ bool SrsMessageHeader::is_user_control_message() | ||
| 1141 | return message_type == RTMP_MSG_UserControlMessage; | 1141 | return message_type == RTMP_MSG_UserControlMessage; |
| 1142 | } | 1142 | } |
| 1143 | 1143 | ||
| 1144 | +bool SrsMessageHeader::is_windows_ackledgement() | ||
| 1145 | +{ | ||
| 1146 | + return message_type == RTMP_MSG_Acknowledgement; | ||
| 1147 | +} | ||
| 1148 | + | ||
| 1144 | SrsChunkStream::SrsChunkStream(int _cid) | 1149 | SrsChunkStream::SrsChunkStream(int _cid) |
| 1145 | { | 1150 | { |
| 1146 | fmt = 0; | 1151 | fmt = 0; |
| @@ -1311,6 +1316,20 @@ int SrsCommonMessage::decode_packet(SrsProtocol* protocol) | @@ -1311,6 +1316,20 @@ int SrsCommonMessage::decode_packet(SrsProtocol* protocol) | ||
| 1311 | srs_info("decode the AMF0/AMF3 data(onMetaData message)."); | 1316 | srs_info("decode the AMF0/AMF3 data(onMetaData message)."); |
| 1312 | packet = new SrsOnMetaDataPacket(); | 1317 | packet = new SrsOnMetaDataPacket(); |
| 1313 | return packet->decode(stream); | 1318 | return packet->decode(stream); |
| 1319 | + } else if( command == SRS_BW_CHECK_FINISHED | ||
| 1320 | + || command == SRS_BW_CHECK_PLAYING | ||
| 1321 | + || command == SRS_BW_CHECK_PUBLISHING | ||
| 1322 | + || command == SRS_BW_CHECK_STARTING_PLAY | ||
| 1323 | + || command == SRS_BW_CHECK_STARTING_PUBLISH | ||
| 1324 | + || command == SRS_BW_CHECK_START_PLAY | ||
| 1325 | + || command == SRS_BW_CHECK_START_PUBLISH | ||
| 1326 | + || command == SRS_BW_CHECK_STOPPED_PLAY | ||
| 1327 | + || command == SRS_BW_CHECK_STOP_PLAY | ||
| 1328 | + || command == SRS_BW_CHECK_STOP_PUBLISH) | ||
| 1329 | + { | ||
| 1330 | + srs_info("decode the AMF0/AMF3 band width check message."); | ||
| 1331 | + packet = new SrsOnStatusCallPacket(); | ||
| 1332 | + return packet->decode(stream); | ||
| 1314 | } | 1333 | } |
| 1315 | 1334 | ||
| 1316 | // default packet to drop message. | 1335 | // default packet to drop message. |
| @@ -1329,6 +1348,10 @@ int SrsCommonMessage::decode_packet(SrsProtocol* protocol) | @@ -1329,6 +1348,10 @@ int SrsCommonMessage::decode_packet(SrsProtocol* protocol) | ||
| 1329 | srs_verbose("start to decode set chunk size message."); | 1348 | srs_verbose("start to decode set chunk size message."); |
| 1330 | packet = new SrsSetChunkSizePacket(); | 1349 | packet = new SrsSetChunkSizePacket(); |
| 1331 | return packet->decode(stream); | 1350 | return packet->decode(stream); |
| 1351 | + } else if(header.is_windows_ackledgement()) { | ||
| 1352 | + srs_verbose("start to decode AcknowledgementPacket message."); | ||
| 1353 | + packet = new SrsAcknowledgementPacket(); | ||
| 1354 | + return packet->decode(stream); | ||
| 1332 | } else { | 1355 | } else { |
| 1333 | // default packet to drop message. | 1356 | // default packet to drop message. |
| 1334 | srs_trace("drop the unknown message, type=%d", header.message_type); | 1357 | srs_trace("drop the unknown message, type=%d", header.message_type); |
| @@ -1775,8 +1798,13 @@ int SrsConnectAppResPacket::get_message_type() | @@ -1775,8 +1798,13 @@ int SrsConnectAppResPacket::get_message_type() | ||
| 1775 | 1798 | ||
| 1776 | int SrsConnectAppResPacket::get_size() | 1799 | int SrsConnectAppResPacket::get_size() |
| 1777 | { | 1800 | { |
| 1778 | - return srs_amf0_get_string_size(command_name) + srs_amf0_get_number_size() | ||
| 1779 | - + srs_amf0_get_object_size(props)+ srs_amf0_get_object_size(info); | 1801 | + int size = srs_amf0_get_string_size(command_name) + srs_amf0_get_number_size(); |
| 1802 | + if(props->size() > 0) | ||
| 1803 | + size += srs_amf0_get_object_size(props); | ||
| 1804 | + if(info->size() > 0) | ||
| 1805 | + size += srs_amf0_get_object_size(info); | ||
| 1806 | + | ||
| 1807 | + return size; | ||
| 1780 | } | 1808 | } |
| 1781 | 1809 | ||
| 1782 | int SrsConnectAppResPacket::encode_packet(SrsStream* stream) | 1810 | int SrsConnectAppResPacket::encode_packet(SrsStream* stream) |
| @@ -1795,16 +1823,22 @@ int SrsConnectAppResPacket::encode_packet(SrsStream* stream) | @@ -1795,16 +1823,22 @@ int SrsConnectAppResPacket::encode_packet(SrsStream* stream) | ||
| 1795 | } | 1823 | } |
| 1796 | srs_verbose("encode transaction_id success."); | 1824 | srs_verbose("encode transaction_id success."); |
| 1797 | 1825 | ||
| 1826 | + if(props->size() > 0){ | ||
| 1798 | if ((ret = srs_amf0_write_object(stream, props)) != ERROR_SUCCESS) { | 1827 | if ((ret = srs_amf0_write_object(stream, props)) != ERROR_SUCCESS) { |
| 1799 | srs_error("encode props failed. ret=%d", ret); | 1828 | srs_error("encode props failed. ret=%d", ret); |
| 1800 | return ret; | 1829 | return ret; |
| 1801 | } | 1830 | } |
| 1831 | + } | ||
| 1832 | + | ||
| 1802 | srs_verbose("encode props success."); | 1833 | srs_verbose("encode props success."); |
| 1803 | 1834 | ||
| 1835 | + if(info->size() > 0){ | ||
| 1804 | if ((ret = srs_amf0_write_object(stream, info)) != ERROR_SUCCESS) { | 1836 | if ((ret = srs_amf0_write_object(stream, info)) != ERROR_SUCCESS) { |
| 1805 | srs_error("encode info failed. ret=%d", ret); | 1837 | srs_error("encode info failed. ret=%d", ret); |
| 1806 | return ret; | 1838 | return ret; |
| 1807 | } | 1839 | } |
| 1840 | + } | ||
| 1841 | + | ||
| 1808 | srs_verbose("encode info success."); | 1842 | srs_verbose("encode info success."); |
| 1809 | 1843 | ||
| 1810 | srs_info("encode connect app response packet success."); | 1844 | srs_info("encode connect app response packet success."); |
| @@ -2540,6 +2574,30 @@ SrsOnStatusCallPacket::~SrsOnStatusCallPacket() | @@ -2540,6 +2574,30 @@ SrsOnStatusCallPacket::~SrsOnStatusCallPacket() | ||
| 2540 | srs_freep(data); | 2574 | srs_freep(data); |
| 2541 | } | 2575 | } |
| 2542 | 2576 | ||
| 2577 | +int SrsOnStatusCallPacket::decode(SrsStream *stream) | ||
| 2578 | +{ | ||
| 2579 | + int ret = ERROR_SUCCESS; | ||
| 2580 | + | ||
| 2581 | + if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { | ||
| 2582 | + srs_error("amf0 decode play command_name failed. ret=%d", ret); | ||
| 2583 | + return ret; | ||
| 2584 | + } | ||
| 2585 | + | ||
| 2586 | + if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { | ||
| 2587 | + srs_error("amf0 decode play transaction_id failed. ret=%d", ret); | ||
| 2588 | + return ret; | ||
| 2589 | + } | ||
| 2590 | + | ||
| 2591 | + if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) { | ||
| 2592 | + srs_error("amf0 decode play command_object failed. ret=%d", ret); | ||
| 2593 | + return ret; | ||
| 2594 | + } | ||
| 2595 | + | ||
| 2596 | + srs_info("decode SrsOnStatusCallPacket success."); | ||
| 2597 | + | ||
| 2598 | + return ret; | ||
| 2599 | +} | ||
| 2600 | + | ||
| 2543 | int SrsOnStatusCallPacket::get_perfer_cid() | 2601 | int SrsOnStatusCallPacket::get_perfer_cid() |
| 2544 | { | 2602 | { |
| 2545 | return RTMP_CID_OverStream; | 2603 | return RTMP_CID_OverStream; |
| @@ -2853,6 +2911,14 @@ SrsAcknowledgementPacket::~SrsAcknowledgementPacket() | @@ -2853,6 +2911,14 @@ SrsAcknowledgementPacket::~SrsAcknowledgementPacket() | ||
| 2853 | { | 2911 | { |
| 2854 | } | 2912 | } |
| 2855 | 2913 | ||
| 2914 | +int SrsAcknowledgementPacket::decode(SrsStream *stream) | ||
| 2915 | +{ | ||
| 2916 | + int ret = ERROR_SUCCESS; | ||
| 2917 | + ret = sequence_number = stream->read_4bytes(); | ||
| 2918 | + | ||
| 2919 | + return ret; | ||
| 2920 | +} | ||
| 2921 | + | ||
| 2856 | int SrsAcknowledgementPacket::get_perfer_cid() | 2922 | int SrsAcknowledgementPacket::get_perfer_cid() |
| 2857 | { | 2923 | { |
| 2858 | return RTMP_CID_ProtocolControl; | 2924 | return RTMP_CID_ProtocolControl; |
| @@ -3078,4 +3144,3 @@ int SrsUserControlPacket::encode_packet(SrsStream* stream) | @@ -3078,4 +3144,3 @@ int SrsUserControlPacket::encode_packet(SrsStream* stream) | ||
| 3078 | 3144 | ||
| 3079 | return ret; | 3145 | return ret; |
| 3080 | } | 3146 | } |
| 3081 | - |
trunk/src/core/srs_core_protocol.hpp
100644 → 100755
| @@ -220,6 +220,7 @@ struct SrsMessageHeader | @@ -220,6 +220,7 @@ struct SrsMessageHeader | ||
| 220 | bool is_window_ackledgement_size(); | 220 | bool is_window_ackledgement_size(); |
| 221 | bool is_set_chunk_size(); | 221 | bool is_set_chunk_size(); |
| 222 | bool is_user_control_message(); | 222 | bool is_user_control_message(); |
| 223 | + bool is_windows_ackledgement(); | ||
| 223 | }; | 224 | }; |
| 224 | 225 | ||
| 225 | /** | 226 | /** |
| @@ -801,6 +802,26 @@ protected: | @@ -801,6 +802,26 @@ protected: | ||
| 801 | virtual int encode_packet(SrsStream* stream); | 802 | virtual int encode_packet(SrsStream* stream); |
| 802 | }; | 803 | }; |
| 803 | 804 | ||
| 805 | + | ||
| 806 | +/** | ||
| 807 | +* band width check method name, which will be invoked by client. | ||
| 808 | +* band width check mothods use SrsOnStatusCallPacket as its internal packet type, | ||
| 809 | +* so ensure you set command name when you use it. | ||
| 810 | +*/ | ||
| 811 | +// for play | ||
| 812 | +#define SRS_BW_CHECK_START_PLAY "onSrsBandCheckStartPlayBytes" | ||
| 813 | +#define SRS_BW_CHECK_STARTING_PLAY "onSrsBandCheckStartingPlayBytes" | ||
| 814 | +#define SRS_BW_CHECK_STOP_PLAY "onSrsBandCheckStopPlayBytes" | ||
| 815 | +#define SRS_BW_CHECK_STOPPED_PLAY "onSrsBandCheckStoppedPlayBytes" | ||
| 816 | +#define SRS_BW_CHECK_PLAYING "onSrsBandCheckPlaying" | ||
| 817 | + | ||
| 818 | +// for publish | ||
| 819 | +#define SRS_BW_CHECK_START_PUBLISH "onSrsBandCheckStartPublishBytes" | ||
| 820 | +#define SRS_BW_CHECK_STARTING_PUBLISH "onSrsBandCheckStartingPublishBytes" | ||
| 821 | +#define SRS_BW_CHECK_STOP_PUBLISH "onSrsBandCheckStopPublishBytes" | ||
| 822 | +#define SRS_BW_CHECK_FINISHED "onSrsBandCheckFinished" | ||
| 823 | +#define SRS_BW_CHECK_PUBLISHING "onSrsBandCheckPublishing" | ||
| 824 | + | ||
| 804 | /** | 825 | /** |
| 805 | * onStatus command, AMF0 Call | 826 | * onStatus command, AMF0 Call |
| 806 | * @remark, user must set the stream_id by SrsMessage.set_packet(). | 827 | * @remark, user must set the stream_id by SrsMessage.set_packet(). |
| @@ -822,6 +843,10 @@ public: | @@ -822,6 +843,10 @@ public: | ||
| 822 | public: | 843 | public: |
| 823 | SrsOnStatusCallPacket(); | 844 | SrsOnStatusCallPacket(); |
| 824 | virtual ~SrsOnStatusCallPacket(); | 845 | virtual ~SrsOnStatusCallPacket(); |
| 846 | + | ||
| 847 | +public: | ||
| 848 | + virtual int decode(SrsStream* stream); | ||
| 849 | + | ||
| 825 | public: | 850 | public: |
| 826 | virtual int get_perfer_cid(); | 851 | virtual int get_perfer_cid(); |
| 827 | public: | 852 | public: |
| @@ -968,6 +993,10 @@ public: | @@ -968,6 +993,10 @@ public: | ||
| 968 | public: | 993 | public: |
| 969 | SrsAcknowledgementPacket(); | 994 | SrsAcknowledgementPacket(); |
| 970 | virtual ~SrsAcknowledgementPacket(); | 995 | virtual ~SrsAcknowledgementPacket(); |
| 996 | + | ||
| 997 | +public: | ||
| 998 | + virtual int decode(SrsStream *stream); | ||
| 999 | + | ||
| 971 | public: | 1000 | public: |
| 972 | virtual int get_perfer_cid(); | 1001 | virtual int get_perfer_cid(); |
| 973 | public: | 1002 | public: |
trunk/src/core/srs_core_rtmp.cpp
100644 → 100755
| @@ -2,6 +2,7 @@ | @@ -2,6 +2,7 @@ | ||
| 2 | The MIT License (MIT) | 2 | The MIT License (MIT) |
| 3 | 3 | ||
| 4 | Copyright (c) 2013 winlin | 4 | Copyright (c) 2013 winlin |
| 5 | +Copyright (c) 2013 wenjiejit | ||
| 5 | 6 | ||
| 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of |
| 7 | this software and associated documentation files (the "Software"), to deal in | 8 | this software and associated documentation files (the "Software"), to deal in |
| @@ -49,8 +50,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -49,8 +50,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 49 | #define StatusClientId "clientid" | 50 | #define StatusClientId "clientid" |
| 50 | // status value | 51 | // status value |
| 51 | #define StatusLevelStatus "status" | 52 | #define StatusLevelStatus "status" |
| 53 | +// status error | ||
| 54 | +#define StatusLevelError "error" | ||
| 52 | // code value | 55 | // code value |
| 53 | #define StatusCodeConnectSuccess "NetConnection.Connect.Success" | 56 | #define StatusCodeConnectSuccess "NetConnection.Connect.Success" |
| 57 | +#define StatusCodeConnectRejected "NetConnection.Connect.Rejected" | ||
| 54 | #define StatusCodeStreamReset "NetStream.Play.Reset" | 58 | #define StatusCodeStreamReset "NetStream.Play.Reset" |
| 55 | #define StatusCodeStreamStart "NetStream.Play.Start" | 59 | #define StatusCodeStreamStart "NetStream.Play.Start" |
| 56 | #define StatusCodeStreamPause "NetStream.Pause.Notify" | 60 | #define StatusCodeStreamPause "NetStream.Pause.Notify" |
| @@ -67,8 +71,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -67,8 +71,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 67 | #define SRS_DEFAULT_SID 1 | 71 | #define SRS_DEFAULT_SID 1 |
| 68 | 72 | ||
| 69 | SrsRequest::SrsRequest() | 73 | SrsRequest::SrsRequest() |
| 74 | + : objectEncoding(RTMP_SIG_AMF0_VER) | ||
| 70 | { | 75 | { |
| 71 | - objectEncoding = RTMP_SIG_AMF0_VER; | ||
| 72 | } | 76 | } |
| 73 | 77 | ||
| 74 | SrsRequest::~SrsRequest() | 78 | SrsRequest::~SrsRequest() |
| @@ -104,6 +108,18 @@ int SrsRequest::discovery_app() | @@ -104,6 +108,18 @@ int SrsRequest::discovery_app() | ||
| 104 | app = url; | 108 | app = url; |
| 105 | srs_vhost_resolve(vhost, app); | 109 | srs_vhost_resolve(vhost, app); |
| 106 | 110 | ||
| 111 | + // reslove bw check key | ||
| 112 | + std::string app_str = url; | ||
| 113 | + if ((pos = app_str.find("key=")) != std::string::npos){ | ||
| 114 | + std::string temp_key = app_str.substr(pos + strlen("key=")); | ||
| 115 | + for(unsigned int i = 0; i < temp_key.size(); ++i){ | ||
| 116 | + char c = temp_key[i]; | ||
| 117 | + if(c != '&') | ||
| 118 | + bw_key.push_back(c); | ||
| 119 | + else break; | ||
| 120 | + } | ||
| 121 | + } | ||
| 122 | + | ||
| 107 | // resolve the vhost from config | 123 | // resolve the vhost from config |
| 108 | SrsConfDirective* parsed_vhost = config->get_vhost(vhost); | 124 | SrsConfDirective* parsed_vhost = config->get_vhost(vhost); |
| 109 | if (parsed_vhost) { | 125 | if (parsed_vhost) { |
| @@ -238,7 +254,7 @@ int SrsRtmpClient::handshake() | @@ -238,7 +254,7 @@ int SrsRtmpClient::handshake() | ||
| 238 | return ret; | 254 | return ret; |
| 239 | } | 255 | } |
| 240 | 256 | ||
| 241 | -int SrsRtmpClient::connect_app(std::string app, std::string tc_url) | 257 | +int SrsRtmpClient::connect_app(const std::string &app, const std::string &tc_url) |
| 242 | { | 258 | { |
| 243 | int ret = ERROR_SUCCESS; | 259 | int ret = ERROR_SUCCESS; |
| 244 | 260 | ||
| @@ -324,7 +340,7 @@ int SrsRtmpClient::create_stream(int& stream_id) | @@ -324,7 +340,7 @@ int SrsRtmpClient::create_stream(int& stream_id) | ||
| 324 | return ret; | 340 | return ret; |
| 325 | } | 341 | } |
| 326 | 342 | ||
| 327 | -int SrsRtmpClient::play(std::string stream, int stream_id) | 343 | +int SrsRtmpClient::play(const std::string &stream, int stream_id) |
| 328 | { | 344 | { |
| 329 | int ret = ERROR_SUCCESS; | 345 | int ret = ERROR_SUCCESS; |
| 330 | 346 | ||
| @@ -366,7 +382,7 @@ int SrsRtmpClient::play(std::string stream, int stream_id) | @@ -366,7 +382,7 @@ int SrsRtmpClient::play(std::string stream, int stream_id) | ||
| 366 | return ret; | 382 | return ret; |
| 367 | } | 383 | } |
| 368 | 384 | ||
| 369 | -int SrsRtmpClient::publish(std::string stream, int stream_id) | 385 | +int SrsRtmpClient::publish(const std::string &stream, int stream_id) |
| 370 | { | 386 | { |
| 371 | int ret = ERROR_SUCCESS; | 387 | int ret = ERROR_SUCCESS; |
| 372 | 388 | ||
| @@ -544,7 +560,7 @@ int SrsRtmp::set_peer_bandwidth(int bandwidth, int type) | @@ -544,7 +560,7 @@ int SrsRtmp::set_peer_bandwidth(int bandwidth, int type) | ||
| 544 | return ret; | 560 | return ret; |
| 545 | } | 561 | } |
| 546 | 562 | ||
| 547 | -int SrsRtmp::response_connect_app(SrsRequest* req) | 563 | +int SrsRtmp::response_connect_app(SrsRequest *req, const char *ip) |
| 548 | { | 564 | { |
| 549 | int ret = ERROR_SUCCESS; | 565 | int ret = ERROR_SUCCESS; |
| 550 | 566 | ||
| @@ -572,6 +588,9 @@ int SrsRtmp::response_connect_app(SrsRequest* req) | @@ -572,6 +588,9 @@ int SrsRtmp::response_connect_app(SrsRequest* req) | ||
| 572 | data->set("srs_email", new SrsAmf0String(RTMP_SIG_SRS_EMAIL)); | 588 | data->set("srs_email", new SrsAmf0String(RTMP_SIG_SRS_EMAIL)); |
| 573 | data->set("srs_copyright", new SrsAmf0String(RTMP_SIG_SRS_COPYRIGHT)); | 589 | data->set("srs_copyright", new SrsAmf0String(RTMP_SIG_SRS_COPYRIGHT)); |
| 574 | 590 | ||
| 591 | + if(ip) | ||
| 592 | + data->set("srs_server_ip", new SrsAmf0String(ip)); | ||
| 593 | + | ||
| 575 | msg->set_packet(pkt, 0); | 594 | msg->set_packet(pkt, 0); |
| 576 | 595 | ||
| 577 | if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | 596 | if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { |
| @@ -583,6 +602,29 @@ int SrsRtmp::response_connect_app(SrsRequest* req) | @@ -583,6 +602,29 @@ int SrsRtmp::response_connect_app(SrsRequest* req) | ||
| 583 | return ret; | 602 | return ret; |
| 584 | } | 603 | } |
| 585 | 604 | ||
| 605 | +int SrsRtmp::response_connect_reject(SrsRequest *req, const std::string &description) | ||
| 606 | +{ | ||
| 607 | + int ret = ERROR_SUCCESS; | ||
| 608 | + | ||
| 609 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 610 | + SrsConnectAppResPacket* pkt = new SrsConnectAppResPacket(); | ||
| 611 | + pkt->command_name = "_error"; | ||
| 612 | + pkt->props->set(StatusLevel, new SrsAmf0String(StatusLevelError)); | ||
| 613 | + pkt->props->set(StatusCode, new SrsAmf0String(StatusCodeConnectRejected)); | ||
| 614 | + pkt->props->set(StatusDescription, new SrsAmf0String(description.c_str())); | ||
| 615 | + //pkt->props->set("objectEncoding", new SrsAmf0Number(req->objectEncoding)); | ||
| 616 | + | ||
| 617 | + msg->set_packet(pkt, 0); | ||
| 618 | + | ||
| 619 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 620 | + srs_error("send connect app response rejected message failed. ret=%d", ret); | ||
| 621 | + return ret; | ||
| 622 | + } | ||
| 623 | + srs_info("send connect app response rejected message success."); | ||
| 624 | + | ||
| 625 | + return ret; | ||
| 626 | +} | ||
| 627 | + | ||
| 586 | int SrsRtmp::on_bw_done() | 628 | int SrsRtmp::on_bw_done() |
| 587 | { | 629 | { |
| 588 | int ret = ERROR_SUCCESS; | 630 | int ret = ERROR_SUCCESS; |
| @@ -1032,6 +1074,59 @@ int SrsRtmp::start_flash_publish(int stream_id) | @@ -1032,6 +1074,59 @@ int SrsRtmp::start_flash_publish(int stream_id) | ||
| 1032 | return ret; | 1074 | return ret; |
| 1033 | } | 1075 | } |
| 1034 | 1076 | ||
| 1077 | +int SrsRtmp::start_bandwidth_check(int max_play_kbps, int max_pub_kbps) | ||
| 1078 | +{ | ||
| 1079 | + int ret = ERROR_SUCCESS; | ||
| 1080 | + | ||
| 1081 | + int play_duration_ms = 3000; | ||
| 1082 | + int play_interval_ms = 0; | ||
| 1083 | + int play_actual_duration_ms = 0; | ||
| 1084 | + int play_bytes = 0; | ||
| 1085 | + | ||
| 1086 | + int publish_duration_ms = 3000; | ||
| 1087 | + int publish_interval_ms = 0; | ||
| 1088 | + int publish_actual_duration_ms = 0; | ||
| 1089 | + int publish_bytes = 0; | ||
| 1090 | + | ||
| 1091 | + int64_t start_time = srs_get_system_time_ms(); | ||
| 1092 | + if((ret = bandwidth_check_play(play_duration_ms, play_interval_ms, | ||
| 1093 | + play_actual_duration_ms, play_bytes, max_play_kbps) != ERROR_SUCCESS) | ||
| 1094 | + || (ret = bandwidth_check_publish(publish_duration_ms, publish_interval_ms, | ||
| 1095 | + publish_actual_duration_ms, publish_bytes, max_pub_kbps)) != ERROR_SUCCESS) | ||
| 1096 | + { | ||
| 1097 | + srs_error("band width check failed. ret = %d", ret); | ||
| 1098 | + | ||
| 1099 | + return ret; | ||
| 1100 | + } | ||
| 1101 | + | ||
| 1102 | + int64_t end_time = srs_get_system_time_ms(); | ||
| 1103 | + int play_kbps = play_bytes * 8 / play_actual_duration_ms; | ||
| 1104 | + int publish_kbps = publish_bytes * 8 / publish_actual_duration_ms; | ||
| 1105 | + | ||
| 1106 | + // send finished msg | ||
| 1107 | + SrsCommonMessage* finish_msg = new SrsCommonMessage(); | ||
| 1108 | + SrsOnStatusCallPacket* finish_pkt = new SrsOnStatusCallPacket; | ||
| 1109 | + finish_pkt->command_name = SRS_BW_CHECK_FINISHED; | ||
| 1110 | + finish_pkt->data->set("code", new SrsAmf0Number(0)); | ||
| 1111 | + finish_pkt->data->set("start_time", new SrsAmf0Number(start_time)); | ||
| 1112 | + finish_pkt->data->set("end_time", new SrsAmf0Number(end_time)); | ||
| 1113 | + finish_pkt->data->set("play_kbps", new SrsAmf0Number(play_kbps)); | ||
| 1114 | + finish_pkt->data->set("publish_kbps", new SrsAmf0Number(publish_kbps)); | ||
| 1115 | + finish_pkt->data->set("play_bytes", new SrsAmf0Number(play_bytes)); | ||
| 1116 | + finish_pkt->data->set("play_time", new SrsAmf0Number(play_actual_duration_ms)); | ||
| 1117 | + finish_pkt->data->set("publish_bytes", new SrsAmf0Number(publish_bytes)); | ||
| 1118 | + finish_pkt->data->set("publish_time", new SrsAmf0Number(publish_actual_duration_ms)); | ||
| 1119 | + | ||
| 1120 | + finish_msg->set_packet(finish_pkt, 0); | ||
| 1121 | + if ((ret = protocol->send_message(finish_msg)) != ERROR_SUCCESS) { | ||
| 1122 | + srs_error("send bandwidth check finish message failed. ret=%d", ret); | ||
| 1123 | + return ret; | ||
| 1124 | + } | ||
| 1125 | + srs_trace("BW check finished."); | ||
| 1126 | + | ||
| 1127 | + return ret; | ||
| 1128 | +} | ||
| 1129 | + | ||
| 1035 | int SrsRtmp::identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name) | 1130 | int SrsRtmp::identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name) |
| 1036 | { | 1131 | { |
| 1037 | int ret = ERROR_SUCCESS; | 1132 | int ret = ERROR_SUCCESS; |
| @@ -1123,3 +1218,218 @@ int SrsRtmp::identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& | @@ -1123,3 +1218,218 @@ int SrsRtmp::identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& | ||
| 1123 | return ret; | 1218 | return ret; |
| 1124 | } | 1219 | } |
| 1125 | 1220 | ||
| 1221 | +int SrsRtmp::bandwidth_check_play(int duration_ms, int interval_ms, int &actual_duration_ms, | ||
| 1222 | + int &play_bytes, int max_play_kbps) | ||
| 1223 | +{ | ||
| 1224 | + int ret = ERROR_SUCCESS; | ||
| 1225 | + | ||
| 1226 | + // send start play command to client | ||
| 1227 | + SrsCommonMessage* start_play_msg = new SrsCommonMessage(); | ||
| 1228 | + SrsOnStatusCallPacket* start_play_packet = new SrsOnStatusCallPacket; | ||
| 1229 | + start_play_packet->command_name = SRS_BW_CHECK_START_PLAY; | ||
| 1230 | + start_play_packet->data->set("duration_ms", new SrsAmf0Number(duration_ms)); | ||
| 1231 | + start_play_packet->data->set("interval_ms", new SrsAmf0Number(interval_ms)); | ||
| 1232 | + | ||
| 1233 | + start_play_msg->set_packet(start_play_packet, 0); | ||
| 1234 | + if ((ret = protocol->send_message(start_play_msg)) != ERROR_SUCCESS) { | ||
| 1235 | + srs_error("send bandwidth check start play message failed. ret=%d", ret); | ||
| 1236 | + return ret; | ||
| 1237 | + } | ||
| 1238 | + srs_trace("BW check begin."); | ||
| 1239 | + | ||
| 1240 | + // recv client's starting play response | ||
| 1241 | + while (true) { | ||
| 1242 | + SrsCommonMessage* msg = 0; | ||
| 1243 | + if( (ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) | ||
| 1244 | + { | ||
| 1245 | + srs_error("recv client's starting play response failed. ret= %d", ret); | ||
| 1246 | + return ret; | ||
| 1247 | + } | ||
| 1248 | + | ||
| 1249 | + msg->decode_packet(protocol); | ||
| 1250 | + SrsOnStatusCallPacket* pkt = dynamic_cast<SrsOnStatusCallPacket*>(msg->get_packet()); | ||
| 1251 | + if(pkt && (pkt->command_name == SRS_BW_CHECK_STARTING_PLAY)) | ||
| 1252 | + break; | ||
| 1253 | + } | ||
| 1254 | + srs_trace("BW check recv play begin response."); | ||
| 1255 | + | ||
| 1256 | + // send play data to client | ||
| 1257 | + int64_t current_Time = srs_get_system_time_ms(); | ||
| 1258 | + int size = 1024*4; // 32KB | ||
| 1259 | + char random_data[size]; | ||
| 1260 | + memset(random_data, 0x01, size); | ||
| 1261 | + | ||
| 1262 | + int64_t last_time = current_Time; | ||
| 1263 | + int interval = 0; | ||
| 1264 | + while ( (srs_get_system_time_ms() - current_Time) < duration_ms ){ | ||
| 1265 | + st_usleep(interval); | ||
| 1266 | + SrsCommonMessage* msg = new SrsCommonMessage; | ||
| 1267 | + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket; | ||
| 1268 | + pkt->command_name = SRS_BW_CHECK_PLAYING; | ||
| 1269 | + | ||
| 1270 | + for(int i = 0; i < 10; ++i) | ||
| 1271 | + { | ||
| 1272 | + char buf[32]; | ||
| 1273 | + sprintf(buf, "%d", i); | ||
| 1274 | + pkt->data->set(buf, new SrsAmf0String(random_data)); | ||
| 1275 | + } | ||
| 1276 | + msg->set_packet(pkt, 0); | ||
| 1277 | + | ||
| 1278 | + play_bytes += pkt->get_payload_length(); | ||
| 1279 | + | ||
| 1280 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 1281 | + srs_error("send bandwidth check play messages failed. ret=%d", ret); | ||
| 1282 | + return ret; | ||
| 1283 | + } | ||
| 1284 | + | ||
| 1285 | + if((srs_get_system_time_ms() - last_time) > 5){ // check kbps every 5 ms; | ||
| 1286 | + int kbps = play_bytes * 8 / (srs_get_system_time_ms() - current_Time); | ||
| 1287 | + if(kbps > max_play_kbps){ | ||
| 1288 | + interval += 1000*3; // 2 ms | ||
| 1289 | + } else { | ||
| 1290 | + interval -= 1000*3; | ||
| 1291 | + if(interval < 0) | ||
| 1292 | + interval = 0; | ||
| 1293 | + } | ||
| 1294 | + } | ||
| 1295 | + } | ||
| 1296 | + actual_duration_ms = srs_get_system_time_ms() - current_Time; | ||
| 1297 | + srs_trace("BW check send play bytes over."); | ||
| 1298 | + | ||
| 1299 | + // notify client to stop play | ||
| 1300 | + SrsCommonMessage* stop_play_msg = new SrsCommonMessage; | ||
| 1301 | + SrsOnStatusCallPacket* stop_play_pkt = new SrsOnStatusCallPacket; | ||
| 1302 | + stop_play_pkt->command_name = SRS_BW_CHECK_STOP_PLAY; | ||
| 1303 | + stop_play_pkt->data->set("duration_ms", new SrsAmf0Number(duration_ms)); | ||
| 1304 | + stop_play_pkt->data->set("interval_ms", new SrsAmf0Number(interval_ms)); | ||
| 1305 | + stop_play_pkt->data->set("duration_delta", new SrsAmf0Number(actual_duration_ms)); | ||
| 1306 | + stop_play_pkt->data->set("bytes_delta", new SrsAmf0Number(play_bytes)); | ||
| 1307 | + | ||
| 1308 | + stop_play_msg->set_packet(stop_play_pkt, 0); | ||
| 1309 | + | ||
| 1310 | + if ((ret = protocol->send_message(stop_play_msg)) != ERROR_SUCCESS) { | ||
| 1311 | + srs_error("send bandwidth check stop play message failed. ret=%d", ret); | ||
| 1312 | + return ret; | ||
| 1313 | + } | ||
| 1314 | + srs_trace("BW check stop play bytes."); | ||
| 1315 | + | ||
| 1316 | + // recv client's stop play response. | ||
| 1317 | + while (true) { | ||
| 1318 | + SrsCommonMessage* msg = 0; | ||
| 1319 | + if((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) | ||
| 1320 | + { | ||
| 1321 | + srs_error("recv client's stop play response failed. ret = %d", ret); | ||
| 1322 | + return ret; | ||
| 1323 | + } | ||
| 1324 | + | ||
| 1325 | + msg->decode_packet(protocol); | ||
| 1326 | + SrsOnStatusCallPacket* pkt = dynamic_cast<SrsOnStatusCallPacket*>(msg->get_packet()); | ||
| 1327 | + if(pkt && (pkt->command_name == SRS_BW_CHECK_STOPPED_PLAY)) | ||
| 1328 | + break; | ||
| 1329 | + } | ||
| 1330 | + srs_trace("BW check recv stop play response."); | ||
| 1331 | + | ||
| 1332 | + return ret; | ||
| 1333 | +} | ||
| 1334 | + | ||
| 1335 | +int SrsRtmp::bandwidth_check_publish(int duration_ms, int interval_ms, int &actual_duration_ms, | ||
| 1336 | + int &publish_bytes, int max_pub_kbps) | ||
| 1337 | +{ | ||
| 1338 | + int ret = ERROR_SUCCESS; | ||
| 1339 | + | ||
| 1340 | + // notify client to start publish | ||
| 1341 | + SrsCommonMessage* start_publish_msg = new SrsCommonMessage; | ||
| 1342 | + SrsOnStatusCallPacket* start_publish_pkt = new SrsOnStatusCallPacket; | ||
| 1343 | + start_publish_pkt->command_name = SRS_BW_CHECK_START_PUBLISH; | ||
| 1344 | + start_publish_pkt->data->set("duration_ms", new SrsAmf0Number(duration_ms)); | ||
| 1345 | + start_publish_pkt->data->set("interval_ms", new SrsAmf0Number(interval_ms)); | ||
| 1346 | + | ||
| 1347 | + start_publish_msg->set_packet(start_publish_pkt, 0); | ||
| 1348 | + if ((ret = protocol->send_message(start_publish_msg)) != ERROR_SUCCESS) { | ||
| 1349 | + srs_error("send bandwidth check start publish message failed. ret=%d", ret); | ||
| 1350 | + return ret; | ||
| 1351 | + } | ||
| 1352 | + srs_trace("BW check publish begin."); | ||
| 1353 | + | ||
| 1354 | + // read client's notification of starting publish | ||
| 1355 | + while (true) { | ||
| 1356 | + SrsCommonMessage* msg = 0; | ||
| 1357 | + if((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) | ||
| 1358 | + { | ||
| 1359 | + srs_error("recv client's notification of starting publish failed. ret = %d", ret); | ||
| 1360 | + return ret; | ||
| 1361 | + } | ||
| 1362 | + | ||
| 1363 | + msg->decode_packet(protocol); | ||
| 1364 | + SrsOnStatusCallPacket* pkt = dynamic_cast<SrsOnStatusCallPacket*>(msg->get_packet()); | ||
| 1365 | + if(pkt && (pkt->command_name == SRS_BW_CHECK_STARTING_PUBLISH)) | ||
| 1366 | + break; | ||
| 1367 | + } | ||
| 1368 | + srs_trace("BW check recv publish begin response."); | ||
| 1369 | + | ||
| 1370 | + // recv publish msgs until @duration_ms ms | ||
| 1371 | + int64_t current_time = srs_get_system_time_ms(); | ||
| 1372 | + int64_t last_time = current_time; | ||
| 1373 | + int interval = 0; | ||
| 1374 | + | ||
| 1375 | + while( (srs_get_system_time_ms() - current_time) < duration_ms ) | ||
| 1376 | + { | ||
| 1377 | + st_usleep(interval); | ||
| 1378 | + SrsCommonMessage* msg = NULL; | ||
| 1379 | + if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) { | ||
| 1380 | + srs_error("recv message failed. ret=%d", ret); | ||
| 1381 | + return ret; | ||
| 1382 | + } | ||
| 1383 | + SrsAutoFree(SrsCommonMessage, msg, false); | ||
| 1384 | + | ||
| 1385 | + publish_bytes += msg->header.payload_length; | ||
| 1386 | + | ||
| 1387 | + if((srs_get_system_time_ms() - last_time) > 5){ // check kbps every 5 ms; | ||
| 1388 | + int kbps = publish_bytes * 8 / (srs_get_system_time_ms() - current_time); | ||
| 1389 | + if(kbps > max_pub_kbps){ | ||
| 1390 | + interval += 1000*3; // 2 ms | ||
| 1391 | + } else { | ||
| 1392 | + interval -= 1000*3; | ||
| 1393 | + if(interval < 0) | ||
| 1394 | + interval = 0; | ||
| 1395 | + } | ||
| 1396 | + } | ||
| 1397 | + } | ||
| 1398 | + actual_duration_ms = srs_get_system_time_ms() - current_time; | ||
| 1399 | + srs_trace("BW check recv publish data over."); | ||
| 1400 | + | ||
| 1401 | + // notify client to stop publish | ||
| 1402 | + SrsCommonMessage* stop_publish_msg = new SrsCommonMessage; | ||
| 1403 | + SrsOnStatusCallPacket* stop_publish_pkt = new SrsOnStatusCallPacket; | ||
| 1404 | + stop_publish_pkt->command_name = SRS_BW_CHECK_STOP_PUBLISH; | ||
| 1405 | + stop_publish_pkt->data->set("duration_ms", new SrsAmf0Number(duration_ms)); | ||
| 1406 | + stop_publish_pkt->data->set("interval_ms", new SrsAmf0Number(interval_ms)); | ||
| 1407 | + stop_publish_pkt->data->set("duration_delta", new SrsAmf0Number(actual_duration_ms)); | ||
| 1408 | + stop_publish_pkt->data->set("bytes_delta", new SrsAmf0Number(publish_bytes)); | ||
| 1409 | + | ||
| 1410 | + stop_publish_msg->set_packet(stop_publish_pkt, 0); | ||
| 1411 | + if ((ret = protocol->send_message(stop_publish_msg)) != ERROR_SUCCESS) { | ||
| 1412 | + srs_error("send bandwidth check stop publish message failed. ret=%d", ret); | ||
| 1413 | + return ret; | ||
| 1414 | + } | ||
| 1415 | + srs_trace("BW check stop pulish."); | ||
| 1416 | + | ||
| 1417 | + // recv left msg | ||
| 1418 | + while (true) { | ||
| 1419 | + if((ret = st_netfd_poll(stfd, POLLIN, 1000*500)) == ERROR_SUCCESS) | ||
| 1420 | + { | ||
| 1421 | + SrsCommonMessage* msg = 0; | ||
| 1422 | + if((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) | ||
| 1423 | + { | ||
| 1424 | + srs_error("recv client's left msg failed, ret = %d", ret); | ||
| 1425 | + return ret; | ||
| 1426 | + } | ||
| 1427 | + } else { | ||
| 1428 | + ret = ERROR_SUCCESS; | ||
| 1429 | + break; | ||
| 1430 | + } | ||
| 1431 | + } | ||
| 1432 | + | ||
| 1433 | + return ret; | ||
| 1434 | +} | ||
| 1435 | + |
trunk/src/core/srs_core_rtmp.hpp
100644 → 100755
| @@ -2,6 +2,7 @@ | @@ -2,6 +2,7 @@ | ||
| 2 | The MIT License (MIT) | 2 | The MIT License (MIT) |
| 3 | 3 | ||
| 4 | Copyright (c) 2013 winlin | 4 | Copyright (c) 2013 winlin |
| 5 | +Copyright (c) 2013 wenjiegit | ||
| 5 | 6 | ||
| 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of |
| 7 | this software and associated documentation files (the "Software"), to deal in | 8 | this software and associated documentation files (the "Software"), to deal in |
| @@ -64,6 +65,7 @@ struct SrsRequest | @@ -64,6 +65,7 @@ struct SrsRequest | ||
| 64 | std::string port; | 65 | std::string port; |
| 65 | std::string app; | 66 | std::string app; |
| 66 | std::string stream; | 67 | std::string stream; |
| 68 | + std::string bw_key; | ||
| 67 | 69 | ||
| 68 | SrsRequest(); | 70 | SrsRequest(); |
| 69 | virtual ~SrsRequest(); | 71 | virtual ~SrsRequest(); |
| @@ -97,7 +99,7 @@ enum SrsClientType | @@ -97,7 +99,7 @@ enum SrsClientType | ||
| 97 | SrsClientUnknown, | 99 | SrsClientUnknown, |
| 98 | SrsClientPlay, | 100 | SrsClientPlay, |
| 99 | SrsClientFMLEPublish, | 101 | SrsClientFMLEPublish, |
| 100 | - SrsClientFlashPublish, | 102 | + SrsClientFlashPublish |
| 101 | }; | 103 | }; |
| 102 | 104 | ||
| 103 | /** | 105 | /** |
| @@ -122,10 +124,10 @@ public: | @@ -122,10 +124,10 @@ public: | ||
| 122 | virtual int send_message(ISrsMessage* msg); | 124 | virtual int send_message(ISrsMessage* msg); |
| 123 | public: | 125 | public: |
| 124 | virtual int handshake(); | 126 | virtual int handshake(); |
| 125 | - virtual int connect_app(std::string app, std::string tc_url); | 127 | + virtual int connect_app(const std::string &app, const std::string &tc_url); |
| 126 | virtual int create_stream(int& stream_id); | 128 | virtual int create_stream(int& stream_id); |
| 127 | - virtual int play(std::string stream, int stream_id); | ||
| 128 | - virtual int publish(std::string stream, int stream_id); | 129 | + virtual int play(const std::string &stream, int stream_id); |
| 130 | + virtual int publish(const std::string &stream, int stream_id); | ||
| 129 | }; | 131 | }; |
| 130 | 132 | ||
| 131 | /** | 133 | /** |
| @@ -161,7 +163,8 @@ public: | @@ -161,7 +163,8 @@ public: | ||
| 161 | * using the Limit type field. | 163 | * using the Limit type field. |
| 162 | */ | 164 | */ |
| 163 | virtual int set_peer_bandwidth(int bandwidth, int type); | 165 | virtual int set_peer_bandwidth(int bandwidth, int type); |
| 164 | - virtual int response_connect_app(SrsRequest* req); | 166 | + virtual int response_connect_app(SrsRequest* req, const char *ip = 0); |
| 167 | + virtual int response_connect_reject(SrsRequest* req, const std::string& description); | ||
| 165 | virtual int on_bw_done(); | 168 | virtual int on_bw_done(); |
| 166 | /** | 169 | /** |
| 167 | * recv some message to identify the client. | 170 | * recv some message to identify the client. |
| @@ -212,10 +215,18 @@ public: | @@ -212,10 +215,18 @@ public: | ||
| 212 | * onStatus(NetStream.Publish.Start) | 215 | * onStatus(NetStream.Publish.Start) |
| 213 | */ | 216 | */ |
| 214 | virtual int start_flash_publish(int stream_id); | 217 | virtual int start_flash_publish(int stream_id); |
| 218 | + | ||
| 219 | + /** | ||
| 220 | + * used to process band width check from client. | ||
| 221 | + */ | ||
| 222 | + virtual int start_bandwidth_check(int max_play_kbps, int max_pub_kbps); | ||
| 223 | + | ||
| 215 | private: | 224 | private: |
| 216 | virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name); | 225 | virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name); |
| 217 | virtual int identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, std::string& stream_name); | 226 | virtual int identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, std::string& stream_name); |
| 218 | virtual int identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name); | 227 | virtual int identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name); |
| 228 | + virtual int bandwidth_check_play(int duration_ms, int interval_ms, int& actual_duration_ms, int& play_bytes, int max_play_kbps); | ||
| 229 | + virtual int bandwidth_check_publish(int duration_ms, int interval_ms, int& actual_duration_ms, int& publish_bytes, int max_pub_kbps); | ||
| 219 | }; | 230 | }; |
| 220 | 231 | ||
| 221 | #endif | 232 | #endif |
trunk/src/core/srs_core_server.cpp
100644 → 100755
trunk/src/core/srs_core_source.cpp
100644 → 100755
| @@ -344,7 +344,7 @@ int SrsGopCache::dump(SrsConsumer* consumer, int tba, int tbv) | @@ -344,7 +344,7 @@ int SrsGopCache::dump(SrsConsumer* consumer, int tba, int tbv) | ||
| 344 | 344 | ||
| 345 | std::map<std::string, SrsSource*> SrsSource::pool; | 345 | std::map<std::string, SrsSource*> SrsSource::pool; |
| 346 | 346 | ||
| 347 | -SrsSource* SrsSource::find(std::string stream_url) | 347 | +SrsSource* SrsSource::find(const std::string &stream_url) |
| 348 | { | 348 | { |
| 349 | if (pool.find(stream_url) == pool.end()) { | 349 | if (pool.find(stream_url) == pool.end()) { |
| 350 | pool[stream_url] = new SrsSource(stream_url); | 350 | pool[stream_url] = new SrsSource(stream_url); |
-
请 注册 或 登录 后发表评论