winlin

fix the m3u8 crash bug, simplify it

@@ -76,9 +76,10 @@ vhost dev { @@ -76,9 +76,10 @@ vhost dev {
76 hls_path ./objs/nginx/html; 76 hls_path ./objs/nginx/html;
77 hls_fragment 5; 77 hls_fragment 5;
78 hls_window 30; 78 hls_window 30;
79 - forward 127.0.0.1:19350; 79 + #forward 127.0.0.1:19350;
  80 + forward 127.0.0.1:1936;
80 transcode { 81 transcode {
81 - enabled on; 82 + enabled off;
82 ffmpeg ./objs/ffmpeg/bin/ffmpeg; 83 ffmpeg ./objs/ffmpeg/bin/ffmpeg;
83 engine dev { 84 engine dev {
84 enabled on; 85 enabled on;
@@ -31,6 +31,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -31,6 +31,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 #include <stdlib.h> 31 #include <stdlib.h>
32 #include <string.h> 32 #include <string.h>
33 33
  34 +#include <algorithm>
  35 +
34 #include <srs_core_error.hpp> 36 #include <srs_core_error.hpp>
35 #include <srs_core_codec.hpp> 37 #include <srs_core_codec.hpp>
36 #include <srs_core_amf0.hpp> 38 #include <srs_core_amf0.hpp>
@@ -704,6 +706,7 @@ int SrsHls::reopen() @@ -704,6 +706,7 @@ int SrsHls::reopen()
704 hls_path = conf->arg0(); 706 hls_path = conf->arg0();
705 } 707 }
706 708
  709 + // TODO: create all parents dirs.
707 // create dir for app. 710 // create dir for app.
708 if ((ret = create_dir()) != ERROR_SUCCESS) { 711 if ((ret = create_dir()) != ERROR_SUCCESS) {
709 return ret; 712 return ret;
@@ -712,10 +715,19 @@ int SrsHls::reopen() @@ -712,10 +715,19 @@ int SrsHls::reopen()
712 // start new segment. 715 // start new segment.
713 if (current) { 716 if (current) {
714 current->duration = (stream_dts - current->segment_start_dts) / 90000.0; 717 current->duration = (stream_dts - current->segment_start_dts) / 90000.0;
  718 + srs_assert(current->duration > 0);
  719 +
  720 + // assert segment duplicate.
  721 + std::vector<SrsM3u8Segment*>::iterator it;
  722 + it = std::find(segments.begin(), segments.end(), current);
  723 + srs_assert(it == segments.end());
  724 +
  725 + // valid, add to segments.
715 segments.push_back(current); 726 segments.push_back(current);
716 727
717 srs_trace("reap ts segment, sequence_no=%d, uri=%s, duration=%.2f, start=%"PRId64"", 728 srs_trace("reap ts segment, sequence_no=%d, uri=%s, duration=%.2f, start=%"PRId64"",
718 - current->sequence_no, current->uri.c_str(), current->duration, current->segment_start_dts); 729 + current->sequence_no, current->uri.c_str(), current->duration,
  730 + current->segment_start_dts);
719 731
720 // close the muxer of finished segment. 732 // close the muxer of finished segment.
721 srs_freep(current->muxer); 733 srs_freep(current->muxer);
@@ -726,31 +738,32 @@ int SrsHls::reopen() @@ -726,31 +738,32 @@ int SrsHls::reopen()
726 738
727 // shrink the segments. 739 // shrink the segments.
728 double duration = 0; 740 double duration = 0;
729 - std::vector<SrsM3u8Segment*>::reverse_iterator it;  
730 - for (it = segments.rbegin(); it != segments.rend(); ++it) {  
731 - SrsM3u8Segment* segment = *it; 741 + int remove_index = -1;
  742 + for (int i = segments.size() - 1; i >= 0; i--) {
  743 + SrsM3u8Segment* segment = segments[i];
  744 + duration += segment->duration;
732 745
733 - // once find the overflow segment, clear all segments before it.  
734 if ((int)duration > hls_window) { 746 if ((int)duration > hls_window) {
735 - segment_to_remove.push_back(segment);  
736 - continue; 747 + remove_index = i;
  748 + break;
737 } 749 }
738 -  
739 - duration += segment->duration;  
740 } 750 }
741 - if (!segment_to_remove.empty()) {  
742 - segments.erase(segments.begin(), segments.begin() + segment_to_remove.size());  
743 -  
744 - // refresh the m3u8, donot contains the removed ts  
745 - ret = refresh_m3u8(); 751 + for (int i = 0; i < remove_index && !segments.empty(); i++) {
  752 + SrsM3u8Segment* segment = *segments.begin();
  753 + segments.erase(segments.begin());
  754 + segment_to_remove.push_back(segment);
746 } 755 }
747 756
  757 + // refresh the m3u8, donot contains the removed ts
  758 + ret = refresh_m3u8();
  759 +
748 // remove the ts file. 760 // remove the ts file.
749 - for (it = segment_to_remove.rbegin(); it != segment_to_remove.rend(); ++it) {  
750 - SrsM3u8Segment* segment = *it; 761 + for (int i = 0; i < (int)segment_to_remove.size(); i++) {
  762 + SrsM3u8Segment* segment = segment_to_remove[i];
751 unlink(segment->full_path.c_str()); 763 unlink(segment->full_path.c_str());
752 srs_freep(segment); 764 srs_freep(segment);
753 } 765 }
  766 + segment_to_remove.clear();
754 767
755 // check ret of refresh m3u8 768 // check ret of refresh m3u8
756 if (ret != ERROR_SUCCESS) { 769 if (ret != ERROR_SUCCESS) {
@@ -760,13 +773,15 @@ int SrsHls::reopen() @@ -760,13 +773,15 @@ int SrsHls::reopen()
760 } 773 }
761 // new segment. 774 // new segment.
762 current = new SrsM3u8Segment(); 775 current = new SrsM3u8Segment();
763 - current->sequence_no = file_index; 776 + current->sequence_no = file_index++;
764 m3u8_dts = current->segment_start_dts = stream_dts; 777 m3u8_dts = current->segment_start_dts = stream_dts;
765 778
766 // generate filename. 779 // generate filename.
767 char filename[128]; 780 char filename[128];
768 - snprintf(filename, sizeof(filename), "%s-%d.ts", stream.c_str(), file_index++); 781 + snprintf(filename, sizeof(filename),
  782 + "%s-%d.ts", stream.c_str(), current->sequence_no);
769 783
  784 + // TODO: use temp file and rename it.
770 current->full_path = hls_path; 785 current->full_path = hls_path;
771 current->full_path += "/"; 786 current->full_path += "/";
772 current->full_path += app; 787 current->full_path += app;
@@ -780,7 +795,8 @@ int SrsHls::reopen() @@ -780,7 +795,8 @@ int SrsHls::reopen()
780 srs_error("open hls muxer failed. ret=%d", ret); 795 srs_error("open hls muxer failed. ret=%d", ret);
781 return ret; 796 return ret;
782 } 797 }
783 - srs_info("open HLS muxer success. vhost=%s, path=%s", vhost.c_str(), current->full_path.c_str()); 798 + srs_info("open HLS muxer success. vhost=%s, path=%s",
  799 + vhost.c_str(), current->full_path.c_str());
784 800
785 // segment open, flush the audio. 801 // segment open, flush the audio.
786 // @see: ngx_rtmp_hls_open_fragment 802 // @see: ngx_rtmp_hls_open_fragment