正在显示
7 个修改的文件
包含
74 行增加
和
20 行删除
| @@ -13,6 +13,8 @@ vhost __defaultVhost__ { | @@ -13,6 +13,8 @@ vhost __defaultVhost__ { | ||
| 13 | gop_cache on; | 13 | gop_cache on; |
| 14 | hls on; | 14 | hls on; |
| 15 | hls_path ./objs/nginx/html; | 15 | hls_path ./objs/nginx/html; |
| 16 | + hls_fragment 10; | ||
| 17 | + hls_window 60; | ||
| 16 | } | 18 | } |
| 17 | # the vhost disabled. | 19 | # the vhost disabled. |
| 18 | vhost removed.vhost.com { | 20 | vhost removed.vhost.com { |
| @@ -39,6 +41,12 @@ vhost no-hls.vhost.com { | @@ -39,6 +41,12 @@ vhost no-hls.vhost.com { | ||
| 39 | # in a word, the hls_path is for vhost. | 41 | # in a word, the hls_path is for vhost. |
| 40 | # default: ./objs/nginx/html | 42 | # default: ./objs/nginx/html |
| 41 | hls_path /data/nginx/html; | 43 | hls_path /data/nginx/html; |
| 44 | + # the hls fragment in seconds, the duration of a piece of ts. | ||
| 45 | + # default: 10 | ||
| 46 | + hls_fragment 10; | ||
| 47 | + # the hls window in seconds, the number of ts in m3u8. | ||
| 48 | + # default: 60 | ||
| 49 | + hls_window 60; | ||
| 42 | } | 50 | } |
| 43 | # the vhost with hls disabled. | 51 | # the vhost with hls disabled. |
| 44 | vhost no-hls.vhost.com { | 52 | vhost no-hls.vhost.com { |
| @@ -332,7 +332,7 @@ int SrsClient::publish(SrsSource* source, bool is_fmle) | @@ -332,7 +332,7 @@ int SrsClient::publish(SrsSource* source, bool is_fmle) | ||
| 332 | SrsPithyPrint pithy_print(SRS_STAGE_PUBLISH_USER); | 332 | SrsPithyPrint pithy_print(SRS_STAGE_PUBLISH_USER); |
| 333 | 333 | ||
| 334 | // notify the hls to prepare when publish start. | 334 | // notify the hls to prepare when publish start. |
| 335 | - if ((ret = source->on_publish(req->vhost, req->stream)) != ERROR_SUCCESS) { | 335 | + if ((ret = source->on_publish(req->vhost, req->app, req->stream)) != ERROR_SUCCESS) { |
| 336 | srs_error("hls on_publish failed. ret=%d", ret); | 336 | srs_error("hls on_publish failed. ret=%d", ret); |
| 337 | return ret; | 337 | return ret; |
| 338 | } | 338 | } |
| @@ -109,7 +109,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -109,7 +109,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 109 | 109 | ||
| 110 | #define ERROR_HLS_METADATA 600 | 110 | #define ERROR_HLS_METADATA 600 |
| 111 | #define ERROR_HLS_DECODE_ERROR 601 | 111 | #define ERROR_HLS_DECODE_ERROR 601 |
| 112 | -//#define ERROR_HLS_BUSY 602 | 112 | +#define ERROR_HLS_CREATE_DIR 602 |
| 113 | #define ERROR_HLS_OPEN_FAILED 603 | 113 | #define ERROR_HLS_OPEN_FAILED 603 |
| 114 | #define ERROR_HLS_WRITE_FAILED 604 | 114 | #define ERROR_HLS_WRITE_FAILED 604 |
| 115 | #define ERROR_HLS_AAC_FRAME_LENGTH 605 | 115 | #define ERROR_HLS_AAC_FRAME_LENGTH 605 |
| @@ -403,12 +403,13 @@ SrsHLS::~SrsHLS() | @@ -403,12 +403,13 @@ SrsHLS::~SrsHLS() | ||
| 403 | srs_freep(video_frame); | 403 | srs_freep(video_frame); |
| 404 | } | 404 | } |
| 405 | 405 | ||
| 406 | -int SrsHLS::on_publish(std::string _vhost, std::string _stream) | 406 | +int SrsHLS::on_publish(std::string _vhost, std::string _app, std::string _stream) |
| 407 | { | 407 | { |
| 408 | int ret = ERROR_SUCCESS; | 408 | int ret = ERROR_SUCCESS; |
| 409 | 409 | ||
| 410 | vhost = _vhost; | 410 | vhost = _vhost; |
| 411 | stream = _stream; | 411 | stream = _stream; |
| 412 | + app = _app; | ||
| 412 | 413 | ||
| 413 | if ((ret = reopen()) != ERROR_SUCCESS) { | 414 | if ((ret = reopen()) != ERROR_SUCCESS) { |
| 414 | return ret; | 415 | return ret; |
| @@ -555,6 +556,7 @@ int SrsHLS::on_video(SrsSharedPtrMessage* video) | @@ -555,6 +556,7 @@ int SrsHLS::on_video(SrsSharedPtrMessage* video) | ||
| 555 | if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) { | 556 | if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) { |
| 556 | int64_t diff = stream_dts - m3u8_dts; | 557 | int64_t diff = stream_dts - m3u8_dts; |
| 557 | // 10s. | 558 | // 10s. |
| 559 | + // TODO: config it. | ||
| 558 | if (diff / 90000 >= 10) { | 560 | if (diff / 90000 >= 10) { |
| 559 | if ((ret = reopen()) != ERROR_SUCCESS) { | 561 | if ((ret = reopen()) != ERROR_SUCCESS) { |
| 560 | return ret; | 562 | return ret; |
| @@ -590,6 +592,11 @@ int SrsHLS::reopen() | @@ -590,6 +592,11 @@ int SrsHLS::reopen() | ||
| 590 | hls_path = conf->arg0(); | 592 | hls_path = conf->arg0(); |
| 591 | } | 593 | } |
| 592 | 594 | ||
| 595 | + // create dir for app. | ||
| 596 | + if ((ret = create_dir()) != ERROR_SUCCESS) { | ||
| 597 | + return ret; | ||
| 598 | + } | ||
| 599 | + | ||
| 593 | // start new segment. | 600 | // start new segment. |
| 594 | if (current) { | 601 | if (current) { |
| 595 | current->duration = (stream_dts - current->segment_start_dts) / 90000.0; | 602 | current->duration = (stream_dts - current->segment_start_dts) / 90000.0; |
| @@ -610,6 +617,8 @@ int SrsHLS::reopen() | @@ -610,6 +617,8 @@ int SrsHLS::reopen() | ||
| 610 | 617 | ||
| 611 | current->full_path = hls_path; | 618 | current->full_path = hls_path; |
| 612 | current->full_path += "/"; | 619 | current->full_path += "/"; |
| 620 | + current->full_path += app; | ||
| 621 | + current->full_path += "/"; | ||
| 613 | current->full_path += filename; | 622 | current->full_path += filename; |
| 614 | 623 | ||
| 615 | // TODO: support base url, and so on. | 624 | // TODO: support base url, and so on. |
| @@ -619,7 +628,7 @@ int SrsHLS::reopen() | @@ -619,7 +628,7 @@ int SrsHLS::reopen() | ||
| 619 | srs_error("open hls muxer failed. ret=%d", ret); | 628 | srs_error("open hls muxer failed. ret=%d", ret); |
| 620 | return ret; | 629 | return ret; |
| 621 | } | 630 | } |
| 622 | - srs_trace("open HLS muxer success. vhost=%s, path=%s", vhost.c_str(), current->full_path.c_str()); | 631 | + srs_info("open HLS muxer success. vhost=%s, path=%s", vhost.c_str(), current->full_path.c_str()); |
| 623 | 632 | ||
| 624 | return ret; | 633 | return ret; |
| 625 | } | 634 | } |
| @@ -628,16 +637,33 @@ int SrsHLS::refresh_m3u8() | @@ -628,16 +637,33 @@ int SrsHLS::refresh_m3u8() | ||
| 628 | { | 637 | { |
| 629 | int ret = ERROR_SUCCESS; | 638 | int ret = ERROR_SUCCESS; |
| 630 | 639 | ||
| 640 | + std::string m3u8_file = hls_path; | ||
| 641 | + m3u8_file += "/"; | ||
| 642 | + m3u8_file += app; | ||
| 643 | + m3u8_file += "/"; | ||
| 644 | + m3u8_file += stream; | ||
| 645 | + m3u8_file += ".m3u8"; | ||
| 646 | + | ||
| 647 | + m3u8 = m3u8_file; | ||
| 648 | + m3u8_file += ".temp"; | ||
| 649 | + | ||
| 631 | int fd = -1; | 650 | int fd = -1; |
| 632 | - ret = _refresh_m3u8(fd); | 651 | + ret = _refresh_m3u8(fd, m3u8_file); |
| 633 | if (fd >= 0) { | 652 | if (fd >= 0) { |
| 634 | close(fd); | 653 | close(fd); |
| 654 | + if (rename(m3u8_file.c_str(), m3u8.c_str()) < 0) { | ||
| 655 | + ret = ERROR_HLS_WRITE_FAILED; | ||
| 656 | + srs_error("rename m3u8 file failed. ret=%d", ret); | ||
| 657 | + } | ||
| 635 | } | 658 | } |
| 636 | 659 | ||
| 660 | + // remove the temp file. | ||
| 661 | + unlink(m3u8_file.c_str()); | ||
| 662 | + | ||
| 637 | return ret; | 663 | return ret; |
| 638 | } | 664 | } |
| 639 | 665 | ||
| 640 | -int SrsHLS::_refresh_m3u8(int& fd) | 666 | +int SrsHLS::_refresh_m3u8(int& fd, std::string m3u8_file) |
| 641 | { | 667 | { |
| 642 | int ret = ERROR_SUCCESS; | 668 | int ret = ERROR_SUCCESS; |
| 643 | 669 | ||
| @@ -646,19 +672,14 @@ int SrsHLS::_refresh_m3u8(int& fd) | @@ -646,19 +672,14 @@ int SrsHLS::_refresh_m3u8(int& fd) | ||
| 646 | return ret; | 672 | return ret; |
| 647 | } | 673 | } |
| 648 | 674 | ||
| 649 | - m3u8 = hls_path; | ||
| 650 | - m3u8 += "/"; | ||
| 651 | - m3u8 += stream; | ||
| 652 | - m3u8 += ".m3u8"; | ||
| 653 | - | ||
| 654 | int flags = O_CREAT|O_WRONLY|O_TRUNC; | 675 | int flags = O_CREAT|O_WRONLY|O_TRUNC; |
| 655 | mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH; | 676 | mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH; |
| 656 | - if ((fd = ::open(m3u8.c_str(), flags, mode)) < 0) { | 677 | + if ((fd = ::open(m3u8_file.c_str(), flags, mode)) < 0) { |
| 657 | ret = ERROR_HLS_OPEN_FAILED; | 678 | ret = ERROR_HLS_OPEN_FAILED; |
| 658 | - srs_error("open m3u8 file %s failed. ret=%d", m3u8.c_str(), ret); | 679 | + srs_error("open m3u8 file %s failed. ret=%d", m3u8_file.c_str(), ret); |
| 659 | return ret; | 680 | return ret; |
| 660 | } | 681 | } |
| 661 | - srs_info("open m3u8 file %s success.", m3u8.c_str()); | 682 | + srs_info("open m3u8 file %s success.", m3u8_file.c_str()); |
| 662 | 683 | ||
| 663 | // #EXTM3U\n#EXT-X-VERSION:3\n | 684 | // #EXTM3U\n#EXT-X-VERSION:3\n |
| 664 | char header[] = { | 685 | char header[] = { |
| @@ -728,8 +749,31 @@ int SrsHLS::_refresh_m3u8(int& fd) | @@ -728,8 +749,31 @@ int SrsHLS::_refresh_m3u8(int& fd) | ||
| 728 | } | 749 | } |
| 729 | srs_verbose("write m3u8 segment uri success."); | 750 | srs_verbose("write m3u8 segment uri success."); |
| 730 | } | 751 | } |
| 731 | - srs_info("write m3u8 %s success.", m3u8.c_str()); | 752 | + srs_info("write m3u8 %s success.", m3u8_file.c_str()); |
| 753 | + | ||
| 754 | + return ret; | ||
| 755 | +} | ||
| 756 | + | ||
| 757 | +int SrsHLS::create_dir() | ||
| 758 | +{ | ||
| 759 | + int ret = ERROR_SUCCESS; | ||
| 760 | + | ||
| 761 | + std::string app_dir = hls_path; | ||
| 762 | + app_dir += "/"; | ||
| 763 | + app_dir += app; | ||
| 732 | 764 | ||
| 765 | + // TODO: cleanup the dir when startup. | ||
| 766 | + | ||
| 767 | + mode_t mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IXOTH; | ||
| 768 | + if (::mkdir(app_dir.c_str(), mode) < 0) { | ||
| 769 | + if (errno != EEXIST) { | ||
| 770 | + ret = ERROR_HLS_CREATE_DIR; | ||
| 771 | + srs_error("create app dir %s failed. ret=%d", app_dir.c_str(), ret); | ||
| 772 | + return ret; | ||
| 773 | + } | ||
| 774 | + } | ||
| 775 | + srs_info("create app dir %s success.", app_dir.c_str()); | ||
| 776 | + | ||
| 733 | return ret; | 777 | return ret; |
| 734 | } | 778 | } |
| 735 | 779 |
| @@ -72,6 +72,7 @@ class SrsHLS | @@ -72,6 +72,7 @@ class SrsHLS | ||
| 72 | private: | 72 | private: |
| 73 | std::string vhost; | 73 | std::string vhost; |
| 74 | std::string stream; | 74 | std::string stream; |
| 75 | + std::string app; | ||
| 75 | std::string hls_path; | 76 | std::string hls_path; |
| 76 | private: | 77 | private: |
| 77 | int file_index; | 78 | int file_index; |
| @@ -103,7 +104,7 @@ public: | @@ -103,7 +104,7 @@ public: | ||
| 103 | SrsHLS(); | 104 | SrsHLS(); |
| 104 | virtual ~SrsHLS(); | 105 | virtual ~SrsHLS(); |
| 105 | public: | 106 | public: |
| 106 | - virtual int on_publish(std::string _vhost, std::string _stream); | 107 | + virtual int on_publish(std::string _vhost, std::string _app, std::string _stream); |
| 107 | virtual void on_unpublish(); | 108 | virtual void on_unpublish(); |
| 108 | virtual int on_meta_data(SrsOnMetaDataPacket* metadata); | 109 | virtual int on_meta_data(SrsOnMetaDataPacket* metadata); |
| 109 | virtual int on_audio(SrsSharedPtrMessage* audio); | 110 | virtual int on_audio(SrsSharedPtrMessage* audio); |
| @@ -111,7 +112,8 @@ public: | @@ -111,7 +112,8 @@ public: | ||
| 111 | private: | 112 | private: |
| 112 | virtual int reopen(); | 113 | virtual int reopen(); |
| 113 | virtual int refresh_m3u8(); | 114 | virtual int refresh_m3u8(); |
| 114 | - virtual int _refresh_m3u8(int& fd); | 115 | + virtual int _refresh_m3u8(int& fd, std::string m3u8_file); |
| 116 | + virtual int create_dir(); | ||
| 115 | }; | 117 | }; |
| 116 | 118 | ||
| 117 | class SrsTSMuxer | 119 | class SrsTSMuxer |
| @@ -452,9 +452,9 @@ int SrsSource::on_video(SrsCommonMessage* video) | @@ -452,9 +452,9 @@ int SrsSource::on_video(SrsCommonMessage* video) | ||
| 452 | return ret; | 452 | return ret; |
| 453 | } | 453 | } |
| 454 | 454 | ||
| 455 | -int SrsSource::on_publish(std::string vhost, std::string stream) | 455 | +int SrsSource::on_publish(std::string vhost, std::string app, std::string stream) |
| 456 | { | 456 | { |
| 457 | - return hls->on_publish(vhost, stream); | 457 | + return hls->on_publish(vhost, app, stream); |
| 458 | } | 458 | } |
| 459 | 459 | ||
| 460 | void SrsSource::on_unpublish() | 460 | void SrsSource::on_unpublish() |
| @@ -166,7 +166,7 @@ public: | @@ -166,7 +166,7 @@ public: | ||
| 166 | virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata); | 166 | virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata); |
| 167 | virtual int on_audio(SrsCommonMessage* audio); | 167 | virtual int on_audio(SrsCommonMessage* audio); |
| 168 | virtual int on_video(SrsCommonMessage* video); | 168 | virtual int on_video(SrsCommonMessage* video); |
| 169 | - virtual int on_publish(std::string vhost, std::string stream); | 169 | + virtual int on_publish(std::string vhost, std::string app, std::string stream); |
| 170 | virtual void on_unpublish(); | 170 | virtual void on_unpublish(); |
| 171 | public: | 171 | public: |
| 172 | virtual int create_consumer(SrsConsumer*& consumer); | 172 | virtual int create_consumer(SrsConsumer*& consumer); |
-
请 注册 或 登录 后发表评论