for #304, rewrite hls/ts code, support h.264+mp3 for hls. 2.0.117.
正在显示
8 个修改的文件
包含
54 行增加
和
10 行删除
| @@ -487,6 +487,8 @@ Supported operating systems and hardware: | @@ -487,6 +487,8 @@ Supported operating systems and hardware: | ||
| 487 | [#301](https://github.com/winlinvip/simple-rtmp-server/issues/301). | 487 | [#301](https://github.com/winlinvip/simple-rtmp-server/issues/301). |
| 488 | 1. Support push MPEG-TS over UDP to SRS, read | 488 | 1. Support push MPEG-TS over UDP to SRS, read |
| 489 | [#250](https://github.com/winlinvip/simple-rtmp-server/issues/250). | 489 | [#250](https://github.com/winlinvip/simple-rtmp-server/issues/250). |
| 490 | +1. Rewrite HLS(h.264+aac/mp3) streaming, read | ||
| 491 | +[#304](https://github.com/winlinvip/simple-rtmp-server/issues/304). | ||
| 490 | 1. [no-plan] Support <500ms latency, FRSC(Fast RTMP-compatible Stream Channel tech). | 492 | 1. [no-plan] Support <500ms latency, FRSC(Fast RTMP-compatible Stream Channel tech). |
| 491 | 1. [no-plan] Support RTMP 302 redirect [#92](https://github.com/winlinvip/simple-rtmp-server/issues/92). | 493 | 1. [no-plan] Support RTMP 302 redirect [#92](https://github.com/winlinvip/simple-rtmp-server/issues/92). |
| 492 | 1. [no-plan] Support multiple processes, for both origin and edge | 494 | 1. [no-plan] Support multiple processes, for both origin and edge |
| @@ -525,6 +527,7 @@ Supported operating systems and hardware: | @@ -525,6 +527,7 @@ Supported operating systems and hardware: | ||
| 525 | 527 | ||
| 526 | ### SRS 2.0 history | 528 | ### SRS 2.0 history |
| 527 | 529 | ||
| 530 | +* v2.0, 2015-02-15, for [#304](https://github.com/winlinvip/simple-rtmp-server/issues/304), rewrite hls/ts code, support h.264+mp3 for hls. 2.0.117. | ||
| 528 | * v2.0, 2015-02-12, for [#304](https://github.com/winlinvip/simple-rtmp-server/issues/304), use stringstream to generate m3u8, add hls_td_ratio. 2.0.116. | 531 | * v2.0, 2015-02-12, for [#304](https://github.com/winlinvip/simple-rtmp-server/issues/304), use stringstream to generate m3u8, add hls_td_ratio. 2.0.116. |
| 529 | * v2.0, 2015-02-11, dev code ZhouGuowen for 2.0.115. | 532 | * v2.0, 2015-02-11, dev code ZhouGuowen for 2.0.115. |
| 530 | * v2.0, 2015-02-10, for [#311](https://github.com/winlinvip/simple-rtmp-server/issues/311), set pcr_base to dts. 2.0.114. | 533 | * v2.0, 2015-02-10, for [#311](https://github.com/winlinvip/simple-rtmp-server/issues/311), set pcr_base to dts. 2.0.114. |
| @@ -492,6 +492,13 @@ vhost with-hls.srs.com { | @@ -492,6 +492,13 @@ vhost with-hls.srs.com { | ||
| 492 | # @remark the hls_mount must endswith .m3u8. | 492 | # @remark the hls_mount must endswith .m3u8. |
| 493 | # default: [vhost]/[app]/[stream].m3u8 | 493 | # default: [vhost]/[app]/[stream].m3u8 |
| 494 | hls_mount [vhost]/[app]/[stream].m3u8; | 494 | hls_mount [vhost]/[app]/[stream].m3u8; |
| 495 | + # the default audio codec of hls. | ||
| 496 | + # when codec changed, write the PAT/PMT table, but maybe ok util next ts. | ||
| 497 | + # so user can set the default codec for mp3. | ||
| 498 | + # the available audio codec: aac, mp3 | ||
| 499 | + # default: aac | ||
| 500 | + # TODO: FIXME: update wiki for it. | ||
| 501 | + hls_acodec aac; | ||
| 495 | } | 502 | } |
| 496 | } | 503 | } |
| 497 | # the vhost with hls disabled. | 504 | # the vhost with hls disabled. |
| @@ -1480,7 +1480,7 @@ int SrsConfig::check_config() | @@ -1480,7 +1480,7 @@ int SrsConfig::check_config() | ||
| 1480 | for (int j = 0; j < (int)conf->directives.size(); j++) { | 1480 | for (int j = 0; j < (int)conf->directives.size(); j++) { |
| 1481 | string m = conf->at(j)->name.c_str(); | 1481 | string m = conf->at(j)->name.c_str(); |
| 1482 | if (m != "enabled" && m != "hls_path" && m != "hls_fragment" && m != "hls_window" && m != "hls_on_error" | 1482 | if (m != "enabled" && m != "hls_path" && m != "hls_fragment" && m != "hls_window" && m != "hls_on_error" |
| 1483 | - && m != "hls_storage" && m != "hls_mount" && m != "hls_td_ratio" | 1483 | + && m != "hls_storage" && m != "hls_mount" && m != "hls_td_ratio" && m != "hls_acodec" |
| 1484 | ) { | 1484 | ) { |
| 1485 | ret = ERROR_SYSTEM_CONFIG_INVALID; | 1485 | ret = ERROR_SYSTEM_CONFIG_INVALID; |
| 1486 | srs_error("unsupported vhost hls directive %s, ret=%d", m.c_str(), ret); | 1486 | srs_error("unsupported vhost hls directive %s, ret=%d", m.c_str(), ret); |
| @@ -3332,6 +3332,23 @@ string SrsConfig::get_hls_mount(string vhost) | @@ -3332,6 +3332,23 @@ string SrsConfig::get_hls_mount(string vhost) | ||
| 3332 | return conf->arg0(); | 3332 | return conf->arg0(); |
| 3333 | } | 3333 | } |
| 3334 | 3334 | ||
| 3335 | +string SrsConfig::get_hls_acodec(string vhost) | ||
| 3336 | +{ | ||
| 3337 | + SrsConfDirective* hls = get_hls(vhost); | ||
| 3338 | + | ||
| 3339 | + if (!hls) { | ||
| 3340 | + return SRS_CONF_DEFAULT_HLS_ACODEC; | ||
| 3341 | + } | ||
| 3342 | + | ||
| 3343 | + SrsConfDirective* conf = hls->get("hls_acodec"); | ||
| 3344 | + | ||
| 3345 | + if (!conf) { | ||
| 3346 | + return SRS_CONF_DEFAULT_HLS_ACODEC; | ||
| 3347 | + } | ||
| 3348 | + | ||
| 3349 | + return conf->arg0(); | ||
| 3350 | +} | ||
| 3351 | + | ||
| 3335 | SrsConfDirective* SrsConfig::get_dvr(string vhost) | 3352 | SrsConfDirective* SrsConfig::get_dvr(string vhost) |
| 3336 | { | 3353 | { |
| 3337 | SrsConfDirective* conf = get_vhost(vhost); | 3354 | SrsConfDirective* conf = get_vhost(vhost); |
| @@ -55,6 +55,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -55,6 +55,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 55 | #define SRS_CONF_DEFAULT_HLS_ON_ERROR SRS_CONF_DEFAULT_HLS_ON_ERROR_IGNORE | 55 | #define SRS_CONF_DEFAULT_HLS_ON_ERROR SRS_CONF_DEFAULT_HLS_ON_ERROR_IGNORE |
| 56 | #define SRS_CONF_DEFAULT_HLS_STORAGE "disk" | 56 | #define SRS_CONF_DEFAULT_HLS_STORAGE "disk" |
| 57 | #define SRS_CONF_DEFAULT_HLS_MOUNT "[vhost]/[app]/[stream].m3u8" | 57 | #define SRS_CONF_DEFAULT_HLS_MOUNT "[vhost]/[app]/[stream].m3u8" |
| 58 | +#define SRS_CONF_DEFAULT_HLS_ACODEC "aac" | ||
| 58 | #define SRS_CONF_DEFAULT_DVR_PATH "./objs/nginx/html" | 59 | #define SRS_CONF_DEFAULT_DVR_PATH "./objs/nginx/html" |
| 59 | #define SRS_CONF_DEFAULT_DVR_PLAN_SESSION "session" | 60 | #define SRS_CONF_DEFAULT_DVR_PLAN_SESSION "session" |
| 60 | #define SRS_CONF_DEFAULT_DVR_PLAN_SEGMENT "segment" | 61 | #define SRS_CONF_DEFAULT_DVR_PLAN_SEGMENT "segment" |
| @@ -922,6 +923,10 @@ public: | @@ -922,6 +923,10 @@ public: | ||
| 922 | * get the HLS mount url for HTTP server. | 923 | * get the HLS mount url for HTTP server. |
| 923 | */ | 924 | */ |
| 924 | virtual std::string get_hls_mount(std::string vhost); | 925 | virtual std::string get_hls_mount(std::string vhost); |
| 926 | + /** | ||
| 927 | + * get the HLS default audio codec. | ||
| 928 | + */ | ||
| 929 | + virtual std::string get_hls_acodec(std::string vhost); | ||
| 925 | // dvr section | 930 | // dvr section |
| 926 | private: | 931 | private: |
| 927 | /** | 932 | /** |
| @@ -131,14 +131,14 @@ string SrsHlsCacheWriter::cache() | @@ -131,14 +131,14 @@ string SrsHlsCacheWriter::cache() | ||
| 131 | return data; | 131 | return data; |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | -SrsHlsSegment::SrsHlsSegment(bool write_cache, bool write_file) | 134 | +SrsHlsSegment::SrsHlsSegment(bool write_cache, bool write_file, SrsCodecAudio ac) |
| 135 | { | 135 | { |
| 136 | duration = 0; | 136 | duration = 0; |
| 137 | sequence_no = 0; | 137 | sequence_no = 0; |
| 138 | segment_start_dts = 0; | 138 | segment_start_dts = 0; |
| 139 | is_sequence_header = false; | 139 | is_sequence_header = false; |
| 140 | writer = new SrsHlsCacheWriter(write_cache, write_file); | 140 | writer = new SrsHlsCacheWriter(write_cache, write_file); |
| 141 | - muxer = new SrsTSMuxer(writer); | 141 | + muxer = new SrsTSMuxer(writer, ac); |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | SrsHlsSegment::~SrsHlsSegment() | 144 | SrsHlsSegment::~SrsHlsSegment() |
| @@ -243,9 +243,22 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts) | @@ -243,9 +243,22 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts) | ||
| 243 | 243 | ||
| 244 | // when segment open, the current segment must be NULL. | 244 | // when segment open, the current segment must be NULL. |
| 245 | srs_assert(!current); | 245 | srs_assert(!current); |
| 246 | + | ||
| 247 | + // load the default acodec from config. | ||
| 248 | + SrsCodecAudio default_acodec = SrsCodecAudioAAC; | ||
| 249 | + std::string default_acodec_str = _srs_config->get_hls_acodec(req->vhost); | ||
| 250 | + if (default_acodec_str == "mp3") { | ||
| 251 | + default_acodec = SrsCodecAudioMP3; | ||
| 252 | + srs_info("hls: use default mp3 acodec"); | ||
| 253 | + } else if (default_acodec_str == "aac") { | ||
| 254 | + default_acodec = SrsCodecAudioAAC; | ||
| 255 | + srs_info("hls: use default aac acodec"); | ||
| 256 | + } else { | ||
| 257 | + srs_warn("hls: use aac for other codec=%s", default_acodec_str.c_str()); | ||
| 258 | + } | ||
| 246 | 259 | ||
| 247 | // new segment. | 260 | // new segment. |
| 248 | - current = new SrsHlsSegment(should_write_cache, should_write_file); | 261 | + current = new SrsHlsSegment(should_write_cache, should_write_file, default_acodec); |
| 249 | current->sequence_no = _sequence_no++; | 262 | current->sequence_no = _sequence_no++; |
| 250 | current->segment_start_dts = segment_start_dts; | 263 | current->segment_start_dts = segment_start_dts; |
| 251 | 264 |
| @@ -144,7 +144,7 @@ public: | @@ -144,7 +144,7 @@ public: | ||
| 144 | // whether current segement is sequence header. | 144 | // whether current segement is sequence header. |
| 145 | bool is_sequence_header; | 145 | bool is_sequence_header; |
| 146 | public: | 146 | public: |
| 147 | - SrsHlsSegment(bool write_cache, bool write_file); | 147 | + SrsHlsSegment(bool write_cache, bool write_file, SrsCodecAudio ac); |
| 148 | virtual ~SrsHlsSegment(); | 148 | virtual ~SrsHlsSegment(); |
| 149 | public: | 149 | public: |
| 150 | /** | 150 | /** |
| @@ -2916,13 +2916,12 @@ int SrsTsPayloadPMT::psi_encode(SrsStream* stream) | @@ -2916,13 +2916,12 @@ int SrsTsPayloadPMT::psi_encode(SrsStream* stream) | ||
| 2916 | return ret; | 2916 | return ret; |
| 2917 | } | 2917 | } |
| 2918 | 2918 | ||
| 2919 | -SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w) | 2919 | +SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w, SrsCodecAudio ac) |
| 2920 | { | 2920 | { |
| 2921 | writer = w; | 2921 | writer = w; |
| 2922 | context = NULL; | 2922 | context = NULL; |
| 2923 | 2923 | ||
| 2924 | - // default to aac. | ||
| 2925 | - acodec = SrsCodecAudioAAC; | 2924 | + acodec = ac; |
| 2926 | // default to avc(h.264) | 2925 | // default to avc(h.264) |
| 2927 | vcodec = SrsCodecVideoAVC; | 2926 | vcodec = SrsCodecVideoAVC; |
| 2928 | } | 2927 | } |
| @@ -3296,7 +3295,7 @@ int SrsTsEncoder::initialize(SrsFileWriter* fs) | @@ -3296,7 +3295,7 @@ int SrsTsEncoder::initialize(SrsFileWriter* fs) | ||
| 3296 | _fs = fs; | 3295 | _fs = fs; |
| 3297 | 3296 | ||
| 3298 | srs_freep(muxer); | 3297 | srs_freep(muxer); |
| 3299 | - muxer = new SrsTSMuxer(fs); | 3298 | + muxer = new SrsTSMuxer(fs, SrsCodecAudioAAC); |
| 3300 | 3299 | ||
| 3301 | if ((ret = muxer->open("")) != ERROR_SUCCESS) { | 3300 | if ((ret = muxer->open("")) != ERROR_SUCCESS) { |
| 3302 | return ret; | 3301 | return ret; |
| @@ -1547,7 +1547,7 @@ private: | @@ -1547,7 +1547,7 @@ private: | ||
| 1547 | SrsFileWriter* writer; | 1547 | SrsFileWriter* writer; |
| 1548 | std::string path; | 1548 | std::string path; |
| 1549 | public: | 1549 | public: |
| 1550 | - SrsTSMuxer(SrsFileWriter* w); | 1550 | + SrsTSMuxer(SrsFileWriter* w, SrsCodecAudio ac); |
| 1551 | virtual ~SrsTSMuxer(); | 1551 | virtual ~SrsTSMuxer(); |
| 1552 | public: | 1552 | public: |
| 1553 | /** | 1553 | /** |
-
请 注册 或 登录 后发表评论