正在显示
21 个修改的文件
包含
1620 行增加
和
1746 行删除
| @@ -81,11 +81,11 @@ vhost __defaultVhost__ { | @@ -81,11 +81,11 @@ vhost __defaultVhost__ { | ||
| 81 | vhost dev { | 81 | vhost dev { |
| 82 | enabled on; | 82 | enabled on; |
| 83 | gop_cache on; | 83 | gop_cache on; |
| 84 | - hls on; | 84 | + hls off; |
| 85 | hls_path ./objs/nginx/html; | 85 | hls_path ./objs/nginx/html; |
| 86 | hls_fragment 5; | 86 | hls_fragment 5; |
| 87 | hls_window 30; | 87 | hls_window 30; |
| 88 | - #forward 127.0.0.1:19350; | 88 | + forward 127.0.0.1:19350; |
| 89 | http_hooks { | 89 | http_hooks { |
| 90 | enabled off; | 90 | enabled off; |
| 91 | on_connect http://127.0.0.1:8085/api/v1/clients; | 91 | on_connect http://127.0.0.1:8085/api/v1/clients; |
| @@ -96,7 +96,7 @@ vhost dev { | @@ -96,7 +96,7 @@ vhost dev { | ||
| 96 | on_stop http://127.0.0.1:8085/api/v1/sessions; | 96 | on_stop http://127.0.0.1:8085/api/v1/sessions; |
| 97 | } | 97 | } |
| 98 | transcode { | 98 | transcode { |
| 99 | - enabled off; | 99 | + enabled on; |
| 100 | ffmpeg ./objs/ffmpeg/bin/ffmpeg; | 100 | ffmpeg ./objs/ffmpeg/bin/ffmpeg; |
| 101 | engine dev { | 101 | engine dev { |
| 102 | enabled on; | 102 | enabled on; |
| @@ -116,7 +116,7 @@ MODULE_FILES=("srs_core" "srs_core_log" "srs_core_server" | @@ -116,7 +116,7 @@ MODULE_FILES=("srs_core" "srs_core_log" "srs_core_server" | ||
| 116 | "srs_core_handshake" "srs_core_pithy_print" | 116 | "srs_core_handshake" "srs_core_pithy_print" |
| 117 | "srs_core_config" "srs_core_refer" "srs_core_reload" | 117 | "srs_core_config" "srs_core_refer" "srs_core_reload" |
| 118 | "srs_core_hls" "srs_core_forward" "srs_core_encoder" | 118 | "srs_core_hls" "srs_core_forward" "srs_core_encoder" |
| 119 | - "srs_core_http") | 119 | + "srs_core_http" "srs_core_thread") |
| 120 | MODULE_DIR="src/core" . auto/modules.sh | 120 | MODULE_DIR="src/core" . auto/modules.sh |
| 121 | CORE_OBJS="${MODULE_OBJS[@]}" | 121 | CORE_OBJS="${MODULE_OBJS[@]}" |
| 122 | 122 |
trunk/research/players/rtmp/RtmpPlayer.swf
100644 → 100755
不能预览此文件类型
| @@ -111,3 +111,17 @@ void srs_vhost_resolve(std::string& vhost, std::string& app) | @@ -111,3 +111,17 @@ void srs_vhost_resolve(std::string& vhost, std::string& app) | ||
| 111 | } | 111 | } |
| 112 | } | 112 | } |
| 113 | } | 113 | } |
| 114 | + | ||
| 115 | +void srs_close_stfd(st_netfd_t& stfd) | ||
| 116 | +{ | ||
| 117 | + if (stfd) { | ||
| 118 | + int fd = st_netfd_fileno(stfd); | ||
| 119 | + st_netfd_close(stfd); | ||
| 120 | + stfd = NULL; | ||
| 121 | + | ||
| 122 | + // st does not close it sometimes, | ||
| 123 | + // close it manually. | ||
| 124 | + close(fd); | ||
| 125 | + } | ||
| 126 | +} | ||
| 127 | + |
| @@ -46,6 +46,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -46,6 +46,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 46 | #include <stddef.h> | 46 | #include <stddef.h> |
| 47 | #include <sys/types.h> | 47 | #include <sys/types.h> |
| 48 | 48 | ||
| 49 | +#include <st.h> | ||
| 50 | + | ||
| 49 | // generated by configure. | 51 | // generated by configure. |
| 50 | #include <srs_auto_headers.hpp> | 52 | #include <srs_auto_headers.hpp> |
| 51 | 53 | ||
| @@ -102,4 +104,7 @@ extern std::string srs_dns_resolve(std::string host); | @@ -102,4 +104,7 @@ extern std::string srs_dns_resolve(std::string host); | ||
| 102 | // app...vhost...request_vhost | 104 | // app...vhost...request_vhost |
| 103 | extern void srs_vhost_resolve(std::string& vhost, std::string& app); | 105 | extern void srs_vhost_resolve(std::string& vhost, std::string& app); |
| 104 | 106 | ||
| 107 | +// close the netfd, and close the underlayer fd. | ||
| 108 | +extern void srs_close_stfd(st_netfd_t& stfd); | ||
| 109 | + | ||
| 105 | #endif | 110 | #endif |
| @@ -36,15 +36,7 @@ SrsConnection::SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd) | @@ -36,15 +36,7 @@ SrsConnection::SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd) | ||
| 36 | 36 | ||
| 37 | SrsConnection::~SrsConnection() | 37 | SrsConnection::~SrsConnection() |
| 38 | { | 38 | { |
| 39 | - if (stfd) { | ||
| 40 | - int fd = st_netfd_fileno(stfd); | ||
| 41 | - st_netfd_close(stfd); | ||
| 42 | - stfd = NULL; | ||
| 43 | - | ||
| 44 | - // st does not close it sometimes, | ||
| 45 | - // close it manually. | ||
| 46 | - close(fd); | ||
| 47 | - } | 39 | + srs_close_stfd(stfd); |
| 48 | } | 40 | } |
| 49 | 41 | ||
| 50 | int SrsConnection::start() | 42 | int SrsConnection::start() |
| @@ -30,8 +30,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -30,8 +30,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 30 | 30 | ||
| 31 | #include <srs_core.hpp> | 31 | #include <srs_core.hpp> |
| 32 | 32 | ||
| 33 | -#include <st.h> | ||
| 34 | - | ||
| 35 | class SrsServer; | 33 | class SrsServer; |
| 36 | class SrsConnection | 34 | class SrsConnection |
| 37 | { | 35 | { |
| @@ -483,52 +483,15 @@ void SrsFFMPEG::stop() | @@ -483,52 +483,15 @@ void SrsFFMPEG::stop() | ||
| 483 | 483 | ||
| 484 | SrsEncoder::SrsEncoder() | 484 | SrsEncoder::SrsEncoder() |
| 485 | { | 485 | { |
| 486 | - tid = NULL; | ||
| 487 | - loop = false; | 486 | + pthread = new SrsThread(this, SRS_ENCODER_SLEEP_MS); |
| 487 | + pithy_print = new SrsPithyPrint(SRS_STAGE_ENCODER); | ||
| 488 | } | 488 | } |
| 489 | 489 | ||
| 490 | SrsEncoder::~SrsEncoder() | 490 | SrsEncoder::~SrsEncoder() |
| 491 | { | 491 | { |
| 492 | on_unpublish(); | 492 | on_unpublish(); |
| 493 | -} | ||
| 494 | - | ||
| 495 | -int SrsEncoder::parse_scope_engines(SrsRequest* req) | ||
| 496 | -{ | ||
| 497 | - int ret = ERROR_SUCCESS; | ||
| 498 | 493 | ||
| 499 | - // parse all transcode engines. | ||
| 500 | - SrsConfDirective* conf = NULL; | ||
| 501 | - | ||
| 502 | - // parse vhost scope engines | ||
| 503 | - std::string scope = ""; | ||
| 504 | - if ((conf = config->get_transcode(req->vhost, scope)) != NULL) { | ||
| 505 | - if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { | ||
| 506 | - srs_error("parse vhost scope=%s transcode engines failed. " | ||
| 507 | - "ret=%d", scope.c_str(), ret); | ||
| 508 | - return ret; | ||
| 509 | - } | ||
| 510 | - } | ||
| 511 | - // parse app scope engines | ||
| 512 | - scope = req->app; | ||
| 513 | - if ((conf = config->get_transcode(req->vhost, scope)) != NULL) { | ||
| 514 | - if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { | ||
| 515 | - srs_error("parse app scope=%s transcode engines failed. " | ||
| 516 | - "ret=%d", scope.c_str(), ret); | ||
| 517 | - return ret; | ||
| 518 | - } | ||
| 519 | - } | ||
| 520 | - // parse stream scope engines | ||
| 521 | - scope += "/"; | ||
| 522 | - scope += req->stream; | ||
| 523 | - if ((conf = config->get_transcode(req->vhost, scope)) != NULL) { | ||
| 524 | - if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { | ||
| 525 | - srs_error("parse stream scope=%s transcode engines failed. " | ||
| 526 | - "ret=%d", scope.c_str(), ret); | ||
| 527 | - return ret; | ||
| 528 | - } | ||
| 529 | - } | ||
| 530 | - | ||
| 531 | - return ret; | 494 | + srs_freep(pthread); |
| 532 | } | 495 | } |
| 533 | 496 | ||
| 534 | int SrsEncoder::on_publish(SrsRequest* req) | 497 | int SrsEncoder::on_publish(SrsRequest* req) |
| @@ -539,6 +502,7 @@ int SrsEncoder::on_publish(SrsRequest* req) | @@ -539,6 +502,7 @@ int SrsEncoder::on_publish(SrsRequest* req) | ||
| 539 | 502 | ||
| 540 | // ignore the loop encoder | 503 | // ignore the loop encoder |
| 541 | if (ret == ERROR_ENCODER_LOOP) { | 504 | if (ret == ERROR_ENCODER_LOOP) { |
| 505 | + clear_engines(); | ||
| 542 | ret = ERROR_SUCCESS; | 506 | ret = ERROR_SUCCESS; |
| 543 | } | 507 | } |
| 544 | 508 | ||
| @@ -548,9 +512,7 @@ int SrsEncoder::on_publish(SrsRequest* req) | @@ -548,9 +512,7 @@ int SrsEncoder::on_publish(SrsRequest* req) | ||
| 548 | } | 512 | } |
| 549 | 513 | ||
| 550 | // start thread to run all encoding engines. | 514 | // start thread to run all encoding engines. |
| 551 | - srs_assert(!tid); | ||
| 552 | - if((tid = st_thread_create(encoder_thread, this, 1, 0)) == NULL) { | ||
| 553 | - ret = ERROR_ST_CREATE_FORWARD_THREAD; | 515 | + if ((ret = pthread->start()) != ERROR_SUCCESS) { |
| 554 | srs_error("st_thread_create failed. ret=%d", ret); | 516 | srs_error("st_thread_create failed. ret=%d", ret); |
| 555 | return ret; | 517 | return ret; |
| 556 | } | 518 | } |
| @@ -560,23 +522,58 @@ int SrsEncoder::on_publish(SrsRequest* req) | @@ -560,23 +522,58 @@ int SrsEncoder::on_publish(SrsRequest* req) | ||
| 560 | 522 | ||
| 561 | void SrsEncoder::on_unpublish() | 523 | void SrsEncoder::on_unpublish() |
| 562 | { | 524 | { |
| 563 | - if (tid) { | ||
| 564 | - loop = false; | ||
| 565 | - st_thread_interrupt(tid); | ||
| 566 | - st_thread_join(tid, NULL); | ||
| 567 | - tid = NULL; | 525 | + pthread->stop(); |
| 526 | + clear_engines(); | ||
| 527 | +} | ||
| 528 | + | ||
| 529 | +int SrsEncoder::cycle() | ||
| 530 | +{ | ||
| 531 | + int ret = ERROR_SUCCESS; | ||
| 532 | + | ||
| 533 | + std::vector<SrsFFMPEG*>::iterator it; | ||
| 534 | + for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) { | ||
| 535 | + SrsFFMPEG* ffmpeg = *it; | ||
| 536 | + | ||
| 537 | + // start all ffmpegs. | ||
| 538 | + if ((ret = ffmpeg->start()) != ERROR_SUCCESS) { | ||
| 539 | + srs_error("ffmpeg start failed. ret=%d", ret); | ||
| 540 | + return ret; | ||
| 541 | + } | ||
| 542 | + | ||
| 543 | + // check ffmpeg status. | ||
| 544 | + if ((ret = ffmpeg->cycle()) != ERROR_SUCCESS) { | ||
| 545 | + srs_error("ffmpeg cycle failed. ret=%d", ret); | ||
| 546 | + return ret; | ||
| 547 | + } | ||
| 568 | } | 548 | } |
| 569 | 549 | ||
| 570 | - clear_engines(); | 550 | + // pithy print |
| 551 | + encoder(); | ||
| 552 | + pithy_print->elapse(SRS_ENCODER_SLEEP_MS); | ||
| 553 | + | ||
| 554 | + return ret; | ||
| 555 | +} | ||
| 556 | + | ||
| 557 | +void SrsEncoder::on_leave_loop() | ||
| 558 | +{ | ||
| 559 | + // kill ffmpeg when finished and it alive | ||
| 560 | + std::vector<SrsFFMPEG*>::iterator it; | ||
| 561 | + | ||
| 562 | + for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) { | ||
| 563 | + SrsFFMPEG* ffmpeg = *it; | ||
| 564 | + ffmpeg->stop(); | ||
| 565 | + } | ||
| 571 | } | 566 | } |
| 572 | 567 | ||
| 573 | void SrsEncoder::clear_engines() | 568 | void SrsEncoder::clear_engines() |
| 574 | { | 569 | { |
| 575 | std::vector<SrsFFMPEG*>::iterator it; | 570 | std::vector<SrsFFMPEG*>::iterator it; |
| 571 | + | ||
| 576 | for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) { | 572 | for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) { |
| 577 | SrsFFMPEG* ffmpeg = *it; | 573 | SrsFFMPEG* ffmpeg = *it; |
| 578 | srs_freep(ffmpeg); | 574 | srs_freep(ffmpeg); |
| 579 | } | 575 | } |
| 576 | + | ||
| 580 | ffmpegs.clear(); | 577 | ffmpegs.clear(); |
| 581 | } | 578 | } |
| 582 | 579 | ||
| @@ -585,6 +582,45 @@ SrsFFMPEG* SrsEncoder::at(int index) | @@ -585,6 +582,45 @@ SrsFFMPEG* SrsEncoder::at(int index) | ||
| 585 | return ffmpegs[index]; | 582 | return ffmpegs[index]; |
| 586 | } | 583 | } |
| 587 | 584 | ||
| 585 | +int SrsEncoder::parse_scope_engines(SrsRequest* req) | ||
| 586 | +{ | ||
| 587 | + int ret = ERROR_SUCCESS; | ||
| 588 | + | ||
| 589 | + // parse all transcode engines. | ||
| 590 | + SrsConfDirective* conf = NULL; | ||
| 591 | + | ||
| 592 | + // parse vhost scope engines | ||
| 593 | + std::string scope = ""; | ||
| 594 | + if ((conf = config->get_transcode(req->vhost, scope)) != NULL) { | ||
| 595 | + if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { | ||
| 596 | + srs_error("parse vhost scope=%s transcode engines failed. " | ||
| 597 | + "ret=%d", scope.c_str(), ret); | ||
| 598 | + return ret; | ||
| 599 | + } | ||
| 600 | + } | ||
| 601 | + // parse app scope engines | ||
| 602 | + scope = req->app; | ||
| 603 | + if ((conf = config->get_transcode(req->vhost, scope)) != NULL) { | ||
| 604 | + if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { | ||
| 605 | + srs_error("parse app scope=%s transcode engines failed. " | ||
| 606 | + "ret=%d", scope.c_str(), ret); | ||
| 607 | + return ret; | ||
| 608 | + } | ||
| 609 | + } | ||
| 610 | + // parse stream scope engines | ||
| 611 | + scope += "/"; | ||
| 612 | + scope += req->stream; | ||
| 613 | + if ((conf = config->get_transcode(req->vhost, scope)) != NULL) { | ||
| 614 | + if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { | ||
| 615 | + srs_error("parse stream scope=%s transcode engines failed. " | ||
| 616 | + "ret=%d", scope.c_str(), ret); | ||
| 617 | + return ret; | ||
| 618 | + } | ||
| 619 | + } | ||
| 620 | + | ||
| 621 | + return ret; | ||
| 622 | +} | ||
| 623 | + | ||
| 588 | int SrsEncoder::parse_transcode(SrsRequest* req, SrsConfDirective* conf) | 624 | int SrsEncoder::parse_transcode(SrsRequest* req, SrsConfDirective* conf) |
| 589 | { | 625 | { |
| 590 | int ret = ERROR_SUCCESS; | 626 | int ret = ERROR_SUCCESS; |
| @@ -631,7 +667,6 @@ int SrsEncoder::parse_transcode(SrsRequest* req, SrsConfDirective* conf) | @@ -631,7 +667,6 @@ int SrsEncoder::parse_transcode(SrsRequest* req, SrsConfDirective* conf) | ||
| 631 | 667 | ||
| 632 | // if got a loop, donot transcode the whole stream. | 668 | // if got a loop, donot transcode the whole stream. |
| 633 | if (ret == ERROR_ENCODER_LOOP) { | 669 | if (ret == ERROR_ENCODER_LOOP) { |
| 634 | - clear_engines(); | ||
| 635 | break; | 670 | break; |
| 636 | } | 671 | } |
| 637 | 672 | ||
| @@ -646,85 +681,14 @@ int SrsEncoder::parse_transcode(SrsRequest* req, SrsConfDirective* conf) | @@ -646,85 +681,14 @@ int SrsEncoder::parse_transcode(SrsRequest* req, SrsConfDirective* conf) | ||
| 646 | return ret; | 681 | return ret; |
| 647 | } | 682 | } |
| 648 | 683 | ||
| 649 | -int SrsEncoder::cycle() | ||
| 650 | -{ | ||
| 651 | - int ret = ERROR_SUCCESS; | ||
| 652 | - | ||
| 653 | - std::vector<SrsFFMPEG*>::iterator it; | ||
| 654 | - for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) { | ||
| 655 | - SrsFFMPEG* ffmpeg = *it; | ||
| 656 | - | ||
| 657 | - // start all ffmpegs. | ||
| 658 | - if ((ret = ffmpeg->start()) != ERROR_SUCCESS) { | ||
| 659 | - srs_error("ffmpeg start failed. ret=%d", ret); | ||
| 660 | - return ret; | ||
| 661 | - } | ||
| 662 | - | ||
| 663 | - // check ffmpeg status. | ||
| 664 | - if ((ret = ffmpeg->cycle()) != ERROR_SUCCESS) { | ||
| 665 | - srs_error("ffmpeg cycle failed. ret=%d", ret); | ||
| 666 | - return ret; | ||
| 667 | - } | ||
| 668 | - } | ||
| 669 | - | ||
| 670 | - return ret; | ||
| 671 | -} | ||
| 672 | - | ||
| 673 | -void SrsEncoder::encoder_cycle() | ||
| 674 | -{ | ||
| 675 | - int ret = ERROR_SUCCESS; | ||
| 676 | - | ||
| 677 | - log_context->generate_id(); | ||
| 678 | - srs_trace("encoder cycle start"); | ||
| 679 | - | ||
| 680 | - SrsPithyPrint pithy_print(SRS_STAGE_ENCODER); | ||
| 681 | - | ||
| 682 | - while (loop) { | ||
| 683 | - if ((ret = cycle()) != ERROR_SUCCESS) { | ||
| 684 | - srs_warn("encoder cycle failed, ignored and retry, ret=%d", ret); | ||
| 685 | - } else { | ||
| 686 | - srs_info("encoder cycle success, retry"); | ||
| 687 | - } | ||
| 688 | - | ||
| 689 | - if (!loop) { | ||
| 690 | - break; | ||
| 691 | - } | ||
| 692 | - | ||
| 693 | - encoder(&pithy_print); | ||
| 694 | - pithy_print.elapse(SRS_ENCODER_SLEEP_MS); | ||
| 695 | - | ||
| 696 | - st_usleep(SRS_ENCODER_SLEEP_MS * 1000); | ||
| 697 | - } | ||
| 698 | - | ||
| 699 | - // kill ffmpeg when finished and it alive | ||
| 700 | - std::vector<SrsFFMPEG*>::iterator it; | ||
| 701 | - for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) { | ||
| 702 | - SrsFFMPEG* ffmpeg = *it; | ||
| 703 | - ffmpeg->stop(); | ||
| 704 | - } | ||
| 705 | - | ||
| 706 | - srs_trace("encoder cycle finished"); | ||
| 707 | -} | ||
| 708 | - | ||
| 709 | -void SrsEncoder::encoder(SrsPithyPrint* pithy_print) | 684 | +void SrsEncoder::encoder() |
| 710 | { | 685 | { |
| 711 | // reportable | 686 | // reportable |
| 712 | if (pithy_print->can_print()) { | 687 | if (pithy_print->can_print()) { |
| 713 | - srs_trace("-> time=%"PRId64", encoders=%d", | ||
| 714 | - pithy_print->get_age(), (int)ffmpegs.size()); | 688 | + // TODO: FIXME: show more info. |
| 689 | + srs_trace("-> time=%"PRId64", encoders=%d", pithy_print->get_age(), (int)ffmpegs.size()); | ||
| 715 | } | 690 | } |
| 716 | } | 691 | } |
| 717 | 692 | ||
| 718 | -void* SrsEncoder::encoder_thread(void* arg) | ||
| 719 | -{ | ||
| 720 | - SrsEncoder* obj = (SrsEncoder*)arg; | ||
| 721 | - srs_assert(obj != NULL); | ||
| 722 | - | ||
| 723 | - obj->loop = true; | ||
| 724 | - obj->encoder_cycle(); | ||
| 725 | - | ||
| 726 | - return NULL; | ||
| 727 | -} | ||
| 728 | - | ||
| 729 | #endif | 693 | #endif |
| 730 | 694 |
| @@ -32,7 +32,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -32,7 +32,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 32 | #include <string> | 32 | #include <string> |
| 33 | #include <vector> | 33 | #include <vector> |
| 34 | 34 | ||
| 35 | -#include <st.h> | 35 | +#include <srs_core_thread.hpp> |
| 36 | 36 | ||
| 37 | class SrsConfDirective; | 37 | class SrsConfDirective; |
| 38 | class SrsRequest; | 38 | class SrsRequest; |
| @@ -85,28 +85,29 @@ public: | @@ -85,28 +85,29 @@ public: | ||
| 85 | * the encoder for a stream, | 85 | * the encoder for a stream, |
| 86 | * may use multiple ffmpegs to transcode the specified stream. | 86 | * may use multiple ffmpegs to transcode the specified stream. |
| 87 | */ | 87 | */ |
| 88 | -class SrsEncoder | 88 | +class SrsEncoder : public ISrsThreadHandler |
| 89 | { | 89 | { |
| 90 | private: | 90 | private: |
| 91 | std::vector<SrsFFMPEG*> ffmpegs; | 91 | std::vector<SrsFFMPEG*> ffmpegs; |
| 92 | private: | 92 | private: |
| 93 | - st_thread_t tid; | ||
| 94 | - bool loop; | 93 | + SrsThread* pthread; |
| 94 | + SrsPithyPrint* pithy_print; | ||
| 95 | public: | 95 | public: |
| 96 | SrsEncoder(); | 96 | SrsEncoder(); |
| 97 | virtual ~SrsEncoder(); | 97 | virtual ~SrsEncoder(); |
| 98 | public: | 98 | public: |
| 99 | virtual int on_publish(SrsRequest* req); | 99 | virtual int on_publish(SrsRequest* req); |
| 100 | virtual void on_unpublish(); | 100 | virtual void on_unpublish(); |
| 101 | +// interface ISrsThreadHandler. | ||
| 102 | +public: | ||
| 103 | + virtual int cycle(); | ||
| 104 | + virtual void on_leave_loop(); | ||
| 101 | private: | 105 | private: |
| 102 | - virtual int parse_scope_engines(SrsRequest* req); | ||
| 103 | virtual void clear_engines(); | 106 | virtual void clear_engines(); |
| 104 | virtual SrsFFMPEG* at(int index); | 107 | virtual SrsFFMPEG* at(int index); |
| 108 | + virtual int parse_scope_engines(SrsRequest* req); | ||
| 105 | virtual int parse_transcode(SrsRequest* req, SrsConfDirective* conf); | 109 | virtual int parse_transcode(SrsRequest* req, SrsConfDirective* conf); |
| 106 | - virtual int cycle(); | ||
| 107 | - virtual void encoder_cycle(); | ||
| 108 | - virtual void encoder(SrsPithyPrint* pithy_print); | ||
| 109 | - static void* encoder_thread(void* arg); | 110 | + virtual void encoder(); |
| 110 | }; | 111 | }; |
| 111 | 112 | ||
| 112 | #endif | 113 | #endif |
| @@ -37,8 +37,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -37,8 +37,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 37 | #define ERROR_ST_OPEN_SOCKET 102 | 37 | #define ERROR_ST_OPEN_SOCKET 102 |
| 38 | #define ERROR_ST_CREATE_LISTEN_THREAD 103 | 38 | #define ERROR_ST_CREATE_LISTEN_THREAD 103 |
| 39 | #define ERROR_ST_CREATE_CYCLE_THREAD 104 | 39 | #define ERROR_ST_CREATE_CYCLE_THREAD 104 |
| 40 | -#define ERROR_ST_CREATE_FORWARD_THREAD 105 | ||
| 41 | -#define ERROR_ST_CONNECT 106 | 40 | +#define ERROR_ST_CONNECT 105 |
| 42 | 41 | ||
| 43 | #define ERROR_SOCKET_CREATE 200 | 42 | #define ERROR_SOCKET_CREATE 200 |
| 44 | #define ERROR_SOCKET_SETREUSE 201 | 43 | #define ERROR_SOCKET_SETREUSE 201 |
trunk/src/core/srs_core_forward.cpp
100755 → 100644
| 1 | -/* | ||
| 2 | -The MIT License (MIT) | ||
| 3 | - | ||
| 4 | -Copyright (c) 2013 winlin | ||
| 5 | - | ||
| 6 | -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 | -the Software without restriction, including without limitation the rights to | ||
| 9 | -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||
| 10 | -the Software, and to permit persons to whom the Software is furnished to do so, | ||
| 11 | -subject to the following conditions: | ||
| 12 | - | ||
| 13 | -The above copyright notice and this permission notice shall be included in all | ||
| 14 | -copies or substantial portions of the Software. | ||
| 15 | - | ||
| 16 | -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||
| 18 | -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||
| 19 | -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||
| 20 | -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 21 | -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | -*/ | ||
| 23 | - | ||
| 24 | -#include <srs_core_forward.hpp> | ||
| 25 | - | ||
| 26 | -#include <stdlib.h> | ||
| 27 | -#include <sys/socket.h> | ||
| 28 | -#include <netinet/in.h> | ||
| 29 | -#include <arpa/inet.h> | ||
| 30 | - | ||
| 31 | -#include <srs_core_error.hpp> | ||
| 32 | -#include <srs_core_rtmp.hpp> | ||
| 33 | -#include <srs_core_log.hpp> | ||
| 34 | -#include <srs_core_protocol.hpp> | ||
| 35 | -#include <srs_core_pithy_print.hpp> | ||
| 36 | -#include <srs_core_rtmp.hpp> | ||
| 37 | -#include <srs_core_config.hpp> | ||
| 38 | - | ||
| 39 | -#define SRS_PULSE_TIMEOUT_MS 100 | ||
| 40 | -#define SRS_FORWARDER_SLEEP_MS 2000 | ||
| 41 | -#define SRS_SEND_TIMEOUT_US 3000000L | ||
| 42 | -#define SRS_RECV_TIMEOUT_US SRS_SEND_TIMEOUT_US | ||
| 43 | - | ||
| 44 | -SrsForwarder::SrsForwarder() | ||
| 45 | -{ | ||
| 46 | - client = NULL; | ||
| 47 | - stfd = NULL; | ||
| 48 | - stream_id = 0; | ||
| 49 | - | ||
| 50 | - tid = NULL; | ||
| 51 | - loop = false; | ||
| 52 | -} | ||
| 53 | - | ||
| 54 | -SrsForwarder::~SrsForwarder() | ||
| 55 | -{ | ||
| 56 | - on_unpublish(); | ||
| 57 | - | ||
| 58 | - std::vector<SrsSharedPtrMessage*>::iterator it; | ||
| 59 | - for (it = msgs.begin(); it != msgs.end(); ++it) { | ||
| 60 | - SrsSharedPtrMessage* msg = *it; | ||
| 61 | - srs_freep(msg); | ||
| 62 | - } | ||
| 63 | - msgs.clear(); | ||
| 64 | -} | ||
| 65 | - | ||
| 66 | -int SrsForwarder::on_publish(SrsRequest* req, std::string forward_server) | ||
| 67 | -{ | ||
| 68 | - int ret = ERROR_SUCCESS; | ||
| 69 | - | ||
| 70 | - // forward app | ||
| 71 | - app = req->app; | ||
| 72 | - | ||
| 73 | - stream_name = req->stream; | ||
| 74 | - server = forward_server; | ||
| 75 | - std::string s_port = RTMP_DEFAULT_PORTS; | ||
| 76 | - port = RTMP_DEFAULT_PORT; | ||
| 77 | - | ||
| 78 | - size_t pos = forward_server.find(":"); | ||
| 79 | - if (pos != std::string::npos) { | ||
| 80 | - s_port = forward_server.substr(pos + 1); | ||
| 81 | - server = forward_server.substr(0, pos); | ||
| 82 | - } | ||
| 83 | - // discovery vhost | ||
| 84 | - std::string vhost = req->vhost; | ||
| 85 | - srs_vhost_resolve(vhost, s_port); | ||
| 86 | - port = ::atoi(s_port.c_str()); | ||
| 87 | - | ||
| 88 | - // generate tcUrl | ||
| 89 | - tc_url = "rtmp://"; | ||
| 90 | - tc_url += vhost; | ||
| 91 | - tc_url += "/"; | ||
| 92 | - tc_url += req->app; | ||
| 93 | - | ||
| 94 | - // dead loop check | ||
| 95 | - std::string source_ep = req->vhost; | ||
| 96 | - source_ep += ":"; | ||
| 97 | - source_ep += req->port; | ||
| 98 | - | ||
| 99 | - std::string dest_ep = vhost; | ||
| 100 | - dest_ep += ":"; | ||
| 101 | - dest_ep += s_port; | ||
| 102 | - | ||
| 103 | - if (source_ep == dest_ep) { | ||
| 104 | - ret = ERROR_SYSTEM_FORWARD_LOOP; | ||
| 105 | - srs_warn("farder loop detected. src=%s, dest=%s, ret=%d", | ||
| 106 | - source_ep.c_str(), dest_ep.c_str(), ret); | ||
| 107 | - return ret; | ||
| 108 | - } | ||
| 109 | - srs_trace("start forward %s to %s, stream: %s/%s", | ||
| 110 | - source_ep.c_str(), dest_ep.c_str(), tc_url.c_str(), | ||
| 111 | - stream_name.c_str()); | ||
| 112 | - | ||
| 113 | - // TODO: seems bug when republish and reforward. | ||
| 114 | - | ||
| 115 | - // start forward | ||
| 116 | - if ((ret = open_socket()) != ERROR_SUCCESS) { | ||
| 117 | - return ret; | ||
| 118 | - } | ||
| 119 | - | ||
| 120 | - srs_assert(!tid); | ||
| 121 | - if((tid = st_thread_create(forward_thread, this, 1, 0)) == NULL){ | ||
| 122 | - ret = ERROR_ST_CREATE_FORWARD_THREAD; | ||
| 123 | - srs_error("st_thread_create failed. ret=%d", ret); | ||
| 124 | - return ret; | ||
| 125 | - } | ||
| 126 | - | ||
| 127 | - return ret; | ||
| 128 | -} | ||
| 129 | - | ||
| 130 | -void SrsForwarder::on_unpublish() | ||
| 131 | -{ | ||
| 132 | - if (tid) { | ||
| 133 | - loop = false; | ||
| 134 | - st_thread_interrupt(tid); | ||
| 135 | - st_thread_join(tid, NULL); | ||
| 136 | - tid = NULL; | ||
| 137 | - } | ||
| 138 | - | ||
| 139 | - if (stfd) { | ||
| 140 | - int fd = st_netfd_fileno(stfd); | ||
| 141 | - st_netfd_close(stfd); | ||
| 142 | - stfd = NULL; | ||
| 143 | - | ||
| 144 | - // st does not close it sometimes, | ||
| 145 | - // close it manually. | ||
| 146 | - close(fd); | ||
| 147 | - } | ||
| 148 | - | ||
| 149 | - srs_freep(client); | ||
| 150 | -} | ||
| 151 | - | ||
| 152 | -int SrsForwarder::on_meta_data(SrsSharedPtrMessage* metadata) | ||
| 153 | -{ | ||
| 154 | - int ret = ERROR_SUCCESS; | ||
| 155 | - | ||
| 156 | - msgs.push_back(metadata); | ||
| 157 | - | ||
| 158 | - return ret; | ||
| 159 | -} | ||
| 160 | - | ||
| 161 | -int SrsForwarder::on_audio(SrsSharedPtrMessage* msg) | ||
| 162 | -{ | ||
| 163 | - int ret = ERROR_SUCCESS; | ||
| 164 | - | ||
| 165 | - // TODO: FIXME: must drop the msgs when server failed. | ||
| 166 | - msgs.push_back(msg); | ||
| 167 | - | ||
| 168 | - return ret; | ||
| 169 | -} | ||
| 170 | - | ||
| 171 | -int SrsForwarder::on_video(SrsSharedPtrMessage* msg) | ||
| 172 | -{ | ||
| 173 | - int ret = ERROR_SUCCESS; | ||
| 174 | - | ||
| 175 | - // TODO: FIXME: must drop the msgs when server failed. | ||
| 176 | - msgs.push_back(msg); | ||
| 177 | - | ||
| 178 | - return ret; | ||
| 179 | -} | ||
| 180 | - | ||
| 181 | -int SrsForwarder::open_socket() | ||
| 182 | -{ | ||
| 183 | - int ret = ERROR_SUCCESS; | ||
| 184 | - | ||
| 185 | - srs_trace("forward stream=%s, tcUrl=%s to server=%s, port=%d", | ||
| 186 | - stream_name.c_str(), tc_url.c_str(), server.c_str(), port); | ||
| 187 | - | ||
| 188 | - int sock = socket(AF_INET, SOCK_STREAM, 0); | ||
| 189 | - if(sock == -1){ | ||
| 190 | - ret = ERROR_SOCKET_CREATE; | ||
| 191 | - srs_error("create socket error. ret=%d", ret); | ||
| 192 | - return ret; | ||
| 193 | - } | ||
| 194 | - | ||
| 195 | - stfd = st_netfd_open_socket(sock); | ||
| 196 | - if(stfd == NULL){ | ||
| 197 | - ret = ERROR_ST_OPEN_SOCKET; | ||
| 198 | - srs_error("st_netfd_open_socket failed. ret=%d", ret); | ||
| 199 | - return ret; | ||
| 200 | - } | ||
| 201 | - | ||
| 202 | - srs_freep(client); | ||
| 203 | - client = new SrsRtmpClient(stfd); | ||
| 204 | - | ||
| 205 | - return ret; | ||
| 206 | -} | ||
| 207 | - | ||
| 208 | -int SrsForwarder::connect_server() | ||
| 209 | -{ | ||
| 210 | - int ret = ERROR_SUCCESS; | ||
| 211 | - | ||
| 212 | - std::string ip = srs_dns_resolve(server); | ||
| 213 | - if (ip.empty()) { | ||
| 214 | - ret = ERROR_SYSTEM_IP_INVALID; | ||
| 215 | - srs_error("dns resolve server error, ip empty. ret=%d", ret); | ||
| 216 | - return ret; | ||
| 217 | - } | ||
| 218 | - | ||
| 219 | - sockaddr_in addr; | ||
| 220 | - addr.sin_family = AF_INET; | ||
| 221 | - addr.sin_port = htons(port); | ||
| 222 | - addr.sin_addr.s_addr = inet_addr(ip.c_str()); | ||
| 223 | - | ||
| 224 | - if (st_connect(stfd, (const struct sockaddr*)&addr, sizeof(sockaddr_in), ST_UTIME_NO_TIMEOUT) == -1){ | ||
| 225 | - ret = ERROR_ST_CONNECT; | ||
| 226 | - srs_error("connect to server error. ip=%s, port=%d, ret=%d", ip.c_str(), port, ret); | ||
| 227 | - return ret; | ||
| 228 | - } | ||
| 229 | - srs_trace("connect to server success. server=%s, ip=%s, port=%d", server.c_str(), ip.c_str(), port); | ||
| 230 | - | ||
| 231 | - return ret; | ||
| 232 | -} | ||
| 233 | - | ||
| 234 | -int SrsForwarder::cycle() | ||
| 235 | -{ | ||
| 236 | - int ret = ERROR_SUCCESS; | ||
| 237 | - | ||
| 238 | - client->set_recv_timeout(SRS_RECV_TIMEOUT_US); | ||
| 239 | - client->set_send_timeout(SRS_SEND_TIMEOUT_US); | ||
| 240 | - | ||
| 241 | - if ((ret = connect_server()) != ERROR_SUCCESS) { | ||
| 242 | - return ret; | ||
| 243 | - } | ||
| 244 | - srs_assert(client); | ||
| 245 | - | ||
| 246 | - if ((ret = client->handshake()) != ERROR_SUCCESS) { | ||
| 247 | - srs_error("handshake with server failed. ret=%d", ret); | ||
| 248 | - return ret; | ||
| 249 | - } | ||
| 250 | - if ((ret = client->connect_app(app, tc_url)) != ERROR_SUCCESS) { | ||
| 251 | - srs_error("connect with server failed, tcUrl=%s. ret=%d", tc_url.c_str(), ret); | ||
| 252 | - return ret; | ||
| 253 | - } | ||
| 254 | - if ((ret = client->create_stream(stream_id)) != ERROR_SUCCESS) { | ||
| 255 | - srs_error("connect with server failed, stream_id=%d. ret=%d", stream_id, ret); | ||
| 256 | - return ret; | ||
| 257 | - } | ||
| 258 | - | ||
| 259 | - // TODO: FIXME: need to cache the metadata and sequence header when reconnect. | ||
| 260 | - | ||
| 261 | - if ((ret = client->publish(stream_name, stream_id)) != ERROR_SUCCESS) { | ||
| 262 | - srs_error("connect with server failed, stream_name=%s, stream_id=%d. ret=%d", | ||
| 263 | - stream_name.c_str(), stream_id, ret); | ||
| 264 | - return ret; | ||
| 265 | - } | ||
| 266 | - | ||
| 267 | - if ((ret = forward()) != ERROR_SUCCESS) { | ||
| 268 | - return ret; | ||
| 269 | - } | ||
| 270 | - | ||
| 271 | - return ret; | ||
| 272 | -} | ||
| 273 | - | ||
| 274 | -int SrsForwarder::forward() | ||
| 275 | -{ | ||
| 276 | - int ret = ERROR_SUCCESS; | ||
| 277 | - | ||
| 278 | - client->set_recv_timeout(SRS_PULSE_TIMEOUT_MS * 1000); | ||
| 279 | - | ||
| 280 | - SrsPithyPrint pithy_print(SRS_STAGE_FORWARDER); | ||
| 281 | - | ||
| 282 | - while (loop) { | ||
| 283 | - pithy_print.elapse(SRS_PULSE_TIMEOUT_MS); | ||
| 284 | - | ||
| 285 | - // switch to other st-threads. | ||
| 286 | - st_usleep(0); | ||
| 287 | - | ||
| 288 | - // read from client. | ||
| 289 | - if (true) { | ||
| 290 | - SrsCommonMessage* msg = NULL; | ||
| 291 | - ret = client->recv_message(&msg); | ||
| 292 | - | ||
| 293 | - srs_verbose("play loop recv message. ret=%d", ret); | ||
| 294 | - if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) { | ||
| 295 | - srs_error("recv server control message failed. ret=%d", ret); | ||
| 296 | - return ret; | ||
| 297 | - } | ||
| 298 | - } | ||
| 299 | - | ||
| 300 | - // ignore when no messages. | ||
| 301 | - int count = (int)msgs.size(); | ||
| 302 | - if (msgs.empty()) { | ||
| 303 | - continue; | ||
| 304 | - } | ||
| 305 | - | ||
| 306 | - // reportable | ||
| 307 | - if (pithy_print.can_print()) { | ||
| 308 | - srs_trace("-> time=%"PRId64", msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d", | ||
| 309 | - pithy_print.get_age(), count, client->get_send_bytes(), client->get_recv_bytes(), client->get_send_kbps(), client->get_recv_kbps()); | ||
| 310 | - } | ||
| 311 | - | ||
| 312 | - // all msgs to forward. | ||
| 313 | - int i = 0; | ||
| 314 | - for (i = 0; i < count; i++) { | ||
| 315 | - SrsSharedPtrMessage* msg = msgs[i]; | ||
| 316 | - msgs[i] = NULL; | ||
| 317 | - | ||
| 318 | - // we erased the sendout messages, the msg must not be NULL. | ||
| 319 | - srs_assert(msg); | ||
| 320 | - | ||
| 321 | - ret = client->send_message(msg); | ||
| 322 | - if (ret != ERROR_SUCCESS) { | ||
| 323 | - srs_error("forwarder send message to server failed. ret=%d", ret); | ||
| 324 | - | ||
| 325 | - // convert the index to count when error. | ||
| 326 | - i++; | ||
| 327 | - | ||
| 328 | - break; | ||
| 329 | - } | ||
| 330 | - } | ||
| 331 | - | ||
| 332 | - // clear sendout mesages. | ||
| 333 | - if (i < count) { | ||
| 334 | - srs_warn("clear forwarded msg, total=%d, forwarded=%d, ret=%d", count, i, ret); | ||
| 335 | - } else { | ||
| 336 | - srs_info("clear forwarded msg, total=%d, forwarded=%d, ret=%d", count, i, ret); | ||
| 337 | - } | ||
| 338 | - msgs.erase(msgs.begin(), msgs.begin() + i); | ||
| 339 | - | ||
| 340 | - if (ret != ERROR_SUCCESS) { | ||
| 341 | - break; | ||
| 342 | - } | ||
| 343 | - } | ||
| 344 | - | ||
| 345 | - return ret; | ||
| 346 | -} | ||
| 347 | - | ||
| 348 | -void SrsForwarder::forward_cycle() | ||
| 349 | -{ | ||
| 350 | - int ret = ERROR_SUCCESS; | ||
| 351 | - | ||
| 352 | - log_context->generate_id(); | ||
| 353 | - srs_trace("forward cycle start"); | ||
| 354 | - | ||
| 355 | - while (loop) { | ||
| 356 | - if ((ret = cycle()) != ERROR_SUCCESS) { | ||
| 357 | - srs_warn("forward cycle failed, ignored and retry, ret=%d", ret); | ||
| 358 | - } else { | ||
| 359 | - srs_info("forward cycle success, retry"); | ||
| 360 | - } | ||
| 361 | - | ||
| 362 | - if (!loop) { | ||
| 363 | - break; | ||
| 364 | - } | ||
| 365 | - | ||
| 366 | - st_usleep(SRS_FORWARDER_SLEEP_MS * 1000); | ||
| 367 | - | ||
| 368 | - if ((ret = open_socket()) != ERROR_SUCCESS) { | ||
| 369 | - srs_warn("forward cycle reopen failed, ignored and retry, ret=%d", ret); | ||
| 370 | - } else { | ||
| 371 | - srs_info("forward cycle reopen success"); | ||
| 372 | - } | ||
| 373 | - } | ||
| 374 | - srs_trace("forward cycle finished"); | ||
| 375 | -} | ||
| 376 | - | ||
| 377 | -void* SrsForwarder::forward_thread(void* arg) | ||
| 378 | -{ | ||
| 379 | - SrsForwarder* obj = (SrsForwarder*)arg; | ||
| 380 | - srs_assert(obj != NULL); | ||
| 381 | - | ||
| 382 | - obj->loop = true; | ||
| 383 | - obj->forward_cycle(); | ||
| 384 | - | ||
| 385 | - return NULL; | ||
| 386 | -} | ||
| 387 | - | 1 | +/* |
| 2 | +The MIT License (MIT) | ||
| 3 | + | ||
| 4 | +Copyright (c) 2013 winlin | ||
| 5 | + | ||
| 6 | +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 | +the Software without restriction, including without limitation the rights to | ||
| 9 | +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||
| 10 | +the Software, and to permit persons to whom the Software is furnished to do so, | ||
| 11 | +subject to the following conditions: | ||
| 12 | + | ||
| 13 | +The above copyright notice and this permission notice shall be included in all | ||
| 14 | +copies or substantial portions of the Software. | ||
| 15 | + | ||
| 16 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||
| 18 | +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||
| 19 | +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||
| 20 | +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 21 | +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | +*/ | ||
| 23 | + | ||
| 24 | +#include <srs_core_forward.hpp> | ||
| 25 | + | ||
| 26 | +#include <stdlib.h> | ||
| 27 | +#include <sys/socket.h> | ||
| 28 | +#include <netinet/in.h> | ||
| 29 | +#include <arpa/inet.h> | ||
| 30 | + | ||
| 31 | +#include <srs_core_error.hpp> | ||
| 32 | +#include <srs_core_rtmp.hpp> | ||
| 33 | +#include <srs_core_log.hpp> | ||
| 34 | +#include <srs_core_protocol.hpp> | ||
| 35 | +#include <srs_core_pithy_print.hpp> | ||
| 36 | +#include <srs_core_rtmp.hpp> | ||
| 37 | +#include <srs_core_config.hpp> | ||
| 38 | + | ||
| 39 | +#define SRS_PULSE_TIMEOUT_MS 100 | ||
| 40 | +#define SRS_FORWARDER_SLEEP_MS 2000 | ||
| 41 | +#define SRS_SEND_TIMEOUT_US 3000000L | ||
| 42 | +#define SRS_RECV_TIMEOUT_US SRS_SEND_TIMEOUT_US | ||
| 43 | + | ||
| 44 | +SrsForwarder::SrsForwarder() | ||
| 45 | +{ | ||
| 46 | + client = NULL; | ||
| 47 | + stfd = NULL; | ||
| 48 | + stream_id = 0; | ||
| 49 | + | ||
| 50 | + pthread = new SrsThread(this, SRS_FORWARDER_SLEEP_MS); | ||
| 51 | +} | ||
| 52 | + | ||
| 53 | +SrsForwarder::~SrsForwarder() | ||
| 54 | +{ | ||
| 55 | + on_unpublish(); | ||
| 56 | + | ||
| 57 | + std::vector<SrsSharedPtrMessage*>::iterator it; | ||
| 58 | + for (it = msgs.begin(); it != msgs.end(); ++it) { | ||
| 59 | + SrsSharedPtrMessage* msg = *it; | ||
| 60 | + srs_freep(msg); | ||
| 61 | + } | ||
| 62 | + msgs.clear(); | ||
| 63 | + | ||
| 64 | + srs_freep(pthread); | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | +int SrsForwarder::on_publish(SrsRequest* req, std::string forward_server) | ||
| 68 | +{ | ||
| 69 | + int ret = ERROR_SUCCESS; | ||
| 70 | + | ||
| 71 | + // forward app | ||
| 72 | + app = req->app; | ||
| 73 | + | ||
| 74 | + stream_name = req->stream; | ||
| 75 | + server = forward_server; | ||
| 76 | + std::string s_port = RTMP_DEFAULT_PORTS; | ||
| 77 | + port = RTMP_DEFAULT_PORT; | ||
| 78 | + | ||
| 79 | + size_t pos = forward_server.find(":"); | ||
| 80 | + if (pos != std::string::npos) { | ||
| 81 | + s_port = forward_server.substr(pos + 1); | ||
| 82 | + server = forward_server.substr(0, pos); | ||
| 83 | + } | ||
| 84 | + // discovery vhost | ||
| 85 | + std::string vhost = req->vhost; | ||
| 86 | + srs_vhost_resolve(vhost, s_port); | ||
| 87 | + port = ::atoi(s_port.c_str()); | ||
| 88 | + | ||
| 89 | + // generate tcUrl | ||
| 90 | + tc_url = "rtmp://"; | ||
| 91 | + tc_url += vhost; | ||
| 92 | + tc_url += "/"; | ||
| 93 | + tc_url += req->app; | ||
| 94 | + | ||
| 95 | + // dead loop check | ||
| 96 | + std::string source_ep = req->vhost; | ||
| 97 | + source_ep += ":"; | ||
| 98 | + source_ep += req->port; | ||
| 99 | + | ||
| 100 | + std::string dest_ep = vhost; | ||
| 101 | + dest_ep += ":"; | ||
| 102 | + dest_ep += s_port; | ||
| 103 | + | ||
| 104 | + if (source_ep == dest_ep) { | ||
| 105 | + ret = ERROR_SYSTEM_FORWARD_LOOP; | ||
| 106 | + srs_warn("farder loop detected. src=%s, dest=%s, ret=%d", | ||
| 107 | + source_ep.c_str(), dest_ep.c_str(), ret); | ||
| 108 | + return ret; | ||
| 109 | + } | ||
| 110 | + srs_trace("start forward %s to %s, stream: %s/%s", | ||
| 111 | + source_ep.c_str(), dest_ep.c_str(), tc_url.c_str(), | ||
| 112 | + stream_name.c_str()); | ||
| 113 | + | ||
| 114 | + if ((ret = pthread->start()) != ERROR_SUCCESS) { | ||
| 115 | + srs_error("start srs thread failed. ret=%d", ret); | ||
| 116 | + return ret; | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + return ret; | ||
| 120 | +} | ||
| 121 | + | ||
| 122 | +void SrsForwarder::on_unpublish() | ||
| 123 | +{ | ||
| 124 | + pthread->stop(); | ||
| 125 | + | ||
| 126 | + close_underlayer_socket(); | ||
| 127 | + | ||
| 128 | + srs_freep(client); | ||
| 129 | +} | ||
| 130 | + | ||
| 131 | +int SrsForwarder::on_meta_data(SrsSharedPtrMessage* metadata) | ||
| 132 | +{ | ||
| 133 | + int ret = ERROR_SUCCESS; | ||
| 134 | + | ||
| 135 | + msgs.push_back(metadata); | ||
| 136 | + | ||
| 137 | + return ret; | ||
| 138 | +} | ||
| 139 | + | ||
| 140 | +int SrsForwarder::on_audio(SrsSharedPtrMessage* msg) | ||
| 141 | +{ | ||
| 142 | + int ret = ERROR_SUCCESS; | ||
| 143 | + | ||
| 144 | + // TODO: FIXME: must drop the msgs when server failed. | ||
| 145 | + msgs.push_back(msg); | ||
| 146 | + | ||
| 147 | + return ret; | ||
| 148 | +} | ||
| 149 | + | ||
| 150 | +int SrsForwarder::on_video(SrsSharedPtrMessage* msg) | ||
| 151 | +{ | ||
| 152 | + int ret = ERROR_SUCCESS; | ||
| 153 | + | ||
| 154 | + // TODO: FIXME: must drop the msgs when server failed. | ||
| 155 | + msgs.push_back(msg); | ||
| 156 | + | ||
| 157 | + return ret; | ||
| 158 | +} | ||
| 159 | + | ||
| 160 | +int SrsForwarder::cycle() | ||
| 161 | +{ | ||
| 162 | + int ret = ERROR_SUCCESS; | ||
| 163 | + | ||
| 164 | + if ((ret = connect_server()) != ERROR_SUCCESS) { | ||
| 165 | + return ret; | ||
| 166 | + } | ||
| 167 | + srs_assert(client); | ||
| 168 | + | ||
| 169 | + client->set_recv_timeout(SRS_RECV_TIMEOUT_US); | ||
| 170 | + client->set_send_timeout(SRS_SEND_TIMEOUT_US); | ||
| 171 | + | ||
| 172 | + if ((ret = client->handshake()) != ERROR_SUCCESS) { | ||
| 173 | + srs_error("handshake with server failed. ret=%d", ret); | ||
| 174 | + return ret; | ||
| 175 | + } | ||
| 176 | + if ((ret = client->connect_app(app, tc_url)) != ERROR_SUCCESS) { | ||
| 177 | + srs_error("connect with server failed, tcUrl=%s. ret=%d", tc_url.c_str(), ret); | ||
| 178 | + return ret; | ||
| 179 | + } | ||
| 180 | + if ((ret = client->create_stream(stream_id)) != ERROR_SUCCESS) { | ||
| 181 | + srs_error("connect with server failed, stream_id=%d. ret=%d", stream_id, ret); | ||
| 182 | + return ret; | ||
| 183 | + } | ||
| 184 | + | ||
| 185 | + // TODO: FIXME: need to cache the metadata and sequence header when reconnect. | ||
| 186 | + | ||
| 187 | + if ((ret = client->publish(stream_name, stream_id)) != ERROR_SUCCESS) { | ||
| 188 | + srs_error("connect with server failed, stream_name=%s, stream_id=%d. ret=%d", | ||
| 189 | + stream_name.c_str(), stream_id, ret); | ||
| 190 | + return ret; | ||
| 191 | + } | ||
| 192 | + | ||
| 193 | + if ((ret = forward()) != ERROR_SUCCESS) { | ||
| 194 | + return ret; | ||
| 195 | + } | ||
| 196 | + | ||
| 197 | + return ret; | ||
| 198 | +} | ||
| 199 | + | ||
| 200 | +void SrsForwarder::close_underlayer_socket() | ||
| 201 | +{ | ||
| 202 | + srs_close_stfd(stfd); | ||
| 203 | +} | ||
| 204 | + | ||
| 205 | +int SrsForwarder::connect_server() | ||
| 206 | +{ | ||
| 207 | + int ret = ERROR_SUCCESS; | ||
| 208 | + | ||
| 209 | + // reopen | ||
| 210 | + close_underlayer_socket(); | ||
| 211 | + | ||
| 212 | + // open socket. | ||
| 213 | + srs_trace("forward stream=%s, tcUrl=%s to server=%s, port=%d", | ||
| 214 | + stream_name.c_str(), tc_url.c_str(), server.c_str(), port); | ||
| 215 | + | ||
| 216 | + int sock = socket(AF_INET, SOCK_STREAM, 0); | ||
| 217 | + if(sock == -1){ | ||
| 218 | + ret = ERROR_SOCKET_CREATE; | ||
| 219 | + srs_error("create socket error. ret=%d", ret); | ||
| 220 | + return ret; | ||
| 221 | + } | ||
| 222 | + | ||
| 223 | + srs_assert(!stfd); | ||
| 224 | + stfd = st_netfd_open_socket(sock); | ||
| 225 | + if(stfd == NULL){ | ||
| 226 | + ret = ERROR_ST_OPEN_SOCKET; | ||
| 227 | + srs_error("st_netfd_open_socket failed. ret=%d", ret); | ||
| 228 | + return ret; | ||
| 229 | + } | ||
| 230 | + | ||
| 231 | + srs_freep(client); | ||
| 232 | + client = new SrsRtmpClient(stfd); | ||
| 233 | + | ||
| 234 | + // connect to server. | ||
| 235 | + std::string ip = srs_dns_resolve(server); | ||
| 236 | + if (ip.empty()) { | ||
| 237 | + ret = ERROR_SYSTEM_IP_INVALID; | ||
| 238 | + srs_error("dns resolve server error, ip empty. ret=%d", ret); | ||
| 239 | + return ret; | ||
| 240 | + } | ||
| 241 | + | ||
| 242 | + sockaddr_in addr; | ||
| 243 | + addr.sin_family = AF_INET; | ||
| 244 | + addr.sin_port = htons(port); | ||
| 245 | + addr.sin_addr.s_addr = inet_addr(ip.c_str()); | ||
| 246 | + | ||
| 247 | + if (st_connect(stfd, (const struct sockaddr*)&addr, sizeof(sockaddr_in), ST_UTIME_NO_TIMEOUT) == -1){ | ||
| 248 | + ret = ERROR_ST_CONNECT; | ||
| 249 | + srs_error("connect to server error. ip=%s, port=%d, ret=%d", ip.c_str(), port, ret); | ||
| 250 | + return ret; | ||
| 251 | + } | ||
| 252 | + srs_trace("connect to server success. server=%s, ip=%s, port=%d", server.c_str(), ip.c_str(), port); | ||
| 253 | + | ||
| 254 | + return ret; | ||
| 255 | +} | ||
| 256 | + | ||
| 257 | +int SrsForwarder::forward() | ||
| 258 | +{ | ||
| 259 | + int ret = ERROR_SUCCESS; | ||
| 260 | + | ||
| 261 | + client->set_recv_timeout(SRS_PULSE_TIMEOUT_MS * 1000); | ||
| 262 | + | ||
| 263 | + SrsPithyPrint pithy_print(SRS_STAGE_FORWARDER); | ||
| 264 | + | ||
| 265 | + while (true) { | ||
| 266 | + // switch to other st-threads. | ||
| 267 | + st_usleep(0); | ||
| 268 | + | ||
| 269 | + // read from client. | ||
| 270 | + if (true) { | ||
| 271 | + SrsCommonMessage* msg = NULL; | ||
| 272 | + ret = client->recv_message(&msg); | ||
| 273 | + | ||
| 274 | + srs_verbose("play loop recv message. ret=%d", ret); | ||
| 275 | + if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) { | ||
| 276 | + srs_error("recv server control message failed. ret=%d", ret); | ||
| 277 | + return ret; | ||
| 278 | + } | ||
| 279 | + } | ||
| 280 | + | ||
| 281 | + // ignore when no messages. | ||
| 282 | + int count = (int)msgs.size(); | ||
| 283 | + if (msgs.empty()) { | ||
| 284 | + continue; | ||
| 285 | + } | ||
| 286 | + | ||
| 287 | + // pithy print | ||
| 288 | + pithy_print.elapse(SRS_PULSE_TIMEOUT_MS); | ||
| 289 | + if (pithy_print.can_print()) { | ||
| 290 | + srs_trace("-> time=%"PRId64", msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d", | ||
| 291 | + pithy_print.get_age(), count, client->get_send_bytes(), client->get_recv_bytes(), client->get_send_kbps(), client->get_recv_kbps()); | ||
| 292 | + } | ||
| 293 | + | ||
| 294 | + // all msgs to forward. | ||
| 295 | + int i = 0; | ||
| 296 | + for (i = 0; i < count; i++) { | ||
| 297 | + SrsSharedPtrMessage* msg = msgs[i]; | ||
| 298 | + msgs[i] = NULL; | ||
| 299 | + | ||
| 300 | + // we erased the sendout messages, the msg must not be NULL. | ||
| 301 | + srs_assert(msg); | ||
| 302 | + | ||
| 303 | + ret = client->send_message(msg); | ||
| 304 | + if (ret != ERROR_SUCCESS) { | ||
| 305 | + srs_error("forwarder send message to server failed. ret=%d", ret); | ||
| 306 | + | ||
| 307 | + // convert the index to count when error. | ||
| 308 | + i++; | ||
| 309 | + | ||
| 310 | + break; | ||
| 311 | + } | ||
| 312 | + } | ||
| 313 | + | ||
| 314 | + // clear sendout mesages. | ||
| 315 | + if (i < count) { | ||
| 316 | + srs_warn("clear forwarded msg, total=%d, forwarded=%d, ret=%d", count, i, ret); | ||
| 317 | + } else { | ||
| 318 | + srs_info("clear forwarded msg, total=%d, forwarded=%d, ret=%d", count, i, ret); | ||
| 319 | + } | ||
| 320 | + msgs.erase(msgs.begin(), msgs.begin() + i); | ||
| 321 | + | ||
| 322 | + if (ret != ERROR_SUCCESS) { | ||
| 323 | + break; | ||
| 324 | + } | ||
| 325 | + } | ||
| 326 | + | ||
| 327 | + return ret; | ||
| 328 | +} | ||
| 329 | + |
| @@ -32,7 +32,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -32,7 +32,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 32 | #include <string> | 32 | #include <string> |
| 33 | #include <vector> | 33 | #include <vector> |
| 34 | 34 | ||
| 35 | -#include <st.h> | 35 | +#include <srs_core_thread.hpp> |
| 36 | 36 | ||
| 37 | class SrsSharedPtrMessage; | 37 | class SrsSharedPtrMessage; |
| 38 | class SrsOnMetaDataPacket; | 38 | class SrsOnMetaDataPacket; |
| @@ -42,7 +42,7 @@ class SrsRequest; | @@ -42,7 +42,7 @@ class SrsRequest; | ||
| 42 | /** | 42 | /** |
| 43 | * forward the stream to other servers. | 43 | * forward the stream to other servers. |
| 44 | */ | 44 | */ |
| 45 | -class SrsForwarder | 45 | +class SrsForwarder : public ISrsThreadHandler |
| 46 | { | 46 | { |
| 47 | private: | 47 | private: |
| 48 | std::string app; | 48 | std::string app; |
| @@ -53,8 +53,7 @@ private: | @@ -53,8 +53,7 @@ private: | ||
| 53 | int port; | 53 | int port; |
| 54 | private: | 54 | private: |
| 55 | st_netfd_t stfd; | 55 | st_netfd_t stfd; |
| 56 | - st_thread_t tid; | ||
| 57 | - bool loop; | 56 | + SrsThread* pthread; |
| 58 | private: | 57 | private: |
| 59 | SrsRtmpClient* client; | 58 | SrsRtmpClient* client; |
| 60 | std::vector<SrsSharedPtrMessage*> msgs; | 59 | std::vector<SrsSharedPtrMessage*> msgs; |
| @@ -67,14 +66,13 @@ public: | @@ -67,14 +66,13 @@ public: | ||
| 67 | virtual int on_meta_data(SrsSharedPtrMessage* metadata); | 66 | virtual int on_meta_data(SrsSharedPtrMessage* metadata); |
| 68 | virtual int on_audio(SrsSharedPtrMessage* msg); | 67 | virtual int on_audio(SrsSharedPtrMessage* msg); |
| 69 | virtual int on_video(SrsSharedPtrMessage* msg); | 68 | virtual int on_video(SrsSharedPtrMessage* msg); |
| 69 | +// interface ISrsThreadHandler. | ||
| 70 | +public: | ||
| 71 | + virtual int cycle(); | ||
| 70 | private: | 72 | private: |
| 71 | - virtual int open_socket(); | 73 | + virtual void close_underlayer_socket(); |
| 72 | virtual int connect_server(); | 74 | virtual int connect_server(); |
| 73 | -private: | ||
| 74 | - virtual int cycle(); | ||
| 75 | virtual int forward(); | 75 | virtual int forward(); |
| 76 | - virtual void forward_cycle(); | ||
| 77 | - static void* forward_thread(void* arg); | ||
| 78 | }; | 76 | }; |
| 79 | 77 | ||
| 80 | #endif | 78 | #endif |
| @@ -184,15 +184,7 @@ void SrsHttpClient::disconnect() | @@ -184,15 +184,7 @@ void SrsHttpClient::disconnect() | ||
| 184 | { | 184 | { |
| 185 | connected = false; | 185 | connected = false; |
| 186 | 186 | ||
| 187 | - if (stfd) { | ||
| 188 | - int fd = st_netfd_fileno(stfd); | ||
| 189 | - st_netfd_close(stfd); | ||
| 190 | - stfd = NULL; | ||
| 191 | - | ||
| 192 | - // st does not close it sometimes, | ||
| 193 | - // close it manually. | ||
| 194 | - ::close(fd); | ||
| 195 | - } | 187 | + srs_close_stfd(stfd); |
| 196 | } | 188 | } |
| 197 | 189 | ||
| 198 | int SrsHttpClient::connect(SrsHttpUri* uri) | 190 | int SrsHttpClient::connect(SrsHttpUri* uri) |
| @@ -29,8 +29,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -29,8 +29,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 29 | #include <string> | 29 | #include <string> |
| 30 | #include <map> | 30 | #include <map> |
| 31 | 31 | ||
| 32 | -#include <st.h> | ||
| 33 | - | ||
| 34 | ILogContext::ILogContext() | 32 | ILogContext::ILogContext() |
| 35 | { | 33 | { |
| 36 | } | 34 | } |
| @@ -33,8 +33,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -33,8 +33,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 33 | #include <map> | 33 | #include <map> |
| 34 | #include <string> | 34 | #include <string> |
| 35 | 35 | ||
| 36 | -#include <st.h> | ||
| 37 | - | ||
| 38 | #include <srs_core_log.hpp> | 36 | #include <srs_core_log.hpp> |
| 39 | #include <srs_core_error.hpp> | 37 | #include <srs_core_error.hpp> |
| 40 | 38 |
trunk/src/core/srs_core_rtmp.cpp
100755 → 100644
| 1 | -/* | ||
| 2 | -The MIT License (MIT) | ||
| 3 | - | ||
| 4 | -Copyright (c) 2013 winlin | ||
| 5 | - | ||
| 6 | -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 | -the Software without restriction, including without limitation the rights to | ||
| 9 | -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||
| 10 | -the Software, and to permit persons to whom the Software is furnished to do so, | ||
| 11 | -subject to the following conditions: | ||
| 12 | - | ||
| 13 | -The above copyright notice and this permission notice shall be included in all | ||
| 14 | -copies or substantial portions of the Software. | ||
| 15 | - | ||
| 16 | -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||
| 18 | -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||
| 19 | -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||
| 20 | -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 21 | -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | -*/ | ||
| 23 | - | ||
| 24 | -#include <srs_core_rtmp.hpp> | ||
| 25 | - | ||
| 26 | -#include <srs_core_log.hpp> | ||
| 27 | -#include <srs_core_error.hpp> | ||
| 28 | -#include <srs_core_socket.hpp> | ||
| 29 | -#include <srs_core_protocol.hpp> | ||
| 30 | -#include <srs_core_autofree.hpp> | ||
| 31 | -#include <srs_core_amf0.hpp> | ||
| 32 | -#include <srs_core_handshake.hpp> | ||
| 33 | -#include <srs_core_config.hpp> | ||
| 34 | - | ||
| 35 | -/** | ||
| 36 | -* the signature for packets to client. | ||
| 37 | -*/ | ||
| 38 | -#define RTMP_SIG_FMS_VER "3,5,3,888" | ||
| 39 | -#define RTMP_SIG_AMF0_VER 0 | ||
| 40 | -#define RTMP_SIG_CLIENT_ID "ASAICiss" | ||
| 41 | - | ||
| 42 | -/** | ||
| 43 | -* onStatus consts. | ||
| 44 | -*/ | ||
| 45 | -#define StatusLevel "level" | ||
| 46 | -#define StatusCode "code" | ||
| 47 | -#define StatusDescription "description" | ||
| 48 | -#define StatusDetails "details" | ||
| 49 | -#define StatusClientId "clientid" | ||
| 50 | -// status value | ||
| 51 | -#define StatusLevelStatus "status" | ||
| 52 | -// code value | ||
| 53 | -#define StatusCodeConnectSuccess "NetConnection.Connect.Success" | ||
| 54 | -#define StatusCodeStreamReset "NetStream.Play.Reset" | ||
| 55 | -#define StatusCodeStreamStart "NetStream.Play.Start" | ||
| 56 | -#define StatusCodeStreamPause "NetStream.Pause.Notify" | ||
| 57 | -#define StatusCodeStreamUnpause "NetStream.Unpause.Notify" | ||
| 58 | -#define StatusCodePublishStart "NetStream.Publish.Start" | ||
| 59 | -#define StatusCodeDataStart "NetStream.Data.Start" | ||
| 60 | -#define StatusCodeUnpublishSuccess "NetStream.Unpublish.Success" | ||
| 61 | - | ||
| 62 | -// FMLE | ||
| 63 | -#define RTMP_AMF0_COMMAND_ON_FC_PUBLISH "onFCPublish" | ||
| 64 | -#define RTMP_AMF0_COMMAND_ON_FC_UNPUBLISH "onFCUnpublish" | ||
| 65 | - | ||
| 66 | -// default stream id for response the createStream request. | ||
| 67 | -#define SRS_DEFAULT_SID 1 | ||
| 68 | - | ||
| 69 | -SrsRequest::SrsRequest() | ||
| 70 | -{ | ||
| 71 | - objectEncoding = RTMP_SIG_AMF0_VER; | ||
| 72 | -} | ||
| 73 | - | ||
| 74 | -SrsRequest::~SrsRequest() | ||
| 75 | -{ | ||
| 76 | -} | ||
| 77 | - | ||
| 78 | -int SrsRequest::discovery_app() | ||
| 79 | -{ | ||
| 80 | - int ret = ERROR_SUCCESS; | ||
| 81 | - | ||
| 82 | - size_t pos = std::string::npos; | ||
| 83 | - std::string url = tcUrl; | ||
| 84 | - | ||
| 85 | - if ((pos = url.find("://")) != std::string::npos) { | ||
| 86 | - schema = url.substr(0, pos); | ||
| 87 | - url = url.substr(schema.length() + 3); | ||
| 88 | - srs_verbose("discovery schema=%s", schema.c_str()); | ||
| 89 | - } | ||
| 90 | - | ||
| 91 | - if ((pos = url.find("/")) != std::string::npos) { | ||
| 92 | - vhost = url.substr(0, pos); | ||
| 93 | - url = url.substr(vhost.length() + 1); | ||
| 94 | - srs_verbose("discovery vhost=%s", vhost.c_str()); | ||
| 95 | - } | ||
| 96 | - | ||
| 97 | - port = RTMP_DEFAULT_PORTS; | ||
| 98 | - if ((pos = vhost.find(":")) != std::string::npos) { | ||
| 99 | - port = vhost.substr(pos + 1); | ||
| 100 | - vhost = vhost.substr(0, pos); | ||
| 101 | - srs_verbose("discovery vhost=%s, port=%s", vhost.c_str(), port.c_str()); | ||
| 102 | - } | ||
| 103 | - | ||
| 104 | - app = url; | ||
| 105 | - srs_vhost_resolve(vhost, app); | ||
| 106 | - | ||
| 107 | - // resolve the vhost from config | ||
| 108 | - SrsConfDirective* parsed_vhost = config->get_vhost(vhost); | ||
| 109 | - if (parsed_vhost) { | ||
| 110 | - vhost = parsed_vhost->arg0(); | ||
| 111 | - } | ||
| 112 | - | ||
| 113 | - // TODO: discovery the params of vhost. | ||
| 114 | - | ||
| 115 | - srs_info("discovery app success. schema=%s, vhost=%s, port=%s, app=%s", | ||
| 116 | - schema.c_str(), vhost.c_str(), port.c_str(), app.c_str()); | ||
| 117 | - | ||
| 118 | - if (schema.empty() || vhost.empty() || port.empty() || app.empty()) { | ||
| 119 | - ret = ERROR_RTMP_REQ_TCURL; | ||
| 120 | - srs_error("discovery tcUrl failed. " | ||
| 121 | - "tcUrl=%s, schema=%s, vhost=%s, port=%s, app=%s, ret=%d", | ||
| 122 | - tcUrl.c_str(), schema.c_str(), vhost.c_str(), port.c_str(), app.c_str(), ret); | ||
| 123 | - return ret; | ||
| 124 | - } | ||
| 125 | - | ||
| 126 | - strip(); | ||
| 127 | - | ||
| 128 | - return ret; | ||
| 129 | -} | ||
| 130 | - | ||
| 131 | -std::string SrsRequest::get_stream_url() | ||
| 132 | -{ | ||
| 133 | - std::string url = ""; | ||
| 134 | - | ||
| 135 | - url += vhost; | ||
| 136 | - url += "/"; | ||
| 137 | - url += app; | ||
| 138 | - url += "/"; | ||
| 139 | - url += stream; | ||
| 140 | - | ||
| 141 | - return url; | ||
| 142 | -} | ||
| 143 | - | ||
| 144 | -void SrsRequest::strip() | ||
| 145 | -{ | ||
| 146 | - trim(vhost, "/ \n\r\t"); | ||
| 147 | - trim(app, "/ \n\r\t"); | ||
| 148 | - trim(stream, "/ \n\r\t"); | ||
| 149 | -} | ||
| 150 | - | ||
| 151 | -std::string& SrsRequest::trim(std::string& str, std::string chs) | ||
| 152 | -{ | ||
| 153 | - for (int i = 0; i < (int)chs.length(); i++) { | ||
| 154 | - char ch = chs.at(i); | ||
| 155 | - | ||
| 156 | - for (std::string::iterator it = str.begin(); it != str.end();) { | ||
| 157 | - if (ch == *it) { | ||
| 158 | - it = str.erase(it); | ||
| 159 | - } else { | ||
| 160 | - ++it; | ||
| 161 | - } | ||
| 162 | - } | ||
| 163 | - } | ||
| 164 | - | ||
| 165 | - return str; | ||
| 166 | -} | ||
| 167 | - | ||
| 168 | -SrsResponse::SrsResponse() | ||
| 169 | -{ | ||
| 170 | - stream_id = SRS_DEFAULT_SID; | ||
| 171 | -} | ||
| 172 | - | ||
| 173 | -SrsResponse::~SrsResponse() | ||
| 174 | -{ | ||
| 175 | -} | ||
| 176 | - | ||
| 177 | -SrsRtmpClient::SrsRtmpClient(st_netfd_t _stfd) | ||
| 178 | -{ | ||
| 179 | - stfd = _stfd; | ||
| 180 | - protocol = new SrsProtocol(stfd); | ||
| 181 | -} | ||
| 182 | - | ||
| 183 | -SrsRtmpClient::~SrsRtmpClient() | ||
| 184 | -{ | ||
| 185 | - srs_freep(protocol); | ||
| 186 | -} | ||
| 187 | - | ||
| 188 | -void SrsRtmpClient::set_recv_timeout(int64_t timeout_us) | ||
| 189 | -{ | ||
| 190 | - protocol->set_recv_timeout(timeout_us); | ||
| 191 | -} | ||
| 192 | - | ||
| 193 | -void SrsRtmpClient::set_send_timeout(int64_t timeout_us) | ||
| 194 | -{ | ||
| 195 | - protocol->set_send_timeout(timeout_us); | ||
| 196 | -} | ||
| 197 | - | ||
| 198 | -int64_t SrsRtmpClient::get_recv_bytes() | ||
| 199 | -{ | ||
| 200 | - return protocol->get_recv_bytes(); | ||
| 201 | -} | ||
| 202 | - | ||
| 203 | -int64_t SrsRtmpClient::get_send_bytes() | ||
| 204 | -{ | ||
| 205 | - return protocol->get_send_bytes(); | ||
| 206 | -} | ||
| 207 | - | ||
| 208 | -int SrsRtmpClient::get_recv_kbps() | ||
| 209 | -{ | ||
| 210 | - return protocol->get_recv_kbps(); | ||
| 211 | -} | ||
| 212 | - | ||
| 213 | -int SrsRtmpClient::get_send_kbps() | ||
| 214 | -{ | ||
| 215 | - return protocol->get_send_kbps(); | ||
| 216 | -} | ||
| 217 | - | ||
| 218 | -int SrsRtmpClient::recv_message(SrsCommonMessage** pmsg) | ||
| 219 | -{ | ||
| 220 | - return protocol->recv_message(pmsg); | ||
| 221 | -} | ||
| 222 | - | ||
| 223 | -int SrsRtmpClient::send_message(ISrsMessage* msg) | ||
| 224 | -{ | ||
| 225 | - return protocol->send_message(msg); | ||
| 226 | -} | ||
| 227 | - | ||
| 228 | -int SrsRtmpClient::handshake() | ||
| 229 | -{ | ||
| 230 | - int ret = ERROR_SUCCESS; | ||
| 231 | - | ||
| 232 | - SrsSocket skt(stfd); | ||
| 233 | - | ||
| 234 | - SrsComplexHandshake complex_hs; | ||
| 235 | - SrsSimpleHandshake simple_hs; | ||
| 236 | - if ((ret = simple_hs.handshake_with_server(skt, complex_hs)) != ERROR_SUCCESS) { | ||
| 237 | - return ret; | ||
| 238 | - } | ||
| 239 | - | ||
| 240 | - return ret; | ||
| 241 | -} | ||
| 242 | - | ||
| 243 | -int SrsRtmpClient::connect_app(std::string app, std::string tc_url) | ||
| 244 | -{ | ||
| 245 | - int ret = ERROR_SUCCESS; | ||
| 246 | - | ||
| 247 | - // Connect(vhost, app) | ||
| 248 | - if (true) { | ||
| 249 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 250 | - SrsConnectAppPacket* pkt = new SrsConnectAppPacket(); | ||
| 251 | - msg->set_packet(pkt, 0); | ||
| 252 | - | ||
| 253 | - pkt->command_object = new SrsAmf0Object(); | ||
| 254 | - pkt->command_object->set("app", new SrsAmf0String(app.c_str())); | ||
| 255 | - pkt->command_object->set("swfUrl", new SrsAmf0String()); | ||
| 256 | - pkt->command_object->set("tcUrl", new SrsAmf0String(tc_url.c_str())); | ||
| 257 | - pkt->command_object->set("fpad", new SrsAmf0Boolean(false)); | ||
| 258 | - pkt->command_object->set("capabilities", new SrsAmf0Number(239)); | ||
| 259 | - pkt->command_object->set("audioCodecs", new SrsAmf0Number(3575)); | ||
| 260 | - pkt->command_object->set("videoCodecs", new SrsAmf0Number(252)); | ||
| 261 | - pkt->command_object->set("videoFunction", new SrsAmf0Number(1)); | ||
| 262 | - pkt->command_object->set("pageUrl", new SrsAmf0String()); | ||
| 263 | - pkt->command_object->set("objectEncoding", new SrsAmf0Number(0)); | ||
| 264 | - | ||
| 265 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 266 | - return ret; | ||
| 267 | - } | ||
| 268 | - } | ||
| 269 | - | ||
| 270 | - // Set Window Acknowledgement size(2500000) | ||
| 271 | - if (true) { | ||
| 272 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 273 | - SrsSetWindowAckSizePacket* pkt = new SrsSetWindowAckSizePacket(); | ||
| 274 | - | ||
| 275 | - pkt->ackowledgement_window_size = 2500000; | ||
| 276 | - msg->set_packet(pkt, 0); | ||
| 277 | - | ||
| 278 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 279 | - return ret; | ||
| 280 | - } | ||
| 281 | - } | ||
| 282 | - | ||
| 283 | - // expect connect _result | ||
| 284 | - SrsCommonMessage* msg = NULL; | ||
| 285 | - SrsConnectAppResPacket* pkt = NULL; | ||
| 286 | - if ((ret = srs_rtmp_expect_message<SrsConnectAppResPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) { | ||
| 287 | - srs_error("expect connect app response message failed. ret=%d", ret); | ||
| 288 | - return ret; | ||
| 289 | - } | ||
| 290 | - SrsAutoFree(SrsCommonMessage, msg, false); | ||
| 291 | - srs_info("get connect app response message"); | ||
| 292 | - | ||
| 293 | - return ret; | ||
| 294 | -} | ||
| 295 | - | ||
| 296 | -int SrsRtmpClient::create_stream(int& stream_id) | ||
| 297 | -{ | ||
| 298 | - int ret = ERROR_SUCCESS; | ||
| 299 | - | ||
| 300 | - // CreateStream | ||
| 301 | - if (true) { | ||
| 302 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 303 | - SrsCreateStreamPacket* pkt = new SrsCreateStreamPacket(); | ||
| 304 | - | ||
| 305 | - msg->set_packet(pkt, 0); | ||
| 306 | - | ||
| 307 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 308 | - return ret; | ||
| 309 | - } | ||
| 310 | - } | ||
| 311 | - | ||
| 312 | - // CreateStream _result. | ||
| 313 | - if (true) { | ||
| 314 | - SrsCommonMessage* msg = NULL; | ||
| 315 | - SrsCreateStreamResPacket* pkt = NULL; | ||
| 316 | - if ((ret = srs_rtmp_expect_message<SrsCreateStreamResPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) { | ||
| 317 | - srs_error("expect create stream response message failed. ret=%d", ret); | ||
| 318 | - return ret; | ||
| 319 | - } | ||
| 320 | - SrsAutoFree(SrsCommonMessage, msg, false); | ||
| 321 | - srs_info("get create stream response message"); | ||
| 322 | - | ||
| 323 | - stream_id = (int)pkt->stream_id; | ||
| 324 | - } | ||
| 325 | - | ||
| 326 | - return ret; | ||
| 327 | -} | ||
| 328 | - | ||
| 329 | -int SrsRtmpClient::play(std::string stream, int stream_id) | ||
| 330 | -{ | ||
| 331 | - int ret = ERROR_SUCCESS; | ||
| 332 | - | ||
| 333 | - // Play(stream) | ||
| 334 | - if (true) { | ||
| 335 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 336 | - SrsPlayPacket* pkt = new SrsPlayPacket(); | ||
| 337 | - | ||
| 338 | - pkt->stream_name = stream; | ||
| 339 | - msg->set_packet(pkt, stream_id); | ||
| 340 | - | ||
| 341 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 342 | - srs_error("send play stream failed. " | ||
| 343 | - "stream=%s, stream_id=%d, ret=%d", | ||
| 344 | - stream.c_str(), stream_id, ret); | ||
| 345 | - return ret; | ||
| 346 | - } | ||
| 347 | - } | ||
| 348 | - | ||
| 349 | - // SetBufferLength(1000ms) | ||
| 350 | - int buffer_length_ms = 1000; | ||
| 351 | - if (true) { | ||
| 352 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 353 | - SrsUserControlPacket* pkt = new SrsUserControlPacket(); | ||
| 354 | - | ||
| 355 | - pkt->event_type = SrcPCUCSetBufferLength; | ||
| 356 | - pkt->event_data = stream_id; | ||
| 357 | - pkt->extra_data = buffer_length_ms; | ||
| 358 | - msg->set_packet(pkt, 0); | ||
| 359 | - | ||
| 360 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 361 | - srs_error("send set buffer length failed. " | ||
| 362 | - "stream=%s, stream_id=%d, bufferLength=%d, ret=%d", | ||
| 363 | - stream.c_str(), stream_id, buffer_length_ms, ret); | ||
| 364 | - return ret; | ||
| 365 | - } | ||
| 366 | - } | ||
| 367 | - | ||
| 368 | - return ret; | ||
| 369 | -} | ||
| 370 | - | ||
| 371 | -int SrsRtmpClient::publish(std::string stream, int stream_id) | ||
| 372 | -{ | ||
| 373 | - int ret = ERROR_SUCCESS; | ||
| 374 | - | ||
| 375 | - // publish(stream) | ||
| 376 | - if (true) { | ||
| 377 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 378 | - SrsPublishPacket* pkt = new SrsPublishPacket(); | ||
| 379 | - | ||
| 380 | - pkt->stream_name = stream; | ||
| 381 | - msg->set_packet(pkt, stream_id); | ||
| 382 | - | ||
| 383 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 384 | - srs_error("send publish message failed. " | ||
| 385 | - "stream=%s, stream_id=%d, ret=%d", | ||
| 386 | - stream.c_str(), stream_id, ret); | ||
| 387 | - return ret; | ||
| 388 | - } | ||
| 389 | - } | ||
| 390 | - | ||
| 391 | - return ret; | ||
| 392 | -} | ||
| 393 | - | ||
| 394 | -SrsRtmp::SrsRtmp(st_netfd_t client_stfd) | ||
| 395 | -{ | ||
| 396 | - protocol = new SrsProtocol(client_stfd); | ||
| 397 | - stfd = client_stfd; | ||
| 398 | -} | ||
| 399 | - | ||
| 400 | -SrsRtmp::~SrsRtmp() | ||
| 401 | -{ | ||
| 402 | - srs_freep(protocol); | ||
| 403 | -} | ||
| 404 | - | ||
| 405 | -SrsProtocol* SrsRtmp::get_protocol() | ||
| 406 | -{ | ||
| 407 | - return protocol; | ||
| 408 | -} | ||
| 409 | - | ||
| 410 | -void SrsRtmp::set_recv_timeout(int64_t timeout_us) | ||
| 411 | -{ | ||
| 412 | - protocol->set_recv_timeout(timeout_us); | ||
| 413 | -} | ||
| 414 | - | ||
| 415 | -int64_t SrsRtmp::get_recv_timeout() | ||
| 416 | -{ | ||
| 417 | - return protocol->get_recv_timeout(); | ||
| 418 | -} | ||
| 419 | - | ||
| 420 | -void SrsRtmp::set_send_timeout(int64_t timeout_us) | ||
| 421 | -{ | ||
| 422 | - protocol->set_send_timeout(timeout_us); | ||
| 423 | -} | ||
| 424 | - | ||
| 425 | -int64_t SrsRtmp::get_recv_bytes() | ||
| 426 | -{ | ||
| 427 | - return protocol->get_recv_bytes(); | ||
| 428 | -} | ||
| 429 | - | ||
| 430 | -int64_t SrsRtmp::get_send_bytes() | ||
| 431 | -{ | ||
| 432 | - return protocol->get_send_bytes(); | ||
| 433 | -} | ||
| 434 | - | ||
| 435 | -int SrsRtmp::get_recv_kbps() | ||
| 436 | -{ | ||
| 437 | - return protocol->get_recv_kbps(); | ||
| 438 | -} | ||
| 439 | - | ||
| 440 | -int SrsRtmp::get_send_kbps() | ||
| 441 | -{ | ||
| 442 | - return protocol->get_send_kbps(); | ||
| 443 | -} | ||
| 444 | - | ||
| 445 | -int SrsRtmp::recv_message(SrsCommonMessage** pmsg) | ||
| 446 | -{ | ||
| 447 | - return protocol->recv_message(pmsg); | ||
| 448 | -} | ||
| 449 | - | ||
| 450 | -int SrsRtmp::send_message(ISrsMessage* msg) | ||
| 451 | -{ | ||
| 452 | - return protocol->send_message(msg); | ||
| 453 | -} | ||
| 454 | - | ||
| 455 | -int SrsRtmp::handshake() | ||
| 456 | -{ | ||
| 457 | - int ret = ERROR_SUCCESS; | ||
| 458 | - | ||
| 459 | - SrsSocket skt(stfd); | ||
| 460 | - | ||
| 461 | - SrsComplexHandshake complex_hs; | ||
| 462 | - SrsSimpleHandshake simple_hs; | ||
| 463 | - if ((ret = simple_hs.handshake_with_client(skt, complex_hs)) != ERROR_SUCCESS) { | ||
| 464 | - return ret; | ||
| 465 | - } | ||
| 466 | - | ||
| 467 | - return ret; | ||
| 468 | -} | ||
| 469 | - | ||
| 470 | -int SrsRtmp::connect_app(SrsRequest* req) | ||
| 471 | -{ | ||
| 472 | - int ret = ERROR_SUCCESS; | ||
| 473 | - | ||
| 474 | - SrsCommonMessage* msg = NULL; | ||
| 475 | - SrsConnectAppPacket* pkt = NULL; | ||
| 476 | - if ((ret = srs_rtmp_expect_message<SrsConnectAppPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) { | ||
| 477 | - srs_error("expect connect app message failed. ret=%d", ret); | ||
| 478 | - return ret; | ||
| 479 | - } | ||
| 480 | - SrsAutoFree(SrsCommonMessage, msg, false); | ||
| 481 | - srs_info("get connect app message"); | ||
| 482 | - | ||
| 483 | - SrsAmf0Any* prop = NULL; | ||
| 484 | - | ||
| 485 | - if ((prop = pkt->command_object->ensure_property_string("tcUrl")) == NULL) { | ||
| 486 | - ret = ERROR_RTMP_REQ_CONNECT; | ||
| 487 | - srs_error("invalid request, must specifies the tcUrl. ret=%d", ret); | ||
| 488 | - return ret; | ||
| 489 | - } | ||
| 490 | - req->tcUrl = srs_amf0_convert<SrsAmf0String>(prop)->value; | ||
| 491 | - | ||
| 492 | - if ((prop = pkt->command_object->ensure_property_string("pageUrl")) != NULL) { | ||
| 493 | - req->pageUrl = srs_amf0_convert<SrsAmf0String>(prop)->value; | ||
| 494 | - } | ||
| 495 | - | ||
| 496 | - if ((prop = pkt->command_object->ensure_property_string("swfUrl")) != NULL) { | ||
| 497 | - req->swfUrl = srs_amf0_convert<SrsAmf0String>(prop)->value; | ||
| 498 | - } | ||
| 499 | - | ||
| 500 | - if ((prop = pkt->command_object->ensure_property_number("objectEncoding")) != NULL) { | ||
| 501 | - req->objectEncoding = srs_amf0_convert<SrsAmf0Number>(prop)->value; | ||
| 502 | - } | ||
| 503 | - | ||
| 504 | - srs_info("get connect app message params success."); | ||
| 505 | - | ||
| 506 | - return req->discovery_app(); | ||
| 507 | -} | ||
| 508 | - | ||
| 509 | -int SrsRtmp::set_window_ack_size(int ack_size) | ||
| 510 | -{ | ||
| 511 | - int ret = ERROR_SUCCESS; | ||
| 512 | - | ||
| 513 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 514 | - SrsSetWindowAckSizePacket* pkt = new SrsSetWindowAckSizePacket(); | ||
| 515 | - | ||
| 516 | - pkt->ackowledgement_window_size = ack_size; | ||
| 517 | - msg->set_packet(pkt, 0); | ||
| 518 | - | ||
| 519 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 520 | - srs_error("send ack size message failed. ret=%d", ret); | ||
| 521 | - return ret; | ||
| 522 | - } | ||
| 523 | - srs_info("send ack size message success. ack_size=%d", ack_size); | ||
| 524 | - | ||
| 525 | - return ret; | ||
| 526 | -} | ||
| 527 | - | ||
| 528 | -int SrsRtmp::set_peer_bandwidth(int bandwidth, int type) | ||
| 529 | -{ | ||
| 530 | - int ret = ERROR_SUCCESS; | ||
| 531 | - | ||
| 532 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 533 | - SrsSetPeerBandwidthPacket* pkt = new SrsSetPeerBandwidthPacket(); | ||
| 534 | - | ||
| 535 | - pkt->bandwidth = bandwidth; | ||
| 536 | - pkt->type = type; | ||
| 537 | - msg->set_packet(pkt, 0); | ||
| 538 | - | ||
| 539 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 540 | - srs_error("send set bandwidth message failed. ret=%d", ret); | ||
| 541 | - return ret; | ||
| 542 | - } | ||
| 543 | - srs_info("send set bandwidth message " | ||
| 544 | - "success. bandwidth=%d, type=%d", bandwidth, type); | ||
| 545 | - | ||
| 546 | - return ret; | ||
| 547 | -} | ||
| 548 | - | ||
| 549 | -int SrsRtmp::response_connect_app(SrsRequest* req) | ||
| 550 | -{ | ||
| 551 | - int ret = ERROR_SUCCESS; | ||
| 552 | - | ||
| 553 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 554 | - SrsConnectAppResPacket* pkt = new SrsConnectAppResPacket(); | ||
| 555 | - | ||
| 556 | - pkt->props->set("fmsVer", new SrsAmf0String("FMS/"RTMP_SIG_FMS_VER)); | ||
| 557 | - pkt->props->set("capabilities", new SrsAmf0Number(127)); | ||
| 558 | - pkt->props->set("mode", new SrsAmf0Number(1)); | ||
| 559 | - | ||
| 560 | - pkt->info->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); | ||
| 561 | - pkt->info->set(StatusCode, new SrsAmf0String(StatusCodeConnectSuccess)); | ||
| 562 | - pkt->info->set(StatusDescription, new SrsAmf0String("Connection succeeded")); | ||
| 563 | - pkt->info->set("objectEncoding", new SrsAmf0Number(req->objectEncoding)); | ||
| 564 | - SrsASrsAmf0EcmaArray* data = new SrsASrsAmf0EcmaArray(); | ||
| 565 | - pkt->info->set("data", data); | ||
| 566 | - | ||
| 567 | - data->set("srs_version", new SrsAmf0String(RTMP_SIG_FMS_VER)); | ||
| 568 | - data->set("srs_server", new SrsAmf0String(RTMP_SIG_SRS_NAME)); | ||
| 569 | - data->set("srs_license", new SrsAmf0String(RTMP_SIG_SRS_LICENSE)); | ||
| 570 | - data->set("srs_role", new SrsAmf0String(RTMP_SIG_SRS_ROLE)); | ||
| 571 | - data->set("srs_url", new SrsAmf0String(RTMP_SIG_SRS_URL)); | ||
| 572 | - data->set("srs_version", new SrsAmf0String(RTMP_SIG_SRS_VERSION)); | ||
| 573 | - data->set("srs_site", new SrsAmf0String(RTMP_SIG_SRS_WEB)); | ||
| 574 | - data->set("srs_email", new SrsAmf0String(RTMP_SIG_SRS_EMAIL)); | ||
| 575 | - data->set("srs_copyright", new SrsAmf0String(RTMP_SIG_SRS_COPYRIGHT)); | ||
| 576 | - | ||
| 577 | - msg->set_packet(pkt, 0); | ||
| 578 | - | ||
| 579 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 580 | - srs_error("send connect app response message failed. ret=%d", ret); | ||
| 581 | - return ret; | ||
| 582 | - } | ||
| 583 | - srs_info("send connect app response message success."); | ||
| 584 | - | ||
| 585 | - return ret; | ||
| 586 | -} | ||
| 587 | - | ||
| 588 | -int SrsRtmp::on_bw_done() | ||
| 589 | -{ | ||
| 590 | - int ret = ERROR_SUCCESS; | ||
| 591 | - | ||
| 592 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 593 | - SrsOnBWDonePacket* pkt = new SrsOnBWDonePacket(); | ||
| 594 | - | ||
| 595 | - msg->set_packet(pkt, 0); | ||
| 596 | - | ||
| 597 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 598 | - srs_error("send onBWDone message failed. ret=%d", ret); | ||
| 599 | - return ret; | ||
| 600 | - } | ||
| 601 | - srs_info("send onBWDone message success."); | ||
| 602 | - | ||
| 603 | - return ret; | ||
| 604 | -} | ||
| 605 | - | ||
| 606 | -int SrsRtmp::identify_client(int stream_id, SrsClientType& type, std::string& stream_name) | ||
| 607 | -{ | ||
| 608 | - type = SrsClientUnknown; | ||
| 609 | - int ret = ERROR_SUCCESS; | ||
| 610 | - | ||
| 611 | - while (true) { | ||
| 612 | - SrsCommonMessage* msg = NULL; | ||
| 613 | - if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) { | ||
| 614 | - srs_error("recv identify client message failed. ret=%d", ret); | ||
| 615 | - return ret; | ||
| 616 | - } | ||
| 617 | - | ||
| 618 | - SrsAutoFree(SrsCommonMessage, msg, false); | ||
| 619 | - | ||
| 620 | - if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) { | ||
| 621 | - srs_trace("identify ignore messages except " | ||
| 622 | - "AMF0/AMF3 command message. type=%#x", msg->header.message_type); | ||
| 623 | - continue; | ||
| 624 | - } | ||
| 625 | - | ||
| 626 | - if ((ret = msg->decode_packet(protocol)) != ERROR_SUCCESS) { | ||
| 627 | - srs_error("identify decode message failed. ret=%d", ret); | ||
| 628 | - return ret; | ||
| 629 | - } | ||
| 630 | - | ||
| 631 | - SrsPacket* pkt = msg->get_packet(); | ||
| 632 | - if (dynamic_cast<SrsCreateStreamPacket*>(pkt)) { | ||
| 633 | - srs_info("identify client by create stream, play or flash publish."); | ||
| 634 | - return identify_create_stream_client( | ||
| 635 | - dynamic_cast<SrsCreateStreamPacket*>(pkt), stream_id, type, stream_name); | ||
| 636 | - } | ||
| 637 | - if (dynamic_cast<SrsFMLEStartPacket*>(pkt)) { | ||
| 638 | - srs_info("identify client by releaseStream, fmle publish."); | ||
| 639 | - return identify_fmle_publish_client( | ||
| 640 | - dynamic_cast<SrsFMLEStartPacket*>(pkt), type, stream_name); | ||
| 641 | - } | ||
| 642 | - | ||
| 643 | - srs_trace("ignore AMF0/AMF3 command message."); | ||
| 644 | - } | ||
| 645 | - | ||
| 646 | - return ret; | ||
| 647 | -} | ||
| 648 | - | ||
| 649 | -int SrsRtmp::set_chunk_size(int chunk_size) | ||
| 650 | -{ | ||
| 651 | - int ret = ERROR_SUCCESS; | ||
| 652 | - | ||
| 653 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 654 | - SrsSetChunkSizePacket* pkt = new SrsSetChunkSizePacket(); | ||
| 655 | - | ||
| 656 | - pkt->chunk_size = chunk_size; | ||
| 657 | - msg->set_packet(pkt, 0); | ||
| 658 | - | ||
| 659 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 660 | - srs_error("send set chunk size message failed. ret=%d", ret); | ||
| 661 | - return ret; | ||
| 662 | - } | ||
| 663 | - srs_info("send set chunk size message success. chunk_size=%d", chunk_size); | ||
| 664 | - | ||
| 665 | - return ret; | ||
| 666 | -} | ||
| 667 | - | ||
| 668 | -int SrsRtmp::start_play(int stream_id) | ||
| 669 | -{ | ||
| 670 | - int ret = ERROR_SUCCESS; | ||
| 671 | - | ||
| 672 | - // StreamBegin | ||
| 673 | - if (true) { | ||
| 674 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 675 | - SrsUserControlPacket* pkt = new SrsUserControlPacket(); | ||
| 676 | - | ||
| 677 | - pkt->event_type = SrcPCUCStreamBegin; | ||
| 678 | - pkt->event_data = stream_id; | ||
| 679 | - msg->set_packet(pkt, 0); | ||
| 680 | - | ||
| 681 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 682 | - srs_error("send PCUC(StreamBegin) message failed. ret=%d", ret); | ||
| 683 | - return ret; | ||
| 684 | - } | ||
| 685 | - srs_info("send PCUC(StreamBegin) message success."); | ||
| 686 | - } | ||
| 687 | - | ||
| 688 | - // onStatus(NetStream.Play.Reset) | ||
| 689 | - if (true) { | ||
| 690 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 691 | - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); | ||
| 692 | - | ||
| 693 | - pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); | ||
| 694 | - pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeStreamReset)); | ||
| 695 | - pkt->data->set(StatusDescription, new SrsAmf0String("Playing and resetting stream.")); | ||
| 696 | - pkt->data->set(StatusDetails, new SrsAmf0String("stream")); | ||
| 697 | - pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); | ||
| 698 | - | ||
| 699 | - msg->set_packet(pkt, stream_id); | ||
| 700 | - | ||
| 701 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 702 | - srs_error("send onStatus(NetStream.Play.Reset) message failed. ret=%d", ret); | ||
| 703 | - return ret; | ||
| 704 | - } | ||
| 705 | - srs_info("send onStatus(NetStream.Play.Reset) message success."); | ||
| 706 | - } | ||
| 707 | - | ||
| 708 | - // onStatus(NetStream.Play.Start) | ||
| 709 | - if (true) { | ||
| 710 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 711 | - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); | ||
| 712 | - | ||
| 713 | - pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); | ||
| 714 | - pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeStreamStart)); | ||
| 715 | - pkt->data->set(StatusDescription, new SrsAmf0String("Started playing stream.")); | ||
| 716 | - pkt->data->set(StatusDetails, new SrsAmf0String("stream")); | ||
| 717 | - pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); | ||
| 718 | - | ||
| 719 | - msg->set_packet(pkt, stream_id); | ||
| 720 | - | ||
| 721 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 722 | - srs_error("send onStatus(NetStream.Play.Reset) message failed. ret=%d", ret); | ||
| 723 | - return ret; | ||
| 724 | - } | ||
| 725 | - srs_info("send onStatus(NetStream.Play.Reset) message success."); | ||
| 726 | - } | ||
| 727 | - | ||
| 728 | - // |RtmpSampleAccess(false, false) | ||
| 729 | - if (true) { | ||
| 730 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 731 | - SrsSampleAccessPacket* pkt = new SrsSampleAccessPacket(); | ||
| 732 | - | ||
| 733 | - msg->set_packet(pkt, stream_id); | ||
| 734 | - | ||
| 735 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 736 | - srs_error("send |RtmpSampleAccess(false, false) message failed. ret=%d", ret); | ||
| 737 | - return ret; | ||
| 738 | - } | ||
| 739 | - srs_info("send |RtmpSampleAccess(false, false) message success."); | ||
| 740 | - } | ||
| 741 | - | ||
| 742 | - // onStatus(NetStream.Data.Start) | ||
| 743 | - if (true) { | ||
| 744 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 745 | - SrsOnStatusDataPacket* pkt = new SrsOnStatusDataPacket(); | ||
| 746 | - | ||
| 747 | - pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeDataStart)); | ||
| 748 | - | ||
| 749 | - msg->set_packet(pkt, stream_id); | ||
| 750 | - | ||
| 751 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 752 | - srs_error("send onStatus(NetStream.Data.Start) message failed. ret=%d", ret); | ||
| 753 | - return ret; | ||
| 754 | - } | ||
| 755 | - srs_info("send onStatus(NetStream.Data.Start) message success."); | ||
| 756 | - } | ||
| 757 | - | ||
| 758 | - srs_info("start play success."); | ||
| 759 | - | ||
| 760 | - return ret; | ||
| 761 | -} | ||
| 762 | - | ||
| 763 | -int SrsRtmp::on_play_client_pause(int stream_id, bool is_pause) | ||
| 764 | -{ | ||
| 765 | - int ret = ERROR_SUCCESS; | ||
| 766 | - | ||
| 767 | - if (is_pause) { | ||
| 768 | - // onStatus(NetStream.Pause.Notify) | ||
| 769 | - if (true) { | ||
| 770 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 771 | - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); | ||
| 772 | - | ||
| 773 | - pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); | ||
| 774 | - pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeStreamPause)); | ||
| 775 | - pkt->data->set(StatusDescription, new SrsAmf0String("Paused stream.")); | ||
| 776 | - | ||
| 777 | - msg->set_packet(pkt, stream_id); | ||
| 778 | - | ||
| 779 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 780 | - srs_error("send onStatus(NetStream.Pause.Notify) message failed. ret=%d", ret); | ||
| 781 | - return ret; | ||
| 782 | - } | ||
| 783 | - srs_info("send onStatus(NetStream.Pause.Notify) message success."); | ||
| 784 | - } | ||
| 785 | - // StreamEOF | ||
| 786 | - if (true) { | ||
| 787 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 788 | - SrsUserControlPacket* pkt = new SrsUserControlPacket(); | ||
| 789 | - | ||
| 790 | - pkt->event_type = SrcPCUCStreamEOF; | ||
| 791 | - pkt->event_data = stream_id; | ||
| 792 | - msg->set_packet(pkt, 0); | ||
| 793 | - | ||
| 794 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 795 | - srs_error("send PCUC(StreamEOF) message failed. ret=%d", ret); | ||
| 796 | - return ret; | ||
| 797 | - } | ||
| 798 | - srs_info("send PCUC(StreamEOF) message success."); | ||
| 799 | - } | ||
| 800 | - } else { | ||
| 801 | - // onStatus(NetStream.Unpause.Notify) | ||
| 802 | - if (true) { | ||
| 803 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 804 | - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); | ||
| 805 | - | ||
| 806 | - pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); | ||
| 807 | - pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeStreamUnpause)); | ||
| 808 | - pkt->data->set(StatusDescription, new SrsAmf0String("Unpaused stream.")); | ||
| 809 | - | ||
| 810 | - msg->set_packet(pkt, stream_id); | ||
| 811 | - | ||
| 812 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 813 | - srs_error("send onStatus(NetStream.Unpause.Notify) message failed. ret=%d", ret); | ||
| 814 | - return ret; | ||
| 815 | - } | ||
| 816 | - srs_info("send onStatus(NetStream.Unpause.Notify) message success."); | ||
| 817 | - } | ||
| 818 | - // StreanBegin | ||
| 819 | - if (true) { | ||
| 820 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 821 | - SrsUserControlPacket* pkt = new SrsUserControlPacket(); | ||
| 822 | - | ||
| 823 | - pkt->event_type = SrcPCUCStreamBegin; | ||
| 824 | - pkt->event_data = stream_id; | ||
| 825 | - msg->set_packet(pkt, 0); | ||
| 826 | - | ||
| 827 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 828 | - srs_error("send PCUC(StreanBegin) message failed. ret=%d", ret); | ||
| 829 | - return ret; | ||
| 830 | - } | ||
| 831 | - srs_info("send PCUC(StreanBegin) message success."); | ||
| 832 | - } | ||
| 833 | - } | ||
| 834 | - | ||
| 835 | - return ret; | ||
| 836 | -} | ||
| 837 | - | ||
| 838 | -int SrsRtmp::start_fmle_publish(int stream_id) | ||
| 839 | -{ | ||
| 840 | - int ret = ERROR_SUCCESS; | ||
| 841 | - | ||
| 842 | - // FCPublish | ||
| 843 | - double fc_publish_tid = 0; | ||
| 844 | - if (true) { | ||
| 845 | - SrsCommonMessage* msg = NULL; | ||
| 846 | - SrsFMLEStartPacket* pkt = NULL; | ||
| 847 | - if ((ret = srs_rtmp_expect_message<SrsFMLEStartPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) { | ||
| 848 | - srs_error("recv FCPublish message failed. ret=%d", ret); | ||
| 849 | - return ret; | ||
| 850 | - } | ||
| 851 | - srs_info("recv FCPublish request message success."); | ||
| 852 | - | ||
| 853 | - SrsAutoFree(SrsCommonMessage, msg, false); | ||
| 854 | - fc_publish_tid = pkt->transaction_id; | ||
| 855 | - } | ||
| 856 | - // FCPublish response | ||
| 857 | - if (true) { | ||
| 858 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 859 | - SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(fc_publish_tid); | ||
| 860 | - | ||
| 861 | - msg->set_packet(pkt, 0); | ||
| 862 | - | ||
| 863 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 864 | - srs_error("send FCPublish response message failed. ret=%d", ret); | ||
| 865 | - return ret; | ||
| 866 | - } | ||
| 867 | - srs_info("send FCPublish response message success."); | ||
| 868 | - } | ||
| 869 | - | ||
| 870 | - // createStream | ||
| 871 | - double create_stream_tid = 0; | ||
| 872 | - if (true) { | ||
| 873 | - SrsCommonMessage* msg = NULL; | ||
| 874 | - SrsCreateStreamPacket* pkt = NULL; | ||
| 875 | - if ((ret = srs_rtmp_expect_message<SrsCreateStreamPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) { | ||
| 876 | - srs_error("recv createStream message failed. ret=%d", ret); | ||
| 877 | - return ret; | ||
| 878 | - } | ||
| 879 | - srs_info("recv createStream request message success."); | ||
| 880 | - | ||
| 881 | - SrsAutoFree(SrsCommonMessage, msg, false); | ||
| 882 | - create_stream_tid = pkt->transaction_id; | ||
| 883 | - } | ||
| 884 | - // createStream response | ||
| 885 | - if (true) { | ||
| 886 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 887 | - SrsCreateStreamResPacket* pkt = new SrsCreateStreamResPacket(create_stream_tid, stream_id); | ||
| 888 | - | ||
| 889 | - msg->set_packet(pkt, 0); | ||
| 890 | - | ||
| 891 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 892 | - srs_error("send createStream response message failed. ret=%d", ret); | ||
| 893 | - return ret; | ||
| 894 | - } | ||
| 895 | - srs_info("send createStream response message success."); | ||
| 896 | - } | ||
| 897 | - | ||
| 898 | - // publish | ||
| 899 | - if (true) { | ||
| 900 | - SrsCommonMessage* msg = NULL; | ||
| 901 | - SrsPublishPacket* pkt = NULL; | ||
| 902 | - if ((ret = srs_rtmp_expect_message<SrsPublishPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) { | ||
| 903 | - srs_error("recv publish message failed. ret=%d", ret); | ||
| 904 | - return ret; | ||
| 905 | - } | ||
| 906 | - srs_info("recv publish request message success."); | ||
| 907 | - | ||
| 908 | - SrsAutoFree(SrsCommonMessage, msg, false); | ||
| 909 | - } | ||
| 910 | - // publish response onFCPublish(NetStream.Publish.Start) | ||
| 911 | - if (true) { | ||
| 912 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 913 | - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); | ||
| 914 | - | ||
| 915 | - pkt->command_name = RTMP_AMF0_COMMAND_ON_FC_PUBLISH; | ||
| 916 | - pkt->data->set(StatusCode, new SrsAmf0String(StatusCodePublishStart)); | ||
| 917 | - pkt->data->set(StatusDescription, new SrsAmf0String("Started publishing stream.")); | ||
| 918 | - | ||
| 919 | - msg->set_packet(pkt, stream_id); | ||
| 920 | - | ||
| 921 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 922 | - srs_error("send onFCPublish(NetStream.Publish.Start) message failed. ret=%d", ret); | ||
| 923 | - return ret; | ||
| 924 | - } | ||
| 925 | - srs_info("send onFCPublish(NetStream.Publish.Start) message success."); | ||
| 926 | - } | ||
| 927 | - // publish response onStatus(NetStream.Publish.Start) | ||
| 928 | - if (true) { | ||
| 929 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 930 | - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); | ||
| 931 | - | ||
| 932 | - pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); | ||
| 933 | - pkt->data->set(StatusCode, new SrsAmf0String(StatusCodePublishStart)); | ||
| 934 | - pkt->data->set(StatusDescription, new SrsAmf0String("Started publishing stream.")); | ||
| 935 | - pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); | ||
| 936 | - | ||
| 937 | - msg->set_packet(pkt, stream_id); | ||
| 938 | - | ||
| 939 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 940 | - srs_error("send onStatus(NetStream.Publish.Start) message failed. ret=%d", ret); | ||
| 941 | - return ret; | ||
| 942 | - } | ||
| 943 | - srs_info("send onStatus(NetStream.Publish.Start) message success."); | ||
| 944 | - } | ||
| 945 | - | ||
| 946 | - srs_info("FMLE publish success."); | ||
| 947 | - | ||
| 948 | - return ret; | ||
| 949 | -} | ||
| 950 | - | ||
| 951 | -int SrsRtmp::fmle_unpublish(int stream_id, double unpublish_tid) | ||
| 952 | -{ | ||
| 953 | - int ret = ERROR_SUCCESS; | ||
| 954 | - | ||
| 955 | - // publish response onFCUnpublish(NetStream.unpublish.Success) | ||
| 956 | - if (true) { | ||
| 957 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 958 | - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); | ||
| 959 | - | ||
| 960 | - pkt->command_name = RTMP_AMF0_COMMAND_ON_FC_UNPUBLISH; | ||
| 961 | - pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeUnpublishSuccess)); | ||
| 962 | - pkt->data->set(StatusDescription, new SrsAmf0String("Stop publishing stream.")); | ||
| 963 | - | ||
| 964 | - msg->set_packet(pkt, stream_id); | ||
| 965 | - | ||
| 966 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 967 | - srs_error("send onFCUnpublish(NetStream.unpublish.Success) message failed. ret=%d", ret); | ||
| 968 | - return ret; | ||
| 969 | - } | ||
| 970 | - srs_info("send onFCUnpublish(NetStream.unpublish.Success) message success."); | ||
| 971 | - } | ||
| 972 | - // FCUnpublish response | ||
| 973 | - if (true) { | ||
| 974 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 975 | - SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(unpublish_tid); | ||
| 976 | - | ||
| 977 | - msg->set_packet(pkt, stream_id); | ||
| 978 | - | ||
| 979 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 980 | - srs_error("send FCUnpublish response message failed. ret=%d", ret); | ||
| 981 | - return ret; | ||
| 982 | - } | ||
| 983 | - srs_info("send FCUnpublish response message success."); | ||
| 984 | - } | ||
| 985 | - // publish response onStatus(NetStream.Unpublish.Success) | ||
| 986 | - if (true) { | ||
| 987 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 988 | - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); | ||
| 989 | - | ||
| 990 | - pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); | ||
| 991 | - pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeUnpublishSuccess)); | ||
| 992 | - pkt->data->set(StatusDescription, new SrsAmf0String("Stream is now unpublished")); | ||
| 993 | - pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); | ||
| 994 | - | ||
| 995 | - msg->set_packet(pkt, stream_id); | ||
| 996 | - | ||
| 997 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 998 | - srs_error("send onStatus(NetStream.Unpublish.Success) message failed. ret=%d", ret); | ||
| 999 | - return ret; | ||
| 1000 | - } | ||
| 1001 | - srs_info("send onStatus(NetStream.Unpublish.Success) message success."); | ||
| 1002 | - } | ||
| 1003 | - | ||
| 1004 | - srs_info("FMLE unpublish success."); | ||
| 1005 | - | ||
| 1006 | - return ret; | ||
| 1007 | -} | ||
| 1008 | - | ||
| 1009 | -int SrsRtmp::start_flash_publish(int stream_id) | ||
| 1010 | -{ | ||
| 1011 | - int ret = ERROR_SUCCESS; | ||
| 1012 | - | ||
| 1013 | - // publish response onStatus(NetStream.Publish.Start) | ||
| 1014 | - if (true) { | ||
| 1015 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 1016 | - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); | ||
| 1017 | - | ||
| 1018 | - pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); | ||
| 1019 | - pkt->data->set(StatusCode, new SrsAmf0String(StatusCodePublishStart)); | ||
| 1020 | - pkt->data->set(StatusDescription, new SrsAmf0String("Started publishing stream.")); | ||
| 1021 | - pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); | ||
| 1022 | - | ||
| 1023 | - msg->set_packet(pkt, stream_id); | ||
| 1024 | - | ||
| 1025 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 1026 | - srs_error("send onStatus(NetStream.Publish.Start) message failed. ret=%d", ret); | ||
| 1027 | - return ret; | ||
| 1028 | - } | ||
| 1029 | - srs_info("send onStatus(NetStream.Publish.Start) message success."); | ||
| 1030 | - } | ||
| 1031 | - | ||
| 1032 | - srs_info("flash publish success."); | ||
| 1033 | - | ||
| 1034 | - return ret; | ||
| 1035 | -} | ||
| 1036 | - | ||
| 1037 | -int SrsRtmp::identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name) | ||
| 1038 | -{ | ||
| 1039 | - int ret = ERROR_SUCCESS; | ||
| 1040 | - | ||
| 1041 | - if (true) { | ||
| 1042 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 1043 | - SrsCreateStreamResPacket* pkt = new SrsCreateStreamResPacket(req->transaction_id, stream_id); | ||
| 1044 | - | ||
| 1045 | - msg->set_packet(pkt, 0); | ||
| 1046 | - | ||
| 1047 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 1048 | - srs_error("send createStream response message failed. ret=%d", ret); | ||
| 1049 | - return ret; | ||
| 1050 | - } | ||
| 1051 | - srs_info("send createStream response message success."); | ||
| 1052 | - } | ||
| 1053 | - | ||
| 1054 | - while (true) { | ||
| 1055 | - SrsCommonMessage* msg = NULL; | ||
| 1056 | - if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) { | ||
| 1057 | - srs_error("recv identify client message failed. ret=%d", ret); | ||
| 1058 | - return ret; | ||
| 1059 | - } | ||
| 1060 | - | ||
| 1061 | - SrsAutoFree(SrsCommonMessage, msg, false); | ||
| 1062 | - | ||
| 1063 | - if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) { | ||
| 1064 | - srs_trace("identify ignore messages except " | ||
| 1065 | - "AMF0/AMF3 command message. type=%#x", msg->header.message_type); | ||
| 1066 | - continue; | ||
| 1067 | - } | ||
| 1068 | - | ||
| 1069 | - if ((ret = msg->decode_packet(protocol)) != ERROR_SUCCESS) { | ||
| 1070 | - srs_error("identify decode message failed. ret=%d", ret); | ||
| 1071 | - return ret; | ||
| 1072 | - } | ||
| 1073 | - | ||
| 1074 | - SrsPacket* pkt = msg->get_packet(); | ||
| 1075 | - if (dynamic_cast<SrsPlayPacket*>(pkt)) { | ||
| 1076 | - SrsPlayPacket* play = dynamic_cast<SrsPlayPacket*>(pkt); | ||
| 1077 | - type = SrsClientPlay; | ||
| 1078 | - stream_name = play->stream_name; | ||
| 1079 | - srs_trace("identity client type=play, stream_name=%s", stream_name.c_str()); | ||
| 1080 | - return ret; | ||
| 1081 | - } | ||
| 1082 | - if (dynamic_cast<SrsPublishPacket*>(pkt)) { | ||
| 1083 | - srs_info("identify client by publish, falsh publish."); | ||
| 1084 | - return identify_flash_publish_client( | ||
| 1085 | - dynamic_cast<SrsPublishPacket*>(pkt), type, stream_name); | ||
| 1086 | - } | ||
| 1087 | - | ||
| 1088 | - srs_trace("ignore AMF0/AMF3 command message."); | ||
| 1089 | - } | ||
| 1090 | - | ||
| 1091 | - return ret; | ||
| 1092 | -} | ||
| 1093 | - | ||
| 1094 | -int SrsRtmp::identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, std::string& stream_name) | ||
| 1095 | -{ | ||
| 1096 | - int ret = ERROR_SUCCESS; | ||
| 1097 | - | ||
| 1098 | - type = SrsClientFMLEPublish; | ||
| 1099 | - stream_name = req->stream_name; | ||
| 1100 | - | ||
| 1101 | - // releaseStream response | ||
| 1102 | - if (true) { | ||
| 1103 | - SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 1104 | - SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(req->transaction_id); | ||
| 1105 | - | ||
| 1106 | - msg->set_packet(pkt, 0); | ||
| 1107 | - | ||
| 1108 | - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 1109 | - srs_error("send releaseStream response message failed. ret=%d", ret); | ||
| 1110 | - return ret; | ||
| 1111 | - } | ||
| 1112 | - srs_info("send releaseStream response message success."); | ||
| 1113 | - } | ||
| 1114 | - | ||
| 1115 | - return ret; | ||
| 1116 | -} | ||
| 1117 | - | ||
| 1118 | -int SrsRtmp::identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name) | ||
| 1119 | -{ | ||
| 1120 | - int ret = ERROR_SUCCESS; | ||
| 1121 | - | ||
| 1122 | - type = SrsClientFlashPublish; | ||
| 1123 | - stream_name = req->stream_name; | ||
| 1124 | - | ||
| 1125 | - return ret; | ||
| 1126 | -} | ||
| 1127 | - | 1 | +/* |
| 2 | +The MIT License (MIT) | ||
| 3 | + | ||
| 4 | +Copyright (c) 2013 winlin | ||
| 5 | + | ||
| 6 | +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 | +the Software without restriction, including without limitation the rights to | ||
| 9 | +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||
| 10 | +the Software, and to permit persons to whom the Software is furnished to do so, | ||
| 11 | +subject to the following conditions: | ||
| 12 | + | ||
| 13 | +The above copyright notice and this permission notice shall be included in all | ||
| 14 | +copies or substantial portions of the Software. | ||
| 15 | + | ||
| 16 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||
| 18 | +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||
| 19 | +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||
| 20 | +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 21 | +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | +*/ | ||
| 23 | + | ||
| 24 | +#include <srs_core_rtmp.hpp> | ||
| 25 | + | ||
| 26 | +#include <srs_core_log.hpp> | ||
| 27 | +#include <srs_core_error.hpp> | ||
| 28 | +#include <srs_core_socket.hpp> | ||
| 29 | +#include <srs_core_protocol.hpp> | ||
| 30 | +#include <srs_core_autofree.hpp> | ||
| 31 | +#include <srs_core_amf0.hpp> | ||
| 32 | +#include <srs_core_handshake.hpp> | ||
| 33 | +#include <srs_core_config.hpp> | ||
| 34 | + | ||
| 35 | +/** | ||
| 36 | +* the signature for packets to client. | ||
| 37 | +*/ | ||
| 38 | +#define RTMP_SIG_FMS_VER "3,5,3,888" | ||
| 39 | +#define RTMP_SIG_AMF0_VER 0 | ||
| 40 | +#define RTMP_SIG_CLIENT_ID "ASAICiss" | ||
| 41 | + | ||
| 42 | +/** | ||
| 43 | +* onStatus consts. | ||
| 44 | +*/ | ||
| 45 | +#define StatusLevel "level" | ||
| 46 | +#define StatusCode "code" | ||
| 47 | +#define StatusDescription "description" | ||
| 48 | +#define StatusDetails "details" | ||
| 49 | +#define StatusClientId "clientid" | ||
| 50 | +// status value | ||
| 51 | +#define StatusLevelStatus "status" | ||
| 52 | +// code value | ||
| 53 | +#define StatusCodeConnectSuccess "NetConnection.Connect.Success" | ||
| 54 | +#define StatusCodeStreamReset "NetStream.Play.Reset" | ||
| 55 | +#define StatusCodeStreamStart "NetStream.Play.Start" | ||
| 56 | +#define StatusCodeStreamPause "NetStream.Pause.Notify" | ||
| 57 | +#define StatusCodeStreamUnpause "NetStream.Unpause.Notify" | ||
| 58 | +#define StatusCodePublishStart "NetStream.Publish.Start" | ||
| 59 | +#define StatusCodeDataStart "NetStream.Data.Start" | ||
| 60 | +#define StatusCodeUnpublishSuccess "NetStream.Unpublish.Success" | ||
| 61 | + | ||
| 62 | +// FMLE | ||
| 63 | +#define RTMP_AMF0_COMMAND_ON_FC_PUBLISH "onFCPublish" | ||
| 64 | +#define RTMP_AMF0_COMMAND_ON_FC_UNPUBLISH "onFCUnpublish" | ||
| 65 | + | ||
| 66 | +// default stream id for response the createStream request. | ||
| 67 | +#define SRS_DEFAULT_SID 1 | ||
| 68 | + | ||
| 69 | +SrsRequest::SrsRequest() | ||
| 70 | +{ | ||
| 71 | + objectEncoding = RTMP_SIG_AMF0_VER; | ||
| 72 | +} | ||
| 73 | + | ||
| 74 | +SrsRequest::~SrsRequest() | ||
| 75 | +{ | ||
| 76 | +} | ||
| 77 | + | ||
| 78 | +int SrsRequest::discovery_app() | ||
| 79 | +{ | ||
| 80 | + int ret = ERROR_SUCCESS; | ||
| 81 | + | ||
| 82 | + size_t pos = std::string::npos; | ||
| 83 | + std::string url = tcUrl; | ||
| 84 | + | ||
| 85 | + if ((pos = url.find("://")) != std::string::npos) { | ||
| 86 | + schema = url.substr(0, pos); | ||
| 87 | + url = url.substr(schema.length() + 3); | ||
| 88 | + srs_verbose("discovery schema=%s", schema.c_str()); | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + if ((pos = url.find("/")) != std::string::npos) { | ||
| 92 | + vhost = url.substr(0, pos); | ||
| 93 | + url = url.substr(vhost.length() + 1); | ||
| 94 | + srs_verbose("discovery vhost=%s", vhost.c_str()); | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + port = RTMP_DEFAULT_PORTS; | ||
| 98 | + if ((pos = vhost.find(":")) != std::string::npos) { | ||
| 99 | + port = vhost.substr(pos + 1); | ||
| 100 | + vhost = vhost.substr(0, pos); | ||
| 101 | + srs_verbose("discovery vhost=%s, port=%s", vhost.c_str(), port.c_str()); | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + app = url; | ||
| 105 | + srs_vhost_resolve(vhost, app); | ||
| 106 | + | ||
| 107 | + // resolve the vhost from config | ||
| 108 | + SrsConfDirective* parsed_vhost = config->get_vhost(vhost); | ||
| 109 | + if (parsed_vhost) { | ||
| 110 | + vhost = parsed_vhost->arg0(); | ||
| 111 | + } | ||
| 112 | + | ||
| 113 | + // TODO: discovery the params of vhost. | ||
| 114 | + | ||
| 115 | + srs_info("discovery app success. schema=%s, vhost=%s, port=%s, app=%s", | ||
| 116 | + schema.c_str(), vhost.c_str(), port.c_str(), app.c_str()); | ||
| 117 | + | ||
| 118 | + if (schema.empty() || vhost.empty() || port.empty() || app.empty()) { | ||
| 119 | + ret = ERROR_RTMP_REQ_TCURL; | ||
| 120 | + srs_error("discovery tcUrl failed. " | ||
| 121 | + "tcUrl=%s, schema=%s, vhost=%s, port=%s, app=%s, ret=%d", | ||
| 122 | + tcUrl.c_str(), schema.c_str(), vhost.c_str(), port.c_str(), app.c_str(), ret); | ||
| 123 | + return ret; | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + strip(); | ||
| 127 | + | ||
| 128 | + return ret; | ||
| 129 | +} | ||
| 130 | + | ||
| 131 | +std::string SrsRequest::get_stream_url() | ||
| 132 | +{ | ||
| 133 | + std::string url = ""; | ||
| 134 | + | ||
| 135 | + url += vhost; | ||
| 136 | + url += "/"; | ||
| 137 | + url += app; | ||
| 138 | + url += "/"; | ||
| 139 | + url += stream; | ||
| 140 | + | ||
| 141 | + return url; | ||
| 142 | +} | ||
| 143 | + | ||
| 144 | +void SrsRequest::strip() | ||
| 145 | +{ | ||
| 146 | + trim(vhost, "/ \n\r\t"); | ||
| 147 | + trim(app, "/ \n\r\t"); | ||
| 148 | + trim(stream, "/ \n\r\t"); | ||
| 149 | +} | ||
| 150 | + | ||
| 151 | +std::string& SrsRequest::trim(std::string& str, std::string chs) | ||
| 152 | +{ | ||
| 153 | + for (int i = 0; i < (int)chs.length(); i++) { | ||
| 154 | + char ch = chs.at(i); | ||
| 155 | + | ||
| 156 | + for (std::string::iterator it = str.begin(); it != str.end();) { | ||
| 157 | + if (ch == *it) { | ||
| 158 | + it = str.erase(it); | ||
| 159 | + } else { | ||
| 160 | + ++it; | ||
| 161 | + } | ||
| 162 | + } | ||
| 163 | + } | ||
| 164 | + | ||
| 165 | + return str; | ||
| 166 | +} | ||
| 167 | + | ||
| 168 | +SrsResponse::SrsResponse() | ||
| 169 | +{ | ||
| 170 | + stream_id = SRS_DEFAULT_SID; | ||
| 171 | +} | ||
| 172 | + | ||
| 173 | +SrsResponse::~SrsResponse() | ||
| 174 | +{ | ||
| 175 | +} | ||
| 176 | + | ||
| 177 | +SrsRtmpClient::SrsRtmpClient(st_netfd_t _stfd) | ||
| 178 | +{ | ||
| 179 | + stfd = _stfd; | ||
| 180 | + protocol = new SrsProtocol(stfd); | ||
| 181 | +} | ||
| 182 | + | ||
| 183 | +SrsRtmpClient::~SrsRtmpClient() | ||
| 184 | +{ | ||
| 185 | + srs_freep(protocol); | ||
| 186 | +} | ||
| 187 | + | ||
| 188 | +void SrsRtmpClient::set_recv_timeout(int64_t timeout_us) | ||
| 189 | +{ | ||
| 190 | + protocol->set_recv_timeout(timeout_us); | ||
| 191 | +} | ||
| 192 | + | ||
| 193 | +void SrsRtmpClient::set_send_timeout(int64_t timeout_us) | ||
| 194 | +{ | ||
| 195 | + protocol->set_send_timeout(timeout_us); | ||
| 196 | +} | ||
| 197 | + | ||
| 198 | +int64_t SrsRtmpClient::get_recv_bytes() | ||
| 199 | +{ | ||
| 200 | + return protocol->get_recv_bytes(); | ||
| 201 | +} | ||
| 202 | + | ||
| 203 | +int64_t SrsRtmpClient::get_send_bytes() | ||
| 204 | +{ | ||
| 205 | + return protocol->get_send_bytes(); | ||
| 206 | +} | ||
| 207 | + | ||
| 208 | +int SrsRtmpClient::get_recv_kbps() | ||
| 209 | +{ | ||
| 210 | + return protocol->get_recv_kbps(); | ||
| 211 | +} | ||
| 212 | + | ||
| 213 | +int SrsRtmpClient::get_send_kbps() | ||
| 214 | +{ | ||
| 215 | + return protocol->get_send_kbps(); | ||
| 216 | +} | ||
| 217 | + | ||
| 218 | +int SrsRtmpClient::recv_message(SrsCommonMessage** pmsg) | ||
| 219 | +{ | ||
| 220 | + return protocol->recv_message(pmsg); | ||
| 221 | +} | ||
| 222 | + | ||
| 223 | +int SrsRtmpClient::send_message(ISrsMessage* msg) | ||
| 224 | +{ | ||
| 225 | + return protocol->send_message(msg); | ||
| 226 | +} | ||
| 227 | + | ||
| 228 | +int SrsRtmpClient::handshake() | ||
| 229 | +{ | ||
| 230 | + int ret = ERROR_SUCCESS; | ||
| 231 | + | ||
| 232 | + SrsSocket skt(stfd); | ||
| 233 | + | ||
| 234 | + SrsComplexHandshake complex_hs; | ||
| 235 | + SrsSimpleHandshake simple_hs; | ||
| 236 | + if ((ret = simple_hs.handshake_with_server(skt, complex_hs)) != ERROR_SUCCESS) { | ||
| 237 | + return ret; | ||
| 238 | + } | ||
| 239 | + | ||
| 240 | + return ret; | ||
| 241 | +} | ||
| 242 | + | ||
| 243 | +int SrsRtmpClient::connect_app(std::string app, std::string tc_url) | ||
| 244 | +{ | ||
| 245 | + int ret = ERROR_SUCCESS; | ||
| 246 | + | ||
| 247 | + // Connect(vhost, app) | ||
| 248 | + if (true) { | ||
| 249 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 250 | + SrsConnectAppPacket* pkt = new SrsConnectAppPacket(); | ||
| 251 | + msg->set_packet(pkt, 0); | ||
| 252 | + | ||
| 253 | + pkt->command_object = new SrsAmf0Object(); | ||
| 254 | + pkt->command_object->set("app", new SrsAmf0String(app.c_str())); | ||
| 255 | + pkt->command_object->set("swfUrl", new SrsAmf0String()); | ||
| 256 | + pkt->command_object->set("tcUrl", new SrsAmf0String(tc_url.c_str())); | ||
| 257 | + pkt->command_object->set("fpad", new SrsAmf0Boolean(false)); | ||
| 258 | + pkt->command_object->set("capabilities", new SrsAmf0Number(239)); | ||
| 259 | + pkt->command_object->set("audioCodecs", new SrsAmf0Number(3575)); | ||
| 260 | + pkt->command_object->set("videoCodecs", new SrsAmf0Number(252)); | ||
| 261 | + pkt->command_object->set("videoFunction", new SrsAmf0Number(1)); | ||
| 262 | + pkt->command_object->set("pageUrl", new SrsAmf0String()); | ||
| 263 | + pkt->command_object->set("objectEncoding", new SrsAmf0Number(0)); | ||
| 264 | + | ||
| 265 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 266 | + return ret; | ||
| 267 | + } | ||
| 268 | + } | ||
| 269 | + | ||
| 270 | + // Set Window Acknowledgement size(2500000) | ||
| 271 | + if (true) { | ||
| 272 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 273 | + SrsSetWindowAckSizePacket* pkt = new SrsSetWindowAckSizePacket(); | ||
| 274 | + | ||
| 275 | + pkt->ackowledgement_window_size = 2500000; | ||
| 276 | + msg->set_packet(pkt, 0); | ||
| 277 | + | ||
| 278 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 279 | + return ret; | ||
| 280 | + } | ||
| 281 | + } | ||
| 282 | + | ||
| 283 | + // expect connect _result | ||
| 284 | + SrsCommonMessage* msg = NULL; | ||
| 285 | + SrsConnectAppResPacket* pkt = NULL; | ||
| 286 | + if ((ret = srs_rtmp_expect_message<SrsConnectAppResPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) { | ||
| 287 | + srs_error("expect connect app response message failed. ret=%d", ret); | ||
| 288 | + return ret; | ||
| 289 | + } | ||
| 290 | + SrsAutoFree(SrsCommonMessage, msg, false); | ||
| 291 | + srs_info("get connect app response message"); | ||
| 292 | + | ||
| 293 | + return ret; | ||
| 294 | +} | ||
| 295 | + | ||
| 296 | +int SrsRtmpClient::create_stream(int& stream_id) | ||
| 297 | +{ | ||
| 298 | + int ret = ERROR_SUCCESS; | ||
| 299 | + | ||
| 300 | + // CreateStream | ||
| 301 | + if (true) { | ||
| 302 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 303 | + SrsCreateStreamPacket* pkt = new SrsCreateStreamPacket(); | ||
| 304 | + | ||
| 305 | + msg->set_packet(pkt, 0); | ||
| 306 | + | ||
| 307 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 308 | + return ret; | ||
| 309 | + } | ||
| 310 | + } | ||
| 311 | + | ||
| 312 | + // CreateStream _result. | ||
| 313 | + if (true) { | ||
| 314 | + SrsCommonMessage* msg = NULL; | ||
| 315 | + SrsCreateStreamResPacket* pkt = NULL; | ||
| 316 | + if ((ret = srs_rtmp_expect_message<SrsCreateStreamResPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) { | ||
| 317 | + srs_error("expect create stream response message failed. ret=%d", ret); | ||
| 318 | + return ret; | ||
| 319 | + } | ||
| 320 | + SrsAutoFree(SrsCommonMessage, msg, false); | ||
| 321 | + srs_info("get create stream response message"); | ||
| 322 | + | ||
| 323 | + stream_id = (int)pkt->stream_id; | ||
| 324 | + } | ||
| 325 | + | ||
| 326 | + return ret; | ||
| 327 | +} | ||
| 328 | + | ||
| 329 | +int SrsRtmpClient::play(std::string stream, int stream_id) | ||
| 330 | +{ | ||
| 331 | + int ret = ERROR_SUCCESS; | ||
| 332 | + | ||
| 333 | + // Play(stream) | ||
| 334 | + if (true) { | ||
| 335 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 336 | + SrsPlayPacket* pkt = new SrsPlayPacket(); | ||
| 337 | + | ||
| 338 | + pkt->stream_name = stream; | ||
| 339 | + msg->set_packet(pkt, stream_id); | ||
| 340 | + | ||
| 341 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 342 | + srs_error("send play stream failed. " | ||
| 343 | + "stream=%s, stream_id=%d, ret=%d", | ||
| 344 | + stream.c_str(), stream_id, ret); | ||
| 345 | + return ret; | ||
| 346 | + } | ||
| 347 | + } | ||
| 348 | + | ||
| 349 | + // SetBufferLength(1000ms) | ||
| 350 | + int buffer_length_ms = 1000; | ||
| 351 | + if (true) { | ||
| 352 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 353 | + SrsUserControlPacket* pkt = new SrsUserControlPacket(); | ||
| 354 | + | ||
| 355 | + pkt->event_type = SrcPCUCSetBufferLength; | ||
| 356 | + pkt->event_data = stream_id; | ||
| 357 | + pkt->extra_data = buffer_length_ms; | ||
| 358 | + msg->set_packet(pkt, 0); | ||
| 359 | + | ||
| 360 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 361 | + srs_error("send set buffer length failed. " | ||
| 362 | + "stream=%s, stream_id=%d, bufferLength=%d, ret=%d", | ||
| 363 | + stream.c_str(), stream_id, buffer_length_ms, ret); | ||
| 364 | + return ret; | ||
| 365 | + } | ||
| 366 | + } | ||
| 367 | + | ||
| 368 | + return ret; | ||
| 369 | +} | ||
| 370 | + | ||
| 371 | +int SrsRtmpClient::publish(std::string stream, int stream_id) | ||
| 372 | +{ | ||
| 373 | + int ret = ERROR_SUCCESS; | ||
| 374 | + | ||
| 375 | + // publish(stream) | ||
| 376 | + if (true) { | ||
| 377 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 378 | + SrsPublishPacket* pkt = new SrsPublishPacket(); | ||
| 379 | + | ||
| 380 | + pkt->stream_name = stream; | ||
| 381 | + msg->set_packet(pkt, stream_id); | ||
| 382 | + | ||
| 383 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 384 | + srs_error("send publish message failed. " | ||
| 385 | + "stream=%s, stream_id=%d, ret=%d", | ||
| 386 | + stream.c_str(), stream_id, ret); | ||
| 387 | + return ret; | ||
| 388 | + } | ||
| 389 | + } | ||
| 390 | + | ||
| 391 | + return ret; | ||
| 392 | +} | ||
| 393 | + | ||
| 394 | +SrsRtmp::SrsRtmp(st_netfd_t client_stfd) | ||
| 395 | +{ | ||
| 396 | + protocol = new SrsProtocol(client_stfd); | ||
| 397 | + stfd = client_stfd; | ||
| 398 | +} | ||
| 399 | + | ||
| 400 | +SrsRtmp::~SrsRtmp() | ||
| 401 | +{ | ||
| 402 | + srs_freep(protocol); | ||
| 403 | +} | ||
| 404 | + | ||
| 405 | +SrsProtocol* SrsRtmp::get_protocol() | ||
| 406 | +{ | ||
| 407 | + return protocol; | ||
| 408 | +} | ||
| 409 | + | ||
| 410 | +void SrsRtmp::set_recv_timeout(int64_t timeout_us) | ||
| 411 | +{ | ||
| 412 | + protocol->set_recv_timeout(timeout_us); | ||
| 413 | +} | ||
| 414 | + | ||
| 415 | +int64_t SrsRtmp::get_recv_timeout() | ||
| 416 | +{ | ||
| 417 | + return protocol->get_recv_timeout(); | ||
| 418 | +} | ||
| 419 | + | ||
| 420 | +void SrsRtmp::set_send_timeout(int64_t timeout_us) | ||
| 421 | +{ | ||
| 422 | + protocol->set_send_timeout(timeout_us); | ||
| 423 | +} | ||
| 424 | + | ||
| 425 | +int64_t SrsRtmp::get_recv_bytes() | ||
| 426 | +{ | ||
| 427 | + return protocol->get_recv_bytes(); | ||
| 428 | +} | ||
| 429 | + | ||
| 430 | +int64_t SrsRtmp::get_send_bytes() | ||
| 431 | +{ | ||
| 432 | + return protocol->get_send_bytes(); | ||
| 433 | +} | ||
| 434 | + | ||
| 435 | +int SrsRtmp::get_recv_kbps() | ||
| 436 | +{ | ||
| 437 | + return protocol->get_recv_kbps(); | ||
| 438 | +} | ||
| 439 | + | ||
| 440 | +int SrsRtmp::get_send_kbps() | ||
| 441 | +{ | ||
| 442 | + return protocol->get_send_kbps(); | ||
| 443 | +} | ||
| 444 | + | ||
| 445 | +int SrsRtmp::recv_message(SrsCommonMessage** pmsg) | ||
| 446 | +{ | ||
| 447 | + return protocol->recv_message(pmsg); | ||
| 448 | +} | ||
| 449 | + | ||
| 450 | +int SrsRtmp::send_message(ISrsMessage* msg) | ||
| 451 | +{ | ||
| 452 | + return protocol->send_message(msg); | ||
| 453 | +} | ||
| 454 | + | ||
| 455 | +int SrsRtmp::handshake() | ||
| 456 | +{ | ||
| 457 | + int ret = ERROR_SUCCESS; | ||
| 458 | + | ||
| 459 | + SrsSocket skt(stfd); | ||
| 460 | + | ||
| 461 | + SrsComplexHandshake complex_hs; | ||
| 462 | + SrsSimpleHandshake simple_hs; | ||
| 463 | + if ((ret = simple_hs.handshake_with_client(skt, complex_hs)) != ERROR_SUCCESS) { | ||
| 464 | + return ret; | ||
| 465 | + } | ||
| 466 | + | ||
| 467 | + return ret; | ||
| 468 | +} | ||
| 469 | + | ||
| 470 | +int SrsRtmp::connect_app(SrsRequest* req) | ||
| 471 | +{ | ||
| 472 | + int ret = ERROR_SUCCESS; | ||
| 473 | + | ||
| 474 | + SrsCommonMessage* msg = NULL; | ||
| 475 | + SrsConnectAppPacket* pkt = NULL; | ||
| 476 | + if ((ret = srs_rtmp_expect_message<SrsConnectAppPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) { | ||
| 477 | + srs_error("expect connect app message failed. ret=%d", ret); | ||
| 478 | + return ret; | ||
| 479 | + } | ||
| 480 | + SrsAutoFree(SrsCommonMessage, msg, false); | ||
| 481 | + srs_info("get connect app message"); | ||
| 482 | + | ||
| 483 | + SrsAmf0Any* prop = NULL; | ||
| 484 | + | ||
| 485 | + if ((prop = pkt->command_object->ensure_property_string("tcUrl")) == NULL) { | ||
| 486 | + ret = ERROR_RTMP_REQ_CONNECT; | ||
| 487 | + srs_error("invalid request, must specifies the tcUrl. ret=%d", ret); | ||
| 488 | + return ret; | ||
| 489 | + } | ||
| 490 | + req->tcUrl = srs_amf0_convert<SrsAmf0String>(prop)->value; | ||
| 491 | + | ||
| 492 | + if ((prop = pkt->command_object->ensure_property_string("pageUrl")) != NULL) { | ||
| 493 | + req->pageUrl = srs_amf0_convert<SrsAmf0String>(prop)->value; | ||
| 494 | + } | ||
| 495 | + | ||
| 496 | + if ((prop = pkt->command_object->ensure_property_string("swfUrl")) != NULL) { | ||
| 497 | + req->swfUrl = srs_amf0_convert<SrsAmf0String>(prop)->value; | ||
| 498 | + } | ||
| 499 | + | ||
| 500 | + if ((prop = pkt->command_object->ensure_property_number("objectEncoding")) != NULL) { | ||
| 501 | + req->objectEncoding = srs_amf0_convert<SrsAmf0Number>(prop)->value; | ||
| 502 | + } | ||
| 503 | + | ||
| 504 | + srs_info("get connect app message params success."); | ||
| 505 | + | ||
| 506 | + return req->discovery_app(); | ||
| 507 | +} | ||
| 508 | + | ||
| 509 | +int SrsRtmp::set_window_ack_size(int ack_size) | ||
| 510 | +{ | ||
| 511 | + int ret = ERROR_SUCCESS; | ||
| 512 | + | ||
| 513 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 514 | + SrsSetWindowAckSizePacket* pkt = new SrsSetWindowAckSizePacket(); | ||
| 515 | + | ||
| 516 | + pkt->ackowledgement_window_size = ack_size; | ||
| 517 | + msg->set_packet(pkt, 0); | ||
| 518 | + | ||
| 519 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 520 | + srs_error("send ack size message failed. ret=%d", ret); | ||
| 521 | + return ret; | ||
| 522 | + } | ||
| 523 | + srs_info("send ack size message success. ack_size=%d", ack_size); | ||
| 524 | + | ||
| 525 | + return ret; | ||
| 526 | +} | ||
| 527 | + | ||
| 528 | +int SrsRtmp::set_peer_bandwidth(int bandwidth, int type) | ||
| 529 | +{ | ||
| 530 | + int ret = ERROR_SUCCESS; | ||
| 531 | + | ||
| 532 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 533 | + SrsSetPeerBandwidthPacket* pkt = new SrsSetPeerBandwidthPacket(); | ||
| 534 | + | ||
| 535 | + pkt->bandwidth = bandwidth; | ||
| 536 | + pkt->type = type; | ||
| 537 | + msg->set_packet(pkt, 0); | ||
| 538 | + | ||
| 539 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 540 | + srs_error("send set bandwidth message failed. ret=%d", ret); | ||
| 541 | + return ret; | ||
| 542 | + } | ||
| 543 | + srs_info("send set bandwidth message " | ||
| 544 | + "success. bandwidth=%d, type=%d", bandwidth, type); | ||
| 545 | + | ||
| 546 | + return ret; | ||
| 547 | +} | ||
| 548 | + | ||
| 549 | +int SrsRtmp::response_connect_app(SrsRequest* req) | ||
| 550 | +{ | ||
| 551 | + int ret = ERROR_SUCCESS; | ||
| 552 | + | ||
| 553 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 554 | + SrsConnectAppResPacket* pkt = new SrsConnectAppResPacket(); | ||
| 555 | + | ||
| 556 | + pkt->props->set("fmsVer", new SrsAmf0String("FMS/"RTMP_SIG_FMS_VER)); | ||
| 557 | + pkt->props->set("capabilities", new SrsAmf0Number(127)); | ||
| 558 | + pkt->props->set("mode", new SrsAmf0Number(1)); | ||
| 559 | + | ||
| 560 | + pkt->info->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); | ||
| 561 | + pkt->info->set(StatusCode, new SrsAmf0String(StatusCodeConnectSuccess)); | ||
| 562 | + pkt->info->set(StatusDescription, new SrsAmf0String("Connection succeeded")); | ||
| 563 | + pkt->info->set("objectEncoding", new SrsAmf0Number(req->objectEncoding)); | ||
| 564 | + SrsASrsAmf0EcmaArray* data = new SrsASrsAmf0EcmaArray(); | ||
| 565 | + pkt->info->set("data", data); | ||
| 566 | + | ||
| 567 | + data->set("srs_version", new SrsAmf0String(RTMP_SIG_FMS_VER)); | ||
| 568 | + data->set("srs_server", new SrsAmf0String(RTMP_SIG_SRS_NAME)); | ||
| 569 | + data->set("srs_license", new SrsAmf0String(RTMP_SIG_SRS_LICENSE)); | ||
| 570 | + data->set("srs_role", new SrsAmf0String(RTMP_SIG_SRS_ROLE)); | ||
| 571 | + data->set("srs_url", new SrsAmf0String(RTMP_SIG_SRS_URL)); | ||
| 572 | + data->set("srs_version", new SrsAmf0String(RTMP_SIG_SRS_VERSION)); | ||
| 573 | + data->set("srs_site", new SrsAmf0String(RTMP_SIG_SRS_WEB)); | ||
| 574 | + data->set("srs_email", new SrsAmf0String(RTMP_SIG_SRS_EMAIL)); | ||
| 575 | + data->set("srs_copyright", new SrsAmf0String(RTMP_SIG_SRS_COPYRIGHT)); | ||
| 576 | + | ||
| 577 | + msg->set_packet(pkt, 0); | ||
| 578 | + | ||
| 579 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 580 | + srs_error("send connect app response message failed. ret=%d", ret); | ||
| 581 | + return ret; | ||
| 582 | + } | ||
| 583 | + srs_info("send connect app response message success."); | ||
| 584 | + | ||
| 585 | + return ret; | ||
| 586 | +} | ||
| 587 | + | ||
| 588 | +int SrsRtmp::on_bw_done() | ||
| 589 | +{ | ||
| 590 | + int ret = ERROR_SUCCESS; | ||
| 591 | + | ||
| 592 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 593 | + SrsOnBWDonePacket* pkt = new SrsOnBWDonePacket(); | ||
| 594 | + | ||
| 595 | + msg->set_packet(pkt, 0); | ||
| 596 | + | ||
| 597 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 598 | + srs_error("send onBWDone message failed. ret=%d", ret); | ||
| 599 | + return ret; | ||
| 600 | + } | ||
| 601 | + srs_info("send onBWDone message success."); | ||
| 602 | + | ||
| 603 | + return ret; | ||
| 604 | +} | ||
| 605 | + | ||
| 606 | +int SrsRtmp::identify_client(int stream_id, SrsClientType& type, std::string& stream_name) | ||
| 607 | +{ | ||
| 608 | + type = SrsClientUnknown; | ||
| 609 | + int ret = ERROR_SUCCESS; | ||
| 610 | + | ||
| 611 | + while (true) { | ||
| 612 | + SrsCommonMessage* msg = NULL; | ||
| 613 | + if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) { | ||
| 614 | + srs_error("recv identify client message failed. ret=%d", ret); | ||
| 615 | + return ret; | ||
| 616 | + } | ||
| 617 | + | ||
| 618 | + SrsAutoFree(SrsCommonMessage, msg, false); | ||
| 619 | + | ||
| 620 | + if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) { | ||
| 621 | + srs_trace("identify ignore messages except " | ||
| 622 | + "AMF0/AMF3 command message. type=%#x", msg->header.message_type); | ||
| 623 | + continue; | ||
| 624 | + } | ||
| 625 | + | ||
| 626 | + if ((ret = msg->decode_packet(protocol)) != ERROR_SUCCESS) { | ||
| 627 | + srs_error("identify decode message failed. ret=%d", ret); | ||
| 628 | + return ret; | ||
| 629 | + } | ||
| 630 | + | ||
| 631 | + SrsPacket* pkt = msg->get_packet(); | ||
| 632 | + if (dynamic_cast<SrsCreateStreamPacket*>(pkt)) { | ||
| 633 | + srs_info("identify client by create stream, play or flash publish."); | ||
| 634 | + return identify_create_stream_client( | ||
| 635 | + dynamic_cast<SrsCreateStreamPacket*>(pkt), stream_id, type, stream_name); | ||
| 636 | + } | ||
| 637 | + if (dynamic_cast<SrsFMLEStartPacket*>(pkt)) { | ||
| 638 | + srs_info("identify client by releaseStream, fmle publish."); | ||
| 639 | + return identify_fmle_publish_client( | ||
| 640 | + dynamic_cast<SrsFMLEStartPacket*>(pkt), type, stream_name); | ||
| 641 | + } | ||
| 642 | + | ||
| 643 | + srs_trace("ignore AMF0/AMF3 command message."); | ||
| 644 | + } | ||
| 645 | + | ||
| 646 | + return ret; | ||
| 647 | +} | ||
| 648 | + | ||
| 649 | +int SrsRtmp::set_chunk_size(int chunk_size) | ||
| 650 | +{ | ||
| 651 | + int ret = ERROR_SUCCESS; | ||
| 652 | + | ||
| 653 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 654 | + SrsSetChunkSizePacket* pkt = new SrsSetChunkSizePacket(); | ||
| 655 | + | ||
| 656 | + pkt->chunk_size = chunk_size; | ||
| 657 | + msg->set_packet(pkt, 0); | ||
| 658 | + | ||
| 659 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 660 | + srs_error("send set chunk size message failed. ret=%d", ret); | ||
| 661 | + return ret; | ||
| 662 | + } | ||
| 663 | + srs_info("send set chunk size message success. chunk_size=%d", chunk_size); | ||
| 664 | + | ||
| 665 | + return ret; | ||
| 666 | +} | ||
| 667 | + | ||
| 668 | +int SrsRtmp::start_play(int stream_id) | ||
| 669 | +{ | ||
| 670 | + int ret = ERROR_SUCCESS; | ||
| 671 | + | ||
| 672 | + // StreamBegin | ||
| 673 | + if (true) { | ||
| 674 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 675 | + SrsUserControlPacket* pkt = new SrsUserControlPacket(); | ||
| 676 | + | ||
| 677 | + pkt->event_type = SrcPCUCStreamBegin; | ||
| 678 | + pkt->event_data = stream_id; | ||
| 679 | + msg->set_packet(pkt, 0); | ||
| 680 | + | ||
| 681 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 682 | + srs_error("send PCUC(StreamBegin) message failed. ret=%d", ret); | ||
| 683 | + return ret; | ||
| 684 | + } | ||
| 685 | + srs_info("send PCUC(StreamBegin) message success."); | ||
| 686 | + } | ||
| 687 | + | ||
| 688 | + // onStatus(NetStream.Play.Reset) | ||
| 689 | + if (true) { | ||
| 690 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 691 | + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); | ||
| 692 | + | ||
| 693 | + pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); | ||
| 694 | + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeStreamReset)); | ||
| 695 | + pkt->data->set(StatusDescription, new SrsAmf0String("Playing and resetting stream.")); | ||
| 696 | + pkt->data->set(StatusDetails, new SrsAmf0String("stream")); | ||
| 697 | + pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); | ||
| 698 | + | ||
| 699 | + msg->set_packet(pkt, stream_id); | ||
| 700 | + | ||
| 701 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 702 | + srs_error("send onStatus(NetStream.Play.Reset) message failed. ret=%d", ret); | ||
| 703 | + return ret; | ||
| 704 | + } | ||
| 705 | + srs_info("send onStatus(NetStream.Play.Reset) message success."); | ||
| 706 | + } | ||
| 707 | + | ||
| 708 | + // onStatus(NetStream.Play.Start) | ||
| 709 | + if (true) { | ||
| 710 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 711 | + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); | ||
| 712 | + | ||
| 713 | + pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); | ||
| 714 | + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeStreamStart)); | ||
| 715 | + pkt->data->set(StatusDescription, new SrsAmf0String("Started playing stream.")); | ||
| 716 | + pkt->data->set(StatusDetails, new SrsAmf0String("stream")); | ||
| 717 | + pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); | ||
| 718 | + | ||
| 719 | + msg->set_packet(pkt, stream_id); | ||
| 720 | + | ||
| 721 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 722 | + srs_error("send onStatus(NetStream.Play.Reset) message failed. ret=%d", ret); | ||
| 723 | + return ret; | ||
| 724 | + } | ||
| 725 | + srs_info("send onStatus(NetStream.Play.Reset) message success."); | ||
| 726 | + } | ||
| 727 | + | ||
| 728 | + // |RtmpSampleAccess(false, false) | ||
| 729 | + if (true) { | ||
| 730 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 731 | + SrsSampleAccessPacket* pkt = new SrsSampleAccessPacket(); | ||
| 732 | + | ||
| 733 | + msg->set_packet(pkt, stream_id); | ||
| 734 | + | ||
| 735 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 736 | + srs_error("send |RtmpSampleAccess(false, false) message failed. ret=%d", ret); | ||
| 737 | + return ret; | ||
| 738 | + } | ||
| 739 | + srs_info("send |RtmpSampleAccess(false, false) message success."); | ||
| 740 | + } | ||
| 741 | + | ||
| 742 | + // onStatus(NetStream.Data.Start) | ||
| 743 | + if (true) { | ||
| 744 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 745 | + SrsOnStatusDataPacket* pkt = new SrsOnStatusDataPacket(); | ||
| 746 | + | ||
| 747 | + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeDataStart)); | ||
| 748 | + | ||
| 749 | + msg->set_packet(pkt, stream_id); | ||
| 750 | + | ||
| 751 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 752 | + srs_error("send onStatus(NetStream.Data.Start) message failed. ret=%d", ret); | ||
| 753 | + return ret; | ||
| 754 | + } | ||
| 755 | + srs_info("send onStatus(NetStream.Data.Start) message success."); | ||
| 756 | + } | ||
| 757 | + | ||
| 758 | + srs_info("start play success."); | ||
| 759 | + | ||
| 760 | + return ret; | ||
| 761 | +} | ||
| 762 | + | ||
| 763 | +int SrsRtmp::on_play_client_pause(int stream_id, bool is_pause) | ||
| 764 | +{ | ||
| 765 | + int ret = ERROR_SUCCESS; | ||
| 766 | + | ||
| 767 | + if (is_pause) { | ||
| 768 | + // onStatus(NetStream.Pause.Notify) | ||
| 769 | + if (true) { | ||
| 770 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 771 | + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); | ||
| 772 | + | ||
| 773 | + pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); | ||
| 774 | + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeStreamPause)); | ||
| 775 | + pkt->data->set(StatusDescription, new SrsAmf0String("Paused stream.")); | ||
| 776 | + | ||
| 777 | + msg->set_packet(pkt, stream_id); | ||
| 778 | + | ||
| 779 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 780 | + srs_error("send onStatus(NetStream.Pause.Notify) message failed. ret=%d", ret); | ||
| 781 | + return ret; | ||
| 782 | + } | ||
| 783 | + srs_info("send onStatus(NetStream.Pause.Notify) message success."); | ||
| 784 | + } | ||
| 785 | + // StreamEOF | ||
| 786 | + if (true) { | ||
| 787 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 788 | + SrsUserControlPacket* pkt = new SrsUserControlPacket(); | ||
| 789 | + | ||
| 790 | + pkt->event_type = SrcPCUCStreamEOF; | ||
| 791 | + pkt->event_data = stream_id; | ||
| 792 | + msg->set_packet(pkt, 0); | ||
| 793 | + | ||
| 794 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 795 | + srs_error("send PCUC(StreamEOF) message failed. ret=%d", ret); | ||
| 796 | + return ret; | ||
| 797 | + } | ||
| 798 | + srs_info("send PCUC(StreamEOF) message success."); | ||
| 799 | + } | ||
| 800 | + } else { | ||
| 801 | + // onStatus(NetStream.Unpause.Notify) | ||
| 802 | + if (true) { | ||
| 803 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 804 | + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); | ||
| 805 | + | ||
| 806 | + pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); | ||
| 807 | + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeStreamUnpause)); | ||
| 808 | + pkt->data->set(StatusDescription, new SrsAmf0String("Unpaused stream.")); | ||
| 809 | + | ||
| 810 | + msg->set_packet(pkt, stream_id); | ||
| 811 | + | ||
| 812 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 813 | + srs_error("send onStatus(NetStream.Unpause.Notify) message failed. ret=%d", ret); | ||
| 814 | + return ret; | ||
| 815 | + } | ||
| 816 | + srs_info("send onStatus(NetStream.Unpause.Notify) message success."); | ||
| 817 | + } | ||
| 818 | + // StreanBegin | ||
| 819 | + if (true) { | ||
| 820 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 821 | + SrsUserControlPacket* pkt = new SrsUserControlPacket(); | ||
| 822 | + | ||
| 823 | + pkt->event_type = SrcPCUCStreamBegin; | ||
| 824 | + pkt->event_data = stream_id; | ||
| 825 | + msg->set_packet(pkt, 0); | ||
| 826 | + | ||
| 827 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 828 | + srs_error("send PCUC(StreanBegin) message failed. ret=%d", ret); | ||
| 829 | + return ret; | ||
| 830 | + } | ||
| 831 | + srs_info("send PCUC(StreanBegin) message success."); | ||
| 832 | + } | ||
| 833 | + } | ||
| 834 | + | ||
| 835 | + return ret; | ||
| 836 | +} | ||
| 837 | + | ||
| 838 | +int SrsRtmp::start_fmle_publish(int stream_id) | ||
| 839 | +{ | ||
| 840 | + int ret = ERROR_SUCCESS; | ||
| 841 | + | ||
| 842 | + // FCPublish | ||
| 843 | + double fc_publish_tid = 0; | ||
| 844 | + if (true) { | ||
| 845 | + SrsCommonMessage* msg = NULL; | ||
| 846 | + SrsFMLEStartPacket* pkt = NULL; | ||
| 847 | + if ((ret = srs_rtmp_expect_message<SrsFMLEStartPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) { | ||
| 848 | + srs_error("recv FCPublish message failed. ret=%d", ret); | ||
| 849 | + return ret; | ||
| 850 | + } | ||
| 851 | + srs_info("recv FCPublish request message success."); | ||
| 852 | + | ||
| 853 | + SrsAutoFree(SrsCommonMessage, msg, false); | ||
| 854 | + fc_publish_tid = pkt->transaction_id; | ||
| 855 | + } | ||
| 856 | + // FCPublish response | ||
| 857 | + if (true) { | ||
| 858 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 859 | + SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(fc_publish_tid); | ||
| 860 | + | ||
| 861 | + msg->set_packet(pkt, 0); | ||
| 862 | + | ||
| 863 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 864 | + srs_error("send FCPublish response message failed. ret=%d", ret); | ||
| 865 | + return ret; | ||
| 866 | + } | ||
| 867 | + srs_info("send FCPublish response message success."); | ||
| 868 | + } | ||
| 869 | + | ||
| 870 | + // createStream | ||
| 871 | + double create_stream_tid = 0; | ||
| 872 | + if (true) { | ||
| 873 | + SrsCommonMessage* msg = NULL; | ||
| 874 | + SrsCreateStreamPacket* pkt = NULL; | ||
| 875 | + if ((ret = srs_rtmp_expect_message<SrsCreateStreamPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) { | ||
| 876 | + srs_error("recv createStream message failed. ret=%d", ret); | ||
| 877 | + return ret; | ||
| 878 | + } | ||
| 879 | + srs_info("recv createStream request message success."); | ||
| 880 | + | ||
| 881 | + SrsAutoFree(SrsCommonMessage, msg, false); | ||
| 882 | + create_stream_tid = pkt->transaction_id; | ||
| 883 | + } | ||
| 884 | + // createStream response | ||
| 885 | + if (true) { | ||
| 886 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 887 | + SrsCreateStreamResPacket* pkt = new SrsCreateStreamResPacket(create_stream_tid, stream_id); | ||
| 888 | + | ||
| 889 | + msg->set_packet(pkt, 0); | ||
| 890 | + | ||
| 891 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 892 | + srs_error("send createStream response message failed. ret=%d", ret); | ||
| 893 | + return ret; | ||
| 894 | + } | ||
| 895 | + srs_info("send createStream response message success."); | ||
| 896 | + } | ||
| 897 | + | ||
| 898 | + // publish | ||
| 899 | + if (true) { | ||
| 900 | + SrsCommonMessage* msg = NULL; | ||
| 901 | + SrsPublishPacket* pkt = NULL; | ||
| 902 | + if ((ret = srs_rtmp_expect_message<SrsPublishPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) { | ||
| 903 | + srs_error("recv publish message failed. ret=%d", ret); | ||
| 904 | + return ret; | ||
| 905 | + } | ||
| 906 | + srs_info("recv publish request message success."); | ||
| 907 | + | ||
| 908 | + SrsAutoFree(SrsCommonMessage, msg, false); | ||
| 909 | + } | ||
| 910 | + // publish response onFCPublish(NetStream.Publish.Start) | ||
| 911 | + if (true) { | ||
| 912 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 913 | + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); | ||
| 914 | + | ||
| 915 | + pkt->command_name = RTMP_AMF0_COMMAND_ON_FC_PUBLISH; | ||
| 916 | + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodePublishStart)); | ||
| 917 | + pkt->data->set(StatusDescription, new SrsAmf0String("Started publishing stream.")); | ||
| 918 | + | ||
| 919 | + msg->set_packet(pkt, stream_id); | ||
| 920 | + | ||
| 921 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 922 | + srs_error("send onFCPublish(NetStream.Publish.Start) message failed. ret=%d", ret); | ||
| 923 | + return ret; | ||
| 924 | + } | ||
| 925 | + srs_info("send onFCPublish(NetStream.Publish.Start) message success."); | ||
| 926 | + } | ||
| 927 | + // publish response onStatus(NetStream.Publish.Start) | ||
| 928 | + if (true) { | ||
| 929 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 930 | + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); | ||
| 931 | + | ||
| 932 | + pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); | ||
| 933 | + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodePublishStart)); | ||
| 934 | + pkt->data->set(StatusDescription, new SrsAmf0String("Started publishing stream.")); | ||
| 935 | + pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); | ||
| 936 | + | ||
| 937 | + msg->set_packet(pkt, stream_id); | ||
| 938 | + | ||
| 939 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 940 | + srs_error("send onStatus(NetStream.Publish.Start) message failed. ret=%d", ret); | ||
| 941 | + return ret; | ||
| 942 | + } | ||
| 943 | + srs_info("send onStatus(NetStream.Publish.Start) message success."); | ||
| 944 | + } | ||
| 945 | + | ||
| 946 | + srs_info("FMLE publish success."); | ||
| 947 | + | ||
| 948 | + return ret; | ||
| 949 | +} | ||
| 950 | + | ||
| 951 | +int SrsRtmp::fmle_unpublish(int stream_id, double unpublish_tid) | ||
| 952 | +{ | ||
| 953 | + int ret = ERROR_SUCCESS; | ||
| 954 | + | ||
| 955 | + // publish response onFCUnpublish(NetStream.unpublish.Success) | ||
| 956 | + if (true) { | ||
| 957 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 958 | + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); | ||
| 959 | + | ||
| 960 | + pkt->command_name = RTMP_AMF0_COMMAND_ON_FC_UNPUBLISH; | ||
| 961 | + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeUnpublishSuccess)); | ||
| 962 | + pkt->data->set(StatusDescription, new SrsAmf0String("Stop publishing stream.")); | ||
| 963 | + | ||
| 964 | + msg->set_packet(pkt, stream_id); | ||
| 965 | + | ||
| 966 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 967 | + srs_error("send onFCUnpublish(NetStream.unpublish.Success) message failed. ret=%d", ret); | ||
| 968 | + return ret; | ||
| 969 | + } | ||
| 970 | + srs_info("send onFCUnpublish(NetStream.unpublish.Success) message success."); | ||
| 971 | + } | ||
| 972 | + // FCUnpublish response | ||
| 973 | + if (true) { | ||
| 974 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 975 | + SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(unpublish_tid); | ||
| 976 | + | ||
| 977 | + msg->set_packet(pkt, stream_id); | ||
| 978 | + | ||
| 979 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 980 | + srs_error("send FCUnpublish response message failed. ret=%d", ret); | ||
| 981 | + return ret; | ||
| 982 | + } | ||
| 983 | + srs_info("send FCUnpublish response message success."); | ||
| 984 | + } | ||
| 985 | + // publish response onStatus(NetStream.Unpublish.Success) | ||
| 986 | + if (true) { | ||
| 987 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 988 | + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); | ||
| 989 | + | ||
| 990 | + pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); | ||
| 991 | + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeUnpublishSuccess)); | ||
| 992 | + pkt->data->set(StatusDescription, new SrsAmf0String("Stream is now unpublished")); | ||
| 993 | + pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); | ||
| 994 | + | ||
| 995 | + msg->set_packet(pkt, stream_id); | ||
| 996 | + | ||
| 997 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 998 | + srs_error("send onStatus(NetStream.Unpublish.Success) message failed. ret=%d", ret); | ||
| 999 | + return ret; | ||
| 1000 | + } | ||
| 1001 | + srs_info("send onStatus(NetStream.Unpublish.Success) message success."); | ||
| 1002 | + } | ||
| 1003 | + | ||
| 1004 | + srs_info("FMLE unpublish success."); | ||
| 1005 | + | ||
| 1006 | + return ret; | ||
| 1007 | +} | ||
| 1008 | + | ||
| 1009 | +int SrsRtmp::start_flash_publish(int stream_id) | ||
| 1010 | +{ | ||
| 1011 | + int ret = ERROR_SUCCESS; | ||
| 1012 | + | ||
| 1013 | + // publish response onStatus(NetStream.Publish.Start) | ||
| 1014 | + if (true) { | ||
| 1015 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 1016 | + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); | ||
| 1017 | + | ||
| 1018 | + pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); | ||
| 1019 | + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodePublishStart)); | ||
| 1020 | + pkt->data->set(StatusDescription, new SrsAmf0String("Started publishing stream.")); | ||
| 1021 | + pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); | ||
| 1022 | + | ||
| 1023 | + msg->set_packet(pkt, stream_id); | ||
| 1024 | + | ||
| 1025 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 1026 | + srs_error("send onStatus(NetStream.Publish.Start) message failed. ret=%d", ret); | ||
| 1027 | + return ret; | ||
| 1028 | + } | ||
| 1029 | + srs_info("send onStatus(NetStream.Publish.Start) message success."); | ||
| 1030 | + } | ||
| 1031 | + | ||
| 1032 | + srs_info("flash publish success."); | ||
| 1033 | + | ||
| 1034 | + return ret; | ||
| 1035 | +} | ||
| 1036 | + | ||
| 1037 | +int SrsRtmp::identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name) | ||
| 1038 | +{ | ||
| 1039 | + int ret = ERROR_SUCCESS; | ||
| 1040 | + | ||
| 1041 | + if (true) { | ||
| 1042 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 1043 | + SrsCreateStreamResPacket* pkt = new SrsCreateStreamResPacket(req->transaction_id, stream_id); | ||
| 1044 | + | ||
| 1045 | + msg->set_packet(pkt, 0); | ||
| 1046 | + | ||
| 1047 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 1048 | + srs_error("send createStream response message failed. ret=%d", ret); | ||
| 1049 | + return ret; | ||
| 1050 | + } | ||
| 1051 | + srs_info("send createStream response message success."); | ||
| 1052 | + } | ||
| 1053 | + | ||
| 1054 | + while (true) { | ||
| 1055 | + SrsCommonMessage* msg = NULL; | ||
| 1056 | + if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) { | ||
| 1057 | + srs_error("recv identify client message failed. ret=%d", ret); | ||
| 1058 | + return ret; | ||
| 1059 | + } | ||
| 1060 | + | ||
| 1061 | + SrsAutoFree(SrsCommonMessage, msg, false); | ||
| 1062 | + | ||
| 1063 | + if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) { | ||
| 1064 | + srs_trace("identify ignore messages except " | ||
| 1065 | + "AMF0/AMF3 command message. type=%#x", msg->header.message_type); | ||
| 1066 | + continue; | ||
| 1067 | + } | ||
| 1068 | + | ||
| 1069 | + if ((ret = msg->decode_packet(protocol)) != ERROR_SUCCESS) { | ||
| 1070 | + srs_error("identify decode message failed. ret=%d", ret); | ||
| 1071 | + return ret; | ||
| 1072 | + } | ||
| 1073 | + | ||
| 1074 | + SrsPacket* pkt = msg->get_packet(); | ||
| 1075 | + if (dynamic_cast<SrsPlayPacket*>(pkt)) { | ||
| 1076 | + SrsPlayPacket* play = dynamic_cast<SrsPlayPacket*>(pkt); | ||
| 1077 | + type = SrsClientPlay; | ||
| 1078 | + stream_name = play->stream_name; | ||
| 1079 | + srs_trace("identity client type=play, stream_name=%s", stream_name.c_str()); | ||
| 1080 | + return ret; | ||
| 1081 | + } | ||
| 1082 | + if (dynamic_cast<SrsPublishPacket*>(pkt)) { | ||
| 1083 | + srs_info("identify client by publish, falsh publish."); | ||
| 1084 | + return identify_flash_publish_client( | ||
| 1085 | + dynamic_cast<SrsPublishPacket*>(pkt), type, stream_name); | ||
| 1086 | + } | ||
| 1087 | + | ||
| 1088 | + srs_trace("ignore AMF0/AMF3 command message."); | ||
| 1089 | + } | ||
| 1090 | + | ||
| 1091 | + return ret; | ||
| 1092 | +} | ||
| 1093 | + | ||
| 1094 | +int SrsRtmp::identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, std::string& stream_name) | ||
| 1095 | +{ | ||
| 1096 | + int ret = ERROR_SUCCESS; | ||
| 1097 | + | ||
| 1098 | + type = SrsClientFMLEPublish; | ||
| 1099 | + stream_name = req->stream_name; | ||
| 1100 | + | ||
| 1101 | + // releaseStream response | ||
| 1102 | + if (true) { | ||
| 1103 | + SrsCommonMessage* msg = new SrsCommonMessage(); | ||
| 1104 | + SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(req->transaction_id); | ||
| 1105 | + | ||
| 1106 | + msg->set_packet(pkt, 0); | ||
| 1107 | + | ||
| 1108 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 1109 | + srs_error("send releaseStream response message failed. ret=%d", ret); | ||
| 1110 | + return ret; | ||
| 1111 | + } | ||
| 1112 | + srs_info("send releaseStream response message success."); | ||
| 1113 | + } | ||
| 1114 | + | ||
| 1115 | + return ret; | ||
| 1116 | +} | ||
| 1117 | + | ||
| 1118 | +int SrsRtmp::identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name) | ||
| 1119 | +{ | ||
| 1120 | + int ret = ERROR_SUCCESS; | ||
| 1121 | + | ||
| 1122 | + type = SrsClientFlashPublish; | ||
| 1123 | + stream_name = req->stream_name; | ||
| 1124 | + | ||
| 1125 | + return ret; | ||
| 1126 | +} | ||
| 1127 | + |
| @@ -32,8 +32,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -32,8 +32,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 32 | 32 | ||
| 33 | #include <string> | 33 | #include <string> |
| 34 | 34 | ||
| 35 | -#include <st.h> | ||
| 36 | - | ||
| 37 | class SrsProtocol; | 35 | class SrsProtocol; |
| 38 | class ISrsMessage; | 36 | class ISrsMessage; |
| 39 | class SrsCommonMessage; | 37 | class SrsCommonMessage; |
| @@ -30,8 +30,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -30,8 +30,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 30 | 30 | ||
| 31 | #include <algorithm> | 31 | #include <algorithm> |
| 32 | 32 | ||
| 33 | -#include <st.h> | ||
| 34 | - | ||
| 35 | #include <srs_core_log.hpp> | 33 | #include <srs_core_log.hpp> |
| 36 | #include <srs_core_error.hpp> | 34 | #include <srs_core_error.hpp> |
| 37 | #include <srs_core_client.hpp> | 35 | #include <srs_core_client.hpp> |
| @@ -48,24 +46,16 @@ SrsListener::SrsListener(SrsServer* _server, SrsListenerType _type) | @@ -48,24 +46,16 @@ SrsListener::SrsListener(SrsServer* _server, SrsListenerType _type) | ||
| 48 | port = 0; | 46 | port = 0; |
| 49 | server = _server; | 47 | server = _server; |
| 50 | type = _type; | 48 | type = _type; |
| 51 | - | ||
| 52 | - tid = NULL; | ||
| 53 | - loop = false; | 49 | + |
| 50 | + pthread = new SrsThread(this, 0); | ||
| 54 | } | 51 | } |
| 55 | 52 | ||
| 56 | SrsListener::~SrsListener() | 53 | SrsListener::~SrsListener() |
| 57 | { | 54 | { |
| 58 | - if (stfd) { | ||
| 59 | - st_netfd_close(stfd); | ||
| 60 | - stfd = NULL; | ||
| 61 | - } | 55 | + srs_close_stfd(stfd); |
| 62 | 56 | ||
| 63 | - if (tid) { | ||
| 64 | - loop = false; | ||
| 65 | - st_thread_interrupt(tid); | ||
| 66 | - st_thread_join(tid, NULL); | ||
| 67 | - tid = NULL; | ||
| 68 | - } | 57 | + pthread->stop(); |
| 58 | + srs_freep(pthread); | ||
| 69 | 59 | ||
| 70 | // st does not close it sometimes, | 60 | // st does not close it sometimes, |
| 71 | // close it manually. | 61 | // close it manually. |
| @@ -118,8 +108,7 @@ int SrsListener::listen(int _port) | @@ -118,8 +108,7 @@ int SrsListener::listen(int _port) | ||
| 118 | } | 108 | } |
| 119 | srs_verbose("st open socket success. fd=%d", fd); | 109 | srs_verbose("st open socket success. fd=%d", fd); |
| 120 | 110 | ||
| 121 | - if ((tid = st_thread_create(listen_thread, this, 1, 0)) == NULL) { | ||
| 122 | - ret = ERROR_ST_CREATE_LISTEN_THREAD; | 111 | + if ((ret = pthread->start()) != ERROR_SUCCESS) { |
| 123 | srs_error("st_thread_create listen thread error. ret=%d", ret); | 112 | srs_error("st_thread_create listen thread error. ret=%d", ret); |
| 124 | return ret; | 113 | return ret; |
| 125 | } | 114 | } |
| @@ -130,41 +119,32 @@ int SrsListener::listen(int _port) | @@ -130,41 +119,32 @@ int SrsListener::listen(int _port) | ||
| 130 | return ret; | 119 | return ret; |
| 131 | } | 120 | } |
| 132 | 121 | ||
| 133 | -void SrsListener::listen_cycle() | 122 | +void SrsListener::on_enter_loop() |
| 134 | { | 123 | { |
| 135 | - int ret = ERROR_SUCCESS; | ||
| 136 | - | ||
| 137 | - log_context->generate_id(); | ||
| 138 | srs_trace("listen cycle start, port=%d, type=%d, fd=%d", port, type, fd); | 124 | srs_trace("listen cycle start, port=%d, type=%d, fd=%d", port, type, fd); |
| 139 | - | ||
| 140 | - while (loop) { | ||
| 141 | - st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT); | ||
| 142 | - | ||
| 143 | - if(client_stfd == NULL){ | ||
| 144 | - // ignore error. | ||
| 145 | - srs_warn("ignore accept thread stoppped for accept client error"); | ||
| 146 | - continue; | ||
| 147 | - } | ||
| 148 | - srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd)); | ||
| 149 | - | ||
| 150 | - if ((ret = server->accept_client(type, client_stfd)) != ERROR_SUCCESS) { | ||
| 151 | - srs_warn("accept client error. ret=%d", ret); | ||
| 152 | - continue; | ||
| 153 | - } | ||
| 154 | - | ||
| 155 | - srs_verbose("accept client finished. conns=%d, ret=%d", (int)conns.size(), ret); | ||
| 156 | - } | ||
| 157 | } | 125 | } |
| 158 | 126 | ||
| 159 | -void* SrsListener::listen_thread(void* arg) | 127 | +int SrsListener::cycle() |
| 160 | { | 128 | { |
| 161 | - SrsListener* obj = (SrsListener*)arg; | ||
| 162 | - srs_assert(obj != NULL); | 129 | + int ret = ERROR_SUCCESS; |
| 163 | 130 | ||
| 164 | - obj->loop = true; | ||
| 165 | - obj->listen_cycle(); | 131 | + st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT); |
| 132 | + | ||
| 133 | + if(client_stfd == NULL){ | ||
| 134 | + // ignore error. | ||
| 135 | + srs_warn("ignore accept thread stoppped for accept client error"); | ||
| 136 | + return ret; | ||
| 137 | + } | ||
| 138 | + srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd)); | ||
| 166 | 139 | ||
| 167 | - return NULL; | 140 | + if ((ret = server->accept_client(type, client_stfd)) != ERROR_SUCCESS) { |
| 141 | + srs_warn("accept client error. ret=%d", ret); | ||
| 142 | + return ret; | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + srs_verbose("accept client finished. conns=%d, ret=%d", (int)conns.size(), ret); | ||
| 146 | + | ||
| 147 | + return ret; | ||
| 168 | } | 148 | } |
| 169 | 149 | ||
| 170 | SrsServer::SrsServer() | 150 | SrsServer::SrsServer() |
| @@ -312,8 +292,7 @@ int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd) | @@ -312,8 +292,7 @@ int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd) | ||
| 312 | srs_error("exceed the max connections, drop client: " | 292 | srs_error("exceed the max connections, drop client: " |
| 313 | "clients=%d, max=%d, fd=%d", (int)conns.size(), max_connections, fd); | 293 | "clients=%d, max=%d, fd=%d", (int)conns.size(), max_connections, fd); |
| 314 | 294 | ||
| 315 | - st_netfd_close(client_stfd); | ||
| 316 | - ::close(fd); | 295 | + srs_close_stfd(client_stfd); |
| 317 | 296 | ||
| 318 | return ret; | 297 | return ret; |
| 319 | } | 298 | } |
| @@ -32,9 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -32,9 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 32 | 32 | ||
| 33 | #include <vector> | 33 | #include <vector> |
| 34 | 34 | ||
| 35 | -#include <st.h> | ||
| 36 | - | ||
| 37 | #include <srs_core_reload.hpp> | 35 | #include <srs_core_reload.hpp> |
| 36 | +#include <srs_core_thread.hpp> | ||
| 38 | 37 | ||
| 39 | class SrsServer; | 38 | class SrsServer; |
| 40 | class SrsConnection; | 39 | class SrsConnection; |
| @@ -45,7 +44,7 @@ enum SrsListenerType | @@ -45,7 +44,7 @@ enum SrsListenerType | ||
| 45 | SrsListenerApi | 44 | SrsListenerApi |
| 46 | }; | 45 | }; |
| 47 | 46 | ||
| 48 | -class SrsListener | 47 | +class SrsListener : public ISrsThreadHandler |
| 49 | { | 48 | { |
| 50 | public: | 49 | public: |
| 51 | SrsListenerType type; | 50 | SrsListenerType type; |
| @@ -54,16 +53,16 @@ private: | @@ -54,16 +53,16 @@ private: | ||
| 54 | st_netfd_t stfd; | 53 | st_netfd_t stfd; |
| 55 | int port; | 54 | int port; |
| 56 | SrsServer* server; | 55 | SrsServer* server; |
| 57 | - st_thread_t tid; | ||
| 58 | - bool loop; | 56 | + SrsThread* pthread; |
| 59 | public: | 57 | public: |
| 60 | SrsListener(SrsServer* _server, SrsListenerType _type); | 58 | SrsListener(SrsServer* _server, SrsListenerType _type); |
| 61 | virtual ~SrsListener(); | 59 | virtual ~SrsListener(); |
| 62 | public: | 60 | public: |
| 63 | virtual int listen(int port); | 61 | virtual int listen(int port); |
| 64 | -private: | ||
| 65 | - virtual void listen_cycle(); | ||
| 66 | - static void* listen_thread(void* arg); | 62 | +// interface ISrsThreadHandler. |
| 63 | +public: | ||
| 64 | + virtual void on_enter_loop(); | ||
| 65 | + virtual int cycle(); | ||
| 67 | }; | 66 | }; |
| 68 | 67 | ||
| 69 | class SrsServer : public SrsReloadHandler | 68 | class SrsServer : public SrsReloadHandler |
| @@ -30,8 +30,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -30,8 +30,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 30 | 30 | ||
| 31 | #include <srs_core.hpp> | 31 | #include <srs_core.hpp> |
| 32 | 32 | ||
| 33 | -#include <st.h> | ||
| 34 | - | ||
| 35 | /** | 33 | /** |
| 36 | * the socket provides TCP socket over st, | 34 | * the socket provides TCP socket over st, |
| 37 | * that is, the sync socket mechanism. | 35 | * that is, the sync socket mechanism. |
-
请 注册 或 登录 后发表评论