1
0
Fork 0
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:
chundonglinlin 2022-06-29 09:47:57 +08:00 committed by chenhaibo
parent d6cbd277cc
commit 91b9228569

View file

@ -392,7 +392,8 @@ srs_error_t SrsHlsMuxer::restore_stream()
return err; 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 // read m3u8
SrsFileReader fr; SrsFileReader fr;
@ -408,7 +409,140 @@ srs_error_t SrsHlsMuxer::restore_stream()
} }
fr.close(); fr.close();
std::string body = fbuf;
// parse // 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; return err;
} }