mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
HLS: support load exists m3u8, to continue publish stream.
This commit is contained in:
parent
26aabe413d
commit
d6cbd277cc
5 changed files with 86 additions and 26 deletions
|
@ -17,5 +17,6 @@ vhost __defaultVhost__ {
|
|||
hls_path ./objs/nginx/html;
|
||||
hls_fragment 10;
|
||||
hls_window 60;
|
||||
hls_continuous on;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -540,7 +540,7 @@ srs_error_t srs_config_transform_vhost(SrsConfDirective* root)
|
|||
// SRS3+:
|
||||
// vhost { play { shadow; } }
|
||||
if (n == "time_jitter" || n == "mix_correct" || n == "atc" || n == "atc_auto"
|
||||
|| n == "mw_latency" || n == "gop_cache" || n == "gop_cache_max_frames"
|
||||
|| n == "mw_latency" || n == "gop_cache" || n == "gop_cache_max_frames"
|
||||
|| n == "queue_length" || n == "send_min_interval"
|
||||
|| n == "reduce_sequence_header") {
|
||||
it = dir->directives.erase(it);
|
||||
|
@ -1553,7 +1553,7 @@ srs_error_t SrsConfig::reload_vhost(SrsConfDirective* old_root)
|
|||
}
|
||||
srs_trace("vhost %s reload publish success.", vhost.c_str());
|
||||
}
|
||||
|
||||
|
||||
// transcode, many per vhost.
|
||||
if ((err = reload_transcode(new_vhost, old_vhost)) != srs_success) {
|
||||
return srs_error_wrap(err, "reload transcode");
|
||||
|
@ -1596,14 +1596,14 @@ srs_error_t SrsConfig::reload_conf(SrsConfig* conf)
|
|||
return srs_error_wrap(err, "listen");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// merge config: max_connections
|
||||
if (!srs_directive_equals(root->get("max_connections"), old_root->get("max_connections"))) {
|
||||
if ((err = do_reload_max_connections()) != srs_success) {
|
||||
return srs_error_wrap(err, "max connections");;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// merge config: pithy_print_ms
|
||||
if (!srs_directive_equals(root->get("pithy_print_ms"), old_root->get("pithy_print_ms"))) {
|
||||
if ((err = do_reload_pithy_print_ms()) != srs_success) {
|
||||
|
@ -2609,7 +2609,7 @@ srs_error_t SrsConfig::check_normal_config()
|
|||
&& m != "hls_storage" && m != "hls_mount" && m != "hls_td_ratio" && m != "hls_aof_ratio" && m != "hls_acodec" && m != "hls_vcodec"
|
||||
&& m != "hls_m3u8_file" && m != "hls_ts_file" && m != "hls_ts_floor" && m != "hls_cleanup" && m != "hls_nb_notify"
|
||||
&& m != "hls_wait_keyframe" && m != "hls_dispose" && m != "hls_keys" && m != "hls_fragments_per_key" && m != "hls_key_file"
|
||||
&& m != "hls_key_file_path" && m != "hls_key_url" && m != "hls_dts_directly" && m != "hls_ctx" && m != "hls_ts_ctx") {
|
||||
&& m != "hls_key_file_path" && m != "hls_key_url" && m != "hls_dts_directly" && m != "hls_ctx" && m != "hls_ts_ctx" && m != "hls_continuous") {
|
||||
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal vhost.hls.%s of %s", m.c_str(), vhost->arg0().c_str());
|
||||
}
|
||||
|
||||
|
@ -2828,7 +2828,7 @@ srs_error_t SrsConfig::parse_buffer(SrsConfigBuffer* buffer)
|
|||
if ((err = root->parse(buffer, this)) != srs_success) {
|
||||
return srs_error_wrap(err, "root parse");
|
||||
}
|
||||
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -2988,7 +2988,7 @@ vector<string> SrsConfig::get_listens()
|
|||
if (!srs_getenv("srs.listen").empty()) { // SRS_LISTEN
|
||||
return srs_string_split(srs_getenv("srs.listen"), " ");
|
||||
}
|
||||
|
||||
|
||||
SrsConfDirective* conf = root->get("listen");
|
||||
if (!conf) {
|
||||
return ports;
|
||||
|
@ -4747,7 +4747,7 @@ int SrsConfig::get_gop_cache_max_frames(string vhost)
|
|||
if (!conf || conf->arg0().empty()) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
return ::atoi(conf->arg0().c_str());
|
||||
}
|
||||
|
||||
|
@ -5372,12 +5372,12 @@ srs_utime_t SrsConfig::get_publish_kickoff_for_idle(SrsConfDirective* vhost)
|
|||
SRS_OVERWRITE_BY_ENV_FLOAT_SECONDS("srs.vhost.publish.kickoff_for_idle"); // SRS_VHOST_PUBLISH_KICKOFF_FOR_IDLE
|
||||
|
||||
static srs_utime_t DEFAULT = 0 * SRS_UTIME_SECONDS;
|
||||
|
||||
|
||||
SrsConfDirective* conf = vhost;
|
||||
if (!conf) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
conf = conf->get("publish");
|
||||
if (!conf) {
|
||||
return DEFAULT;
|
||||
|
@ -5387,7 +5387,7 @@ srs_utime_t SrsConfig::get_publish_kickoff_for_idle(SrsConfDirective* vhost)
|
|||
if (!conf || conf->arg0().empty()) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
return (srs_utime_t)(::atof(conf->arg0().c_str()) * SRS_UTIME_SECONDS);
|
||||
}
|
||||
|
||||
|
@ -6683,17 +6683,17 @@ int SrsConfig::get_dash_window_size(std::string vhost)
|
|||
SRS_OVERWRITE_BY_ENV_FLOAT_SECONDS("srs.vhost.dash.dash_window_size"); // SRS_VHOST_DASH_DASH_WINDOW_SIZE
|
||||
|
||||
static int DEFAULT = 5;
|
||||
|
||||
|
||||
SrsConfDirective* conf = get_dash(vhost);
|
||||
if (!conf) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
conf = conf->get("dash_window_size");
|
||||
if (!conf || conf->arg0().empty()) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
return ::atoi(conf->arg0().c_str());
|
||||
}
|
||||
|
||||
|
@ -6702,17 +6702,17 @@ bool SrsConfig::get_dash_cleanup(std::string vhost)
|
|||
SRS_OVERWRITE_BY_ENV_BOOL2("srs.vhost.dash.dash_cleanup"); // SRS_VHOST_DASH_DASH_CLEANUP
|
||||
|
||||
static bool DEFAULT = true;
|
||||
|
||||
|
||||
SrsConfDirective* conf = get_dash(vhost);
|
||||
if (!conf) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
conf = conf->get("dash_cleanup");
|
||||
if (!conf || conf->arg0().empty()) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
return SRS_CONF_PERFER_TRUE(conf->arg0());
|
||||
}
|
||||
|
||||
|
@ -6721,17 +6721,17 @@ srs_utime_t SrsConfig::get_dash_dispose(std::string vhost)
|
|||
SRS_OVERWRITE_BY_ENV_SECONDS("srs.vhost.dash.dash_dispose"); // SRS_VHOST_DASH_DASH_DISPOSE
|
||||
|
||||
static srs_utime_t DEFAULT = 0;
|
||||
|
||||
|
||||
SrsConfDirective* conf = get_dash(vhost);
|
||||
if (!conf) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
conf = conf->get("dash_dispose");
|
||||
if (!conf || conf->arg0().empty()) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
return (srs_utime_t)(::atoi(conf->arg0().c_str()) * SRS_UTIME_SECONDS);
|
||||
}
|
||||
|
||||
|
@ -7234,6 +7234,23 @@ string SrsConfig::get_hls_key_url(std::string vhost)
|
|||
return conf->arg0();
|
||||
}
|
||||
|
||||
bool SrsConfig::get_hls_continuous(string vhost)
|
||||
{
|
||||
static bool DEFAULT = true;
|
||||
|
||||
SrsConfDirective* conf = get_hls(vhost);
|
||||
if (!conf) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
conf = conf->get("hls_continuous");
|
||||
if (!conf || conf->arg0().empty()) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
return SRS_CONF_PERFER_TRUE(conf->arg0());
|
||||
}
|
||||
|
||||
SrsConfDirective *SrsConfig::get_hds(const string &vhost)
|
||||
{
|
||||
SrsConfDirective* conf = get_vhost(vhost);
|
||||
|
@ -7619,22 +7636,22 @@ bool SrsConfig::get_http_api_auth_enabled()
|
|||
SRS_OVERWRITE_BY_ENV_BOOL("srs.http_api.auth.enabled"); // SRS_HTTP_API_AUTH_ENABLED
|
||||
|
||||
static bool DEFAULT = false;
|
||||
|
||||
|
||||
SrsConfDirective* conf = root->get("http_api");
|
||||
if (!conf) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
conf = conf->get("auth");
|
||||
if (!conf) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
conf = conf->get("enabled");
|
||||
if (!conf || conf->arg0().empty()) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
return SRS_CONF_PERFER_FALSE(conf->arg0());
|
||||
}
|
||||
|
||||
|
@ -8043,7 +8060,7 @@ string SrsConfig::get_srto_passphrase()
|
|||
if (!conf) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
conf = conf->get("passphrase");
|
||||
if (!conf || conf->arg0().empty()) {
|
||||
return DEFAULT;
|
||||
|
@ -8060,7 +8077,7 @@ int SrsConfig::get_srto_pbkeylen()
|
|||
if (!conf) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
conf = conf->get("pbkeylen");
|
||||
if (!conf || conf->arg0().empty()) {
|
||||
return DEFAULT;
|
||||
|
|
|
@ -967,6 +967,10 @@ public:
|
|||
virtual bool get_hls_ctx_enabled(std::string vhost);
|
||||
// Whether enable session for ts file.
|
||||
virtual bool get_hls_ts_ctx_enabled(std::string vhost);
|
||||
// Toggles HLS continuous mode.
|
||||
// In this mode HLS sequence number is started from where it stopped last time.
|
||||
// Old fragments are kept. Default is on.
|
||||
virtual bool get_hls_continuous(std::string vhost);
|
||||
// hds section
|
||||
private:
|
||||
// Get the hds directive of vhost.
|
||||
|
|
|
@ -383,6 +383,36 @@ srs_error_t SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix,
|
|||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsHlsMuxer::restore_stream()
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// exist the m3u8 file.
|
||||
if (!srs_path_exists(m3u8)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_trace("hls: restore stream m3u8=%s, m3u8_url=%s", m3u8.c_str(), m3u8_url.c_str());
|
||||
|
||||
// read m3u8
|
||||
SrsFileReader fr;
|
||||
if ((err = fr.open(m3u8)) != srs_success) {
|
||||
return srs_error_wrap(err, "open file");
|
||||
}
|
||||
|
||||
int nb_fbuf = fr.filesize();
|
||||
char* fbuf = new char[nb_fbuf];
|
||||
SrsAutoFreeA(char, fbuf);
|
||||
if ((err = fr.read(fbuf, nb_fbuf, NULL)) != srs_success) {
|
||||
return srs_error_wrap(err, "read data");
|
||||
}
|
||||
fr.close();
|
||||
|
||||
// parse
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsHlsMuxer::segment_open()
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
@ -949,6 +979,7 @@ srs_error_t SrsHlsController::on_publish(SrsRequest* req)
|
|||
|
||||
// TODO: FIXME: support load exists m3u8, to continue publish stream.
|
||||
// for the HLS donot requires the EXT-X-MEDIA-SEQUENCE be monotonically increase.
|
||||
bool continuous = _srs_config->get_hls_continuous(vhost);
|
||||
|
||||
if ((err = muxer->on_publish(req)) != srs_success) {
|
||||
return srs_error_wrap(err, "muxer publish");
|
||||
|
@ -959,6 +990,10 @@ srs_error_t SrsHlsController::on_publish(SrsRequest* req)
|
|||
hls_key_file, hls_key_file_path, hls_key_url)) != srs_success ) {
|
||||
return srs_error_wrap(err, "hls: update config");
|
||||
}
|
||||
|
||||
if (continuous && (err = muxer->restore_stream()) != srs_success ) {
|
||||
return srs_error_wrap(err, "hls: restore stream");
|
||||
}
|
||||
|
||||
if ((err = muxer->segment_open()) != srs_success) {
|
||||
return srs_error_wrap(err, "hls: segment open");
|
||||
|
|
|
@ -211,6 +211,9 @@ private:
|
|||
virtual srs_error_t write_hls_key();
|
||||
virtual srs_error_t refresh_m3u8();
|
||||
virtual srs_error_t _refresh_m3u8(std::string m3u8_file);
|
||||
public:
|
||||
// HLS continuous mode.
|
||||
srs_error_t restore_stream();
|
||||
};
|
||||
|
||||
// The hls stream cache,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue