胡斌

save and load sequence_no,load total duration,erase last #EXT-X-ENDLIST in total.m3u8 if srs restart

... ... @@ -392,6 +392,9 @@ int SrsHlsMuxer::initialize()
return ret;
}
#define LINE_EXT_X_ENDLIST "#EXT-X-ENDLIST\n"
#define LENGTH_OF_LINE_EXT_X_ENDLIST (sizeof(LINE_EXT_X_ENDLIST)-1)
int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix,
string path, string m3u8_file, string total_m3u8_file, string total_file, string ts_file, double fragment, double window,
bool ts_floor, double aof_ratio, bool cleanup, bool wait_keyframe
... ... @@ -427,6 +430,74 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix,
total_url = srs_path_build_stream(total_file, req->vhost, req->app, req->stream);
total = path + "/" + total_url;
if (save_m3u8_total) {
//read last seq_no if exist
{
next_seq_no_file = total_m3u8 + "_seq_no";
SrsFileReader fr;
// open seq file
if ((ret = fr.open(next_seq_no_file)) == ERROR_SUCCESS) {
int64_t size = fr.filesize();
fr.lseek(0);
char * buf = new char[size + 1];
if (buf) {
ssize_t readsize = 0;
fr.read(buf, size, &readsize);
if (readsize == size) {
buf[size] = 0;
_sequence_no = atoi(buf);
}
delete[] buf;
}
}
}
//read last total duration if exist
if (!total_url.empty()) {
SrsFileReader fr;
// open seq file
if ((ret = fr.open(total)) == ERROR_SUCCESS) {
int64_t size = fr.filesize();
fr.lseek(0);
char * buf = new char[size + 1];
if (buf) {
ssize_t readsize = 0;
fr.read(buf, size, &readsize);
if (readsize == size) {
buf[size] = 0;
total_duraion = atof(buf);
}
delete[] buf;
}
}
}
//judge if last total.m3u8 end with #EXT-X-ENDLIST
{
SrsFileReader fr;
if ((ret = fr.open(total_m3u8)) == ERROR_SUCCESS) {
int64_t size = fr.filesize();
if (size > (int64_t)LENGTH_OF_LINE_EXT_X_ENDLIST) {
fr.lseek(size - LENGTH_OF_LINE_EXT_X_ENDLIST);
char * buf = new char[LENGTH_OF_LINE_EXT_X_ENDLIST + 1];
if (buf) {
ssize_t readsize = 0;
fr.read(buf, LENGTH_OF_LINE_EXT_X_ENDLIST, &readsize);
if (readsize == LENGTH_OF_LINE_EXT_X_ENDLIST) {
buf[LENGTH_OF_LINE_EXT_X_ENDLIST] = 0;
if (!strcmp(buf, LINE_EXT_X_ENDLIST)) {
m3u8_total_endlist_saved = true;
}
}
delete[] buf;
}
}
}
}
}
// when update config, reset the history target duration.
max_td = (int)(fragment * _srs_config->get_hls_td_ratio(r->vhost));
... ... @@ -836,14 +907,14 @@ int SrsHlsMuxer::segment_close(string log_desc)
srs_trace("---log_desc:%s",log_desc.c_str());
if(log_desc == "unpublish"){
ss << "#EXT-X-ENDLIST" << SRS_CONSTS_LF;
ss << LINE_EXT_X_ENDLIST;
m3u8_total_endlist_saved = true;
}
if(erase_last_endlist){
int64_t cur_pos = total_m3u8_writer.tellg();
cur_pos -= sizeof("#EXT-X-ENDLIST");// sizeof("#EXT-X-ENDLIST") = strlen("#EXT-X-ENDLIST") + 1 = strlen("#EXT-X-ENDLIST") + strlen("\n")
cur_pos -= LENGTH_OF_LINE_EXT_X_ENDLIST;
total_m3u8_writer.lseek(cur_pos);
}
... ... @@ -900,15 +971,14 @@ int SrsHlsMuxer::segment_close(string log_desc)
current->duration, current->segment_start_dts);
return ret;
}
std::stringstream ss;
ss << "#EXT-X-ENDLIST" << SRS_CONSTS_LF;
m3u8_total_endlist_saved = true;
std::string m3u8 = ss.str();
if ((ret = total_m3u8_writer.write((char*) m3u8.c_str(),
(int) m3u8.length(), NULL)) != ERROR_SUCCESS) {
if ((ret = total_m3u8_writer.write( (void *)LINE_EXT_X_ENDLIST,
LENGTH_OF_LINE_EXT_X_ENDLIST , NULL)) != ERROR_SUCCESS) {
srs_error("write m3u8 failed. ret=%d", ret);
return ret;
}
m3u8_total_endlist_saved = true;
}
srs_trace("%s drop ts segment, sequence_no=%d, uri=%s, duration=%.2f, start=%"PRId64"",
... ... @@ -926,6 +996,22 @@ int SrsHlsMuxer::segment_close(string log_desc)
srs_freep(current);
}
if(save_m3u8_total){
SrsFileWriter seq_no_writer;
std::stringstream ss_seq_no;
ret = seq_no_writer.open(next_seq_no_file);
if (ret == ERROR_SUCCESS) {
ss_seq_no << _sequence_no;
if ((ret = seq_no_writer.write((char*) ss_seq_no.str().c_str(),
(int) ss_seq_no.str().length(), NULL)) != ERROR_SUCCESS) {
srs_error("write next_seq_no_file:%s failed. ret=%d",
(char* ) next_seq_no_file.c_str(), ret);
}
}
}
// the segments to remove
std::vector<SrsHlsSegment*> segment_to_remove;
... ... @@ -1125,7 +1211,7 @@ int SrsHlsCache::on_publish(SrsHlsMuxer* muxer, SrsRequest* req, int64_t segment
// TODO: FIXME: support load exists m3u8, to continue publish stream.
// for the HLS donot requires the EXT-X-MEDIA-SEQUENCE be monotonically increase.
// open muxer
if ((ret = muxer->update_config(req, entry_prefix,
path, m3u8_file, total_m3u8_file, total_file, ts_file, hls_fragment, hls_window, ts_floor, hls_aof_ratio,
... ...
... ... @@ -213,6 +213,8 @@ private:
bool m3u8_total_endlist_saved;
//total duration for all segments
double total_duraion;
//the file to save last saved seq no
std::string next_seq_no_file;
private:
// TODO: FIXME: remove it.
bool should_write_cache;
... ...