From eff2d810165bef93831aad1d932a337bdecc551f Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 18 Jan 2015 18:00:40 +0800 Subject: [PATCH] for #293, add http flv stream --- trunk/conf/full.conf | 26 ++++++++-- trunk/conf/http.flv.live.conf | 17 +++++++ trunk/src/app/srs_app_config.cpp | 66 ++++++++++++++++++++++++- trunk/src/app/srs_app_config.hpp | 25 ++++++---- trunk/src/app/srs_app_http_conn.cpp | 77 +++++++++++++++++++++++++++-- trunk/src/app/srs_app_http_conn.hpp | 23 +++++++++ trunk/src/app/srs_app_reload.cpp | 5 ++ trunk/src/app/srs_app_reload.hpp | 1 + 8 files changed, 223 insertions(+), 17 deletions(-) create mode 100644 trunk/conf/http.flv.live.conf diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index b6c2e594e4..644fbba1cc 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -343,11 +343,11 @@ vhost ingest.srs.com { } } -# vhost for http server config in each vhost. -vhost http.srs.com { - # http vhost specified config +# vhost for http static and flv vod stream for each vhost. +vhost http.static.srs.com { + # http static vhost specified config http { - # whether enabled the http streaming service for vhost. + # whether enabled the http static service for vhost. # default: off enabled on; # the virtual directory root for this vhost to mount at @@ -364,6 +364,24 @@ vhost http.srs.com { } } +# vhost for http flv live stream for each vhost. +vhost http.flv.srs.com { + # http flv stream vhost specified config + http_flv { + # whether enable the http flv live streaming service for vhost. + # default: off + enabled on; + # the stream mout for rtmp to remux to flv live streaming. + # for example, if mount to [vhost]/[app]/[stream].flv, user access by http://[vhost]/[app]/[stream].flv + # the variables: + # [vhost] current vhost for http flv live stream. + # [app] current app for http flv live stream. + # [stream] current stream for http flv live stream. + # default: [vhost]/[app]/[stream].flv + mount [vhost]/[app]/[stream].flv; + } +} + # the vhost with hls specified. vhost with-hls.srs.com { hls { diff --git a/trunk/conf/http.flv.live.conf b/trunk/conf/http.flv.live.conf new file mode 100644 index 0000000000..ac3bff1bcf --- /dev/null +++ b/trunk/conf/http.flv.live.conf @@ -0,0 +1,17 @@ +# the config for srs to remux rtmp to flv live stream. +# @see https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_DeliveryHttpFlvStream +# @see full.conf for detail config. + +listen 1935; +max_connections 1000; +http_stream { + enabled on; + listen 8080; + dir ./objs/nginx/html; +} +vhost __defaultVhost__ { + http_flv { + enabled on; + mount [vhost]/[app]/[stream].flv; + } +} diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index a6a695fb8d..2c17e7bea9 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -876,6 +876,17 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root) } srs_trace("vhost %s reload http success.", vhost.c_str()); } + // http_flv, only one per vhost. + if (!srs_directive_equals(new_vhost->get("http_flv"), old_vhost->get("http_flv"))) { + for (it = subscribes.begin(); it != subscribes.end(); ++it) { + ISrsReloadHandler* subscribe = *it; + if ((ret = subscribe->on_reload_vhost_http_flv_updated()) != ERROR_SUCCESS) { + srs_error("vhost %s notify subscribes http_flv failed. ret=%d", vhost.c_str(), ret); + return ret; + } + } + srs_trace("vhost %s reload http_flv success.", vhost.c_str()); + } // transcode, many per vhost. if ((ret = reload_transcode(new_vhost, old_vhost)) != ERROR_SUCCESS) { return ret; @@ -1364,7 +1375,7 @@ int SrsConfig::check_config() && n != "atc" && n != "atc_auto" && n != "debug_srs_upnode" && n != "mr" && n != "mw_latency" && n != "min_latency" - && n != "security" + && n != "security" && n != "http_flv" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost directive %s, ret=%d", n.c_str(), ret); @@ -1412,6 +1423,15 @@ int SrsConfig::check_config() return ret; } } + } else if (n == "http_flv") { + for (int j = 0; j < (int)conf->directives.size(); j++) { + string m = conf->at(j)->name.c_str(); + if (m != "enabled" && m != "mount") { + ret = ERROR_SYSTEM_CONFIG_INVALID; + srs_error("unsupported vhost http_flv directive %s, ret=%d", m.c_str(), ret); + return ret; + } + } } else if (n == "hls") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); @@ -3425,6 +3445,50 @@ string SrsConfig::get_vhost_http_dir(string vhost) return conf->arg0(); } +bool SrsConfig::get_vhost_http_flv_enabled(string vhost) +{ + SrsConfDirective* conf = get_vhost(vhost); + if (!conf) { + return false; + } + + conf = conf->get("http_flv"); + if (!conf) { + return false; + } + + conf = conf->get("enabled"); + if (!conf) { + return false; + } + + if (conf->arg0() == "on") { + return true; + } + + return false; +} + +string SrsConfig::get_vhost_http_flv_mount(string vhost) +{ + SrsConfDirective* conf = get_vhost(vhost); + if (!conf) { + return SRS_CONF_DEFAULT_HTTP_FLV_MOUNT; + } + + conf = conf->get("http_flv"); + if (!conf) { + return SRS_CONF_DEFAULT_HTTP_FLV_MOUNT; + } + + conf = conf->get("mount"); + if (!conf || conf->arg0().empty()) { + return SRS_CONF_DEFAULT_HTTP_FLV_MOUNT; + } + + return conf->arg0(); +} + SrsConfDirective* SrsConfig::get_heartbeart() { return root->get("heartbeat"); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 80858be5a3..f5a9c6a18b 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -65,7 +65,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // the interval in seconds for bandwidth check #define SRS_CONF_DEFAULT_BANDWIDTH_LIMIT_KBPS 1000 -#define SRS_CONF_DEFAULT_HTTP_MOUNT "/" +#define SRS_CONF_DEFAULT_HTTP_MOUNT "[vhost]/" +#define SRS_CONF_DEFAULT_HTTP_FLV_MOUNT "[vhost]/[app]/[stream].flv" #define SRS_CONF_DEFAULT_HTTP_DIR SRS_CONF_DEFAULT_HLS_PATH #define SRS_CONF_DEFAULT_HTTP_STREAM_PORT 8080 @@ -954,20 +955,26 @@ class SrsConfig */ virtual bool get_vhost_http_enabled(std::string vhost); /** - * get the http mount point for vhost, - * vhost can use sub dir of http. - * for example, http://server/vhost1/live/livestream - * where the vhost1 is mount point for vhost1. + * get the http mount point for vhost. + * for example, http://vhost/live/livestream */ virtual std::string get_vhost_http_mount(std::string vhost); /** * get the http dir for vhost. - * the http dir of vhost will mount to the mount point of vhost. - * for example, http://server/vhost1/live/livestream - * where the vhost1 is mount point for vhost1, - * and vhost1 dir is specified by this http dir. + * the path on disk for mount root of http vhost. */ virtual std::string get_vhost_http_dir(std::string vhost); +// flv live streaming section +public: + /** + * get whether vhost enabled http flv live stream + */ + virtual bool get_vhost_http_flv_enabled(std::string vhost); + /** + * get the http flv live stream mount point for vhost. + * used to generate the flv stream mount path. + */ + virtual std::string get_vhost_http_flv_mount(std::string vhost); // http heartbeart section private: /** diff --git a/trunk/src/app/srs_app_http_conn.cpp b/trunk/src/app/srs_app_http_conn.cpp index 3d630b913a..8ef0cbb4ff 100644 --- a/trunk/src/app/srs_app_http_conn.cpp +++ b/trunk/src/app/srs_app_http_conn.cpp @@ -135,21 +135,69 @@ int SrsVodStream::serve_flv_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* return ret; } +SrsLiveStream::SrsLiveStream() +{ +} + +SrsLiveStream::~SrsLiveStream() +{ +} + +int SrsLiveStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) +{ + int ret = ERROR_SUCCESS; + // TODO: FIMXE: implements it. + return ret; +} + SrsHttpServer::SrsHttpServer() { } SrsHttpServer::~SrsHttpServer() { + flvs.clear(); } int SrsHttpServer::initialize() { int ret = ERROR_SUCCESS; + // static file + // flv vod streaming. + if ((ret = mount_static_file()) != ERROR_SUCCESS) { + return ret; + } + + // remux rtmp to flv live streaming + if ((ret = mount_flv_streaming()) != ERROR_SUCCESS) { + return ret; + } + + return ret; +} + +int SrsHttpServer::on_reload_vhost_http_updated() +{ + int ret = ERROR_SUCCESS; + // TODO: FIXME: implements it. + return ret; +} + +int SrsHttpServer::on_reload_vhost_http_flv_updated() +{ + int ret = ERROR_SUCCESS; + // TODO: FIXME: implements it. + return ret; +} + +int SrsHttpServer::mount_static_file() +{ + int ret = ERROR_SUCCESS; + bool default_root_exists = false; - // add other virtual path + // http static file and flv vod stream mount for each vhost. SrsConfDirective* root = _srs_config->get_root(); for (int i = 0; i < (int)root->directives.size(); i++) { SrsConfDirective* conf = root->at(i); @@ -168,6 +216,9 @@ int SrsHttpServer::initialize() // replace the vhost variable mount = srs_string_replace(mount, "[vhost]", vhost); + + // remove the default vhost mount + mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", ""); // the dir mount must always ends with "/" if (mount != "/" && mount.rfind("/") != mount.length() - 1) { @@ -199,10 +250,30 @@ int SrsHttpServer::initialize() return ret; } -int SrsHttpServer::on_reload_vhost_http_updated() +int SrsHttpServer::mount_flv_streaming() { int ret = ERROR_SUCCESS; - // TODO: FIXME: implements it. + + // http flv live stream mount for each vhost. + SrsConfDirective* root = _srs_config->get_root(); + for (int i = 0; i < (int)root->directives.size(); i++) { + SrsConfDirective* conf = root->at(i); + + if (!conf->is_vhost()) { + continue; + } + + std::string vhost = conf->arg0(); + if (!_srs_config->get_vhost_http_flv_enabled(vhost)) { + continue; + } + + std::string mount = _srs_config->get_vhost_http_flv_mount(vhost); + flvs[vhost] = mount; + srs_trace("http flv live stream, vhost=%s, mount=%s", + vhost.c_str(), mount.c_str()); + } + return ret; } diff --git a/trunk/src/app/srs_app_http_conn.hpp b/trunk/src/app/srs_app_http_conn.hpp index 0f20bee401..7fbeae3f48 100644 --- a/trunk/src/app/srs_app_http_conn.hpp +++ b/trunk/src/app/srs_app_http_conn.hpp @@ -57,10 +57,29 @@ class SrsVodStream : public SrsGoHttpFileServer virtual int serve_flv_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int offset); }; +/** +* the flv live stream supports access rtmp in flv over http. +* srs will remux rtmp to flv streaming. +*/ +class SrsLiveStream : public ISrsGoHttpHandler +{ +public: + SrsLiveStream(); + virtual ~SrsLiveStream(); +public: + virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); +}; + +/** +* the http server instance, +* serve http static file, flv vod stream and flv live stream. +*/ class SrsHttpServer : public ISrsReloadHandler { public: SrsGoHttpServeMux mux; + // the flv live streaming template. + std::map flvs; public: SrsHttpServer(); virtual ~SrsHttpServer(); @@ -69,6 +88,10 @@ class SrsHttpServer : public ISrsReloadHandler // interface ISrsThreadHandler. public: virtual int on_reload_vhost_http_updated(); + virtual int on_reload_vhost_http_flv_updated(); +private: + virtual int mount_static_file(); + virtual int mount_flv_streaming(); }; class SrsHttpConn : public SrsConnection diff --git a/trunk/src/app/srs_app_reload.cpp b/trunk/src/app/srs_app_reload.cpp index b0c34603e1..cf9db06a92 100644 --- a/trunk/src/app/srs_app_reload.cpp +++ b/trunk/src/app/srs_app_reload.cpp @@ -95,6 +95,11 @@ int ISrsReloadHandler::on_reload_vhost_http_updated() return ERROR_SUCCESS; } +int ISrsReloadHandler::on_reload_vhost_http_flv_updated() +{ + return ERROR_SUCCESS; +} + int ISrsReloadHandler::on_reload_vhost_added(string /*vhost*/) { return ERROR_SUCCESS; diff --git a/trunk/src/app/srs_app_reload.hpp b/trunk/src/app/srs_app_reload.hpp index 38ca66a349..7634928e66 100644 --- a/trunk/src/app/srs_app_reload.hpp +++ b/trunk/src/app/srs_app_reload.hpp @@ -56,6 +56,7 @@ class ISrsReloadHandler virtual int on_reload_http_stream_disabled(); virtual int on_reload_http_stream_updated(); virtual int on_reload_vhost_http_updated(); + virtual int on_reload_vhost_http_flv_updated(); virtual int on_reload_vhost_added(std::string vhost); virtual int on_reload_vhost_removed(std::string vhost); virtual int on_reload_vhost_atc(std::string vhost);