正在显示
4 个修改的文件
包含
121 行增加
和
4 行删除
| @@ -72,6 +72,8 @@ const char* _srs_version = "XCORE-"RTMP_SIG_SRS_SERVER; | @@ -72,6 +72,8 @@ const char* _srs_version = "XCORE-"RTMP_SIG_SRS_SERVER; | ||
| 72 | #define SRS_CONF_DEFAULT_MAX_CONNECTIONS 1000 | 72 | #define SRS_CONF_DEFAULT_MAX_CONNECTIONS 1000 |
| 73 | #define SRS_CONF_DEFAULT_HLS_PATH "./objs/nginx/html" | 73 | #define SRS_CONF_DEFAULT_HLS_PATH "./objs/nginx/html" |
| 74 | #define SRS_CONF_DEFAULT_HLS_M3U8_FILE "[app]/[stream].m3u8" | 74 | #define SRS_CONF_DEFAULT_HLS_M3U8_FILE "[app]/[stream].m3u8" |
| 75 | +#define SRS_CONF_DEFAULT_HLS_TOTAL_M3U8_FILE "[app]/[stream]_total.m3u8" | ||
| 76 | +#define SRS_CONF_DEFAULT_HLS_TOTAL_FILE "[app]/[stream]_total" | ||
| 75 | #define SRS_CONF_DEFAULT_HLS_TS_FILE "[app]/[stream]-[seq].ts" | 77 | #define SRS_CONF_DEFAULT_HLS_TS_FILE "[app]/[stream]-[seq].ts" |
| 76 | #define SRS_CONF_DEFAULT_HLS_TS_FLOOR false | 78 | #define SRS_CONF_DEFAULT_HLS_TS_FLOOR false |
| 77 | #define SRS_CONF_DEFAULT_HLS_FRAGMENT 10 | 79 | #define SRS_CONF_DEFAULT_HLS_FRAGMENT 10 |
| @@ -1898,7 +1900,7 @@ int SrsConfig::check_config() | @@ -1898,7 +1900,7 @@ int SrsConfig::check_config() | ||
| 1898 | if (m != "enabled" && m != "hls_entry_prefix" && m != "hls_path" && m != "hls_fragment" && m != "hls_window" && m != "hls_on_error" | 1900 | if (m != "enabled" && m != "hls_entry_prefix" && m != "hls_path" && m != "hls_fragment" && m != "hls_window" && m != "hls_on_error" |
| 1899 | && m != "hls_storage" && m != "hls_mount" && m != "hls_td_ratio" && m != "hls_aof_ratio" && m != "hls_acodec" && m != "hls_vcodec" | 1901 | && m != "hls_storage" && m != "hls_mount" && m != "hls_td_ratio" && m != "hls_aof_ratio" && m != "hls_acodec" && m != "hls_vcodec" |
| 1900 | && m != "hls_m3u8_file" && m != "hls_ts_file" && m != "hls_ts_floor" && m != "hls_cleanup" && m != "hls_nb_notify" | 1902 | && m != "hls_m3u8_file" && m != "hls_ts_file" && m != "hls_ts_floor" && m != "hls_cleanup" && m != "hls_nb_notify" |
| 1901 | - && m != "hls_wait_keyframe" && m != "hls_dispose" | 1903 | + && m != "hls_wait_keyframe" && m != "hls_dispose" && m != "hls_total_m3u8_file" && m != "hls_total_file" |
| 1902 | ) { | 1904 | ) { |
| 1903 | ret = ERROR_SYSTEM_CONFIG_INVALID; | 1905 | ret = ERROR_SYSTEM_CONFIG_INVALID; |
| 1904 | srs_error("unsupported vhost hls directive %s, ret=%d", m.c_str(), ret); | 1906 | srs_error("unsupported vhost hls directive %s, ret=%d", m.c_str(), ret); |
| @@ -3677,6 +3679,40 @@ string SrsConfig::get_hls_m3u8_file(string vhost) | @@ -3677,6 +3679,40 @@ string SrsConfig::get_hls_m3u8_file(string vhost) | ||
| 3677 | return conf->arg0(); | 3679 | return conf->arg0(); |
| 3678 | } | 3680 | } |
| 3679 | 3681 | ||
| 3682 | +string SrsConfig::get_hls_total_m3u8_file(string vhost) | ||
| 3683 | +{ | ||
| 3684 | + SrsConfDirective* hls = get_hls(vhost); | ||
| 3685 | + | ||
| 3686 | + if (!hls) { | ||
| 3687 | + return SRS_CONF_DEFAULT_HLS_TOTAL_M3U8_FILE; | ||
| 3688 | + } | ||
| 3689 | + | ||
| 3690 | + SrsConfDirective* conf = hls->get("hls_total_m3u8_file"); | ||
| 3691 | + | ||
| 3692 | + if (!conf) { | ||
| 3693 | + return SRS_CONF_DEFAULT_HLS_TOTAL_M3U8_FILE; | ||
| 3694 | + } | ||
| 3695 | + | ||
| 3696 | + return conf->arg0(); | ||
| 3697 | +} | ||
| 3698 | + | ||
| 3699 | +string SrsConfig::get_hls_total_file(string vhost) | ||
| 3700 | +{ | ||
| 3701 | + SrsConfDirective* hls = get_hls(vhost); | ||
| 3702 | + | ||
| 3703 | + if (!hls) { | ||
| 3704 | + return SRS_CONF_DEFAULT_HLS_TOTAL_FILE; | ||
| 3705 | + } | ||
| 3706 | + | ||
| 3707 | + SrsConfDirective* conf = hls->get("hls_total_file"); | ||
| 3708 | + | ||
| 3709 | + if (!conf) { | ||
| 3710 | + return SRS_CONF_DEFAULT_HLS_TOTAL_FILE; | ||
| 3711 | + } | ||
| 3712 | + | ||
| 3713 | + return conf->arg0(); | ||
| 3714 | +} | ||
| 3715 | + | ||
| 3680 | string SrsConfig::get_hls_ts_file(string vhost) | 3716 | string SrsConfig::get_hls_ts_file(string vhost) |
| 3681 | { | 3717 | { |
| 3682 | SrsConfDirective* hls = get_hls(vhost); | 3718 | SrsConfDirective* hls = get_hls(vhost); |
| @@ -882,6 +882,14 @@ public: | @@ -882,6 +882,14 @@ public: | ||
| 882 | */ | 882 | */ |
| 883 | virtual std::string get_hls_m3u8_file(std::string vhost); | 883 | virtual std::string get_hls_m3u8_file(std::string vhost); |
| 884 | /** | 884 | /** |
| 885 | + * get the HLS total m3u8 file path template. | ||
| 886 | + */ | ||
| 887 | + virtual std::string get_hls_total_m3u8_file(std::string vhost); | ||
| 888 | + /** | ||
| 889 | + * get the HLS total file path template. | ||
| 890 | + */ | ||
| 891 | + virtual std::string get_hls_total_file(std::string vhost); | ||
| 892 | + /** | ||
| 885 | * get the HLS ts file path template. | 893 | * get the HLS ts file path template. |
| 886 | */ | 894 | */ |
| 887 | virtual std::string get_hls_ts_file(std::string vhost); | 895 | virtual std::string get_hls_ts_file(std::string vhost); |
| @@ -387,7 +387,7 @@ int SrsHlsMuxer::initialize() | @@ -387,7 +387,7 @@ int SrsHlsMuxer::initialize() | ||
| 387 | } | 387 | } |
| 388 | 388 | ||
| 389 | int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, | 389 | int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, |
| 390 | - string path, string m3u8_file, string ts_file, double fragment, double window, | 390 | + string path, string m3u8_file, string total_m3u8_file, string total_file, string ts_file, double fragment, double window, |
| 391 | bool ts_floor, double aof_ratio, bool cleanup, bool wait_keyframe | 391 | bool ts_floor, double aof_ratio, bool cleanup, bool wait_keyframe |
| 392 | ) { | 392 | ) { |
| 393 | int ret = ERROR_SUCCESS; | 393 | int ret = ERROR_SUCCESS; |
| @@ -412,6 +412,14 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, | @@ -412,6 +412,14 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, | ||
| 412 | m3u8_url = srs_path_build_stream(m3u8_file, req->vhost, req->app, req->stream); | 412 | m3u8_url = srs_path_build_stream(m3u8_file, req->vhost, req->app, req->stream); |
| 413 | m3u8 = path + "/" + m3u8_url; | 413 | m3u8 = path + "/" + m3u8_url; |
| 414 | 414 | ||
| 415 | + // generate the total m3u8 dir and path. | ||
| 416 | + total_m3u8_url = srs_path_build_stream(total_m3u8_file, req->vhost, req->app, req->stream); | ||
| 417 | + total_m3u8 = path + "/" + total_m3u8_url; | ||
| 418 | + | ||
| 419 | + // generate the m3u8 dir and path. | ||
| 420 | + total_url = srs_path_build_stream(total_file, req->vhost, req->app, req->stream); | ||
| 421 | + total = path + "/" + total_url; | ||
| 422 | + | ||
| 415 | // when update config, reset the history target duration. | 423 | // when update config, reset the history target duration. |
| 416 | max_td = (int)(fragment * _srs_config->get_hls_td_ratio(r->vhost)); | 424 | max_td = (int)(fragment * _srs_config->get_hls_td_ratio(r->vhost)); |
| 417 | 425 | ||
| @@ -736,6 +744,8 @@ int SrsHlsMuxer::segment_close(string log_desc) | @@ -736,6 +744,8 @@ int SrsHlsMuxer::segment_close(string log_desc) | ||
| 736 | log_desc.c_str(), current->sequence_no, current->uri.c_str(), current->duration, | 744 | log_desc.c_str(), current->sequence_no, current->uri.c_str(), current->duration, |
| 737 | current->segment_start_dts); | 745 | current->segment_start_dts); |
| 738 | 746 | ||
| 747 | + SrsHlsSegment* currentSeg = current; | ||
| 748 | + | ||
| 739 | // close the muxer of finished segment. | 749 | // close the muxer of finished segment. |
| 740 | srs_freep(current->muxer); | 750 | srs_freep(current->muxer); |
| 741 | std::string full_path = current->full_path; | 751 | std::string full_path = current->full_path; |
| @@ -749,6 +759,63 @@ int SrsHlsMuxer::segment_close(string log_desc) | @@ -749,6 +759,63 @@ int SrsHlsMuxer::segment_close(string log_desc) | ||
| 749 | tmp_file.c_str(), full_path.c_str(), ret); | 759 | tmp_file.c_str(), full_path.c_str(), ret); |
| 750 | return ret; | 760 | return ret; |
| 751 | } | 761 | } |
| 762 | + | ||
| 763 | + | ||
| 764 | + SrsFileWriter total_m3u8_writer; | ||
| 765 | + //add segment to total.m3u8 | ||
| 766 | + std::stringstream ss; | ||
| 767 | + | ||
| 768 | + if(currentSeg->sequence_no == 0){ | ||
| 769 | + ret = total_m3u8_writer.open(total_m3u8); | ||
| 770 | + if(ret != ERROR_SUCCESS){ | ||
| 771 | + srs_error("open total file %s error:%s reap ts segment, sequence_no=%d, uri=%s, duration=%.2f, start=%"PRId64, | ||
| 772 | + total_m3u8.c_str(), log_desc.c_str(), currentSeg->sequence_no, currentSeg->uri.c_str(), currentSeg->duration, | ||
| 773 | + currentSeg->segment_start_dts); | ||
| 774 | + return ret; | ||
| 775 | + } | ||
| 776 | + //write total m3u8 header | ||
| 777 | + | ||
| 778 | + ss << "#EXTM3U" << SRS_CONSTS_LF | ||
| 779 | + << "#EXT-X-VERSION:3" << SRS_CONSTS_LF | ||
| 780 | + << "#EXT-X-ALLOW-CACHE:YES" << SRS_CONSTS_LF; | ||
| 781 | + srs_verbose("write m3u8 header success."); | ||
| 782 | + | ||
| 783 | + } | ||
| 784 | + else{ | ||
| 785 | + ret = total_m3u8_writer.open_append(total_m3u8); | ||
| 786 | + if(ret != ERROR_SUCCESS){ | ||
| 787 | + srs_error("open total file %s error:%s reap ts segment, sequence_no=%d, uri=%s, duration=%.2f, start=%"PRId64, | ||
| 788 | + total_m3u8.c_str(), log_desc.c_str(), currentSeg->sequence_no, currentSeg->uri.c_str(), currentSeg->duration, | ||
| 789 | + currentSeg->segment_start_dts); | ||
| 790 | + return ret; | ||
| 791 | + } | ||
| 792 | + } | ||
| 793 | + | ||
| 794 | + | ||
| 795 | + if (currentSeg->is_sequence_header) { | ||
| 796 | + // #EXT-X-DISCONTINUITY\n | ||
| 797 | + ss << "#EXT-X-DISCONTINUITY" << SRS_CONSTS_LF; | ||
| 798 | + srs_verbose("write m3u8 segment discontinuity success."); | ||
| 799 | + } | ||
| 800 | + | ||
| 801 | + // "#EXTINF:4294967295.208,\n" | ||
| 802 | + ss.precision(3); | ||
| 803 | + ss.setf(std::ios::fixed, std::ios::floatfield); | ||
| 804 | + ss << "#EXTINF:" << currentSeg->duration << ", no desc" << SRS_CONSTS_LF; | ||
| 805 | + srs_verbose("write m3u8 segment info success."); | ||
| 806 | + | ||
| 807 | + // {file name}\n | ||
| 808 | + ss << currentSeg->uri << SRS_CONSTS_LF; | ||
| 809 | + srs_verbose("write m3u8 segment uri success."); | ||
| 810 | + | ||
| 811 | + // write m3u8 to writer. | ||
| 812 | + std::string m3u8 = ss.str(); | ||
| 813 | + if ((ret = total_m3u8_writer.write((char*)m3u8.c_str(), (int)m3u8.length(), NULL)) != ERROR_SUCCESS) { | ||
| 814 | + srs_error("write m3u8 failed. ret=%d", ret); | ||
| 815 | + return ret; | ||
| 816 | + } | ||
| 817 | + srs_info("write total m3u8 %s success.", m3u8_total_file.c_str()); | ||
| 818 | + | ||
| 752 | } else { | 819 | } else { |
| 753 | // reuse current segment index. | 820 | // reuse current segment index. |
| 754 | _sequence_no--; | 821 | _sequence_no--; |
| @@ -953,6 +1020,8 @@ int SrsHlsCache::on_publish(SrsHlsMuxer* muxer, SrsRequest* req, int64_t segment | @@ -953,6 +1020,8 @@ int SrsHlsCache::on_publish(SrsHlsMuxer* muxer, SrsRequest* req, int64_t segment | ||
| 953 | // get the hls path config | 1020 | // get the hls path config |
| 954 | std::string path = _srs_config->get_hls_path(vhost); | 1021 | std::string path = _srs_config->get_hls_path(vhost); |
| 955 | std::string m3u8_file = _srs_config->get_hls_m3u8_file(vhost); | 1022 | std::string m3u8_file = _srs_config->get_hls_m3u8_file(vhost); |
| 1023 | + std::string total_m3u8_file = _srs_config->get_hls_total_m3u8_file(vhost); | ||
| 1024 | + std::string total_file = _srs_config->get_hls_total_file(vhost); | ||
| 956 | std::string ts_file = _srs_config->get_hls_ts_file(vhost); | 1025 | std::string ts_file = _srs_config->get_hls_ts_file(vhost); |
| 957 | bool cleanup = _srs_config->get_hls_cleanup(vhost); | 1026 | bool cleanup = _srs_config->get_hls_cleanup(vhost); |
| 958 | bool wait_keyframe = _srs_config->get_hls_wait_keyframe(vhost); | 1027 | bool wait_keyframe = _srs_config->get_hls_wait_keyframe(vhost); |
| @@ -968,7 +1037,7 @@ int SrsHlsCache::on_publish(SrsHlsMuxer* muxer, SrsRequest* req, int64_t segment | @@ -968,7 +1037,7 @@ int SrsHlsCache::on_publish(SrsHlsMuxer* muxer, SrsRequest* req, int64_t segment | ||
| 968 | 1037 | ||
| 969 | // open muxer | 1038 | // open muxer |
| 970 | if ((ret = muxer->update_config(req, entry_prefix, | 1039 | if ((ret = muxer->update_config(req, entry_prefix, |
| 971 | - path, m3u8_file, ts_file, hls_fragment, hls_window, ts_floor, hls_aof_ratio, | 1040 | + path, m3u8_file, total_m3u8_file, total_file, ts_file, hls_fragment, hls_window, ts_floor, hls_aof_ratio, |
| 972 | cleanup, wait_keyframe)) != ERROR_SUCCESS | 1041 | cleanup, wait_keyframe)) != ERROR_SUCCESS |
| 973 | ) { | 1042 | ) { |
| 974 | srs_error("m3u8 muxer update config failed. ret=%d", ret); | 1043 | srs_error("m3u8 muxer update config failed. ret=%d", ret); |
| @@ -205,6 +205,10 @@ private: | @@ -205,6 +205,10 @@ private: | ||
| 205 | int max_td; | 205 | int max_td; |
| 206 | std::string m3u8; | 206 | std::string m3u8; |
| 207 | std::string m3u8_url; | 207 | std::string m3u8_url; |
| 208 | + std::string total_m3u8; | ||
| 209 | + std::string total_m3u8_url; | ||
| 210 | + std::string total; | ||
| 211 | + std::string total_url; | ||
| 208 | private: | 212 | private: |
| 209 | // TODO: FIXME: remove it. | 213 | // TODO: FIXME: remove it. |
| 210 | bool should_write_cache; | 214 | bool should_write_cache; |
| @@ -248,7 +252,7 @@ public: | @@ -248,7 +252,7 @@ public: | ||
| 248 | * when publish, update the config for muxer. | 252 | * when publish, update the config for muxer. |
| 249 | */ | 253 | */ |
| 250 | virtual int update_config(SrsRequest* r, std::string entry_prefix, | 254 | virtual int update_config(SrsRequest* r, std::string entry_prefix, |
| 251 | - std::string path, std::string m3u8_file, std::string ts_file, | 255 | + std::string path, std::string m3u8_file, std::string total_m3u8_file, std::string total_file, std::string ts_file, |
| 252 | double fragment, double window, bool ts_floor, double aof_ratio, | 256 | double fragment, double window, bool ts_floor, double aof_ratio, |
| 253 | bool cleanup, bool wait_keyframe); | 257 | bool cleanup, bool wait_keyframe); |
| 254 | /** | 258 | /** |
-
请 注册 或 登录 后发表评论