diff --git a/README.md b/README.md index 8fd93055a..0354c226b 100755 --- a/README.md +++ b/README.md @@ -343,6 +343,8 @@ Remark: ## History ### SRS 2.0 history + +* 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. * v2.0, 2015-05-24, fix [#404](https://github.com/simple-rtmp-server/srs/issues/404) register handler then start http thread. 2.0.167. diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index a03aaf2cd..6ac0c2b5f 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -292,7 +292,6 @@ SrsHlsMuxer::SrsHlsMuxer() SrsHlsMuxer::~SrsHlsMuxer() { - std::vector::iterator it; for (it = segments.begin(); it != segments.end(); ++it) { SrsHlsSegment* segment = *it; @@ -308,38 +307,35 @@ SrsHlsMuxer::~SrsHlsMuxer() void SrsHlsMuxer::dispose() { - if (!should_write_file) { - return; - } - - std::vector::iterator it; - for (it = segments.begin(); it != segments.end(); ++it) { - SrsHlsSegment* segment = *it; - if (unlink(segment->full_path.c_str()) < 0) { - srs_warn("dispose unlink path failed, file=%s.", segment->full_path.c_str()); + if (should_write_file) { + std::vector::iterator it; + for (it = segments.begin(); it != segments.end(); ++it) { + SrsHlsSegment* segment = *it; + if (unlink(segment->full_path.c_str()) < 0) { + srs_warn("dispose unlink path failed, file=%s.", segment->full_path.c_str()); + } + srs_freep(segment); + } + segments.clear(); + + if (current) { + std::string path = current->full_path + ".tmp"; + if (unlink(path.c_str()) < 0) { + srs_warn("dispose unlink path failed, file=%s", path.c_str()); + } + srs_freep(current); + } + + if (unlink(m3u8.c_str()) < 0) { + srs_warn("dispose unlink path failed. file=%s", m3u8.c_str()); } } - if (current) { - std::string path = current->full_path + ".tmp"; - if (unlink(path.c_str()) < 0) { - srs_warn("dispose unlink path failed, file=%s", path.c_str()); - } - } + // TODO: FIXME: support hls dispose in HTTP cache. - if (unlink(m3u8.c_str()) < 0) { - srs_warn("dispose unlink path failed. file=%s", m3u8.c_str()); - } srs_trace("gracefully dispose hls %s", req? req->get_stream_url().c_str() : ""); } -int SrsHlsMuxer::cycle() -{ - int ret = ERROR_SUCCESS; - // TODO: FIXME: implements it. - return ret; -} - int SrsHlsMuxer::sequence_no() { return _sequence_no; @@ -1125,6 +1121,8 @@ SrsHls::SrsHls() handler = NULL; hls_enabled = false; + hls_can_dispose = false; + last_update_time = 0; codec = new SrsAvcAacCodec(); sample = new SrsCodecSample(); @@ -1160,8 +1158,33 @@ void SrsHls::dispose() int SrsHls::cycle() { + int ret = ERROR_SUCCESS; + srs_info("hls cycle for source %d", source->source_id()); - return muxer->cycle(); + + if (last_update_time <= 0) { + last_update_time = srs_get_system_time_ms(); + } + + if (!_req) { + return ret; + } + + int hls_dispose = _srs_config->get_hls_dispose(_req->vhost) * 1000; + if (srs_get_system_time_ms() - last_update_time <= hls_dispose) { + return ret; + } + last_update_time = srs_get_system_time_ms(); + + if (!hls_can_dispose) { + return ret; + } + hls_can_dispose = false; + + srs_trace("hls cycle to dispose hls %s, timeout=%dms", _req->get_stream_url().c_str(), hls_dispose); + dispose(); + + return ret; } int SrsHls::initialize(SrsSource* s, ISrsHlsHandler* h) @@ -1182,6 +1205,11 @@ int SrsHls::on_publish(SrsRequest* req) { int ret = ERROR_SUCCESS; + _req = req; + + // update the hls time, for hls_dispose. + last_update_time = srs_get_system_time_ms(); + // support multiple publish. if (hls_enabled) { return ret; @@ -1199,6 +1227,9 @@ int SrsHls::on_publish(SrsRequest* req) // if enabled, open the muxer. hls_enabled = true; + // ok, the hls can be dispose, or need to be dispose. + hls_can_dispose = true; + // notice the source to get the cached sequence header. // when reload to start hls, hls will never get the sequence header in stream, // use the SrsSource.on_hls_start to push the sequence header to HLS. @@ -1250,6 +1281,9 @@ int SrsHls::on_audio(SrsSharedPtrMessage* shared_audio) if (!hls_enabled) { return ret; } + + // update the hls time, for hls_dispose. + last_update_time = srs_get_system_time_ms(); SrsSharedPtrMessage* audio = shared_audio->copy(); SrsAutoFree(SrsSharedPtrMessage, audio); @@ -1311,6 +1345,9 @@ int SrsHls::on_video(SrsSharedPtrMessage* shared_video) if (!hls_enabled) { return ret; } + + // update the hls time, for hls_dispose. + last_update_time = srs_get_system_time_ms(); SrsSharedPtrMessage* video = shared_video->copy(); SrsAutoFree(SrsSharedPtrMessage, video); diff --git a/trunk/src/app/srs_app_hls.hpp b/trunk/src/app/srs_app_hls.hpp index 192ba3a9c..e2657a1fe 100644 --- a/trunk/src/app/srs_app_hls.hpp +++ b/trunk/src/app/srs_app_hls.hpp @@ -261,7 +261,6 @@ public: virtual ~SrsHlsMuxer(); public: virtual void dispose(); - virtual int cycle(); public: virtual int sequence_no(); virtual std::string ts_url(); @@ -382,7 +381,11 @@ private: SrsHlsCache* hls_cache; ISrsHlsHandler* handler; private: + SrsRequest* _req; bool hls_enabled; + bool hls_can_dispose; + int64_t last_update_time; +private: SrsSource* source; SrsAvcAacCodec* codec; SrsCodecSample* sample; diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 277308c91..cb1e34055 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 172 +#define VERSION_REVISION 173 // server info. #define RTMP_SIG_SRS_KEY "SRS"