diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 5efd66e4d..886f5d2bb 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -498,6 +498,12 @@ vhost with-hls.srs.com { # @see https://github.com/winlinvip/simple-rtmp-server/issues/304#issuecomment-74000081 # default: 1.5 hls_td_ratio 1.5; + # the audio overflow ratio. + # for pure audio, the duration to reap the segment. + # for example, the hls_fragment is 10s, hsl_aof_ratio is 2.0, + # the segemnt will reap to 20s for pure audio. + # default: 2.0 + hls_aof_ratio 2.0; # the hls window in seconds, the number of ts in m3u8. # default: 60 hls_window 60; diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 582ef722f..563da4b20 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -1481,7 +1481,7 @@ int SrsConfig::check_config() for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "hls_entry_prefix" && m != "hls_path" && m != "hls_fragment" && m != "hls_window" && m != "hls_on_error" - && m != "hls_storage" && m != "hls_mount" && m != "hls_td_ratio" && m != "hls_acodec" && m != "hls_vcodec" + && m != "hls_storage" && m != "hls_mount" && m != "hls_td_ratio" && m != "hls_aof_ratio" && m != "hls_acodec" && m != "hls_vcodec" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; 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) if (!conf) { return SRS_CONF_DEFAULT_HLS_TD_RATIO; } + + return ::atof(conf->arg0().c_str()); +} +double SrsConfig::get_hls_aof_ratio(string vhost) +{ + SrsConfDirective* hls = get_hls(vhost); + + if (!hls) { + return SRS_CONF_DEFAULT_HLS_AOF_RATIO; + } + + SrsConfDirective* conf = hls->get("hls_aof_ratio"); + + if (!conf) { + return SRS_CONF_DEFAULT_HLS_AOF_RATIO; + } + return ::atof(conf->arg0().c_str()); } diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 68b4b9bd4..98cfa799e 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -48,6 +48,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SRS_CONF_DEFAULT_HLS_PATH "./objs/nginx/html" #define SRS_CONF_DEFAULT_HLS_FRAGMENT 10 #define SRS_CONF_DEFAULT_HLS_TD_RATIO 1.5 +#define SRS_CONF_DEFAULT_HLS_AOF_RATIO 2.0 #define SRS_CONF_DEFAULT_HLS_WINDOW 60 #define SRS_CONF_DEFAULT_HLS_ON_ERROR_IGNORE "ignore" #define SRS_CONF_DEFAULT_HLS_ON_ERROR_DISCONNECT "disconnect" @@ -875,14 +876,16 @@ public: virtual std::string get_hls_path(std::string vhost); /** * get the hls fragment time, in seconds. - * a fragment is a ts file. */ virtual double get_hls_fragment(std::string vhost); /** * get the hls td(target duration) ratio. - * a fragment is a ts file. */ virtual double get_hls_td_ratio(std::string vhost); + /** + * get the hls aof(audio overflow) ratio. + */ + virtual double get_hls_aof_ratio(std::string vhost); /** * get the hls window time, in seconds. * a window is a set of ts, the ts collection in m3u8. diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index ee66bf7b2..fd6b3c129 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -168,6 +168,7 @@ SrsHlsMuxer::SrsHlsMuxer() req = NULL; handler = NULL; hls_fragment = hls_window = 0; + hls_aof_ratio = 1.0; target_duration = 0; _sequence_no = 0; current = NULL; @@ -203,7 +204,7 @@ int SrsHlsMuxer::sequence_no() return _sequence_no; } -int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, string path, int fragment, int window) +int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, string path, int fragment, int window, double aof_ratio) { int ret = ERROR_SUCCESS; @@ -213,11 +214,12 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, string path, hls_entry_prefix = entry_prefix; hls_path = path; hls_fragment = fragment; + hls_aof_ratio = aof_ratio; hls_window = window; // we always keep the target duration increasing. int max_td = srs_max(target_duration, (int)(fragment * _srs_config->get_hls_td_ratio(r->vhost))); - srs_info("hls update target duration %d=>%d", target_duration, max_td); + srs_info("hls update target duration %d=>%d, aof=%.2f", target_duration, max_td, aof_ratio); target_duration = max_td; std::string storage = _srs_config->get_hls_storage(r->vhost); @@ -345,7 +347,7 @@ bool SrsHlsMuxer::is_segment_overflow() bool SrsHlsMuxer::is_segment_absolutely_overflow() { srs_assert(current); - return current->duration >= 2 * hls_fragment; + return current->duration >= hls_aof_ratio * hls_fragment; } int SrsHlsMuxer::update_acodec(SrsCodecAudio ac) @@ -676,12 +678,14 @@ int SrsHlsCache::on_publish(SrsHlsMuxer* muxer, SrsRequest* req, int64_t segment std::string entry_prefix = _srs_config->get_hls_entry_prefix(vhost); // get the hls path config std::string hls_path = _srs_config->get_hls_path(vhost); + // the audio overflow, for pure audio to reap segment. + double hls_aof_ratio = _srs_config->get_hls_aof_ratio(vhost); // TODO: FIXME: support load exists m3u8, to continue publish stream. // for the HLS donot requires the EXT-X-MEDIA-SEQUENCE be monotonically increase. // open muxer - if ((ret = muxer->update_config(req, entry_prefix, hls_path, hls_fragment, hls_window)) != ERROR_SUCCESS) { + if ((ret = muxer->update_config(req, entry_prefix, hls_path, hls_fragment, hls_window, hls_aof_ratio)) != ERROR_SUCCESS) { srs_error("m3u8 muxer update config failed. ret=%d", ret); return ret; } @@ -737,17 +741,13 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t } } - // cache->audio will be free in flush_audio - // so we must check whether it's null ptr. - if (!cache->audio) { - return ret; - } - // TODO: config it. // in ms, audio delay to flush the audios. int64_t audio_delay = SRS_CONF_DEFAULT_AAC_DELAY; // flush if audio delay exceed - if (pts - cache->audio->start_pts > audio_delay * 90) { + // cache->audio will be free in flush_audio + // so we must check whether it's null ptr. + if (cache->audio && pts - cache->audio->start_pts > audio_delay * 90) { if ((ret = muxer->flush_audio(cache)) != ERROR_SUCCESS) { return ret; } @@ -761,7 +761,7 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t // @see https://github.com/winlinvip/simple-rtmp-server/issues/151 // we use absolutely overflow of segment to make jwplayer/ffplay happy // @see https://github.com/winlinvip/simple-rtmp-server/issues/151#issuecomment-71155184 - if (muxer->is_segment_absolutely_overflow()) { + if (cache->audio && muxer->is_segment_absolutely_overflow()) { if ((ret = reap_segment("audio", muxer, cache->audio->pts)) != ERROR_SUCCESS) { return ret; } diff --git a/trunk/src/app/srs_app_hls.hpp b/trunk/src/app/srs_app_hls.hpp index bebba66ce..a8f61cad2 100644 --- a/trunk/src/app/srs_app_hls.hpp +++ b/trunk/src/app/srs_app_hls.hpp @@ -169,6 +169,7 @@ private: private: std::string hls_entry_prefix; std::string hls_path; + double hls_aof_ratio; int hls_fragment; int hls_window; private: @@ -208,7 +209,7 @@ public: /** * when publish, update the config for muxer. */ - virtual int update_config(SrsRequest* r, std::string entry_prefix, std::string path, int fragment, int window); + virtual int update_config(SrsRequest* r, std::string entry_prefix, std::string path, int fragment, int window, double aof_ratio); /** * open a new segment(a new ts file), * @param segment_start_dts use to calc the segment duration,