From 26b76c0e4cc9a360fa40a87c9f884941a2de0d75 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 5 Jun 2015 20:38:01 +0800 Subject: [PATCH 1/2] fix #420, remove ts for hls ram mode. --- README.md | 1 + trunk/src/app/srs_app_hls.cpp | 9 ++- trunk/src/app/srs_app_hls.hpp | 21 ++++--- trunk/src/app/srs_app_http_conn.cpp | 88 ++++++++++++++++++++++------- trunk/src/app/srs_app_http_conn.hpp | 6 ++ trunk/src/app/srs_app_server.cpp | 14 +++++ trunk/src/app/srs_app_server.hpp | 1 + 7 files changed, 111 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 0354c226b..71ded5a63 100755 --- a/README.md +++ b/README.md @@ -344,6 +344,7 @@ Remark: ### SRS 2.0 history +* v2.0, 2015-05-30, fix [#420](https://github.com/simple-rtmp-server/srs/issues/420) remove ts for hls ram mode. * v2.0, 2015-05-30, fix [#209](https://github.com/simple-rtmp-server/srs/issues/209) cleanup hls when stop and timeout. 2.0.173. * v2.0, 2015-05-29, fix [#409](https://github.com/simple-rtmp-server/srs/issues/409) support pure video hls. 2.0.172. * v2.0, 2015-05-28, support [srs-dolphin][srs-dolphin], the multiple-process SRS. diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index 6ac0c2b5f..f54b5df7f 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -787,12 +787,19 @@ int SrsHlsMuxer::segment_close(string log_desc) for (int i = 0; i < (int)segment_to_remove.size(); i++) { SrsHlsSegment* segment = segment_to_remove[i]; - if (hls_cleanup) { + if (hls_cleanup && should_write_file) { if (unlink(segment->full_path.c_str()) < 0) { srs_warn("cleanup unlink path failed, file=%s.", segment->full_path.c_str()); } } + if (should_write_cache) { + if ((ret = handler->on_remove_ts(req, segment->uri)) != ERROR_SUCCESS) { + srs_warn("remove the ts from ram hls failed. ret=%d", ret); + return ret; + } + } + srs_freep(segment); } segment_to_remove.clear(); diff --git a/trunk/src/app/srs_app_hls.hpp b/trunk/src/app/srs_app_hls.hpp index e2657a1fe..431a0fb3f 100644 --- a/trunk/src/app/srs_app_hls.hpp +++ b/trunk/src/app/srs_app_hls.hpp @@ -64,20 +64,25 @@ public: virtual ~ISrsHlsHandler(); public: /** - * when publish stream - */ + * when publish stream + */ virtual int on_hls_publish(SrsRequest* req) = 0; /** - * when update the m3u8 file. - */ + * when update the m3u8 file. + */ virtual int on_update_m3u8(SrsRequest* r, std::string m3u8) = 0; /** - * when reap new ts file. - */ + * when reap new ts file. + */ virtual int on_update_ts(SrsRequest* r, std::string uri, std::string ts) = 0; /** - * when unpublish stream - */ + * when remove the specified ts file, + * for the hls to remove the expired ts not in hls window. + */ + virtual int on_remove_ts(SrsRequest* r, std::string uri) = 0; + /** + * when unpublish stream + */ virtual int on_hls_unpublish(SrsRequest* req) = 0; }; diff --git a/trunk/src/app/srs_app_http_conn.cpp b/trunk/src/app/srs_app_http_conn.cpp index 36544b1f5..1e78f3adb 100644 --- a/trunk/src/app/srs_app_http_conn.cpp +++ b/trunk/src/app/srs_app_http_conn.cpp @@ -1878,6 +1878,7 @@ int SrsHlsTsStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) SrsHlsEntry::SrsHlsEntry() { + tmpl = NULL; } SrsHttpServer::SrsHttpServer(SrsServer* svr) @@ -1948,6 +1949,7 @@ int SrsHttpServer::initialize() return ret; } +// TODO: FIXME: rename for HTTP FLV mount. int SrsHttpServer::http_mount(SrsSource* s, SrsRequest* r) { int ret = ERROR_SUCCESS; @@ -2063,6 +2065,7 @@ int SrsHttpServer::hls_update_m3u8(SrsRequest* r, string m3u8) } SrsHlsEntry* tmpl = thls[r->vhost]; + srs_assert(tmpl); entry = new SrsHlsEntry(); mount = tmpl->mount; @@ -2075,6 +2078,7 @@ int SrsHttpServer::hls_update_m3u8(SrsRequest* r, string m3u8) // remove the default vhost mount mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/"); + entry->tmpl = tmpl; entry->mount = mount; shls[sid] = entry; @@ -2109,32 +2113,18 @@ int SrsHttpServer::hls_update_ts(SrsRequest* r, string uri, string ts) std::string sid = r->get_stream_url(); - // when no hls mounted, ignore. + // when no hls mounted, init with empty m3u8. if (shls.find(sid) == shls.end()) { - return ret; + if ((ret = hls_update_m3u8(r, "")) != ERROR_SUCCESS) { + return ret; + } } SrsHlsEntry* entry = shls[sid]; srs_assert(entry); + srs_assert(entry->tmpl); - std::string mount = entry->mount; - - // the ts is relative from the m3u8, the same start dir. - size_t pos = string::npos; - if ((pos = mount.rfind("/")) != string::npos) { - mount = mount.substr(0, pos); - } - - // replace the vhost variable - mount = srs_string_replace(mount, "[vhost]", r->vhost); - mount = srs_string_replace(mount, "[app]", r->app); - - // remove the default vhost mount - mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/"); - - // mount with ts. - mount += "/"; - mount += uri; + std::string mount = hls_mount_generate(r, uri, entry->tmpl->mount); if (entry->streams.find(mount) == entry->streams.end()) { ISrsHttpHandler* he = new SrsHlsTsStream(); @@ -2156,6 +2146,40 @@ int SrsHttpServer::hls_update_ts(SrsRequest* r, string uri, string ts) return ret; } + +int SrsHttpServer::hls_remove_ts(SrsRequest* r, string uri) +{ + int ret = ERROR_SUCCESS; + + std::string sid = r->get_stream_url(); + + // when no hls mounted, ignore. + if (shls.find(sid) == shls.end()) { + return ret; + } + + SrsHlsEntry* entry = shls[sid]; + srs_assert(entry); + srs_assert(entry->tmpl); + + std::string mount = hls_mount_generate(r, uri, entry->tmpl->mount); + + // ignore when no ts mounted. + if (entry->streams.find(mount) == entry->streams.end()) { + return ret; + } + + // update the ts stream. + SrsHlsTsStream* hts = dynamic_cast(entry->streams[mount]); + if (hts) { + hts->set_ts(""); + // TODO: FIXME: unmount and remove the http handler. + } + srs_trace("hls remove ts ok, mount=%s", mount.c_str()); + + return ret; +} + void SrsHttpServer::unmount_hls(SrsRequest* r) { std::string sid = r->get_stream_url(); @@ -2423,6 +2447,30 @@ int SrsHttpServer::initialize_hls_streaming() return ret; } +string SrsHttpServer::hls_mount_generate(SrsRequest* r, string uri, string tmpl) +{ + std::string mount = tmpl; + + // the ts is relative from the m3u8, the same start dir. + size_t pos = string::npos; + if ((pos = mount.rfind("/")) != string::npos) { + mount = mount.substr(0, pos); + } + + // replace the vhost variable + mount = srs_string_replace(mount, "[vhost]", r->vhost); + mount = srs_string_replace(mount, "[app]", r->app); + + // remove the default vhost mount + mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/"); + + // mount with ts. + mount += "/"; + mount += uri; + + return mount; +} + #endif #ifdef SRS_AUTO_HTTP_CORE diff --git a/trunk/src/app/srs_app_http_conn.hpp b/trunk/src/app/srs_app_http_conn.hpp index 21b73defb..fdfd2a164 100644 --- a/trunk/src/app/srs_app_http_conn.hpp +++ b/trunk/src/app/srs_app_http_conn.hpp @@ -650,11 +650,15 @@ public: /** * the srs hls entry. */ +// TODO: FIXME: use hte hls template and entry. struct SrsHlsEntry { // for template, the mount contains variables. // for concrete stream, the mount is url to access. std::string mount; + + // the template to create the entry + SrsHlsEntry* tmpl; // key: the m3u8/ts file path. // value: the http handler. @@ -696,6 +700,7 @@ public: virtual int mount_hls(SrsRequest* r); virtual int hls_update_m3u8(SrsRequest* r, std::string m3u8); virtual int hls_update_ts(SrsRequest* r, std::string uri, std::string ts); + virtual int hls_remove_ts(SrsRequest* r, std::string uri); virtual void unmount_hls(SrsRequest* r); // interface ISrsReloadHandler. public: @@ -709,6 +714,7 @@ private: virtual int initialize_static_file(); virtual int initialize_flv_streaming(); virtual int initialize_hls_streaming(); + virtual std::string hls_mount_generate(SrsRequest* r, std::string uri, std::string tmpl); }; #endif diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp index f9918d56f..1fcfff052 100644 --- a/trunk/src/app/srs_app_server.cpp +++ b/trunk/src/app/srs_app_server.cpp @@ -1411,6 +1411,20 @@ int SrsServer::on_update_ts(SrsRequest* r, string uri, string ts) return ret; } + +int SrsServer::on_remove_ts(SrsRequest* r, string uri) +{ + int ret = ERROR_SUCCESS; + +#ifdef SRS_AUTO_HTTP_SERVER + if ((ret = http_stream_mux->hls_remove_ts(r, uri)) != ERROR_SUCCESS) { + return ret; + } +#endif + + return ret; +} + int SrsServer::on_hls_unpublish(SrsRequest* r) { int ret = ERROR_SUCCESS; diff --git a/trunk/src/app/srs_app_server.hpp b/trunk/src/app/srs_app_server.hpp index d9013a625..32646afa1 100644 --- a/trunk/src/app/srs_app_server.hpp +++ b/trunk/src/app/srs_app_server.hpp @@ -375,6 +375,7 @@ public: virtual int on_hls_publish(SrsRequest* r); virtual int on_update_m3u8(SrsRequest* r, std::string m3u8); virtual int on_update_ts(SrsRequest* r, std::string uri, std::string ts); + virtual int on_remove_ts(SrsRequest* r, std::string uri); virtual int on_hls_unpublish(SrsRequest* r); }; From e4c27a51b8ebc595cc32cbba966d48924b278497 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 5 Jun 2015 21:34:28 +0800 Subject: [PATCH 2/2] fix the hls bug --- trunk/src/app/srs_app_http_conn.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/trunk/src/app/srs_app_http_conn.cpp b/trunk/src/app/srs_app_http_conn.cpp index 1e78f3adb..3caf7f28a 100644 --- a/trunk/src/app/srs_app_http_conn.cpp +++ b/trunk/src/app/srs_app_http_conn.cpp @@ -2119,6 +2119,11 @@ int SrsHttpServer::hls_update_ts(SrsRequest* r, string uri, string ts) return ret; } } + + // find again, ignore if not exits. + if (shls.find(sid) == shls.end()) { + return ret; + } SrsHlsEntry* entry = shls[sid]; srs_assert(entry);