Skip to content

Commit

Permalink
HLS: parse exist m3u8 when stream publish.
Browse files Browse the repository at this point in the history
  • Loading branch information
chundonglinlin committed Jun 29, 2022
1 parent d0f4870 commit 13261d9
Showing 1 changed file with 135 additions and 1 deletion.
136 changes: 135 additions & 1 deletion trunk/src/app/srs_app_hls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,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;
Expand All @@ -370,7 +371,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;
}
Expand Down

0 comments on commit 13261d9

Please sign in to comment.