winlin

merge from 2.0release

@@ -814,7 +814,9 @@ About the HLS overhead of SRS, we compare the overhead to FLV by remux the HLS t @@ -814,7 +814,9 @@ About the HLS overhead of SRS, we compare the overhead to FLV by remux the HLS t
814 | 5147kbps | 370s | 195040 | 200280 | 2.68% | 814 | 5147kbps | 370s | 195040 | 200280 | 2.68% |
815 | 5158kbps | 1327s | 835664 | 858092 | 2.68% | 815 | 5158kbps | 1327s | 835664 | 858092 | 2.68% |
816 816
817 -The HLS overhead is calc by: (HLS - FLV) / FLV * 100% 817 +The HLS overhead is calc by: (HLS - FLV) / FLV * 100%.
  818 +
  819 +The overhead is larger than this benchmark(48kbps audio is best overhead), for we fix the [#512][bug#512].
818 820
819 ## Architecture 821 ## Architecture
820 822
@@ -1265,6 +1267,7 @@ Winlin @@ -1265,6 +1267,7 @@ Winlin
1265 [bug #59]: https://github.com/simple-rtmp-server/srs/issues/59 1267 [bug #59]: https://github.com/simple-rtmp-server/srs/issues/59
1266 [bug #50]: https://github.com/simple-rtmp-server/srs/issues/50 1268 [bug #50]: https://github.com/simple-rtmp-server/srs/issues/50
1267 [bug #34]: https://github.com/simple-rtmp-server/srs/issues/34 1269 [bug #34]: https://github.com/simple-rtmp-server/srs/issues/34
  1270 +<<<<<<< HEAD
1268 [bug #367]: https://github.com/simple-rtmp-server/srs/issues/367 1271 [bug #367]: https://github.com/simple-rtmp-server/srs/issues/367
1269 [bug #319]: https://github.com/simple-rtmp-server/srs/issues/319 1272 [bug #319]: https://github.com/simple-rtmp-server/srs/issues/319
1270 [bug #367]: https://github.com/simple-rtmp-server/srs/issues/367 1273 [bug #367]: https://github.com/simple-rtmp-server/srs/issues/367
@@ -1282,6 +1285,10 @@ Winlin @@ -1282,6 +1285,10 @@ Winlin
1282 [bug #502]: https://github.com/simple-rtmp-server/srs/issues/502 1285 [bug #502]: https://github.com/simple-rtmp-server/srs/issues/502
1283 [bug #467]: https://github.com/simple-rtmp-server/srs/issues/467 1286 [bug #467]: https://github.com/simple-rtmp-server/srs/issues/467
1284 [bug #xxxxxxx]: https://github.com/simple-rtmp-server/srs/issues/xxxxxxx 1287 [bug #xxxxxxx]: https://github.com/simple-rtmp-server/srs/issues/xxxxxxx
  1288 +=======
  1289 +[bug #512]: https://github.com/simple-rtmp-server/srs/issues/512
  1290 +[bug #xxxxxxxxxx]: https://github.com/simple-rtmp-server/srs/issues/xxxxxxxxxx
  1291 +>>>>>>> 2.0release
1285 1292
1286 [r2.0a2]: https://github.com/simple-rtmp-server/srs/releases/tag/v2.0-a2 1293 [r2.0a2]: https://github.com/simple-rtmp-server/srs/releases/tag/v2.0-a2
1287 [r2.0a1]: https://github.com/simple-rtmp-server/srs/releases/tag/2.0a1 1294 [r2.0a1]: https://github.com/simple-rtmp-server/srs/releases/tag/2.0a1
@@ -578,6 +578,7 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts) @@ -578,6 +578,7 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts)
578 current->full_path.c_str(), tmp_file.c_str()); 578 current->full_path.c_str(), tmp_file.c_str());
579 579
580 // set the segment muxer audio codec. 580 // set the segment muxer audio codec.
  581 + // TODO: FIXME: refine code, use event instead.
581 if (acodec != SrsCodecAudioReserved1) { 582 if (acodec != SrsCodecAudioReserved1) {
582 current->muxer->update_acodec(acodec); 583 current->muxer->update_acodec(acodec);
583 } 584 }
@@ -646,6 +647,11 @@ int SrsHlsMuxer::update_acodec(SrsCodecAudio ac) @@ -646,6 +647,11 @@ int SrsHlsMuxer::update_acodec(SrsCodecAudio ac)
646 return current->muxer->update_acodec(ac); 647 return current->muxer->update_acodec(ac);
647 } 648 }
648 649
  650 +bool SrsHlsMuxer::pure_audio()
  651 +{
  652 + return current && current->muxer && current->muxer->video_codec() == SrsCodecVideoDisabled;
  653 +}
  654 +
649 int SrsHlsMuxer::flush_audio(SrsTsCache* cache) 655 int SrsHlsMuxer::flush_audio(SrsTsCache* cache)
650 { 656 {
651 int ret = ERROR_SUCCESS; 657 int ret = ERROR_SUCCESS;
@@ -1049,25 +1055,6 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t @@ -1049,25 +1055,6 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t
1049 return ret; 1055 return ret;
1050 } 1056 }
1051 1057
1052 - // flush if buffer exceed max size.  
1053 - if (cache->audio->payload->length() > SRS_AUTO_HLS_AUDIO_CACHE_SIZE) {  
1054 - if ((ret = muxer->flush_audio(cache)) != ERROR_SUCCESS) {  
1055 - return ret;  
1056 - }  
1057 - }  
1058 -  
1059 - // TODO: config it.  
1060 - // in ms, audio delay to flush the audios.  
1061 - int64_t audio_delay = SRS_CONF_DEFAULT_AAC_DELAY;  
1062 - // flush if audio delay exceed  
1063 - // cache->audio will be free in flush_audio  
1064 - // so we must check whether it's null ptr.  
1065 - if (cache->audio && pts - cache->audio->start_pts > audio_delay * 90) {  
1066 - if ((ret = muxer->flush_audio(cache)) != ERROR_SUCCESS) {  
1067 - return ret;  
1068 - }  
1069 - }  
1070 -  
1071 // reap when current source is pure audio. 1058 // reap when current source is pure audio.
1072 // it maybe changed when stream info changed, 1059 // it maybe changed when stream info changed,
1073 // for example, pure audio when start, audio/video when publishing, 1060 // for example, pure audio when start, audio/video when publishing,
@@ -1083,6 +1070,21 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t @@ -1083,6 +1070,21 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t
1083 } 1070 }
1084 } 1071 }
1085 1072
  1073 + // for pure audio, aggregate some frame to one.
  1074 + if (muxer->pure_audio() && cache->audio) {
  1075 + if (pts - cache->audio->start_pts < SRS_CONSTS_HLS_PURE_AUDIO_AGGREGATE) {
  1076 + return ret;
  1077 + }
  1078 + }
  1079 +
  1080 + // directly write the audio frame by frame to ts,
  1081 + // it's ok for the hls overload, or maybe cause the audio corrupt,
  1082 + // which introduced by aggregate the audios to a big one.
  1083 + // @see https://github.com/simple-rtmp-server/srs/issues/512
  1084 + if ((ret = muxer->flush_audio(cache)) != ERROR_SUCCESS) {
  1085 + return ret;
  1086 + }
  1087 +
1086 return ret; 1088 return ret;
1087 } 1089 }
1088 1090
@@ -1100,7 +1102,7 @@ int SrsHlsCache::write_video(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t @@ -1100,7 +1102,7 @@ int SrsHlsCache::write_video(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t
1100 // do reap ts if any of: 1102 // do reap ts if any of:
1101 // a. wait keyframe and got keyframe. 1103 // a. wait keyframe and got keyframe.
1102 // b. always reap when not wait keyframe. 1104 // b. always reap when not wait keyframe.
1103 - if (!muxer->wait_keyframe()|| sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) { 1105 + if (!muxer->wait_keyframe() || sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) {
1104 // when wait keyframe, there must exists idr frame in sample. 1106 // when wait keyframe, there must exists idr frame in sample.
1105 if (!sample->has_idr && muxer->wait_keyframe()) { 1107 if (!sample->has_idr && muxer->wait_keyframe()) {
1106 srs_warn("hls: ts starts without IDR, first nalu=%d, idr=%d", sample->first_nalu_type, sample->has_idr); 1108 srs_warn("hls: ts starts without IDR, first nalu=%d, idr=%d", sample->first_nalu_type, sample->has_idr);
@@ -1110,9 +1112,6 @@ int SrsHlsCache::write_video(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t @@ -1110,9 +1112,6 @@ int SrsHlsCache::write_video(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t
1110 if ((ret = reap_segment("video", muxer, cache->video->dts)) != ERROR_SUCCESS) { 1112 if ((ret = reap_segment("video", muxer, cache->video->dts)) != ERROR_SUCCESS) {
1111 return ret; 1113 return ret;
1112 } 1114 }
1113 -  
1114 - // the video must be flushed, just return.  
1115 - return ret;  
1116 } 1115 }
1117 } 1116 }
1118 1117
@@ -309,6 +309,10 @@ public: @@ -309,6 +309,10 @@ public:
309 virtual bool is_segment_absolutely_overflow(); 309 virtual bool is_segment_absolutely_overflow();
310 public: 310 public:
311 virtual int update_acodec(SrsCodecAudio ac); 311 virtual int update_acodec(SrsCodecAudio ac);
  312 + /**
  313 + * whether current hls muxer is pure audio mode.
  314 + */
  315 + virtual bool pure_audio();
312 virtual int flush_audio(SrsTsCache* cache); 316 virtual int flush_audio(SrsTsCache* cache);
313 virtual int flush_video(SrsTsCache* cache); 317 virtual int flush_video(SrsTsCache* cache);
314 /** 318 /**
@@ -246,12 +246,6 @@ extern int aac_sample_rates[]; @@ -246,12 +246,6 @@ extern int aac_sample_rates[];
246 #define SRS_SRS_MAX_CODEC_SAMPLE 128 246 #define SRS_SRS_MAX_CODEC_SAMPLE 128
247 #define SRS_AAC_SAMPLE_RATE_UNSET 15 247 #define SRS_AAC_SAMPLE_RATE_UNSET 15
248 248
249 -// in ms, for HLS aac flush the audio  
250 -#define SRS_CONF_DEFAULT_AAC_DELAY 60  
251 -  
252 -// max PES packets size to flush the video.  
253 -#define SRS_AUTO_HLS_AUDIO_CACHE_SIZE 128 * 1024  
254 -  
255 /** 249 /**
256 * the FLV/RTMP supported audio sample size. 250 * the FLV/RTMP supported audio sample size.
257 * Size of each audio sample. This parameter only pertains to 251 * Size of each audio sample. This parameter only pertains to
@@ -469,8 +469,11 @@ int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t p @@ -469,8 +469,11 @@ int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t p
469 while (p < end) { 469 while (p < end) {
470 SrsTsPacket* pkt = NULL; 470 SrsTsPacket* pkt = NULL;
471 if (p == start) { 471 if (p == start) {
472 - // for pure audio stream, always write pcr. 472 + // write pcr according to message.
473 bool write_pcr = msg->write_pcr; 473 bool write_pcr = msg->write_pcr;
  474 +
  475 + // for pure audio, always write pcr.
  476 + // TODO: FIXME: maybe only need to write at begin and end of ts.
474 if (pure_audio && msg->is_audio()) { 477 if (pure_audio && msg->is_audio()) {
475 write_pcr = true; 478 write_pcr = true;
476 } 479 }
@@ -2772,6 +2775,11 @@ void SrsTSMuxer::close() @@ -2772,6 +2775,11 @@ void SrsTSMuxer::close()
2772 writer->close(); 2775 writer->close();
2773 } 2776 }
2774 2777
  2778 +SrsCodecVideo SrsTSMuxer::video_codec()
  2779 +{
  2780 + return vcodec;
  2781 +}
  2782 +
2775 SrsTsCache::SrsTsCache() 2783 SrsTsCache::SrsTsCache()
2776 { 2784 {
2777 audio = NULL; 2785 audio = NULL;
@@ -2792,11 +2800,12 @@ int SrsTsCache::cache_audio(SrsAvcAacCodec* codec, int64_t dts, SrsCodecSample* @@ -2792,11 +2800,12 @@ int SrsTsCache::cache_audio(SrsAvcAacCodec* codec, int64_t dts, SrsCodecSample*
2792 if (!audio) { 2800 if (!audio) {
2793 audio = new SrsTsMessage(); 2801 audio = new SrsTsMessage();
2794 audio->write_pcr = false; 2802 audio->write_pcr = false;
2795 - audio->start_pts = dts; 2803 + audio->dts = audio->pts = audio->start_pts = dts;
2796 } 2804 }
2797 2805
2798 - audio->dts = dts;  
2799 - audio->pts = audio->dts; 2806 + // TODO: FIXME: refine code.
  2807 + //audio->dts = dts;
  2808 + //audio->pts = audio->dts;
2800 audio->sid = SrsTsPESStreamIdAudioCommon; 2809 audio->sid = SrsTsPESStreamIdAudioCommon;
2801 2810
2802 // must be aac or mp3 2811 // must be aac or mp3
@@ -3146,20 +3155,11 @@ int SrsTsEncoder::write_audio(int64_t timestamp, char* data, int size) @@ -3146,20 +3155,11 @@ int SrsTsEncoder::write_audio(int64_t timestamp, char* data, int size)
3146 return ret; 3155 return ret;
3147 } 3156 }
3148 3157
3149 - // flush if buffer exceed max size.  
3150 - if (cache->audio->payload->length() > SRS_AUTO_HLS_AUDIO_CACHE_SIZE) {  
3151 - return flush_video();  
3152 - } 3158 + // TODO: FIXME: for pure audio, aggregate some frame to one.
3153 3159
3154 - // TODO: config it.  
3155 - // in ms, audio delay to flush the audios.  
3156 - int64_t audio_delay = SRS_CONF_DEFAULT_AAC_DELAY;  
3157 - // flush if audio delay exceed  
3158 - if (dts - cache->audio->start_pts > audio_delay * 90) { 3160 + // always flush audio frame by frame.
  3161 + // @see https://github.com/simple-rtmp-server/srs/issues/512
3159 return flush_audio(); 3162 return flush_audio();
3160 - }  
3161 -  
3162 - return ret;  
3163 } 3163 }
3164 3164
3165 int SrsTsEncoder::write_video(int64_t timestamp, char* data, int size) 3165 int SrsTsEncoder::write_video(int64_t timestamp, char* data, int size)
@@ -54,6 +54,9 @@ class SrsTsContext; @@ -54,6 +54,9 @@ class SrsTsContext;
54 // Transport Stream packets are 188 bytes in length. 54 // Transport Stream packets are 188 bytes in length.
55 #define SRS_TS_PACKET_SIZE 188 55 #define SRS_TS_PACKET_SIZE 188
56 56
  57 +// the aggregate pure audio for hls, in ts tbn(ms * 90).
  58 +#define SRS_CONSTS_HLS_PURE_AUDIO_AGGREGATE 720 * 90
  59 +
57 /** 60 /**
58 * the pid of ts packet, 61 * the pid of ts packet,
59 * Table 2-3 - PID table, hls-mpeg-ts-iso13818-1.pdf, page 37 62 * Table 2-3 - PID table, hls-mpeg-ts-iso13818-1.pdf, page 37
@@ -360,6 +363,7 @@ public: @@ -360,6 +363,7 @@ public:
360 /** 363 /**
361 * whether the hls stream is pure audio stream. 364 * whether the hls stream is pure audio stream.
362 */ 365 */
  366 + // TODO: FIXME: merge with muxer codec detect.
363 virtual bool is_pure_audio(); 367 virtual bool is_pure_audio();
364 /** 368 /**
365 * when PMT table parsed, we know some info about stream. 369 * when PMT table parsed, we know some info about stream.
@@ -1594,6 +1598,11 @@ public: @@ -1594,6 +1598,11 @@ public:
1594 * close the writer. 1598 * close the writer.
1595 */ 1599 */
1596 virtual void close(); 1600 virtual void close();
  1601 +public:
  1602 + /**
  1603 + * get the video codec of ts muxer.
  1604 + */
  1605 + virtual SrsCodecVideo video_codec();
1597 }; 1606 };
1598 1607
1599 /** 1608 /**