Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HLS: Support reload HLS asynchronously. v5.0.172 v6.0.67 #3782

Merged
merged 4 commits into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 61 additions & 9 deletions trunk/src/app/srs_app_hls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1136,6 +1136,7 @@ SrsHls::SrsHls()

enabled = false;
disposable = false;
async_reload_ = reloading_ = false;
last_update_time = 0;
hls_dts_directly = false;

Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions trunk/src/app/srs_app_hls.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -293,6 +299,11 @@ class SrsHls
public:
SrsHls();
virtual ~SrsHls();
public:
virtual void async_reload();
private:
srs_error_t reload();
winlinvip marked this conversation as resolved.
Show resolved Hide resolved
srs_error_t do_reload(int *reloading, int *reloaded, int *refreshed);
public:
virtual void dispose();
virtual srs_error_t cycle();
Expand Down
84 changes: 34 additions & 50 deletions trunk/src/app/srs_app_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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();
Expand All @@ -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.
Expand Down Expand Up @@ -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;
}
Expand All @@ -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();
Expand All @@ -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();
Expand Down Expand Up @@ -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();

Expand All @@ -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();

Expand Down
2 changes: 2 additions & 0 deletions trunk/src/app/srs_app_source.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down