winlin

support config the audio overflow ratio.

@@ -498,6 +498,12 @@ vhost with-hls.srs.com { @@ -498,6 +498,12 @@ vhost with-hls.srs.com {
498 # @see https://github.com/winlinvip/simple-rtmp-server/issues/304#issuecomment-74000081 498 # @see https://github.com/winlinvip/simple-rtmp-server/issues/304#issuecomment-74000081
499 # default: 1.5 499 # default: 1.5
500 hls_td_ratio 1.5; 500 hls_td_ratio 1.5;
  501 + # the audio overflow ratio.
  502 + # for pure audio, the duration to reap the segment.
  503 + # for example, the hls_fragment is 10s, hsl_aof_ratio is 2.0,
  504 + # the segemnt will reap to 20s for pure audio.
  505 + # default: 2.0
  506 + hls_aof_ratio 2.0;
501 # the hls window in seconds, the number of ts in m3u8. 507 # the hls window in seconds, the number of ts in m3u8.
502 # default: 60 508 # default: 60
503 hls_window 60; 509 hls_window 60;
@@ -1481,7 +1481,7 @@ int SrsConfig::check_config() @@ -1481,7 +1481,7 @@ int SrsConfig::check_config()
1481 for (int j = 0; j < (int)conf->directives.size(); j++) { 1481 for (int j = 0; j < (int)conf->directives.size(); j++) {
1482 string m = conf->at(j)->name.c_str(); 1482 string m = conf->at(j)->name.c_str();
1483 if (m != "enabled" && m != "hls_entry_prefix" && m != "hls_path" && m != "hls_fragment" && m != "hls_window" && m != "hls_on_error" 1483 if (m != "enabled" && m != "hls_entry_prefix" && m != "hls_path" && m != "hls_fragment" && m != "hls_window" && m != "hls_on_error"
1484 - && m != "hls_storage" && m != "hls_mount" && m != "hls_td_ratio" && m != "hls_acodec" && m != "hls_vcodec" 1484 + && m != "hls_storage" && m != "hls_mount" && m != "hls_td_ratio" && m != "hls_aof_ratio" && m != "hls_acodec" && m != "hls_vcodec"
1485 ) { 1485 ) {
1486 ret = ERROR_SYSTEM_CONFIG_INVALID; 1486 ret = ERROR_SYSTEM_CONFIG_INVALID;
1487 srs_error("unsupported vhost hls directive %s, ret=%d", m.c_str(), ret); 1487 srs_error("unsupported vhost hls directive %s, ret=%d", m.c_str(), ret);
@@ -3202,7 +3202,24 @@ double SrsConfig::get_hls_td_ratio(string vhost) @@ -3202,7 +3202,24 @@ double SrsConfig::get_hls_td_ratio(string vhost)
3202 if (!conf) { 3202 if (!conf) {
3203 return SRS_CONF_DEFAULT_HLS_TD_RATIO; 3203 return SRS_CONF_DEFAULT_HLS_TD_RATIO;
3204 } 3204 }
  3205 +
  3206 + return ::atof(conf->arg0().c_str());
  3207 +}
3205 3208
  3209 +double SrsConfig::get_hls_aof_ratio(string vhost)
  3210 +{
  3211 + SrsConfDirective* hls = get_hls(vhost);
  3212 +
  3213 + if (!hls) {
  3214 + return SRS_CONF_DEFAULT_HLS_AOF_RATIO;
  3215 + }
  3216 +
  3217 + SrsConfDirective* conf = hls->get("hls_aof_ratio");
  3218 +
  3219 + if (!conf) {
  3220 + return SRS_CONF_DEFAULT_HLS_AOF_RATIO;
  3221 + }
  3222 +
3206 return ::atof(conf->arg0().c_str()); 3223 return ::atof(conf->arg0().c_str());
3207 } 3224 }
3208 3225
@@ -48,6 +48,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -48,6 +48,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
48 #define SRS_CONF_DEFAULT_HLS_PATH "./objs/nginx/html" 48 #define SRS_CONF_DEFAULT_HLS_PATH "./objs/nginx/html"
49 #define SRS_CONF_DEFAULT_HLS_FRAGMENT 10 49 #define SRS_CONF_DEFAULT_HLS_FRAGMENT 10
50 #define SRS_CONF_DEFAULT_HLS_TD_RATIO 1.5 50 #define SRS_CONF_DEFAULT_HLS_TD_RATIO 1.5
  51 +#define SRS_CONF_DEFAULT_HLS_AOF_RATIO 2.0
51 #define SRS_CONF_DEFAULT_HLS_WINDOW 60 52 #define SRS_CONF_DEFAULT_HLS_WINDOW 60
52 #define SRS_CONF_DEFAULT_HLS_ON_ERROR_IGNORE "ignore" 53 #define SRS_CONF_DEFAULT_HLS_ON_ERROR_IGNORE "ignore"
53 #define SRS_CONF_DEFAULT_HLS_ON_ERROR_DISCONNECT "disconnect" 54 #define SRS_CONF_DEFAULT_HLS_ON_ERROR_DISCONNECT "disconnect"
@@ -875,15 +876,17 @@ public: @@ -875,15 +876,17 @@ public:
875 virtual std::string get_hls_path(std::string vhost); 876 virtual std::string get_hls_path(std::string vhost);
876 /** 877 /**
877 * get the hls fragment time, in seconds. 878 * get the hls fragment time, in seconds.
878 - * a fragment is a ts file.  
879 */ 879 */
880 virtual double get_hls_fragment(std::string vhost); 880 virtual double get_hls_fragment(std::string vhost);
881 /** 881 /**
882 * get the hls td(target duration) ratio. 882 * get the hls td(target duration) ratio.
883 - * a fragment is a ts file.  
884 */ 883 */
885 virtual double get_hls_td_ratio(std::string vhost); 884 virtual double get_hls_td_ratio(std::string vhost);
886 /** 885 /**
  886 + * get the hls aof(audio overflow) ratio.
  887 + */
  888 + virtual double get_hls_aof_ratio(std::string vhost);
  889 + /**
887 * get the hls window time, in seconds. 890 * get the hls window time, in seconds.
888 * a window is a set of ts, the ts collection in m3u8. 891 * a window is a set of ts, the ts collection in m3u8.
889 * @remark SRS will delete the ts exceed the window. 892 * @remark SRS will delete the ts exceed the window.
@@ -168,6 +168,7 @@ SrsHlsMuxer::SrsHlsMuxer() @@ -168,6 +168,7 @@ SrsHlsMuxer::SrsHlsMuxer()
168 req = NULL; 168 req = NULL;
169 handler = NULL; 169 handler = NULL;
170 hls_fragment = hls_window = 0; 170 hls_fragment = hls_window = 0;
  171 + hls_aof_ratio = 1.0;
171 target_duration = 0; 172 target_duration = 0;
172 _sequence_no = 0; 173 _sequence_no = 0;
173 current = NULL; 174 current = NULL;
@@ -203,7 +204,7 @@ int SrsHlsMuxer::sequence_no() @@ -203,7 +204,7 @@ int SrsHlsMuxer::sequence_no()
203 return _sequence_no; 204 return _sequence_no;
204 } 205 }
205 206
206 -int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, string path, int fragment, int window) 207 +int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, string path, int fragment, int window, double aof_ratio)
207 { 208 {
208 int ret = ERROR_SUCCESS; 209 int ret = ERROR_SUCCESS;
209 210
@@ -213,11 +214,12 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, string path, @@ -213,11 +214,12 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, string path,
213 hls_entry_prefix = entry_prefix; 214 hls_entry_prefix = entry_prefix;
214 hls_path = path; 215 hls_path = path;
215 hls_fragment = fragment; 216 hls_fragment = fragment;
  217 + hls_aof_ratio = aof_ratio;
216 hls_window = window; 218 hls_window = window;
217 219
218 // we always keep the target duration increasing. 220 // we always keep the target duration increasing.
219 int max_td = srs_max(target_duration, (int)(fragment * _srs_config->get_hls_td_ratio(r->vhost))); 221 int max_td = srs_max(target_duration, (int)(fragment * _srs_config->get_hls_td_ratio(r->vhost)));
220 - srs_info("hls update target duration %d=>%d", target_duration, max_td); 222 + srs_info("hls update target duration %d=>%d, aof=%.2f", target_duration, max_td, aof_ratio);
221 target_duration = max_td; 223 target_duration = max_td;
222 224
223 std::string storage = _srs_config->get_hls_storage(r->vhost); 225 std::string storage = _srs_config->get_hls_storage(r->vhost);
@@ -345,7 +347,7 @@ bool SrsHlsMuxer::is_segment_overflow() @@ -345,7 +347,7 @@ bool SrsHlsMuxer::is_segment_overflow()
345 bool SrsHlsMuxer::is_segment_absolutely_overflow() 347 bool SrsHlsMuxer::is_segment_absolutely_overflow()
346 { 348 {
347 srs_assert(current); 349 srs_assert(current);
348 - return current->duration >= 2 * hls_fragment; 350 + return current->duration >= hls_aof_ratio * hls_fragment;
349 } 351 }
350 352
351 int SrsHlsMuxer::update_acodec(SrsCodecAudio ac) 353 int SrsHlsMuxer::update_acodec(SrsCodecAudio ac)
@@ -676,12 +678,14 @@ int SrsHlsCache::on_publish(SrsHlsMuxer* muxer, SrsRequest* req, int64_t segment @@ -676,12 +678,14 @@ int SrsHlsCache::on_publish(SrsHlsMuxer* muxer, SrsRequest* req, int64_t segment
676 std::string entry_prefix = _srs_config->get_hls_entry_prefix(vhost); 678 std::string entry_prefix = _srs_config->get_hls_entry_prefix(vhost);
677 // get the hls path config 679 // get the hls path config
678 std::string hls_path = _srs_config->get_hls_path(vhost); 680 std::string hls_path = _srs_config->get_hls_path(vhost);
  681 + // the audio overflow, for pure audio to reap segment.
  682 + double hls_aof_ratio = _srs_config->get_hls_aof_ratio(vhost);
679 683
680 // TODO: FIXME: support load exists m3u8, to continue publish stream. 684 // TODO: FIXME: support load exists m3u8, to continue publish stream.
681 // for the HLS donot requires the EXT-X-MEDIA-SEQUENCE be monotonically increase. 685 // for the HLS donot requires the EXT-X-MEDIA-SEQUENCE be monotonically increase.
682 686
683 // open muxer 687 // open muxer
684 - if ((ret = muxer->update_config(req, entry_prefix, hls_path, hls_fragment, hls_window)) != ERROR_SUCCESS) { 688 + if ((ret = muxer->update_config(req, entry_prefix, hls_path, hls_fragment, hls_window, hls_aof_ratio)) != ERROR_SUCCESS) {
685 srs_error("m3u8 muxer update config failed. ret=%d", ret); 689 srs_error("m3u8 muxer update config failed. ret=%d", ret);
686 return ret; 690 return ret;
687 } 691 }
@@ -737,17 +741,13 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t @@ -737,17 +741,13 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t
737 } 741 }
738 } 742 }
739 743
740 - // cache->audio will be free in flush_audio  
741 - // so we must check whether it's null ptr.  
742 - if (!cache->audio) {  
743 - return ret;  
744 - }  
745 -  
746 // TODO: config it. 744 // TODO: config it.
747 // in ms, audio delay to flush the audios. 745 // in ms, audio delay to flush the audios.
748 int64_t audio_delay = SRS_CONF_DEFAULT_AAC_DELAY; 746 int64_t audio_delay = SRS_CONF_DEFAULT_AAC_DELAY;
749 // flush if audio delay exceed 747 // flush if audio delay exceed
750 - if (pts - cache->audio->start_pts > audio_delay * 90) { 748 + // cache->audio will be free in flush_audio
  749 + // so we must check whether it's null ptr.
  750 + if (cache->audio && pts - cache->audio->start_pts > audio_delay * 90) {
751 if ((ret = muxer->flush_audio(cache)) != ERROR_SUCCESS) { 751 if ((ret = muxer->flush_audio(cache)) != ERROR_SUCCESS) {
752 return ret; 752 return ret;
753 } 753 }
@@ -761,7 +761,7 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t @@ -761,7 +761,7 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t
761 // @see https://github.com/winlinvip/simple-rtmp-server/issues/151 761 // @see https://github.com/winlinvip/simple-rtmp-server/issues/151
762 // we use absolutely overflow of segment to make jwplayer/ffplay happy 762 // we use absolutely overflow of segment to make jwplayer/ffplay happy
763 // @see https://github.com/winlinvip/simple-rtmp-server/issues/151#issuecomment-71155184 763 // @see https://github.com/winlinvip/simple-rtmp-server/issues/151#issuecomment-71155184
764 - if (muxer->is_segment_absolutely_overflow()) { 764 + if (cache->audio && muxer->is_segment_absolutely_overflow()) {
765 if ((ret = reap_segment("audio", muxer, cache->audio->pts)) != ERROR_SUCCESS) { 765 if ((ret = reap_segment("audio", muxer, cache->audio->pts)) != ERROR_SUCCESS) {
766 return ret; 766 return ret;
767 } 767 }
@@ -169,6 +169,7 @@ private: @@ -169,6 +169,7 @@ private:
169 private: 169 private:
170 std::string hls_entry_prefix; 170 std::string hls_entry_prefix;
171 std::string hls_path; 171 std::string hls_path;
  172 + double hls_aof_ratio;
172 int hls_fragment; 173 int hls_fragment;
173 int hls_window; 174 int hls_window;
174 private: 175 private:
@@ -208,7 +209,7 @@ public: @@ -208,7 +209,7 @@ public:
208 /** 209 /**
209 * when publish, update the config for muxer. 210 * when publish, update the config for muxer.
210 */ 211 */
211 - virtual int update_config(SrsRequest* r, std::string entry_prefix, std::string path, int fragment, int window); 212 + virtual int update_config(SrsRequest* r, std::string entry_prefix, std::string path, int fragment, int window, double aof_ratio);
212 /** 213 /**
213 * open a new segment(a new ts file), 214 * open a new segment(a new ts file),
214 * @param segment_start_dts use to calc the segment duration, 215 * @param segment_start_dts use to calc the segment duration,