winlin

for #512, write audio frame by frame for video+audio hls.

@@ -765,7 +765,9 @@ About the HLS overhead of SRS, we compare the overhead to FLV by remux the HLS t @@ -765,7 +765,9 @@ About the HLS overhead of SRS, we compare the overhead to FLV by remux the HLS t
765 | 5147kbps | 370s | 195040 | 200280 | 2.68% | 765 | 5147kbps | 370s | 195040 | 200280 | 2.68% |
766 | 5158kbps | 1327s | 835664 | 858092 | 2.68% | 766 | 5158kbps | 1327s | 835664 | 858092 | 2.68% |
767 767
768 -The HLS overhead is calc by: (HLS - FLV) / FLV * 100% 768 +The HLS overhead is calc by: (HLS - FLV) / FLV * 100%.
  769 +
  770 +The overhead is larger than this benchmark(48kbps audio is best overhead), for we fix the [#512][bug#512].
769 771
770 ## Architecture 772 ## Architecture
771 773
@@ -1193,6 +1195,8 @@ Winlin @@ -1193,6 +1195,8 @@ Winlin
1193 [bug #59]: https://github.com/simple-rtmp-server/srs/issues/59 1195 [bug #59]: https://github.com/simple-rtmp-server/srs/issues/59
1194 [bug #50]: https://github.com/simple-rtmp-server/srs/issues/50 1196 [bug #50]: https://github.com/simple-rtmp-server/srs/issues/50
1195 [bug #34]: https://github.com/simple-rtmp-server/srs/issues/34 1197 [bug #34]: https://github.com/simple-rtmp-server/srs/issues/34
  1198 +[bug #512]: https://github.com/simple-rtmp-server/srs/issues/512
  1199 +[bug #xxxxxxxxxx]: https://github.com/simple-rtmp-server/srs/issues/xxxxxxxxxx
1196 1200
1197 [r2.0a2]: https://github.com/simple-rtmp-server/srs/releases/tag/v2.0-a2 1201 [r2.0a2]: https://github.com/simple-rtmp-server/srs/releases/tag/v2.0-a2
1198 [r2.0a1]: https://github.com/simple-rtmp-server/srs/releases/tag/2.0a1 1202 [r2.0a1]: https://github.com/simple-rtmp-server/srs/releases/tag/2.0a1
@@ -646,6 +646,11 @@ int SrsHlsMuxer::update_acodec(SrsCodecAudio ac) @@ -646,6 +646,11 @@ int SrsHlsMuxer::update_acodec(SrsCodecAudio ac)
646 return current->muxer->update_acodec(ac); 646 return current->muxer->update_acodec(ac);
647 } 647 }
648 648
  649 +bool SrsHlsMuxer::pure_audio()
  650 +{
  651 + return current && current->muxer && current->muxer->video_codec() == SrsCodecVideoDisabled;
  652 +}
  653 +
649 int SrsHlsMuxer::flush_audio(SrsTsCache* cache) 654 int SrsHlsMuxer::flush_audio(SrsTsCache* cache)
650 { 655 {
651 int ret = ERROR_SUCCESS; 656 int ret = ERROR_SUCCESS;
@@ -1049,25 +1054,6 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t @@ -1049,25 +1054,6 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t
1049 return ret; 1054 return ret;
1050 } 1055 }
1051 1056
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. 1057 // reap when current source is pure audio.
1072 // it maybe changed when stream info changed, 1058 // it maybe changed when stream info changed,
1073 // for example, pure audio when start, audio/video when publishing, 1059 // for example, pure audio when start, audio/video when publishing,
@@ -1083,6 +1069,14 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t @@ -1083,6 +1069,14 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t
1083 } 1069 }
1084 } 1070 }
1085 1071
  1072 + // directly write the audio frame by frame to ts,
  1073 + // it's ok for the hls overload, or maybe cause the audio corrupt,
  1074 + // which introduced by aggregate the audios to a big one.
  1075 + // @see https://github.com/simple-rtmp-server/srs/issues/512
  1076 + if ((ret = muxer->flush_audio(cache)) != ERROR_SUCCESS) {
  1077 + return ret;
  1078 + }
  1079 +
1086 return ret; 1080 return ret;
1087 } 1081 }
1088 1082
@@ -1100,7 +1094,7 @@ int SrsHlsCache::write_video(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t @@ -1100,7 +1094,7 @@ int SrsHlsCache::write_video(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t
1100 // do reap ts if any of: 1094 // do reap ts if any of:
1101 // a. wait keyframe and got keyframe. 1095 // a. wait keyframe and got keyframe.
1102 // b. always reap when not wait keyframe. 1096 // b. always reap when not wait keyframe.
1103 - if (!muxer->wait_keyframe()|| sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) { 1097 + if (!muxer->wait_keyframe() || sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) {
1104 // when wait keyframe, there must exists idr frame in sample. 1098 // when wait keyframe, there must exists idr frame in sample.
1105 if (!sample->has_idr && muxer->wait_keyframe()) { 1099 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); 1100 srs_warn("hls: ts starts without IDR, first nalu=%d, idr=%d", sample->first_nalu_type, sample->has_idr);
@@ -1110,9 +1104,6 @@ int SrsHlsCache::write_video(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t @@ -1110,9 +1104,6 @@ int SrsHlsCache::write_video(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t
1110 if ((ret = reap_segment("video", muxer, cache->video->dts)) != ERROR_SUCCESS) { 1104 if ((ret = reap_segment("video", muxer, cache->video->dts)) != ERROR_SUCCESS) {
1111 return ret; 1105 return ret;
1112 } 1106 }
1113 -  
1114 - // the video must be flushed, just return.  
1115 - return ret;  
1116 } 1107 }
1117 } 1108 }
1118 1109
@@ -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
@@ -2760,6 +2760,11 @@ void SrsTSMuxer::close() @@ -2760,6 +2760,11 @@ void SrsTSMuxer::close()
2760 writer->close(); 2760 writer->close();
2761 } 2761 }
2762 2762
  2763 +SrsCodecVideo SrsTSMuxer::video_codec()
  2764 +{
  2765 + return vcodec;
  2766 +}
  2767 +
2763 SrsTsCache::SrsTsCache() 2768 SrsTsCache::SrsTsCache()
2764 { 2769 {
2765 audio = NULL; 2770 audio = NULL;
@@ -3134,20 +3139,9 @@ int SrsTsEncoder::write_audio(int64_t timestamp, char* data, int size) @@ -3134,20 +3139,9 @@ int SrsTsEncoder::write_audio(int64_t timestamp, char* data, int size)
3134 return ret; 3139 return ret;
3135 } 3140 }
3136 3141
3137 - // flush if buffer exceed max size.  
3138 - if (cache->audio->payload->length() > SRS_AUTO_HLS_AUDIO_CACHE_SIZE) {  
3139 - return flush_video();  
3140 - }  
3141 -  
3142 - // TODO: config it.  
3143 - // in ms, audio delay to flush the audios.  
3144 - int64_t audio_delay = SRS_CONF_DEFAULT_AAC_DELAY;  
3145 - // flush if audio delay exceed  
3146 - if (dts - cache->audio->start_pts > audio_delay * 90) { 3142 + // always flush audio frame by frame.
  3143 + // @see https://github.com/simple-rtmp-server/srs/issues/512
3147 return flush_audio(); 3144 return flush_audio();
3148 - }  
3149 -  
3150 - return ret;  
3151 } 3145 }
3152 3146
3153 int SrsTsEncoder::write_video(int64_t timestamp, char* data, int size) 3147 int SrsTsEncoder::write_video(int64_t timestamp, char* data, int size)
@@ -1586,6 +1586,11 @@ public: @@ -1586,6 +1586,11 @@ public:
1586 * close the writer. 1586 * close the writer.
1587 */ 1587 */
1588 virtual void close(); 1588 virtual void close();
  1589 +public:
  1590 + /**
  1591 + * get the video codec of ts muxer.
  1592 + */
  1593 + virtual SrsCodecVideo video_codec();
1589 }; 1594 };
1590 1595
1591 /** 1596 /**