正在显示
6 个修改的文件
包含
61 行增加
和
9 行删除
| @@ -346,6 +346,7 @@ Remark: | @@ -346,6 +346,7 @@ Remark: | ||
| 346 | * v3.0, 2015-03-15, fork srs2 and start srs3. 3.0.0 | 346 | * v3.0, 2015-03-15, fork srs2 and start srs3. 3.0.0 |
| 347 | 347 | ||
| 348 | ### SRS 2.0 history | 348 | ### SRS 2.0 history |
| 349 | +* v2.0, 2015-05-29, fix [#409](https://github.com/simple-rtmp-server/srs/issues/409) support pure video hls. 2.0.172. | ||
| 349 | * v2.0, 2015-05-28, support [srs-dolphin][srs-dolphin], the multiple-process SRS. | 350 | * v2.0, 2015-05-28, support [srs-dolphin][srs-dolphin], the multiple-process SRS. |
| 350 | * v2.0, 2015-05-24, fix [#404](https://github.com/simple-rtmp-server/srs/issues/404) register handler then start http thread. 2.0.167. | 351 | * v2.0, 2015-05-24, fix [#404](https://github.com/simple-rtmp-server/srs/issues/404) register handler then start http thread. 2.0.167. |
| 351 | * v2.0, 2015-05-23, refine the thread, protocol, kbps code. 2.0.166 | 352 | * v2.0, 2015-05-23, refine the thread, protocol, kbps code. 2.0.166 |
| @@ -735,7 +736,7 @@ The latency between encoder and player with realtime config( | @@ -735,7 +736,7 @@ The latency between encoder and player with realtime config( | ||
| 735 | [CN](https://github.com/simple-rtmp-server/srs/wiki/v2_CN_LowLatency), | 736 | [CN](https://github.com/simple-rtmp-server/srs/wiki/v2_CN_LowLatency), |
| 736 | [EN](https://github.com/simple-rtmp-server/srs/wiki/v2_EN_LowLatency) | 737 | [EN](https://github.com/simple-rtmp-server/srs/wiki/v2_EN_LowLatency) |
| 737 | ): | 738 | ): |
| 738 | - | 739 | +| |
| 739 | 740 | ||
| 740 | | Update | SRS | VP6 | H.264 | VP6+MP3 | H.264+MP3 | | 741 | | Update | SRS | VP6 | H.264 | VP6+MP3 | H.264+MP3 | |
| 741 | | ------------- | --------- | --------- | --------- | --------- | -------- | | 742 | | ------------- | --------- | --------- | --------- | --------- | -------- | |
| @@ -747,6 +748,32 @@ We use FMLE as encoder for benchmark. The latency of server is 0.1s+, | @@ -747,6 +748,32 @@ We use FMLE as encoder for benchmark. The latency of server is 0.1s+, | ||
| 747 | and the bottleneck is the encoder. For more information, read | 748 | and the bottleneck is the encoder. For more information, read |
| 748 | [bug #257](https://github.com/simple-rtmp-server/srs/issues/257#issuecomment-66864413). | 749 | [bug #257](https://github.com/simple-rtmp-server/srs/issues/257#issuecomment-66864413). |
| 749 | 750 | ||
| 751 | +### HLS overhead | ||
| 752 | + | ||
| 753 | +About the HLS overhead of SRS, we compare the overhead to FLV by remux the HLS to FLV by ffmpeg. | ||
| 754 | + | ||
| 755 | +| Bitrate | Duration | FLV(KB) | HLS(KB) | Overhead | | ||
| 756 | +| ------- | -------- | ------- | -------- | --------- | | ||
| 757 | +| 275kbps | 600s | 11144 | 12756 | 14.46% | | ||
| 758 | +| 260kbps | 1860s | 59344 | 68004 | 14.59% | | ||
| 759 | +| 697kbps | 60s | 5116 | 5476 | 7.03% | | ||
| 760 | +| 565kbps | 453s | 31316 | 33544 | 7.11% | | ||
| 761 | +| 565kbps | 1813s | 125224 | 134140 | 7.12% | | ||
| 762 | +| 861kbps | 497s | 52316 | 54924 | 4.98% | | ||
| 763 | +| 857kbps | 1862s | 195008 | 204768 | 5.00% | | ||
| 764 | +| 1301kbps | 505s | 80320 | 83676 | 4.17% | | ||
| 765 | +| 1312kbps | 1915s | 306920 | 319680 | 4.15% | | ||
| 766 | +| 2707kbps | 600s | 198356 | 204560 | 3.12% | | ||
| 767 | +| 2814kbps | 1800s | 618456 | 637660 | 3.10% | | ||
| 768 | +| 2828kbps | 60s | 20716 | 21356 | 3.08% | | ||
| 769 | +| 2599kbps | 307s | 97580 | 100672 | 3.16% | | ||
| 770 | +| 2640kbps | 1283s | 413880 | 426912 | 3.14% | | ||
| 771 | +| 5254kbps | 71s | 45832 | 47056 | 2.67% | | ||
| 772 | +| 5147kbps | 370s | 195040 | 200280 | 2.68% | | ||
| 773 | +| 5158kbps | 1327s | 835664 | 858092 | 2.68% | | ||
| 774 | + | ||
| 775 | +The HLS overhead is calc by: (HLS - FLV) / FLV * 100% | ||
| 776 | + | ||
| 750 | ## Architecture | 777 | ## Architecture |
| 751 | 778 | ||
| 752 | SRS always use the most simple architecture to support complex transaction. | 779 | SRS always use the most simple architecture to support complex transaction. |
| @@ -608,7 +608,7 @@ vhost with-hls.srs.com { | @@ -608,7 +608,7 @@ vhost with-hls.srs.com { | ||
| 608 | # when codec changed, write the PAT/PMT table, but maybe ok util next ts. | 608 | # when codec changed, write the PAT/PMT table, but maybe ok util next ts. |
| 609 | # so user can set the default codec for mp3. | 609 | # so user can set the default codec for mp3. |
| 610 | # the available audio codec: | 610 | # the available audio codec: |
| 611 | - # aac, mp3 | 611 | + # aac, mp3, an |
| 612 | # default: aac | 612 | # default: aac |
| 613 | hls_acodec aac; | 613 | hls_acodec aac; |
| 614 | # the default video codec of hls. | 614 | # the default video codec of hls. |
| @@ -420,6 +420,9 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts) | @@ -420,6 +420,9 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts) | ||
| 420 | } else if (default_acodec_str == "aac") { | 420 | } else if (default_acodec_str == "aac") { |
| 421 | default_acodec = SrsCodecAudioAAC; | 421 | default_acodec = SrsCodecAudioAAC; |
| 422 | srs_info("hls: use default aac acodec"); | 422 | srs_info("hls: use default aac acodec"); |
| 423 | + } else if (default_acodec_str == "an") { | ||
| 424 | + default_acodec = SrsCodecAudioDisabled; | ||
| 425 | + srs_info("hls: use default an acodec for pure video"); | ||
| 423 | } else { | 426 | } else { |
| 424 | srs_warn("hls: use aac for other codec=%s", default_acodec_str.c_str()); | 427 | srs_warn("hls: use aac for other codec=%s", default_acodec_str.c_str()); |
| 425 | } | 428 | } |
| @@ -136,6 +136,9 @@ enum SrsCodecAudio | @@ -136,6 +136,9 @@ enum SrsCodecAudio | ||
| 136 | // set to the max value to reserved, for array map. | 136 | // set to the max value to reserved, for array map. |
| 137 | SrsCodecAudioReserved1 = 16, | 137 | SrsCodecAudioReserved1 = 16, |
| 138 | 138 | ||
| 139 | + // for user to disable audio, for example, use pure video hls. | ||
| 140 | + SrsCodecAudioDisabled = 17, | ||
| 141 | + | ||
| 139 | SrsCodecAudioLinearPCMPlatformEndian = 0, | 142 | SrsCodecAudioLinearPCMPlatformEndian = 0, |
| 140 | SrsCodecAudioADPCM = 1, | 143 | SrsCodecAudioADPCM = 1, |
| 141 | SrsCodecAudioMP3 = 2, | 144 | SrsCodecAudioMP3 = 2, |
| @@ -215,13 +215,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -215,13 +215,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 215 | #define ERROR_HTTP_DVR_CREATE_REQUEST 3053 | 215 | #define ERROR_HTTP_DVR_CREATE_REQUEST 3053 |
| 216 | #define ERROR_HTTP_DVR_NO_TAEGET 3054 | 216 | #define ERROR_HTTP_DVR_NO_TAEGET 3054 |
| 217 | #define ERROR_ADTS_ID_NOT_AAC 3055 | 217 | #define ERROR_ADTS_ID_NOT_AAC 3055 |
| 218 | -// HDS error code | ||
| 219 | #define ERROR_HDS_OPEN_F4M_FAILED 3056 | 218 | #define ERROR_HDS_OPEN_F4M_FAILED 3056 |
| 220 | #define ERROR_HDS_WRITE_F4M_FAILED 3057 | 219 | #define ERROR_HDS_WRITE_F4M_FAILED 3057 |
| 221 | #define ERROR_HDS_OPEN_BOOTSTRAP_FAILED 3058 | 220 | #define ERROR_HDS_OPEN_BOOTSTRAP_FAILED 3058 |
| 222 | #define ERROR_HDS_WRITE_BOOTSTRAP_FAILED 3059 | 221 | #define ERROR_HDS_WRITE_BOOTSTRAP_FAILED 3059 |
| 223 | #define ERROR_HDS_OPEN_FRAGMENT_FAILED 3060 | 222 | #define ERROR_HDS_OPEN_FRAGMENT_FAILED 3060 |
| 224 | #define ERROR_HDS_WRITE_FRAGMENT_FAILED 3061 | 223 | #define ERROR_HDS_WRITE_FRAGMENT_FAILED 3061 |
| 224 | +#define ERROR_HLS_NO_STREAM 3062 | ||
| 225 | 225 | ||
| 226 | /////////////////////////////////////////////////////// | 226 | /////////////////////////////////////////////////////// |
| 227 | // HTTP/StreamCaster protocol error. | 227 | // HTTP/StreamCaster protocol error. |
| @@ -302,10 +302,12 @@ int SrsTsContext::encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsCodecVideo | @@ -302,10 +302,12 @@ int SrsTsContext::encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsCodecVideo | ||
| 302 | vs = SrsTsStreamVideoH264; | 302 | vs = SrsTsStreamVideoH264; |
| 303 | video_pid = TS_VIDEO_AVC_PID; | 303 | video_pid = TS_VIDEO_AVC_PID; |
| 304 | break; | 304 | break; |
| 305 | + case SrsCodecVideoDisabled: | ||
| 306 | + vs = SrsTsStreamReserved; | ||
| 307 | + break; | ||
| 305 | case SrsCodecVideoReserved: | 308 | case SrsCodecVideoReserved: |
| 306 | case SrsCodecVideoReserved1: | 309 | case SrsCodecVideoReserved1: |
| 307 | case SrsCodecVideoReserved2: | 310 | case SrsCodecVideoReserved2: |
| 308 | - case SrsCodecVideoDisabled: | ||
| 309 | case SrsCodecVideoSorensonH263: | 311 | case SrsCodecVideoSorensonH263: |
| 310 | case SrsCodecVideoScreenVideo: | 312 | case SrsCodecVideoScreenVideo: |
| 311 | case SrsCodecVideoOn2VP6: | 313 | case SrsCodecVideoOn2VP6: |
| @@ -323,6 +325,9 @@ int SrsTsContext::encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsCodecVideo | @@ -323,6 +325,9 @@ int SrsTsContext::encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsCodecVideo | ||
| 323 | as = SrsTsStreamAudioMp3; | 325 | as = SrsTsStreamAudioMp3; |
| 324 | audio_pid = TS_AUDIO_MP3_PID; | 326 | audio_pid = TS_AUDIO_MP3_PID; |
| 325 | break; | 327 | break; |
| 328 | + case SrsCodecAudioDisabled: | ||
| 329 | + as = SrsTsStreamReserved; | ||
| 330 | + break; | ||
| 326 | case SrsCodecAudioReserved1: | 331 | case SrsCodecAudioReserved1: |
| 327 | case SrsCodecAudioLinearPCMPlatformEndian: | 332 | case SrsCodecAudioLinearPCMPlatformEndian: |
| 328 | case SrsCodecAudioADPCM: | 333 | case SrsCodecAudioADPCM: |
| @@ -340,6 +345,12 @@ int SrsTsContext::encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsCodecVideo | @@ -340,6 +345,12 @@ int SrsTsContext::encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsCodecVideo | ||
| 340 | break; | 345 | break; |
| 341 | } | 346 | } |
| 342 | 347 | ||
| 348 | + if (as == SrsTsStreamReserved && vs == SrsTsStreamReserved) { | ||
| 349 | + ret = ERROR_HLS_NO_STREAM; | ||
| 350 | + srs_error("hls: no video or audio stream, vcodec=%d, acodec=%d. ret=%d", vc, ac, ret); | ||
| 351 | + return ret; | ||
| 352 | + } | ||
| 353 | + | ||
| 343 | // when any codec changed, write PAT/PMT table. | 354 | // when any codec changed, write PAT/PMT table. |
| 344 | if (vcodec != vc || acodec != ac) { | 355 | if (vcodec != vc || acodec != ac) { |
| 345 | vcodec = vc; | 356 | vcodec = vc; |
| @@ -360,6 +371,12 @@ int SrsTsContext::encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsCodecVideo | @@ -360,6 +371,12 @@ int SrsTsContext::encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsCodecVideo | ||
| 360 | int SrsTsContext::encode_pat_pmt(SrsFileWriter* writer, int16_t vpid, SrsTsStream vs, int16_t apid, SrsTsStream as) | 371 | int SrsTsContext::encode_pat_pmt(SrsFileWriter* writer, int16_t vpid, SrsTsStream vs, int16_t apid, SrsTsStream as) |
| 361 | { | 372 | { |
| 362 | int ret = ERROR_SUCCESS; | 373 | int ret = ERROR_SUCCESS; |
| 374 | + | ||
| 375 | + if (vs != SrsTsStreamVideoH264 && as != SrsTsStreamAudioAAC && as != SrsTsStreamAudioMp3) { | ||
| 376 | + ret = ERROR_HLS_NO_STREAM; | ||
| 377 | + srs_error("hls: no pmt pcr pid, vs=%d, as=%d. ret=%d", vs, as, ret); | ||
| 378 | + return ret; | ||
| 379 | + } | ||
| 363 | 380 | ||
| 364 | int16_t pmt_number = TS_PMT_NUMBER; | 381 | int16_t pmt_number = TS_PMT_NUMBER; |
| 365 | int16_t pmt_pid = TS_PMT_PID; | 382 | int16_t pmt_pid = TS_PMT_PID; |
| @@ -754,15 +771,17 @@ SrsTsPacket* SrsTsPacket::create_pmt(SrsTsContext* context, int16_t pmt_number, | @@ -754,15 +771,17 @@ SrsTsPacket* SrsTsPacket::create_pmt(SrsTsContext* context, int16_t pmt_number, | ||
| 754 | pmt->last_section_number = 0; | 771 | pmt->last_section_number = 0; |
| 755 | pmt->program_info_length = 0; | 772 | pmt->program_info_length = 0; |
| 756 | 773 | ||
| 757 | - // use audio to carray pcr by default. | ||
| 758 | - // for hls, there must be atleast one audio channel. | ||
| 759 | - pmt->PCR_PID = apid; | ||
| 760 | - pmt->infos.push_back(new SrsTsPayloadPMTESInfo(as, apid)); | ||
| 761 | - | ||
| 762 | // if h.264 specified, use video to carry pcr. | 774 | // if h.264 specified, use video to carry pcr. |
| 763 | if (vs == SrsTsStreamVideoH264) { | 775 | if (vs == SrsTsStreamVideoH264) { |
| 764 | pmt->PCR_PID = vpid; | 776 | pmt->PCR_PID = vpid; |
| 765 | pmt->infos.push_back(new SrsTsPayloadPMTESInfo(vs, vpid)); | 777 | pmt->infos.push_back(new SrsTsPayloadPMTESInfo(vs, vpid)); |
| 778 | + } else if (as == SrsTsStreamAudioAAC || as == SrsTsStreamAudioMp3) { | ||
| 779 | + // use audio to carray pcr by default. | ||
| 780 | + // for hls, there must be atleast one audio channel. | ||
| 781 | + pmt->PCR_PID = apid; | ||
| 782 | + pmt->infos.push_back(new SrsTsPayloadPMTESInfo(as, apid)); | ||
| 783 | + } else { | ||
| 784 | + srs_assert(false); | ||
| 766 | } | 785 | } |
| 767 | 786 | ||
| 768 | pmt->CRC_32 = 0; // calc in encode. | 787 | pmt->CRC_32 = 0; // calc in encode. |
-
请 注册 或 登录 后发表评论