Skip to content

Commit b5347e1

Browse files
winlinvipduiniuluantanqinchundonglinlin
committed
HLS: Support reload HLS asynchronously. v5.0.172 v6.0.67 (#3782)
When reloading HLS, it directly operates unpublish and publish. At this time, if HLS is pushed, an exception may occur. The reason is that these two coroutines operated on the HLS object at the same time, causing a null pointer. Solution: Use asynchronous reload. During reload, only set variables and let the message processing coroutine implement the reload. --------- Co-authored-by: Haibo Chen <[email protected]> Co-authored-by: chundonglinlin <[email protected]>
1 parent 6babf01 commit b5347e1

7 files changed

+112
-61
lines changed

trunk/doc/CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ The changelog for SRS.
77
<a name="v6-changes"></a>
88

99
## SRS 6.0 Changelog
10+
* v6.0, 2023-08-25, Merge [#3782](https://github.com/ossrs/srs/pull/3782): HLS: Support reload HLS asynchronously. v6.0.67 (#3782)
1011
* 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)
1112
* 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)
1213
* 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.
7879
<a name="v5-changes"></a>
7980

8081
## SRS 5.0 Changelog
82+
* v5.0, 2023-08-25, Merge [#3782](https://github.com/ossrs/srs/pull/3782): HLS: Support reload HLS asynchronously.. v5.0.171 (#3782)
8183
* 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)
8284
* v5.0, 2023-08-02, HLS: Ignore empty NALU to avoid error. v5.0.170
8385
* 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)

trunk/src/app/srs_app_hls.cpp

+61-9
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,7 @@ SrsHls::SrsHls()
11361136

11371137
enabled = false;
11381138
disposable = false;
1139+
async_reload_ = reloading_ = false;
11391140
last_update_time = 0;
11401141
hls_dts_directly = false;
11411142

@@ -1155,6 +1156,53 @@ SrsHls::~SrsHls()
11551156
srs_freep(pprint);
11561157
}
11571158

1159+
void SrsHls::async_reload()
1160+
{
1161+
async_reload_ = true;
1162+
}
1163+
1164+
srs_error_t SrsHls::reload()
1165+
{
1166+
srs_error_t err = srs_success;
1167+
1168+
// Ignore if not active.
1169+
if (!enabled) return err;
1170+
1171+
int reloading = 0, reloaded = 0, refreshed = 0;
1172+
err = do_reload(&reloading, &reloaded, &refreshed);
1173+
srs_trace("async reload hls %s, reloading=%d, reloaded=%d, refreshed=%d",
1174+
req->get_stream_url().c_str(), reloading, reloaded, refreshed);
1175+
1176+
return err;
1177+
}
1178+
1179+
srs_error_t SrsHls::do_reload(int *reloading, int *reloaded, int *refreshed)
1180+
{
1181+
srs_error_t err = srs_success;
1182+
1183+
if (!async_reload_ || reloading_) return err;
1184+
reloading_ = true;
1185+
*reloading = 1;
1186+
1187+
on_unpublish();
1188+
if ((err = on_publish()) != srs_success) {
1189+
return srs_error_wrap(err, "hls publish failed");
1190+
}
1191+
*reloaded = 1;
1192+
1193+
// Before feed the sequence header, must reset the reloading.
1194+
reloading_ = false;
1195+
async_reload_ = false;
1196+
1197+
// After reloading, we must request the sequence header again.
1198+
if ((err = hub->on_hls_request_sh()) != srs_success) {
1199+
return srs_error_wrap(err, "hls request sh");
1200+
}
1201+
*refreshed = 1;
1202+
1203+
return err;
1204+
}
1205+
11581206
void SrsHls::dispose()
11591207
{
11601208
if (enabled) {
@@ -1182,7 +1230,11 @@ srs_error_t SrsHls::cycle()
11821230
if (!req) {
11831231
return err;
11841232
}
1185-
1233+
1234+
// When reloading, we must wait for it done.
1235+
if (async_reload_) return err;
1236+
1237+
// If not unpublishing and not reloading, try to dispose HLS stream.
11861238
srs_utime_t hls_dispose = _srs_config->get_hls_dispose(req->vhost);
11871239
if (hls_dispose <= 0) {
11881240
return err;
@@ -1270,10 +1322,10 @@ void SrsHls::on_unpublish()
12701322
srs_error_t SrsHls::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format)
12711323
{
12721324
srs_error_t err = srs_success;
1273-
1274-
if (!enabled) {
1275-
return err;
1276-
}
1325+
1326+
// If not able to transmux to HLS, ignore.
1327+
if (!enabled) return err;
1328+
if (async_reload_) return reload();
12771329

12781330
// Ignore if no format->acodec, it means the codec is not parsed, or unknown codec.
12791331
// @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
13521404
srs_error_t SrsHls::on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format)
13531405
{
13541406
srs_error_t err = srs_success;
1355-
1356-
if (!enabled) {
1357-
return err;
1358-
}
1407+
1408+
// If not able to transmux to HLS, ignore.
1409+
if (!enabled) return err;
1410+
if (async_reload_) return reload();
13591411

13601412
// Ignore if no format->vcodec, it means the codec is not parsed, or unknown codec.
13611413
// @issue https://github.com/ossrs/srs/issues/1506#issuecomment-562079474

trunk/src/app/srs_app_hls.hpp

+11
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,14 @@ class SrsHls
275275
SrsHlsController* controller;
276276
private:
277277
SrsRequest* req;
278+
// Whether the HLS is enabled.
278279
bool enabled;
280+
// Whether the HLS stream is able to be disposed.
279281
bool disposable;
282+
// Whether requires HLS to do reload asynchronously.
283+
bool async_reload_;
284+
bool reloading_;
285+
// To detect heartbeat and dipose it if configured.
280286
srs_utime_t last_update_time;
281287
private:
282288
// If the diff=dts-previous_audio_dts is about 23,
@@ -293,6 +299,11 @@ class SrsHls
293299
public:
294300
SrsHls();
295301
virtual ~SrsHls();
302+
public:
303+
virtual void async_reload();
304+
private:
305+
srs_error_t reload();
306+
srs_error_t do_reload(int *reloading, int *reloaded, int *refreshed);
296307
public:
297308
virtual void dispose();
298309
virtual srs_error_t cycle();

trunk/src/app/srs_app_source.cpp

+34-50
Original file line numberDiff line numberDiff line change
@@ -1228,6 +1228,27 @@ srs_error_t SrsOriginHub::on_dvr_request_sh()
12281228
return err;
12291229
}
12301230

1231+
srs_error_t SrsOriginHub::on_hls_request_sh()
1232+
{
1233+
srs_error_t err = srs_success;
1234+
1235+
SrsSharedPtrMessage* cache_sh_video = source->meta->vsh();
1236+
if (cache_sh_video) {
1237+
if ((err = hls->on_video(cache_sh_video, source->meta->vsh_format())) != srs_success) {
1238+
return srs_error_wrap(err, "hls video");
1239+
}
1240+
}
1241+
1242+
SrsSharedPtrMessage* cache_sh_audio = source->meta->ash();
1243+
if (cache_sh_audio) {
1244+
if ((err = hls->on_audio(cache_sh_audio, source->meta->ash_format())) != srs_success) {
1245+
return srs_error_wrap(err, "hls audio");
1246+
}
1247+
}
1248+
1249+
return err;
1250+
}
1251+
12311252
srs_error_t SrsOriginHub::on_reload_vhost_forward(string vhost)
12321253
{
12331254
srs_error_t err = srs_success;
@@ -1236,7 +1257,7 @@ srs_error_t SrsOriginHub::on_reload_vhost_forward(string vhost)
12361257
return err;
12371258
}
12381259

1239-
// TODO: FIXME: maybe should ignore when publish already stopped?
1260+
// TODO: FIXME: Must do async reload, see SrsHls::async_reload.
12401261

12411262
// forwarders
12421263
destroy_forwarders();
@@ -1262,7 +1283,9 @@ srs_error_t SrsOriginHub::on_reload_vhost_dash(string vhost)
12621283
if (req_->vhost != vhost) {
12631284
return err;
12641285
}
1265-
1286+
1287+
// TODO: FIXME: Must do async reload, see SrsHls::async_reload.
1288+
12661289
dash->on_unpublish();
12671290

12681291
// Don't start DASH when source is not active.
@@ -1306,47 +1329,8 @@ srs_error_t SrsOriginHub::on_reload_vhost_hls(string vhost)
13061329
if (req_->vhost != vhost) {
13071330
return err;
13081331
}
1309-
1310-
// TODO: FIXME: maybe should ignore when publish already stopped?
1311-
1312-
hls->on_unpublish();
1313-
1314-
// Don't start HLS when source is not active.
1315-
if (!is_active) {
1316-
return err;
1317-
}
1318-
1319-
if ((err = hls->on_publish()) != srs_success) {
1320-
return srs_error_wrap(err, "hls publish failed");
1321-
}
1322-
srs_trace("vhost %s hls reload success", vhost.c_str());
13231332

1324-
SrsRtmpFormat* format = source->format_;
1325-
1326-
// when publish, don't need to fetch sequence header, which is old and maybe corrupt.
1327-
// when reload, we must fetch the sequence header from source cache.
1328-
// notice the source to get the cached sequence header.
1329-
// when reload to start hls, hls will never get the sequence header in stream,
1330-
// use the SrsLiveSource.on_hls_start to push the sequence header to HLS.
1331-
SrsSharedPtrMessage* cache_sh_video = source->meta->vsh();
1332-
if (cache_sh_video) {
1333-
if ((err = format->on_video(cache_sh_video)) != srs_success) {
1334-
return srs_error_wrap(err, "format on_video");
1335-
}
1336-
if ((err = hls->on_video(cache_sh_video, format)) != srs_success) {
1337-
return srs_error_wrap(err, "hls on_video");
1338-
}
1339-
}
1340-
1341-
SrsSharedPtrMessage* cache_sh_audio = source->meta->ash();
1342-
if (cache_sh_audio) {
1343-
if ((err = format->on_audio(cache_sh_audio)) != srs_success) {
1344-
return srs_error_wrap(err, "format on_audio");
1345-
}
1346-
if ((err = hls->on_audio(cache_sh_audio, format)) != srs_success) {
1347-
return srs_error_wrap(err, "hls on_audio");
1348-
}
1349-
}
1333+
hls->async_reload();
13501334

13511335
return err;
13521336
}
@@ -1358,8 +1342,8 @@ srs_error_t SrsOriginHub::on_reload_vhost_hds(string vhost)
13581342
if (req_->vhost != vhost) {
13591343
return err;
13601344
}
1361-
1362-
// TODO: FIXME: maybe should ignore when publish already stopped?
1345+
1346+
// TODO: FIXME: Must do async reload, see SrsHls::async_reload.
13631347

13641348
#ifdef SRS_HDS
13651349
hds->on_unpublish();
@@ -1385,8 +1369,8 @@ srs_error_t SrsOriginHub::on_reload_vhost_dvr(string vhost)
13851369
if (req_->vhost != vhost) {
13861370
return err;
13871371
}
1388-
1389-
// TODO: FIXME: maybe should ignore when publish already stopped?
1372+
1373+
// TODO: FIXME: Must do async reload, see SrsHls::async_reload.
13901374

13911375
// cleanup dvr
13921376
dvr->on_unpublish();
@@ -1422,8 +1406,8 @@ srs_error_t SrsOriginHub::on_reload_vhost_transcode(string vhost)
14221406
if (req_->vhost != vhost) {
14231407
return err;
14241408
}
1425-
1426-
// TODO: FIXME: maybe should ignore when publish already stopped?
1409+
1410+
// TODO: FIXME: Must do async reload, see SrsHls::async_reload.
14271411

14281412
encoder->on_unpublish();
14291413

@@ -1447,8 +1431,8 @@ srs_error_t SrsOriginHub::on_reload_vhost_exec(string vhost)
14471431
if (req_->vhost != vhost) {
14481432
return err;
14491433
}
1450-
1451-
// TODO: FIXME: maybe should ignore when publish already stopped?
1434+
1435+
// TODO: FIXME: Must do async reload, see SrsHls::async_reload.
14521436

14531437
ng_exec->on_unpublish();
14541438

trunk/src/app/srs_app_source.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,8 @@ class SrsOriginHub : public ISrsReloadHandler
368368
virtual srs_error_t on_forwarder_start(SrsForwarder* forwarder);
369369
// For the SrsDvr to callback to request the sequence headers.
370370
virtual srs_error_t on_dvr_request_sh();
371+
// For the SrsHls to callback to request the sequence headers.
372+
virtual srs_error_t on_hls_request_sh();
371373
// Interface ISrsReloadHandler
372374
public:
373375
virtual srs_error_t on_reload_vhost_forward(std::string vhost);

trunk/src/core/srs_core_version5.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@
99

1010
#define VERSION_MAJOR 5
1111
#define VERSION_MINOR 0
12-
#define VERSION_REVISION 171
12+
#define VERSION_REVISION 172
1313

1414
#endif

trunk/src/core/srs_core_version6.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@
99

1010
#define VERSION_MAJOR 6
1111
#define VERSION_MINOR 0
12-
#define VERSION_REVISION 66
12+
#define VERSION_REVISION 67
1313

1414
#endif

0 commit comments

Comments
 (0)