diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index 438465dc23e..1217e64cb45 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -7,6 +7,7 @@ The changelog for SRS. ## SRS 6.0 Changelog +* v6.0, 2023-08-25, Merge [#3782](https://github.com/ossrs/srs/pull/3782): HLS: Support reload HLS asynchronously.. v6.0.66 (#3782) * v6.0, 2023-08-22, Merge [#3775](https://github.com/ossrs/srs/pull/3775): Bugfix: Log format output type does not match. v6.0.66 (#3699) * v6.0, 2023-08-02, Merge [#3750](https://github.com/ossrs/srs/pull/3750): HLS: Ignore empty NALU to avoid error. v6.0.64 (#3750) * v6.0, 2023-07-27, Merge [#3611](https://github.com/ossrs/srs/pull/3611): Design and implement helm capabilities to streamline the deployment process of an SRS cluster.. v6.0.63 (#3611) @@ -78,6 +79,7 @@ The changelog for SRS. ## SRS 5.0 Changelog +* v5.0, 2023-08-25, Merge [#3782](https://github.com/ossrs/srs/pull/3782): HLS: Support reload HLS asynchronously.. v5.0.171 (#3782) * v5.0, 2023-08-22, Merge [#3775](https://github.com/ossrs/srs/pull/3775): Bugfix: Log format output type does not match. v5.0.171 (#3699) * v5.0, 2023-08-02, HLS: Ignore empty NALU to avoid error. v5.0.170 * v5.0, 2023-07-26, Merge [#3699](https://github.com/ossrs/srs/pull/3699): Bugfix: Eliminate the redundant declaration of the _srs_rtc_manager variable. v5.0.168 (#3699) diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index bd3e26aecd5..8ac72547b0f 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -1136,6 +1136,7 @@ SrsHls::SrsHls() enabled = false; disposable = false; + async_reload_ = reloading_ = false; last_update_time = 0; hls_dts_directly = false; @@ -1155,6 +1156,53 @@ SrsHls::~SrsHls() srs_freep(pprint); } +void SrsHls::async_reload() +{ + async_reload_ = true; +} + +srs_error_t SrsHls::reload() +{ + srs_error_t err = srs_success; + + // Ignore if not active. + if (!enabled) return err; + + int reloading = 0, reloaded = 0, refreshed = 0; + err = do_reload(&reloading, &reloaded, &refreshed); + srs_trace("async reload hls %s, reloading=%d, reloaded=%d, refreshed=%d", + req->get_stream_url().c_str(), reloading, reloaded, refreshed); + + return err; +} + +srs_error_t SrsHls::do_reload(int *reloading, int *reloaded, int *refreshed) +{ + srs_error_t err = srs_success; + + if (!async_reload_ || reloading_) return err; + reloading_ = true; + *reloading = 1; + + on_unpublish(); + if ((err = on_publish()) != srs_success) { + return srs_error_wrap(err, "hls publish failed"); + } + *reloaded = 1; + + // Before feed the sequence header, must reset the reloading. + reloading_ = false; + async_reload_ = false; + + // After reloading, we must request the sequence header again. + if ((err = hub->on_hls_request_sh()) != srs_success) { + return srs_error_wrap(err, "hls request sh"); + } + *refreshed = 1; + + return err; +} + void SrsHls::dispose() { if (enabled) { @@ -1182,7 +1230,11 @@ srs_error_t SrsHls::cycle() if (!req) { return err; } - + + // When reloading, we must wait for it done. + if (async_reload_) return err; + + // If not unpublishing and not reloading, try to dispose HLS stream. srs_utime_t hls_dispose = _srs_config->get_hls_dispose(req->vhost); if (hls_dispose <= 0) { return err; @@ -1270,10 +1322,10 @@ void SrsHls::on_unpublish() srs_error_t SrsHls::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format) { srs_error_t err = srs_success; - - if (!enabled) { - return err; - } + + // If not able to transmux to HLS, ignore. + if (!enabled) return err; + if (async_reload_) return reload(); // Ignore if no format->acodec, it means the codec is not parsed, or unknown codec. // @issue https://github.com/ossrs/srs/issues/1506#issuecomment-562079474 @@ -1352,10 +1404,10 @@ srs_error_t SrsHls::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* forma srs_error_t SrsHls::on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format) { srs_error_t err = srs_success; - - if (!enabled) { - return err; - } + + // If not able to transmux to HLS, ignore. + if (!enabled) return err; + if (async_reload_) return reload(); // Ignore if no format->vcodec, it means the codec is not parsed, or unknown codec. // @issue https://github.com/ossrs/srs/issues/1506#issuecomment-562079474 diff --git a/trunk/src/app/srs_app_hls.hpp b/trunk/src/app/srs_app_hls.hpp index 1f4a9429628..7975230e07b 100644 --- a/trunk/src/app/srs_app_hls.hpp +++ b/trunk/src/app/srs_app_hls.hpp @@ -275,8 +275,14 @@ class SrsHls SrsHlsController* controller; private: SrsRequest* req; + // Whether the HLS is enabled. bool enabled; + // Whether the HLS stream is able to be disposed. bool disposable; + // Whether requires HLS to do reload asynchronously. + bool async_reload_; + bool reloading_; + // To detect heartbeat and dipose it if configured. srs_utime_t last_update_time; private: // If the diff=dts-previous_audio_dts is about 23, @@ -293,6 +299,11 @@ class SrsHls public: SrsHls(); virtual ~SrsHls(); +public: + virtual void async_reload(); +private: + srs_error_t reload(); + srs_error_t do_reload(int *reloading, int *reloaded, int *refreshed); public: virtual void dispose(); virtual srs_error_t cycle(); diff --git a/trunk/src/app/srs_app_source.cpp b/trunk/src/app/srs_app_source.cpp index ba9e9e70202..d860cd38e13 100755 --- a/trunk/src/app/srs_app_source.cpp +++ b/trunk/src/app/srs_app_source.cpp @@ -1228,6 +1228,27 @@ srs_error_t SrsOriginHub::on_dvr_request_sh() return err; } +srs_error_t SrsOriginHub::on_hls_request_sh() +{ + srs_error_t err = srs_success; + + SrsSharedPtrMessage* cache_sh_video = source->meta->vsh(); + if (cache_sh_video) { + if ((err = hls->on_video(cache_sh_video, source->meta->vsh_format())) != srs_success) { + return srs_error_wrap(err, "hls video"); + } + } + + SrsSharedPtrMessage* cache_sh_audio = source->meta->ash(); + if (cache_sh_audio) { + if ((err = hls->on_audio(cache_sh_audio, source->meta->ash_format())) != srs_success) { + return srs_error_wrap(err, "hls audio"); + } + } + + return err; +} + srs_error_t SrsOriginHub::on_reload_vhost_forward(string vhost) { srs_error_t err = srs_success; @@ -1236,7 +1257,7 @@ srs_error_t SrsOriginHub::on_reload_vhost_forward(string vhost) return err; } - // TODO: FIXME: maybe should ignore when publish already stopped? + // TODO: FIXME: Must do async reload, see SrsHls::async_reload. // forwarders destroy_forwarders(); @@ -1262,7 +1283,9 @@ srs_error_t SrsOriginHub::on_reload_vhost_dash(string vhost) if (req_->vhost != vhost) { return err; } - + + // TODO: FIXME: Must do async reload, see SrsHls::async_reload. + dash->on_unpublish(); // Don't start DASH when source is not active. @@ -1306,47 +1329,8 @@ srs_error_t SrsOriginHub::on_reload_vhost_hls(string vhost) if (req_->vhost != vhost) { return err; } - - // TODO: FIXME: maybe should ignore when publish already stopped? - - hls->on_unpublish(); - - // Don't start HLS when source is not active. - if (!is_active) { - return err; - } - - if ((err = hls->on_publish()) != srs_success) { - return srs_error_wrap(err, "hls publish failed"); - } - srs_trace("vhost %s hls reload success", vhost.c_str()); - SrsRtmpFormat* format = source->format_; - - // when publish, don't need to fetch sequence header, which is old and maybe corrupt. - // when reload, we must fetch the sequence header from source cache. - // 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 SrsLiveSource.on_hls_start to push the sequence header to HLS. - SrsSharedPtrMessage* cache_sh_video = source->meta->vsh(); - if (cache_sh_video) { - if ((err = format->on_video(cache_sh_video)) != srs_success) { - return srs_error_wrap(err, "format on_video"); - } - if ((err = hls->on_video(cache_sh_video, format)) != srs_success) { - return srs_error_wrap(err, "hls on_video"); - } - } - - SrsSharedPtrMessage* cache_sh_audio = source->meta->ash(); - if (cache_sh_audio) { - if ((err = format->on_audio(cache_sh_audio)) != srs_success) { - return srs_error_wrap(err, "format on_audio"); - } - if ((err = hls->on_audio(cache_sh_audio, format)) != srs_success) { - return srs_error_wrap(err, "hls on_audio"); - } - } + hls->async_reload(); return err; } @@ -1358,8 +1342,8 @@ srs_error_t SrsOriginHub::on_reload_vhost_hds(string vhost) if (req_->vhost != vhost) { return err; } - - // TODO: FIXME: maybe should ignore when publish already stopped? + + // TODO: FIXME: Must do async reload, see SrsHls::async_reload. #ifdef SRS_HDS hds->on_unpublish(); @@ -1385,8 +1369,8 @@ srs_error_t SrsOriginHub::on_reload_vhost_dvr(string vhost) if (req_->vhost != vhost) { return err; } - - // TODO: FIXME: maybe should ignore when publish already stopped? + + // TODO: FIXME: Must do async reload, see SrsHls::async_reload. // cleanup dvr dvr->on_unpublish(); @@ -1422,8 +1406,8 @@ srs_error_t SrsOriginHub::on_reload_vhost_transcode(string vhost) if (req_->vhost != vhost) { return err; } - - // TODO: FIXME: maybe should ignore when publish already stopped? + + // TODO: FIXME: Must do async reload, see SrsHls::async_reload. encoder->on_unpublish(); @@ -1447,8 +1431,8 @@ srs_error_t SrsOriginHub::on_reload_vhost_exec(string vhost) if (req_->vhost != vhost) { return err; } - - // TODO: FIXME: maybe should ignore when publish already stopped? + + // TODO: FIXME: Must do async reload, see SrsHls::async_reload. ng_exec->on_unpublish(); diff --git a/trunk/src/app/srs_app_source.hpp b/trunk/src/app/srs_app_source.hpp index daae1f03462..0f7a57d1f4f 100644 --- a/trunk/src/app/srs_app_source.hpp +++ b/trunk/src/app/srs_app_source.hpp @@ -368,6 +368,8 @@ class SrsOriginHub : public ISrsReloadHandler virtual srs_error_t on_forwarder_start(SrsForwarder* forwarder); // For the SrsDvr to callback to request the sequence headers. virtual srs_error_t on_dvr_request_sh(); + // For the SrsHls to callback to request the sequence headers. + virtual srs_error_t on_hls_request_sh(); // Interface ISrsReloadHandler public: virtual srs_error_t on_reload_vhost_forward(std::string vhost); diff --git a/trunk/src/core/srs_core_version5.hpp b/trunk/src/core/srs_core_version5.hpp index a56accabfcf..40bf1075b57 100644 --- a/trunk/src/core/srs_core_version5.hpp +++ b/trunk/src/core/srs_core_version5.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 5 #define VERSION_MINOR 0 -#define VERSION_REVISION 171 +#define VERSION_REVISION 172 #endif diff --git a/trunk/src/core/srs_core_version6.hpp b/trunk/src/core/srs_core_version6.hpp index d1f7dea1c23..a11ec6128ad 100644 --- a/trunk/src/core/srs_core_version6.hpp +++ b/trunk/src/core/srs_core_version6.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 6 #define VERSION_MINOR 0 -#define VERSION_REVISION 66 +#define VERSION_REVISION 67 #endif