winlin

support hls_fragment and hls_window

@@ -62,8 +62,8 @@ m3u8 url: http://127.0.0.1:1935/live/livestream.m3u8 @@ -62,8 +62,8 @@ m3u8 url: http://127.0.0.1:1935/live/livestream.m3u8
62 * nginx v1.5.0: 139524 lines <br/> 62 * nginx v1.5.0: 139524 lines <br/>
63 63
64 ### History 64 ### History
65 -* v0.5, 2013-11-24, support HLS(m3u8).  
66 -* v0.5, 2013-11-24, support write ts file. 65 +* v0.5, 2013-11-24, support HLS(m3u8), fragment and window.
  66 +* v0.5, 2013-11-24, support record to ts file for HLS.
67 * v0.5, 2013-11-21, add ts_info tool to demux ts file. 67 * v0.5, 2013-11-21, add ts_info tool to demux ts file.
68 * v0.5, 2013-11-16, add rtmp players(OSMF/jwplayer5/jwplayer6). 68 * v0.5, 2013-11-16, add rtmp players(OSMF/jwplayer5/jwplayer6).
69 * v0.4, 2013-11-10, v0.4 released. 12500 lines. 69 * v0.4, 2013-11-10, v0.4 released. 12500 lines.
@@ -595,6 +595,28 @@ SrsConfDirective* SrsConfig::get_hls_path(std::string vhost) @@ -595,6 +595,28 @@ SrsConfDirective* SrsConfig::get_hls_path(std::string vhost)
595 return conf->get("hls_path"); 595 return conf->get("hls_path");
596 } 596 }
597 597
  598 +SrsConfDirective* SrsConfig::get_hls_fragment(std::string vhost)
  599 +{
  600 + SrsConfDirective* conf = get_vhost(vhost);
  601 +
  602 + if (!conf) {
  603 + return NULL;
  604 + }
  605 +
  606 + return conf->get("hls_fragment");
  607 +}
  608 +
  609 +SrsConfDirective* SrsConfig::get_hls_window(std::string vhost)
  610 +{
  611 + SrsConfDirective* conf = get_vhost(vhost);
  612 +
  613 + if (!conf) {
  614 + return NULL;
  615 + }
  616 +
  617 + return conf->get("hls_window");
  618 +}
  619 +
598 SrsConfDirective* SrsConfig::get_refer(std::string vhost) 620 SrsConfDirective* SrsConfig::get_refer(std::string vhost)
599 { 621 {
600 SrsConfDirective* conf = get_vhost(vhost); 622 SrsConfDirective* conf = get_vhost(vhost);
@@ -38,6 +38,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -38,6 +38,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 #define RTMP_VHOST_DEFAULT "__defaultVhost__" 38 #define RTMP_VHOST_DEFAULT "__defaultVhost__"
39 39
40 #define SRS_CONF_DEFAULT_HLS_PATH "./objs/nginx/html" 40 #define SRS_CONF_DEFAULT_HLS_PATH "./objs/nginx/html"
  41 +#define SRS_CONF_DEFAULT_HLS_FRAGMENT 10
  42 +#define SRS_CONF_DEFAULT_HLS_WINDOW 60
41 43
42 class SrsFileBuffer 44 class SrsFileBuffer
43 { 45 {
@@ -111,6 +113,8 @@ public: @@ -111,6 +113,8 @@ public:
111 virtual SrsConfDirective* get_gop_cache(std::string vhost); 113 virtual SrsConfDirective* get_gop_cache(std::string vhost);
112 virtual SrsConfDirective* get_hls(std::string vhost); 114 virtual SrsConfDirective* get_hls(std::string vhost);
113 virtual SrsConfDirective* get_hls_path(std::string vhost); 115 virtual SrsConfDirective* get_hls_path(std::string vhost);
  116 + virtual SrsConfDirective* get_hls_fragment(std::string vhost);
  117 + virtual SrsConfDirective* get_hls_window(std::string vhost);
114 virtual SrsConfDirective* get_refer(std::string vhost); 118 virtual SrsConfDirective* get_refer(std::string vhost);
115 virtual SrsConfDirective* get_refer_play(std::string vhost); 119 virtual SrsConfDirective* get_refer_play(std::string vhost);
116 virtual SrsConfDirective* get_refer_publish(std::string vhost); 120 virtual SrsConfDirective* get_refer_publish(std::string vhost);
@@ -370,6 +370,7 @@ SrsHLS::SrsHLS() @@ -370,6 +370,7 @@ SrsHLS::SrsHLS()
370 jitter = new SrsRtmpJitter(); 370 jitter = new SrsRtmpJitter();
371 file_index = 0; 371 file_index = 0;
372 m3u8_dts = stream_dts = 0; 372 m3u8_dts = stream_dts = 0;
  373 + hls_fragment = hls_window = 0;
373 374
374 audio_buffer = new SrsCodecBuffer(); 375 audio_buffer = new SrsCodecBuffer();
375 video_buffer = new SrsCodecBuffer(); 376 video_buffer = new SrsCodecBuffer();
@@ -411,6 +412,23 @@ int SrsHLS::on_publish(std::string _vhost, std::string _app, std::string _stream @@ -411,6 +412,23 @@ int SrsHLS::on_publish(std::string _vhost, std::string _app, std::string _stream
411 stream = _stream; 412 stream = _stream;
412 app = _app; 413 app = _app;
413 414
  415 + // TODO: subscribe the reload event.
  416 +
  417 + SrsConfDirective* conf = NULL;
  418 + if ((conf = config->get_hls_fragment(vhost)) != NULL && !conf->arg0().empty()) {
  419 + hls_fragment = ::atoi(conf->arg0().c_str());
  420 + }
  421 + if (hls_fragment <= 0) {
  422 + hls_fragment = SRS_CONF_DEFAULT_HLS_FRAGMENT;
  423 + }
  424 +
  425 + if ((conf = config->get_hls_window(vhost)) != NULL && !conf->arg0().empty()) {
  426 + hls_window = ::atoi(conf->arg0().c_str());
  427 + }
  428 + if (hls_window <= 0) {
  429 + hls_window = SRS_CONF_DEFAULT_HLS_WINDOW;
  430 + }
  431 +
414 if ((ret = reopen()) != ERROR_SUCCESS) { 432 if ((ret = reopen()) != ERROR_SUCCESS) {
415 return ret; 433 return ret;
416 } 434 }
@@ -555,9 +573,7 @@ int SrsHLS::on_video(SrsSharedPtrMessage* video) @@ -555,9 +573,7 @@ int SrsHLS::on_video(SrsSharedPtrMessage* video)
555 // reopen the muxer for a gop 573 // reopen the muxer for a gop
556 if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) { 574 if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) {
557 int64_t diff = stream_dts - m3u8_dts; 575 int64_t diff = stream_dts - m3u8_dts;
558 - // 10s.  
559 - // TODO: config it.  
560 - if (diff / 90000 >= 10) { 576 + if (diff / 90000 >= hls_fragment) {
561 if ((ret = reopen()) != ERROR_SUCCESS) { 577 if ((ret = reopen()) != ERROR_SUCCESS) {
562 return ret; 578 return ret;
563 } 579 }
@@ -603,12 +619,39 @@ int SrsHLS::reopen() @@ -603,12 +619,39 @@ int SrsHLS::reopen()
603 segments.push_back(current); 619 segments.push_back(current);
604 current = NULL; 620 current = NULL;
605 621
  622 + // the segments to remove
  623 + std::vector<SrsM3u8Segment*> segment_to_remove;
  624 +
  625 + // shrink the segments.
  626 + double duration = 0;
  627 + std::vector<SrsM3u8Segment*>::reverse_iterator it;
  628 + for (it = segments.rbegin(); it != segments.rend(); ++it) {
  629 + SrsM3u8Segment* segment = *it;
  630 + duration += segment->duration;
  631 +
  632 + if ((int)duration > hls_window) {
  633 + segment_to_remove.push_back(segment);
  634 + }
  635 + }
  636 + if (!segment_to_remove.empty()) {
  637 + segments.erase(segments.begin(), segments.begin() + segment_to_remove.size());
  638 + }
  639 +
  640 + // refresh the m3u8, donot contains the removed ts
606 if ((ret = refresh_m3u8()) != ERROR_SUCCESS) { 641 if ((ret = refresh_m3u8()) != ERROR_SUCCESS) {
607 return ret; 642 return ret;
608 } 643 }
  644 +
  645 + // remove the ts file.
  646 + for (it = segment_to_remove.rbegin(); it != segment_to_remove.rend(); ++it) {
  647 + SrsM3u8Segment* segment = *it;
  648 + unlink(segment->full_path.c_str());
  649 + srs_freep(segment);
  650 + }
609 } 651 }
610 // new segment. 652 // new segment.
611 current = new SrsM3u8Segment(); 653 current = new SrsM3u8Segment();
  654 + current->sequence_no = file_index;
612 m3u8_dts = current->segment_start_dts = stream_dts; 655 m3u8_dts = current->segment_start_dts = stream_dts;
613 656
614 // generate filename. 657 // generate filename.
@@ -74,6 +74,8 @@ private: @@ -74,6 +74,8 @@ private:
74 std::string stream; 74 std::string stream;
75 std::string app; 75 std::string app;
76 std::string hls_path; 76 std::string hls_path;
  77 + int hls_fragment;
  78 + int hls_window;
77 private: 79 private:
78 int file_index; 80 int file_index;
79 std::string m3u8; 81 std::string m3u8;