From f26e719800bc7dde51c3bef6d9d924cac8cbe49f Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 6 Mar 2015 13:37:57 +0800 Subject: [PATCH] fix #322, fix http-flv stream bug, support multiple streams. 2.0.133. --- README.md | 1 + trunk/src/app/srs_app_http_conn.cpp | 180 +++++++++++++++++----------- trunk/src/app/srs_app_http_conn.hpp | 19 ++- trunk/src/core/srs_core.hpp | 2 +- 4 files changed, 125 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index ca13cbe83..fbbcc5842 100755 --- a/README.md +++ b/README.md @@ -551,6 +551,7 @@ Supported operating systems and hardware: ### SRS 2.0 history +* v2.0, 2015-03-06, for [#322](https://github.com/winlinvip/simple-rtmp-server/issues/322), fix http-flv stream bug, support multiple streams. 2.0.133. * v2.0, 2015-03-06, refine http request parse. 2.0.132. * v2.0, 2015-03-01, for [#179](https://github.com/winlinvip/simple-rtmp-server/issues/179), revert dvr http api. 2.0.128. * v2.0, 2015-02-24, for [#304](https://github.com/winlinvip/simple-rtmp-server/issues/304), fix hls bug, write pts/dts error. 2.0.124 diff --git a/trunk/src/app/srs_app_http_conn.cpp b/trunk/src/app/srs_app_http_conn.cpp index 407355f5e..21c1c8dfe 100644 --- a/trunk/src/app/srs_app_http_conn.cpp +++ b/trunk/src/app/srs_app_http_conn.cpp @@ -771,19 +771,35 @@ SrsHttpServer::~SrsHttpServer() { if (true) { std::map::iterator it; - for (it = flvs.begin(); it != flvs.end(); ++it) { + for (it = tflvs.begin(); it != tflvs.end(); ++it) { SrsLiveEntry* entry = it->second; srs_freep(entry); } - flvs.clear(); + tflvs.clear(); + } + if (true) { + std::map::iterator it; + for (it = sflvs.begin(); it != sflvs.end(); ++it) { + SrsLiveEntry* entry = it->second; + srs_freep(entry); + } + sflvs.clear(); } if (true) { std::map::iterator it; - for (it = hls.begin(); it != hls.end(); ++it) { + for (it = thls.begin(); it != thls.end(); ++it) { SrsHlsEntry* entry = it->second; srs_freep(entry); } - hls.clear(); + thls.clear(); + } + if (true) { + std::map::iterator it; + for (it = shls.begin(); it != shls.end(); ++it) { + SrsHlsEntry* entry = it->second; + srs_freep(entry); + } + shls.clear(); } } @@ -814,56 +830,72 @@ int SrsHttpServer::mount(SrsSource* s, SrsRequest* r) { int ret = ERROR_SUCCESS; - if (flvs.find(r->vhost) == flvs.end()) { - srs_info("ignore mount flv stream for disabled"); - return ret; - } + // the id to identify stream. + std::string sid = r->get_stream_url(); + SrsLiveEntry* entry = NULL; - SrsLiveEntry* entry = flvs[r->vhost]; + // create stream from template when not found. + if (sflvs.find(sid) == sflvs.end()) { + if (tflvs.find(r->vhost) == tflvs.end()) { + srs_info("ignore mount flv stream for disabled"); + return ret; + } + + SrsLiveEntry* tmpl = tflvs[r->vhost]; + + std::string mount = tmpl->mount; + + // replace the vhost variable + mount = srs_string_replace(mount, "[vhost]", r->vhost); + mount = srs_string_replace(mount, "[app]", r->app); + mount = srs_string_replace(mount, "[stream]", r->stream); + + // remove the default vhost mount + mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/"); + + entry = new SrsLiveEntry(); + entry->mount = mount; + + entry->cache = new SrsStreamCache(s, r); + entry->stream = new SrsLiveStream(s, r, entry->cache); + + sflvs[sid] = entry; + + // start http stream cache thread + if ((ret = entry->cache->start()) != ERROR_SUCCESS) { + srs_error("http: start stream cache failed. ret=%d", ret); + return ret; + } + + // mount the http flv stream. + if ((ret = mux.handle(mount, entry->stream)) != ERROR_SUCCESS) { + srs_error("http: mount flv stream for vhost=%s failed. ret=%d", sid.c_str(), ret); + return ret; + } + srs_trace("http: mount flv stream for vhost=%s, mount=%s", sid.c_str(), mount.c_str()); + } else { + entry = sflvs[sid]; + } // TODO: FIXME: supports reload. if (entry->stream) { entry->stream->entry->enabled = true; return ret; } - - std::string mount = entry->mount; - - // replace the vhost variable - mount = srs_string_replace(mount, "[vhost]", r->vhost); - mount = srs_string_replace(mount, "[app]", r->app); - mount = srs_string_replace(mount, "[stream]", r->stream); - - // remove the default vhost mount - mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/"); - - entry->cache = new SrsStreamCache(s, r); - entry->stream = new SrsLiveStream(s, r, entry->cache); - - // start http stream cache thread - if ((ret = entry->cache->start()) != ERROR_SUCCESS) { - srs_error("http: start stream cache failed. ret=%d", ret); - return ret; - } - - // mount the http flv stream. - if ((ret = mux.handle(mount, entry->stream)) != ERROR_SUCCESS) { - srs_error("http: mount flv stream for vhost=%s failed. ret=%d", r->vhost.c_str(), ret); - return ret; - } - srs_trace("http: mount flv stream for vhost=%s, mount=%s", r->vhost.c_str(), mount.c_str()); return ret; } void SrsHttpServer::unmount(SrsSource* s, SrsRequest* r) { - if (flvs.find(r->vhost) == flvs.end()) { + std::string sid = r->get_stream_url(); + + if (sflvs.find(sid) == sflvs.end()) { srs_info("ignore unmount flv stream for disabled"); return; } - SrsLiveEntry* entry = flvs[r->vhost]; + SrsLiveEntry* entry = sflvs[sid]; entry->stream->entry->enabled = false; } @@ -871,12 +903,14 @@ int SrsHttpServer::mount_hls(SrsRequest* r) { int ret = ERROR_SUCCESS; - if (hls.find(r->vhost) == hls.end()) { + std::string sid = r->get_stream_url(); + + if (shls.find(sid) == shls.end()) { srs_info("ignore mount hls stream for disabled"); return ret; } - SrsHlsEntry* entry = hls[r->vhost]; + SrsHlsEntry* entry = shls[sid]; // TODO: FIXME: supports reload. std::map::iterator it; @@ -891,33 +925,37 @@ int SrsHttpServer::mount_hls(SrsRequest* r) int SrsHttpServer::hls_update_m3u8(SrsRequest* r, string m3u8) { int ret = ERROR_SUCCESS; + + std::string mount = m3u8; - // when no hls mounted, ignore. - if (hls.find(r->vhost) == hls.end()) { - return ret; - } + std::string sid = r->get_stream_url(); + SrsHlsEntry* entry = NULL; - SrsHlsEntry* entry = hls[r->vhost]; - srs_assert(entry); - - std::string mount = entry->mount; - - // replace the vhost variable - mount = srs_string_replace(mount, "[vhost]", r->vhost); - mount = srs_string_replace(mount, "[app]", r->app); - mount = srs_string_replace(mount, "[stream]", r->stream); - - // remove the default vhost mount - mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/"); - - if (entry->streams.find(mount) == entry->streams.end()) { - ISrsHttpHandler* he = new SrsHlsM3u8Stream(); - entry->streams[mount] = he; - - if ((ret = mux.handle(mount, he)) != ERROR_SUCCESS) { - srs_error("handle mount=%s failed. ret=%d", mount.c_str(), ret); + // create stream from template when not found. + if (shls.find(sid) == shls.end()) { + if (thls.find(r->vhost) == thls.end()) { + srs_info("ignore mount hls stream for disabled"); return ret; } + + SrsHlsEntry* tmpl = thls[r->vhost]; + + entry = new SrsHlsEntry(); + entry->mount = tmpl->mount; + + shls[sid] = entry; + + if (entry->streams.find(mount) == entry->streams.end()) { + ISrsHttpHandler* he = new SrsHlsM3u8Stream(); + entry->streams[mount] = he; + + if ((ret = mux.handle(mount, he)) != ERROR_SUCCESS) { + srs_error("handle mount=%s failed. ret=%d", mount.c_str(), ret); + return ret; + } + } + } else { + entry = shls[sid]; } // update the m3u8 stream. @@ -934,12 +972,14 @@ int SrsHttpServer::hls_update_ts(SrsRequest* r, string uri, string ts) { int ret = ERROR_SUCCESS; + std::string sid = r->get_stream_url(); + // when no hls mounted, ignore. - if (hls.find(r->vhost) == hls.end()) { + if (shls.find(sid) == shls.end()) { return ret; } - SrsHlsEntry* entry = hls[r->vhost]; + SrsHlsEntry* entry = shls[sid]; srs_assert(entry); std::string mount = entry->mount; @@ -983,12 +1023,14 @@ int SrsHttpServer::hls_update_ts(SrsRequest* r, string uri, string ts) void SrsHttpServer::unmount_hls(SrsRequest* r) { - if (hls.find(r->vhost) == hls.end()) { + std::string sid = r->get_stream_url(); + + if (shls.find(sid) == shls.end()) { srs_info("ignore unmount hls stream for disabled"); return; } - SrsHlsEntry* entry = hls[r->vhost]; + SrsHlsEntry* entry = shls[sid]; std::map::iterator it; for (it = entry->streams.begin(); it != entry->streams.end(); ++it) { @@ -1097,9 +1139,8 @@ int SrsHttpServer::initialize_flv_streaming() } SrsLiveEntry* entry = new SrsLiveEntry(); - entry->vhost = vhost; entry->mount = _srs_config->get_vhost_http_remux_mount(vhost); - flvs[vhost] = entry; + tflvs[vhost] = entry; srs_trace("http flv live stream, vhost=%s, mount=%s", vhost.c_str(), entry->mount.c_str()); } @@ -1131,9 +1172,8 @@ int SrsHttpServer::initialize_hls_streaming() } SrsHlsEntry* entry = new SrsHlsEntry(); - entry->vhost = vhost; entry->mount = _srs_config->get_hls_mount(vhost); - hls[vhost] = entry; + thls[vhost] = entry; srs_trace("http hls live stream, vhost=%s, mount=%s", vhost.c_str(), entry->mount.c_str()); } diff --git a/trunk/src/app/srs_app_http_conn.hpp b/trunk/src/app/srs_app_http_conn.hpp index cd3b6bb22..9eff31186 100644 --- a/trunk/src/app/srs_app_http_conn.hpp +++ b/trunk/src/app/srs_app_http_conn.hpp @@ -252,8 +252,10 @@ private: */ struct SrsLiveEntry { - std::string vhost; + // for template, the mount contains variables. + // for concrete stream, the mount is url to access. std::string mount; + SrsLiveStream* stream; SrsStreamCache* cache; @@ -297,7 +299,8 @@ public: */ struct SrsHlsEntry { - std::string vhost; + // for template, the mount contains variables. + // for concrete stream, the mount is url to access. std::string mount; // key: the m3u8/ts file path. @@ -315,10 +318,14 @@ class SrsHttpServer : public ISrsReloadHandler { public: SrsHttpServeMux mux; - // the flv live streaming template. - std::map flvs; - // the hls live streaming template. - std::map hls; + // the flv live streaming template, to create streams. + std::map tflvs; + // the flv live streaming streams, crote by template. + std::map sflvs; + // the hls live streaming template, to create streams. + std::map thls; + // the hls live streaming streams, crote by template. + std::map shls; public: SrsHttpServer(); virtual ~SrsHttpServer(); diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 945870807..d714ec41a 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // current release version #define VERSION_MAJOR 2 #define VERSION_MINOR 0 -#define VERSION_REVISION 132 +#define VERSION_REVISION 133 // server info. #define RTMP_SIG_SRS_KEY "SRS"