mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
HLS: parse exist m3u8 when stream publish.
This commit is contained in:
parent
d6cbd277cc
commit
91b9228569
1 changed files with 135 additions and 1 deletions
|
@ -392,7 +392,8 @@ srs_error_t SrsHlsMuxer::restore_stream()
|
|||
return err;
|
||||
}
|
||||
|
||||
srs_trace("hls: restore stream m3u8=%s, m3u8_url=%s", m3u8.c_str(), m3u8_url.c_str());
|
||||
srs_trace("hls: restore stream m3u8=%s, m3u8_url=%s, hls_path=%s",
|
||||
m3u8.c_str(), m3u8_url.c_str(), hls_path.c_str());
|
||||
|
||||
// read m3u8
|
||||
SrsFileReader fr;
|
||||
|
@ -408,7 +409,140 @@ srs_error_t SrsHlsMuxer::restore_stream()
|
|||
}
|
||||
fr.close();
|
||||
|
||||
std::string body = fbuf;
|
||||
|
||||
// parse
|
||||
if (body.empty()) {
|
||||
return srs_error_wrap(err, "read empty m3u8");
|
||||
}
|
||||
|
||||
int sequence_num = 0;
|
||||
srs_utime_t max_target_duration = 0;
|
||||
bool discon = false;
|
||||
|
||||
std::string ptl;
|
||||
while (!body.empty()) {
|
||||
size_t pos = string::npos;
|
||||
|
||||
std::string line;
|
||||
if ((pos = body.find("\n")) != string::npos) {
|
||||
line = body.substr(0, pos);
|
||||
body = body.substr(pos + 1);
|
||||
} else {
|
||||
line = body;
|
||||
body = "";
|
||||
}
|
||||
|
||||
line = srs_string_replace(line, "\r", "");
|
||||
line = srs_string_replace(line, " ", "");
|
||||
|
||||
// #EXT-X-VERSION:3
|
||||
// the version must be 3.0
|
||||
if (srs_string_starts_with(line, "#EXT-X-VERSION:")) {
|
||||
if (!srs_string_ends_with(line, ":3")) {
|
||||
srs_warn("m3u8 3.0 required, actual is %s", line.c_str());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// #EXT-X-PLAYLIST-TYPE:VOD
|
||||
// the playlist type, vod or nothing.
|
||||
if (srs_string_starts_with(line, "#EXT-X-PLAYLIST-TYPE:")) {
|
||||
ptl = line;
|
||||
continue;
|
||||
}
|
||||
|
||||
// #EXT-X-MEDIA-SEQUENCE:4294967295
|
||||
// the media sequence no.
|
||||
if (srs_string_starts_with(line, "#EXT-X-MEDIA-SEQUENCE:")) {
|
||||
sequence_num = ::atof(line.substr(string("#EXT-X-MEDIA-SEQUENCE:").length()).c_str());
|
||||
}
|
||||
|
||||
// #EXT-X-TARGETDURATION:12
|
||||
// the target duration is required.
|
||||
if (srs_string_starts_with(line, "#EXT-X-TARGETDURATION:")) {
|
||||
max_target_duration = ::atof(line.substr(string("#EXT-X-TARGETDURATION:").length()).c_str());
|
||||
}
|
||||
|
||||
// #EXT-X-DISCONTINUITY
|
||||
// the discontinuity tag.
|
||||
if (srs_string_starts_with(line, "#EXT-X-DISCONTINUITY")) {
|
||||
discon = true;
|
||||
}
|
||||
|
||||
// #EXT-X-ENDLIST
|
||||
// parse completed.
|
||||
if (line == "#EXT-X-ENDLIST") {
|
||||
break;
|
||||
}
|
||||
|
||||
// #EXTINF:11.401,
|
||||
// livestream-5.ts
|
||||
// parse each ts entry, expect current line is inf.
|
||||
if (!srs_string_starts_with(line, "#EXTINF:")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// expect next line is url.
|
||||
std::string ts_url;
|
||||
if ((pos = body.find("\n")) != string::npos) {
|
||||
ts_url = body.substr(0, pos);
|
||||
body = body.substr(pos + 1);
|
||||
} else {
|
||||
srs_warn("ts entry unexpected eof, inf=%s", line.c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
// parse the ts duration.
|
||||
line = line.substr(string("#EXTINF:").length());
|
||||
if ((pos = line.find(",")) != string::npos) {
|
||||
line = line.substr(0, pos);
|
||||
}
|
||||
|
||||
double ts_duration = ::atof(line.c_str());
|
||||
|
||||
// load the default acodec from config.
|
||||
SrsAudioCodecId default_acodec = SrsAudioCodecIdAAC;
|
||||
if (true) {
|
||||
std::string default_acodec_str = _srs_config->get_hls_acodec(req->vhost);
|
||||
if (default_acodec_str == "mp3") {
|
||||
default_acodec = SrsAudioCodecIdMP3;
|
||||
} else if (default_acodec_str == "aac") {
|
||||
default_acodec = SrsAudioCodecIdAAC;
|
||||
} else if (default_acodec_str == "an") {
|
||||
default_acodec = SrsAudioCodecIdDisabled;
|
||||
} else {
|
||||
srs_warn("hls: use aac for other codec=%s", default_acodec_str.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// load the default vcodec from config.
|
||||
SrsVideoCodecId default_vcodec = SrsVideoCodecIdAVC;
|
||||
if (true) {
|
||||
std::string default_vcodec_str = _srs_config->get_hls_vcodec(req->vhost);
|
||||
if (default_vcodec_str == "h264") {
|
||||
default_vcodec = SrsVideoCodecIdAVC;
|
||||
} else if (default_vcodec_str == "vn") {
|
||||
default_vcodec = SrsVideoCodecIdDisabled;
|
||||
} else {
|
||||
srs_warn("hls: use h264 for other codec=%s", default_vcodec_str.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// new segment.
|
||||
SrsHlsSegment* seg = new SrsHlsSegment(context, default_acodec, default_vcodec, writer);
|
||||
seg->sequence_no = sequence_num++;
|
||||
seg->set_path(hls_path + "/" + req->app + "/" + ts_url);
|
||||
seg->uri = ts_url;
|
||||
seg->set_sequence_header(discon);
|
||||
|
||||
seg->append(0);
|
||||
seg->append(ts_duration * 1000);
|
||||
|
||||
segments->append(seg);
|
||||
|
||||
discon = false;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue