diff --git a/README.md b/README.md index f9ec9c7f8..7103aa146 100755 --- a/README.md +++ b/README.md @@ -62,8 +62,8 @@ m3u8 url: http://127.0.0.1:1935/live/livestream.m3u8 * nginx v1.5.0: 139524 lines
### History -* v0.5, 2013-11-24, support HLS(m3u8). -* v0.5, 2013-11-24, support write ts file. +* v0.5, 2013-11-24, support HLS(m3u8), fragment and window. +* v0.5, 2013-11-24, support record to ts file for HLS. * v0.5, 2013-11-21, add ts_info tool to demux ts file. * v0.5, 2013-11-16, add rtmp players(OSMF/jwplayer5/jwplayer6). * v0.4, 2013-11-10, v0.4 released. 12500 lines. diff --git a/trunk/src/core/srs_core_config.cpp b/trunk/src/core/srs_core_config.cpp index 50d809654..e8dde1853 100644 --- a/trunk/src/core/srs_core_config.cpp +++ b/trunk/src/core/srs_core_config.cpp @@ -595,6 +595,28 @@ SrsConfDirective* SrsConfig::get_hls_path(std::string vhost) return conf->get("hls_path"); } +SrsConfDirective* SrsConfig::get_hls_fragment(std::string vhost) +{ + SrsConfDirective* conf = get_vhost(vhost); + + if (!conf) { + return NULL; + } + + return conf->get("hls_fragment"); +} + +SrsConfDirective* SrsConfig::get_hls_window(std::string vhost) +{ + SrsConfDirective* conf = get_vhost(vhost); + + if (!conf) { + return NULL; + } + + return conf->get("hls_window"); +} + SrsConfDirective* SrsConfig::get_refer(std::string vhost) { SrsConfDirective* conf = get_vhost(vhost); diff --git a/trunk/src/core/srs_core_config.hpp b/trunk/src/core/srs_core_config.hpp index 32d7d910a..2c0adeb88 100644 --- a/trunk/src/core/srs_core_config.hpp +++ b/trunk/src/core/srs_core_config.hpp @@ -38,6 +38,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define RTMP_VHOST_DEFAULT "__defaultVhost__" #define SRS_CONF_DEFAULT_HLS_PATH "./objs/nginx/html" +#define SRS_CONF_DEFAULT_HLS_FRAGMENT 10 +#define SRS_CONF_DEFAULT_HLS_WINDOW 60 class SrsFileBuffer { @@ -111,6 +113,8 @@ public: virtual SrsConfDirective* get_gop_cache(std::string vhost); virtual SrsConfDirective* get_hls(std::string vhost); virtual SrsConfDirective* get_hls_path(std::string vhost); + virtual SrsConfDirective* get_hls_fragment(std::string vhost); + virtual SrsConfDirective* get_hls_window(std::string vhost); virtual SrsConfDirective* get_refer(std::string vhost); virtual SrsConfDirective* get_refer_play(std::string vhost); virtual SrsConfDirective* get_refer_publish(std::string vhost); diff --git a/trunk/src/core/srs_core_hls.cpp b/trunk/src/core/srs_core_hls.cpp index b8020dc20..b34a3022f 100644 --- a/trunk/src/core/srs_core_hls.cpp +++ b/trunk/src/core/srs_core_hls.cpp @@ -370,6 +370,7 @@ SrsHLS::SrsHLS() jitter = new SrsRtmpJitter(); file_index = 0; m3u8_dts = stream_dts = 0; + hls_fragment = hls_window = 0; audio_buffer = new SrsCodecBuffer(); video_buffer = new SrsCodecBuffer(); @@ -411,6 +412,23 @@ int SrsHLS::on_publish(std::string _vhost, std::string _app, std::string _stream stream = _stream; app = _app; + // TODO: subscribe the reload event. + + SrsConfDirective* conf = NULL; + if ((conf = config->get_hls_fragment(vhost)) != NULL && !conf->arg0().empty()) { + hls_fragment = ::atoi(conf->arg0().c_str()); + } + if (hls_fragment <= 0) { + hls_fragment = SRS_CONF_DEFAULT_HLS_FRAGMENT; + } + + if ((conf = config->get_hls_window(vhost)) != NULL && !conf->arg0().empty()) { + hls_window = ::atoi(conf->arg0().c_str()); + } + if (hls_window <= 0) { + hls_window = SRS_CONF_DEFAULT_HLS_WINDOW; + } + if ((ret = reopen()) != ERROR_SUCCESS) { return ret; } @@ -555,9 +573,7 @@ int SrsHLS::on_video(SrsSharedPtrMessage* video) // reopen the muxer for a gop if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) { int64_t diff = stream_dts - m3u8_dts; - // 10s. - // TODO: config it. - if (diff / 90000 >= 10) { + if (diff / 90000 >= hls_fragment) { if ((ret = reopen()) != ERROR_SUCCESS) { return ret; } @@ -603,12 +619,39 @@ int SrsHLS::reopen() segments.push_back(current); current = NULL; + // the segments to remove + std::vector segment_to_remove; + + // shrink the segments. + double duration = 0; + std::vector::reverse_iterator it; + for (it = segments.rbegin(); it != segments.rend(); ++it) { + SrsM3u8Segment* segment = *it; + duration += segment->duration; + + if ((int)duration > hls_window) { + segment_to_remove.push_back(segment); + } + } + if (!segment_to_remove.empty()) { + segments.erase(segments.begin(), segments.begin() + segment_to_remove.size()); + } + + // refresh the m3u8, donot contains the removed ts if ((ret = refresh_m3u8()) != ERROR_SUCCESS) { return ret; } + + // remove the ts file. + for (it = segment_to_remove.rbegin(); it != segment_to_remove.rend(); ++it) { + SrsM3u8Segment* segment = *it; + unlink(segment->full_path.c_str()); + srs_freep(segment); + } } // new segment. current = new SrsM3u8Segment(); + current->sequence_no = file_index; m3u8_dts = current->segment_start_dts = stream_dts; // generate filename. diff --git a/trunk/src/core/srs_core_hls.hpp b/trunk/src/core/srs_core_hls.hpp index aed348871..e75b7198e 100644 --- a/trunk/src/core/srs_core_hls.hpp +++ b/trunk/src/core/srs_core_hls.hpp @@ -74,6 +74,8 @@ private: std::string stream; std::string app; std::string hls_path; + int hls_fragment; + int hls_window; private: int file_index; std::string m3u8;