胡斌

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() @@ -392,6 +392,9 @@ int SrsHlsMuxer::initialize()
392 return ret; 392 return ret;
393 } 393 }
394 394
  395 +#define LINE_EXT_X_ENDLIST "#EXT-X-ENDLIST\n"
  396 +#define LENGTH_OF_LINE_EXT_X_ENDLIST (sizeof(LINE_EXT_X_ENDLIST)-1)
  397 +
395 int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, 398 int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix,
396 string path, string m3u8_file, string total_m3u8_file, string total_file, string ts_file, double fragment, double window, 399 string path, string m3u8_file, string total_m3u8_file, string total_file, string ts_file, double fragment, double window,
397 bool ts_floor, double aof_ratio, bool cleanup, bool wait_keyframe 400 bool ts_floor, double aof_ratio, bool cleanup, bool wait_keyframe
@@ -427,6 +430,74 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, @@ -427,6 +430,74 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix,
427 total_url = srs_path_build_stream(total_file, req->vhost, req->app, req->stream); 430 total_url = srs_path_build_stream(total_file, req->vhost, req->app, req->stream);
428 total = path + "/" + total_url; 431 total = path + "/" + total_url;
429 432
  433 + if (save_m3u8_total) {
  434 + //read last seq_no if exist
  435 + {
  436 + next_seq_no_file = total_m3u8 + "_seq_no";
  437 + SrsFileReader fr;
  438 + // open seq file
  439 + if ((ret = fr.open(next_seq_no_file)) == ERROR_SUCCESS) {
  440 + int64_t size = fr.filesize();
  441 + fr.lseek(0);
  442 +
  443 + char * buf = new char[size + 1];
  444 + if (buf) {
  445 + ssize_t readsize = 0;
  446 + fr.read(buf, size, &readsize);
  447 + if (readsize == size) {
  448 + buf[size] = 0;
  449 + _sequence_no = atoi(buf);
  450 + }
  451 + delete[] buf;
  452 + }
  453 + }
  454 + }
  455 + //read last total duration if exist
  456 + if (!total_url.empty()) {
  457 + SrsFileReader fr;
  458 + // open seq file
  459 + if ((ret = fr.open(total)) == ERROR_SUCCESS) {
  460 + int64_t size = fr.filesize();
  461 + fr.lseek(0);
  462 +
  463 + char * buf = new char[size + 1];
  464 + if (buf) {
  465 + ssize_t readsize = 0;
  466 + fr.read(buf, size, &readsize);
  467 + if (readsize == size) {
  468 + buf[size] = 0;
  469 + total_duraion = atof(buf);
  470 + }
  471 + delete[] buf;
  472 + }
  473 + }
  474 + }
  475 + //judge if last total.m3u8 end with #EXT-X-ENDLIST
  476 + {
  477 + SrsFileReader fr;
  478 +
  479 + if ((ret = fr.open(total_m3u8)) == ERROR_SUCCESS) {
  480 + int64_t size = fr.filesize();
  481 + if (size > (int64_t)LENGTH_OF_LINE_EXT_X_ENDLIST) {
  482 + fr.lseek(size - LENGTH_OF_LINE_EXT_X_ENDLIST);
  483 +
  484 + char * buf = new char[LENGTH_OF_LINE_EXT_X_ENDLIST + 1];
  485 + if (buf) {
  486 + ssize_t readsize = 0;
  487 + fr.read(buf, LENGTH_OF_LINE_EXT_X_ENDLIST, &readsize);
  488 + if (readsize == LENGTH_OF_LINE_EXT_X_ENDLIST) {
  489 + buf[LENGTH_OF_LINE_EXT_X_ENDLIST] = 0;
  490 + if (!strcmp(buf, LINE_EXT_X_ENDLIST)) {
  491 + m3u8_total_endlist_saved = true;
  492 + }
  493 + }
  494 + delete[] buf;
  495 + }
  496 + }
  497 + }
  498 + }
  499 + }
  500 +
430 // when update config, reset the history target duration. 501 // when update config, reset the history target duration.
431 max_td = (int)(fragment * _srs_config->get_hls_td_ratio(r->vhost)); 502 max_td = (int)(fragment * _srs_config->get_hls_td_ratio(r->vhost));
432 503
@@ -836,14 +907,14 @@ int SrsHlsMuxer::segment_close(string log_desc) @@ -836,14 +907,14 @@ int SrsHlsMuxer::segment_close(string log_desc)
836 907
837 srs_trace("---log_desc:%s",log_desc.c_str()); 908 srs_trace("---log_desc:%s",log_desc.c_str());
838 if(log_desc == "unpublish"){ 909 if(log_desc == "unpublish"){
839 - ss << "#EXT-X-ENDLIST" << SRS_CONSTS_LF; 910 + ss << LINE_EXT_X_ENDLIST;
840 m3u8_total_endlist_saved = true; 911 m3u8_total_endlist_saved = true;
841 } 912 }
842 913
843 if(erase_last_endlist){ 914 if(erase_last_endlist){
844 int64_t cur_pos = total_m3u8_writer.tellg(); 915 int64_t cur_pos = total_m3u8_writer.tellg();
845 916
846 - cur_pos -= sizeof("#EXT-X-ENDLIST");// sizeof("#EXT-X-ENDLIST") = strlen("#EXT-X-ENDLIST") + 1 = strlen("#EXT-X-ENDLIST") + strlen("\n") 917 + cur_pos -= LENGTH_OF_LINE_EXT_X_ENDLIST;
847 918
848 total_m3u8_writer.lseek(cur_pos); 919 total_m3u8_writer.lseek(cur_pos);
849 } 920 }
@@ -900,15 +971,14 @@ int SrsHlsMuxer::segment_close(string log_desc) @@ -900,15 +971,14 @@ int SrsHlsMuxer::segment_close(string log_desc)
900 current->duration, current->segment_start_dts); 971 current->duration, current->segment_start_dts);
901 return ret; 972 return ret;
902 } 973 }
903 - std::stringstream ss;  
904 - ss << "#EXT-X-ENDLIST" << SRS_CONSTS_LF;  
905 - m3u8_total_endlist_saved = true;  
906 - std::string m3u8 = ss.str();  
907 - if ((ret = total_m3u8_writer.write((char*) m3u8.c_str(),  
908 - (int) m3u8.length(), NULL)) != ERROR_SUCCESS) { 974 +
  975 + if ((ret = total_m3u8_writer.write( (void *)LINE_EXT_X_ENDLIST,
  976 + LENGTH_OF_LINE_EXT_X_ENDLIST , NULL)) != ERROR_SUCCESS) {
909 srs_error("write m3u8 failed. ret=%d", ret); 977 srs_error("write m3u8 failed. ret=%d", ret);
910 return ret; 978 return ret;
911 } 979 }
  980 +
  981 + m3u8_total_endlist_saved = true;
912 } 982 }
913 983
914 srs_trace("%s drop ts segment, sequence_no=%d, uri=%s, duration=%.2f, start=%"PRId64"", 984 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) @@ -926,6 +996,22 @@ int SrsHlsMuxer::segment_close(string log_desc)
926 srs_freep(current); 996 srs_freep(current);
927 } 997 }
928 998
  999 + if(save_m3u8_total){
  1000 + SrsFileWriter seq_no_writer;
  1001 + std::stringstream ss_seq_no;
  1002 +
  1003 + ret = seq_no_writer.open(next_seq_no_file);
  1004 + if (ret == ERROR_SUCCESS) {
  1005 + ss_seq_no << _sequence_no;
  1006 +
  1007 + if ((ret = seq_no_writer.write((char*) ss_seq_no.str().c_str(),
  1008 + (int) ss_seq_no.str().length(), NULL)) != ERROR_SUCCESS) {
  1009 + srs_error("write next_seq_no_file:%s failed. ret=%d",
  1010 + (char* ) next_seq_no_file.c_str(), ret);
  1011 + }
  1012 + }
  1013 + }
  1014 +
929 // the segments to remove 1015 // the segments to remove
930 std::vector<SrsHlsSegment*> segment_to_remove; 1016 std::vector<SrsHlsSegment*> segment_to_remove;
931 1017
@@ -1125,7 +1211,7 @@ int SrsHlsCache::on_publish(SrsHlsMuxer* muxer, SrsRequest* req, int64_t segment @@ -1125,7 +1211,7 @@ int SrsHlsCache::on_publish(SrsHlsMuxer* muxer, SrsRequest* req, int64_t segment
1125 1211
1126 // TODO: FIXME: support load exists m3u8, to continue publish stream. 1212 // TODO: FIXME: support load exists m3u8, to continue publish stream.
1127 // for the HLS donot requires the EXT-X-MEDIA-SEQUENCE be monotonically increase. 1213 // for the HLS donot requires the EXT-X-MEDIA-SEQUENCE be monotonically increase.
1128 - 1214 +
1129 // open muxer 1215 // open muxer
1130 if ((ret = muxer->update_config(req, entry_prefix, 1216 if ((ret = muxer->update_config(req, entry_prefix,
1131 path, m3u8_file, total_m3u8_file, total_file, ts_file, hls_fragment, hls_window, ts_floor, hls_aof_ratio, 1217 path, m3u8_file, total_m3u8_file, total_file, ts_file, hls_fragment, hls_window, ts_floor, hls_aof_ratio,
@@ -213,6 +213,8 @@ private: @@ -213,6 +213,8 @@ private:
213 bool m3u8_total_endlist_saved; 213 bool m3u8_total_endlist_saved;
214 //total duration for all segments 214 //total duration for all segments
215 double total_duraion; 215 double total_duraion;
  216 + //the file to save last saved seq no
  217 + std::string next_seq_no_file;
216 private: 218 private:
217 // TODO: FIXME: remove it. 219 // TODO: FIXME: remove it.
218 bool should_write_cache; 220 bool should_write_cache;