From cac195fd8b1399700b59d3aca66a95129e93cf40 Mon Sep 17 00:00:00 2001 From: duiniuluantanqin <495810242@qq.com> Date: Sun, 1 Jan 2023 21:57:53 +0800 Subject: [PATCH] HLS: support kick-off hls client --- trunk/src/app/srs_app_conn.hpp | 2 +- trunk/src/app/srs_app_http_api.cpp | 2 +- trunk/src/app/srs_app_http_conn.cpp | 2 +- trunk/src/app/srs_app_http_conn.hpp | 2 +- trunk/src/app/srs_app_http_static.cpp | 31 +++++++++++++++++++++++++-- trunk/src/app/srs_app_http_static.hpp | 7 +++++- trunk/src/app/srs_app_rtc_conn.cpp | 2 +- trunk/src/app/srs_app_rtc_conn.hpp | 2 +- trunk/src/app/srs_app_rtmp_conn.cpp | 2 +- trunk/src/app/srs_app_rtmp_conn.hpp | 2 +- trunk/src/app/srs_app_srt_conn.cpp | 2 +- trunk/src/app/srs_app_srt_conn.hpp | 2 +- 12 files changed, 45 insertions(+), 13 deletions(-) diff --git a/trunk/src/app/srs_app_conn.hpp b/trunk/src/app/srs_app_conn.hpp index e06d648b00..8f41c7ee08 100644 --- a/trunk/src/app/srs_app_conn.hpp +++ b/trunk/src/app/srs_app_conn.hpp @@ -227,7 +227,7 @@ class ISrsExpire virtual ~ISrsExpire(); public: // Set connection to expired to kick-off it. - virtual void expire() = 0; + virtual void expire(std::string id) = 0; }; // The basic connection of SRS, for TCP based protocols, diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index 3062231e50..9f4f265cf1 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -847,7 +847,7 @@ srs_error_t SrsGoApiClients::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessa } if (client->conn) { - client->conn->expire(); + client->conn->expire(client_id); srs_warn("kickoff client id=%s ok", client_id.c_str()); } else { srs_error("kickoff client id=%s error", client_id.c_str()); diff --git a/trunk/src/app/srs_app_http_conn.cpp b/trunk/src/app/srs_app_http_conn.cpp index 31aeaa3b1d..2169ecac44 100644 --- a/trunk/src/app/srs_app_http_conn.cpp +++ b/trunk/src/app/srs_app_http_conn.cpp @@ -280,7 +280,7 @@ const SrsContextId& SrsHttpConn::get_id() return trd->cid(); } -void SrsHttpConn::expire() +void SrsHttpConn::expire(std::string id) { trd->interrupt(); } diff --git a/trunk/src/app/srs_app_http_conn.hpp b/trunk/src/app/srs_app_http_conn.hpp index 4c0c20ff20..253aed95ce 100644 --- a/trunk/src/app/srs_app_http_conn.hpp +++ b/trunk/src/app/srs_app_http_conn.hpp @@ -119,7 +119,7 @@ class SrsHttpConn : public ISrsConnection, public ISrsStartable, public ISrsCoro virtual const SrsContextId& get_id(); // Interface ISrsExpire. public: - virtual void expire(); + virtual void expire(std::string id); }; // Drop body of request, only process the response. diff --git a/trunk/src/app/srs_app_http_static.cpp b/trunk/src/app/srs_app_http_static.cpp index bbcd8f3dc4..8688bc1dbf 100644 --- a/trunk/src/app/srs_app_http_static.cpp +++ b/trunk/src/app/srs_app_http_static.cpp @@ -44,6 +44,7 @@ using namespace std; SrsM3u8CtxInfo::SrsM3u8CtxInfo() { req = NULL; + alive = true; } SrsM3u8CtxInfo::~SrsM3u8CtxInfo() @@ -94,6 +95,10 @@ srs_error_t SrsHlsStream::serve_m3u8_ctx(ISrsHttpResponseWriter* w, ISrsHttpMess *served = false; return srs_success; } + + if (!can_serve_m3u8(ctx)) + return srs_error_new(ERROR_HTTP_STREAM_EOF, "HTTP stream is EOF"); + err = serve_exists_session(w, r, factory, fullpath); } else { // Create a m3u8 in memory, contains the session id(ctx). @@ -147,7 +152,7 @@ srs_error_t SrsHlsStream::serve_new_session(ISrsHttpResponseWriter* w, ISrsHttpM // We must do stat the client before hooks, because hooks depends on it. SrsStatistic* stat = SrsStatistic::instance(); - if ((err = stat->on_client(ctx, req, NULL, SrsHlsPlay)) != srs_success) { + if ((err = stat->on_client(ctx, req, this, SrsHlsPlay)) != srs_success) { return srs_error_wrap(err, "stat on client"); } @@ -251,7 +256,8 @@ void SrsHlsStream::alive(std::string ctx, SrsRequest* req) // Update alive time of context. SrsM3u8CtxInfo* info = it->second; - info->request_time = srs_get_system_time(); + if (info->alive) + info->request_time = srs_get_system_time(); } srs_error_t SrsHlsStream::http_hooks_on_play(SrsRequest* req) @@ -347,6 +353,27 @@ srs_error_t SrsHlsStream::on_timer(srs_utime_t interval) return err; } +void SrsHlsStream::expire(std::string id) +{ + std::map::iterator it = map_ctx_info_.find(id); + if (it != map_ctx_info_.end()) { + SrsM3u8CtxInfo* info = it->second; + info->alive = false; + + // remove statistic quickly + SrsStatistic* stat = SrsStatistic::instance(); + stat->on_disconnect(id, srs_success); + } +} + +bool SrsHlsStream::can_serve_m3u8(std::string id) { + std::map::iterator it = map_ctx_info_.find(id); + if (it != map_ctx_info_.end()) { + return it->second->alive; + } + return true; +} + SrsVodStream::SrsVodStream(string root_dir) : SrsHttpFileServer(root_dir) { } diff --git a/trunk/src/app/srs_app_http_static.hpp b/trunk/src/app/srs_app_http_static.hpp index 0ceaf3ff3b..ad5db75f76 100644 --- a/trunk/src/app/srs_app_http_static.hpp +++ b/trunk/src/app/srs_app_http_static.hpp @@ -17,12 +17,13 @@ struct SrsM3u8CtxInfo { srs_utime_t request_time; SrsRequest* req; + bool alive; SrsM3u8CtxInfo(); virtual ~SrsM3u8CtxInfo(); }; // Server HLS streaming. -class SrsHlsStream : public ISrsFastTimer +class SrsHlsStream : public ISrsFastTimer, public ISrsExpire { private: // The period of validity of the ctx @@ -33,6 +34,9 @@ class SrsHlsStream : public ISrsFastTimer public: 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); +// Interface ISrsExpire. +public: + virtual void expire(std::string id); private: srs_error_t serve_new_session(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, SrsRequest *req, std::string& ctx); srs_error_t serve_exists_session(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, ISrsFileReaderFactory* factory, std::string fullpath); @@ -40,6 +44,7 @@ class SrsHlsStream : public ISrsFastTimer void alive(std::string ctx, SrsRequest* req); srs_error_t http_hooks_on_play(SrsRequest* req); void http_hooks_on_stop(SrsRequest* req); + bool can_serve_m3u8(std::string id); // interface ISrsFastTimer private: srs_error_t on_timer(srs_utime_t interval); diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 8757067740..830d406277 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1871,7 +1871,7 @@ std::string SrsRtcConnection::desc() return "RtcConn"; } -void SrsRtcConnection::expire() +void SrsRtcConnection::expire(std::string id) { _srs_rtc_manager->remove(this); } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index a2ad43064b..bf1ec7c946 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -490,7 +490,7 @@ class SrsRtcConnection : public ISrsResource, public ISrsDisposingHandler, publi virtual std::string desc(); // Interface ISrsExpire. public: - virtual void expire(); + virtual void expire(std::string id); public: void switch_to_context(); const SrsContextId& context_id(); diff --git a/trunk/src/app/srs_app_rtmp_conn.cpp b/trunk/src/app/srs_app_rtmp_conn.cpp index 32b2bd5b48..80a011d692 100644 --- a/trunk/src/app/srs_app_rtmp_conn.cpp +++ b/trunk/src/app/srs_app_rtmp_conn.cpp @@ -1635,7 +1635,7 @@ const SrsContextId& SrsRtmpConn::get_id() return trd->cid(); } -void SrsRtmpConn::expire() +void SrsRtmpConn::expire(std::string id) { trd->interrupt(); } diff --git a/trunk/src/app/srs_app_rtmp_conn.hpp b/trunk/src/app/srs_app_rtmp_conn.hpp index b38e098fe8..c97d6dc39b 100644 --- a/trunk/src/app/srs_app_rtmp_conn.hpp +++ b/trunk/src/app/srs_app_rtmp_conn.hpp @@ -192,7 +192,7 @@ class SrsRtmpConn : public ISrsConnection, public ISrsStartable, public ISrsRelo virtual const SrsContextId& get_id(); // Interface ISrsExpire. public: - virtual void expire(); + virtual void expire(std::string id); }; #endif diff --git a/trunk/src/app/srs_app_srt_conn.cpp b/trunk/src/app/srs_app_srt_conn.cpp index df51160597..d77637caff 100644 --- a/trunk/src/app/srs_app_srt_conn.cpp +++ b/trunk/src/app/srs_app_srt_conn.cpp @@ -196,7 +196,7 @@ ISrsKbpsDelta* SrsMpegtsSrtConn::delta() return delta_; } -void SrsMpegtsSrtConn::expire() +void SrsMpegtsSrtConn::expire(std::string id) { trd_->interrupt(); } diff --git a/trunk/src/app/srs_app_srt_conn.hpp b/trunk/src/app/srs_app_srt_conn.hpp index d651659f29..c1aa7ca549 100644 --- a/trunk/src/app/srs_app_srt_conn.hpp +++ b/trunk/src/app/srs_app_srt_conn.hpp @@ -83,7 +83,7 @@ class SrsMpegtsSrtConn : public ISrsConnection, public ISrsStartable, public ISr ISrsKbpsDelta* delta(); // Interface ISrsExpire public: - virtual void expire(); + virtual void expire(std::string id); public: virtual srs_error_t start(); // Interface ISrsConnection.