diff --git a/src/Common/MediaSink.cpp b/src/Common/MediaSink.cpp index e8dae600..4d74e2c9 100644 --- a/src/Common/MediaSink.cpp +++ b/src/Common/MediaSink.cpp @@ -35,16 +35,6 @@ void MediaSink::addTrack(const Track::Ptr &track_in) { //克隆Track,只拷贝其数据,不拷贝其数据转发关系 auto track = track_in->clone(); - weak_ptr weakSelf = shared_from_this(); - track->addDelegate(std::make_shared([weakSelf](const Frame::Ptr &frame){ - auto strongSelf = weakSelf.lock(); - if(!strongSelf){ - return; - } - if(!strongSelf->_anyTrackUnReady){ - strongSelf->onTrackFrame(frame); - } - })); auto codec_id = track->getCodecId(); _track_map[codec_id] = track; auto lam = [this,track](){ @@ -58,6 +48,17 @@ void MediaSink::addTrack(const Track::Ptr &track_in) { _trackReadyCallback[codec_id] = lam; _ticker.resetTime(); } + + weak_ptr weakSelf = shared_from_this(); + track->addDelegate(std::make_shared([weakSelf](const Frame::Ptr &frame){ + auto strongSelf = weakSelf.lock(); + if(!strongSelf){ + return; + } + if(!strongSelf->_anyTrackUnReady){ + strongSelf->onTrackFrame(frame); + } + })); } void MediaSink::resetTracks() { diff --git a/src/MediaFile/HlsMaker.cpp b/src/MediaFile/HlsMaker.cpp index a438ad0b..959fcc36 100644 --- a/src/MediaFile/HlsMaker.cpp +++ b/src/MediaFile/HlsMaker.cpp @@ -43,11 +43,6 @@ void HlsMaker::makeIndexFile(bool eof) { char file_content[1024]; int maxSegmentDuration = 0; - //停止写之后将最后的片段也写进m3u8文件中 - if (eof && _stampInc > 0) { - _seg_dur_list.push_back(std::make_tuple(_stampInc, _last_file_name)); - } - for (auto &tp : _seg_dur_list) { int dur = std::get<0>(tp); if (dur > maxSegmentDuration) { @@ -83,18 +78,16 @@ void HlsMaker::makeIndexFile(bool eof) { void HlsMaker::inputData(void *data, uint32_t len, uint32_t timestamp) { //分片数据中断结束 if (data && len) { - addNewFile(timestamp); - onWriteFile((char *) data, len); + addNewSegment(timestamp); + onWriteSegment((char *) data, len); + //记录上次写入数据时间 + _ticker_last_data.resetTime(); } else { - _noData = true; - _stampInc = _ticker.elapsedTime(); - _seg_dur_list.push_back(std::make_tuple(_stampInc, _last_file_name)); - delOldFile(); - makeIndexFile(); + flushLastSegment(true); } } -void HlsMaker::delOldFile() { +void HlsMaker::delOldSegment() { if(_seg_number == 0){ //如果设置为保留0个切片,则认为是保存为点播 return; @@ -106,28 +99,38 @@ void HlsMaker::delOldFile() { //但是实际保存的切片个数比m3u8所述多两个,这样做的目的是防止播放器在切片删除前能下载完毕 if (_file_index >= _seg_number + 4) { - onDelFile(_file_index - _seg_number - 4); + onDelSegment(_file_index - _seg_number - 4); } } -void HlsMaker::addNewFile(uint32_t) { - //上次分片数据中断结束,重置时间避免中途的等待 - if (_noData) { - _ticker.resetTime(); - _last_file_name = onOpenFile(_file_index++); - _noData = false; +void HlsMaker::addNewSegment(uint32_t) { + if(!_last_file_name.empty() && _ticker.elapsedTime() < _seg_duration * 1000){ + //存在上个切片,并且未到分片时间 + return; } - _stampInc = _ticker.elapsedTime(); - if (_file_index == 0 || _stampInc >= _seg_duration * 1000) { - _ticker.resetTime(); - auto file_name = onOpenFile(_file_index); - if (_file_index++ > 0) { - _seg_dur_list.push_back(std::make_tuple(_stampInc, _last_file_name)); - delOldFile(); - makeIndexFile(); - } - _last_file_name = file_name; + + //关闭并保存上一个切片 + flushLastSegment(); + //新增切片 + _last_file_name = onOpenSegment(_file_index++); + //重置切片计时器 + _ticker.resetTime(); +} + +void HlsMaker::flushLastSegment(bool eof){ + if(_last_file_name.empty()){ + //不存在上个切片 + return; } + //文件创建到最后一次数据写入的时间即为切片长度 + auto seg_dur = _ticker.elapsedTime() - _ticker_last_data.elapsedTime(); + if(seg_dur <= 0){ + seg_dur = 100; + } + _seg_dur_list.push_back(std::make_tuple(seg_dur, _last_file_name)); + delOldSegment(); + makeIndexFile(eof); + _last_file_name.clear(); } }//namespace mediakit \ No newline at end of file diff --git a/src/MediaFile/HlsMaker.h b/src/MediaFile/HlsMaker.h index 46731759..49635a60 100644 --- a/src/MediaFile/HlsMaker.h +++ b/src/MediaFile/HlsMaker.h @@ -60,20 +60,20 @@ protected: * @param index * @return */ - virtual string onOpenFile(int index) = 0; + virtual string onOpenSegment(int index) = 0; /** * 删除ts切片文件回调 * @param index */ - virtual void onDelFile(int index) = 0; + virtual void onDelSegment(int index) = 0; /** * 写ts切片文件回调 * @param data * @param len */ - virtual void onWriteFile(const char *data, int len) = 0; + virtual void onWriteSegment(const char *data, int len) = 0; /** * 写m3u8文件回调 @@ -82,21 +82,34 @@ protected: */ virtual void onWriteHls(const char *data, int len) = 0; + /** + * 关闭上个ts切片并且写入m3u8索引 + * @param eof + */ + void flushLastSegment(bool eof = false); +private: /** * 生成m3u8文件 * @param eof true代表点播 */ void makeIndexFile(bool eof = false); - void delOldFile(); - void addNewFile(uint32_t timestamp); -protected: - uint32_t _seg_number = 0; + + /** + * 删除旧的ts切片 + */ + void delOldSegment(); + + /** + * 添加新的ts切片 + * @param timestamp + */ + void addNewSegment(uint32_t timestamp); private: - bool _noData = false; - int _stampInc = 0; + uint32_t _seg_number = 0; float _seg_duration = 0; uint64_t _file_index = 0; Ticker _ticker; + Ticker _ticker_last_data; string _last_file_name; std::deque > _seg_dur_list; }; diff --git a/src/MediaFile/HlsMakerImp.cpp b/src/MediaFile/HlsMakerImp.cpp index 77763e30..8fa9d4fd 100644 --- a/src/MediaFile/HlsMakerImp.cpp +++ b/src/MediaFile/HlsMakerImp.cpp @@ -40,6 +40,7 @@ HlsMakerImp::HlsMakerImp(const string &m3u8_file, _path_hls = m3u8_file; _params = params; _buf_size = bufSize; + _is_vod = seg_number == 0; _file_buf.reset(new char[bufSize],[](char *ptr){ delete[] ptr; }); @@ -47,14 +48,14 @@ HlsMakerImp::HlsMakerImp(const string &m3u8_file, HlsMakerImp::~HlsMakerImp() { //录制完了 - makeIndexFile(true); - if(_seg_number){ + flushLastSegment(true); + if(!_is_vod){ //hls直播才删除文件 File::delete_file(_path_prefix.data()); } } -string HlsMakerImp::onOpenFile(int index) { +string HlsMakerImp::onOpenSegment(int index) { auto full_path = fullPath(index); _file = makeFile(full_path, true); if(!_file){ @@ -67,12 +68,12 @@ string HlsMakerImp::onOpenFile(int index) { return StrPrinter << index << ".ts" << "?" << _params; } -void HlsMakerImp::onDelFile(int index) { +void HlsMakerImp::onDelSegment(int index) { //WarnL << index; File::delete_file(fullPath(index).data()); } -void HlsMakerImp::onWriteFile(const char *data, int len) { +void HlsMakerImp::onWriteSegment(const char *data, int len) { if (_file) { fwrite(data, len, 1, _file.get()); } diff --git a/src/MediaFile/HlsMakerImp.h b/src/MediaFile/HlsMakerImp.h index d04de216..55637fd8 100644 --- a/src/MediaFile/HlsMakerImp.h +++ b/src/MediaFile/HlsMakerImp.h @@ -44,9 +44,9 @@ public: uint32_t seg_number = 3); virtual ~HlsMakerImp(); protected: - string onOpenFile(int index) override ; - void onDelFile(int index) override; - void onWriteFile(const char *data, int len) override; + string onOpenSegment(int index) override ; + void onDelSegment(int index) override; + void onWriteSegment(const char *data, int len) override; void onWriteHls(const char *data, int len) override; private: string fullPath(int index); @@ -58,6 +58,8 @@ private: string _path_hls; string _params; int _buf_size; + //是否为点播 + bool _is_vod; }; }//namespace mediakit