diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 38b50f89b..470a0555e 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -1392,6 +1392,13 @@ vhost hls.srs.com { # Note that it will make NGINX edge cache always missed, so never enable HLS streaming if use NGINX edges. # Default: on hls_ctx on; + # For HLS pseudo streaming, whether enable the session for each TS segment. + # If enabled, SRS HTTP API will show the statistics about HLS streaming bandwidth, both m3u8 and ts file. Please + # note that it also consumes resource, because each ts file should be served by SRS, all NGINX cache will be + # missed because we add session id to each ts file. + # Note that it will make NGINX edge cache always missed, so never enable HLS streaming if use NGINX edges. + # Default: on + hls_ts_ctx on; # the hls fragment in seconds, the duration of a piece of ts. # default: 10 diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 3e7ddf13a..7c44fb377 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -2539,7 +2539,7 @@ srs_error_t SrsConfig::check_normal_config() && m != "hls_storage" && m != "hls_mount" && m != "hls_td_ratio" && m != "hls_aof_ratio" && m != "hls_acodec" && m != "hls_vcodec" && m != "hls_m3u8_file" && m != "hls_ts_file" && m != "hls_ts_floor" && m != "hls_cleanup" && m != "hls_nb_notify" && m != "hls_wait_keyframe" && m != "hls_dispose" && m != "hls_keys" && m != "hls_fragments_per_key" && m != "hls_key_file" - && m != "hls_key_file_path" && m != "hls_key_url" && m != "hls_dts_directly" && m != "hls_ctx") { + && m != "hls_key_file_path" && m != "hls_key_url" && m != "hls_dts_directly" && m != "hls_ctx" && m != "hls_ts_ctx") { return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal vhost.hls.%s of %s", m.c_str(), vhost->arg0().c_str()); } @@ -6148,6 +6148,23 @@ bool SrsConfig::get_hls_ctx_enabled(std::string vhost) return SRS_CONF_PERFER_TRUE(conf->arg0()); } +bool SrsConfig::get_hls_ts_ctx_enabled(std::string vhost) +{ + static bool DEFAULT = true; + + SrsConfDirective* conf = get_hls(vhost); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("hls_ts_ctx"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return SRS_CONF_PERFER_TRUE(conf->arg0()); +} + bool SrsConfig::get_hls_cleanup(string vhost) { static bool DEFAULT = true; diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 5fffb276b..6b1baf368 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -936,6 +936,8 @@ public: virtual bool get_vhost_hls_dts_directly(std::string vhost); // Whether enable hls_ctx virtual bool get_hls_ctx_enabled(std::string vhost); + // Whether enable session for ts file. + virtual bool get_hls_ts_ctx_enabled(std::string vhost); // hds section private: // Get the hds directive of vhost. diff --git a/trunk/src/app/srs_app_http_static.cpp b/trunk/src/app/srs_app_http_static.cpp index 930d0bfdc..f13c62e15 100644 --- a/trunk/src/app/srs_app_http_static.cpp +++ b/trunk/src/app/srs_app_http_static.cpp @@ -68,10 +68,16 @@ SrsHlsStream::~SrsHlsStream() map_ctx_info_.clear(); } -srs_error_t SrsHlsStream::serve_m3u8_ctx(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, ISrsFileReaderFactory* factory, string fullpath, SrsRequest* req) +srs_error_t SrsHlsStream::serve_m3u8_ctx(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, ISrsFileReaderFactory* factory, string fullpath, SrsRequest* req, bool* served) { string ctx = r->query_get(SRS_CONTEXT_IN_HLS); + // If HLS stream is disabled, use SrsHttpFileServer to serve HLS, which is normal file server. + if (!_srs_config->get_hls_ctx_enabled(req->vhost)) { + *served = false; + return srs_success; + } + // Correct the app and stream by path, which is created from template. // @remark Be careful that the stream has extension now, might cause identify fail. req->stream = srs_path_basename(r->path()); @@ -79,8 +85,16 @@ srs_error_t SrsHlsStream::serve_m3u8_ctx(ISrsHttpResponseWriter* w, ISrsHttpMess // Always make the ctx alive now. alive(ctx, req); + // Served by us. + *served = true; + // Already exists context, response with rebuilt m3u8 content. if (!ctx.empty() && ctx_is_exist(ctx)) { + // If HLS stream is disabled, use SrsHttpFileServer to serve HLS, which is normal file server. + if (!_srs_config->get_hls_ts_ctx_enabled(req->vhost)) { + *served = false; + return srs_success; + } return serve_exists_session(w, r, factory, fullpath); } @@ -470,6 +484,8 @@ srs_error_t SrsVodStream::serve_mp4_stream(ISrsHttpResponseWriter* w, ISrsHttpMe srs_error_t SrsVodStream::serve_m3u8_ctx(ISrsHttpResponseWriter * w, ISrsHttpMessage * r, std::string fullpath) { + srs_error_t err = srs_success; + SrsHttpMessage* hr = dynamic_cast(r); srs_assert(hr); @@ -482,14 +498,18 @@ srs_error_t SrsVodStream::serve_m3u8_ctx(ISrsHttpResponseWriter * w, ISrsHttpMes req->vhost = parsed_vhost->arg0(); } - // If HLS stream is disabled, use SrsHttpFileServer to serve HLS, which is normal file server. - if (!_srs_config->get_hls_ctx_enabled(req->vhost)) { - // Serve by default HLS handler. + // Try to serve by HLS streaming. + bool served = false; + if ((err = hls_.serve_m3u8_ctx(w, r, fs_factory, fullpath, req, &served)) != srs_success) { + return srs_error_wrap(err, "hls ctx"); + } + + // Serve by default HLS handler. + if (!served) { return SrsHttpFileServer::serve_m3u8_ctx(w, r, fullpath); } - // Try to serve by HLS streaming. - return hls_.serve_m3u8_ctx(w, r, fs_factory, fullpath, req); + return err; } srs_error_t SrsVodStream::serve_ts_ctx(ISrsHttpResponseWriter * w, ISrsHttpMessage * r, std::string fullpath) diff --git a/trunk/src/app/srs_app_http_static.hpp b/trunk/src/app/srs_app_http_static.hpp index 8470ec74b..c7a2c7880 100644 --- a/trunk/src/app/srs_app_http_static.hpp +++ b/trunk/src/app/srs_app_http_static.hpp @@ -31,7 +31,7 @@ public: SrsHlsStream(); virtual ~SrsHlsStream(); public: - virtual srs_error_t serve_m3u8_ctx(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, ISrsFileReaderFactory* factory, std::string fullpath, SrsRequest* req); + virtual srs_error_t serve_m3u8_ctx(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, ISrsFileReaderFactory* factory, std::string fullpath, SrsRequest* req, bool* served); virtual void on_serve_ts_ctx(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); private: srs_error_t serve_new_session(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, SrsRequest *req);