From 2e9ff3ed3c58773e682713231825b092a8b543b4 Mon Sep 17 00:00:00 2001 From: ziyue <1213642868@qq.com> Date: Wed, 22 Dec 2021 15:42:03 +0800 Subject: [PATCH] =?UTF-8?q?HLS:=20=E4=BF=AE=E5=A4=8Dhls=E7=9B=B4=E6=92=ADt?= =?UTF-8?q?s/m3u8=E6=96=87=E4=BB=B6=E6=9B=B4=E6=96=B0=E5=AF=BC=E8=87=B4mma?= =?UTF-8?q?p=E5=A4=B1=E6=95=88=EF=BC=8C=E8=A7=A6=E5=8F=91bus=20error?= =?UTF-8?q?=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Http/HttpBody.cpp | 55 ++++++++++++++++++------------------ src/Http/HttpBody.h | 7 +++-- src/Http/HttpFileManager.cpp | 9 +++--- src/Http/HttpFileManager.h | 2 +- src/Record/HlsMaker.cpp | 4 ++- src/Record/HlsMakerImp.cpp | 5 ++-- 6 files changed, 44 insertions(+), 38 deletions(-) diff --git a/src/Http/HttpBody.cpp b/src/Http/HttpBody.cpp index 7dec29f1..fa1aaca2 100644 --- a/src/Http/HttpBody.cpp +++ b/src/Http/HttpBody.cpp @@ -45,54 +45,55 @@ Buffer::Ptr HttpStringBody::readData(size_t size) { ////////////////////////////////////////////////////////////////// -HttpFileBody::HttpFileBody(const string &filePath){ +HttpFileBody::HttpFileBody(const string &filePath, bool use_mmap) { std::shared_ptr fp(fopen(filePath.data(), "rb"), [](FILE *fp) { if (fp) { fclose(fp); } }); if (!fp) { - init(fp, 0, 0); + init(fp, 0, 0, use_mmap); } else { - init(fp, 0, File::fileSize(fp.get())); + init(fp, 0, File::fileSize(fp.get()), use_mmap); } } -HttpFileBody::HttpFileBody(const std::shared_ptr &fp, size_t offset, size_t max_size) { - init(fp,offset,max_size); +HttpFileBody::HttpFileBody(const std::shared_ptr &fp, size_t offset, size_t max_size, bool use_mmap) { + init(fp, offset, max_size, use_mmap); } -void HttpFileBody::init(const std::shared_ptr &fp, size_t offset, size_t max_size) { +void HttpFileBody::init(const std::shared_ptr &fp, size_t offset, size_t max_size, bool use_mmap) { _fp = fp; _max_size = max_size; #ifdef ENABLE_MMAP - do { - if(!_fp){ - //文件不存在 - break; - } - int fd = fileno(fp.get()); - if (fd < 0) { - WarnL << "fileno failed:" << get_uv_errmsg(false); - break; - } - auto ptr = (char *) mmap(NULL, max_size, PROT_READ, MAP_SHARED, fd, offset); - if (ptr == MAP_FAILED) { - WarnL << "mmap failed:" << get_uv_errmsg(false); - break; - } - _map_addr.reset(ptr,[max_size,fp](char *ptr){ - munmap(ptr,max_size); - }); - } while (false); + if (use_mmap) { + do { + if (!_fp) { + //文件不存在 + break; + } + int fd = fileno(fp.get()); + if (fd < 0) { + WarnL << "fileno failed:" << get_uv_errmsg(false); + break; + } + auto ptr = (char *) mmap(NULL, max_size, PROT_READ, MAP_SHARED, fd, offset); + if (ptr == MAP_FAILED) { + WarnL << "mmap failed:" << get_uv_errmsg(false); + break; + } + _map_addr.reset(ptr, [max_size, fp](char *ptr) { + munmap(ptr, max_size); + }); + } while (false); + } #endif - if(!_map_addr && offset && fp.get()){ + if (!_map_addr && offset && fp.get()) { //未映射,那么fseek设置偏移量 fseek64(fp.get(), offset, SEEK_SET); } } - class BufferMmap : public Buffer{ public: typedef std::shared_ptr Ptr; diff --git a/src/Http/HttpBody.h b/src/Http/HttpBody.h index 1f974fa8..5c0de8ec 100644 --- a/src/Http/HttpBody.h +++ b/src/Http/HttpBody.h @@ -107,16 +107,17 @@ public: * @param fp 文件句柄,文件的偏移量必须为0 * @param offset 相对文件头的偏移量 * @param max_size 最大读取字节数,未判断是否大于文件真实大小 + * @param use_mmap 是否使用mmap方式访问文件 */ - HttpFileBody(const std::shared_ptr &fp, size_t offset, size_t max_size); - HttpFileBody(const string &file_path); + HttpFileBody(const std::shared_ptr &fp, size_t offset, size_t max_size, bool use_mmap = true); + HttpFileBody(const string &file_path, bool use_mmap = true); ~HttpFileBody() override = default; ssize_t remainSize() override ; Buffer::Ptr readData(size_t size) override; private: - void init(const std::shared_ptr &fp,size_t offset,size_t max_size); + void init(const std::shared_ptr &fp,size_t offset,size_t max_size, bool use_mmap); private: size_t _max_size; diff --git a/src/Http/HttpFileManager.cpp b/src/Http/HttpFileManager.cpp index dec1cd0b..54ebb995 100644 --- a/src/Http/HttpFileManager.cpp +++ b/src/Http/HttpFileManager.cpp @@ -405,7 +405,7 @@ static void accessFile(TcpSession &sender, const Parser &parser, const MediaInfo return; } - auto response_file = [file_exist](const HttpServerCookie::Ptr &cookie, const HttpFileManager::invoker &cb, const string &strFile, const Parser &parser) { + auto response_file = [file_exist, is_hls](const HttpServerCookie::Ptr &cookie, const HttpFileManager::invoker &cb, const string &strFile, const Parser &parser) { StrCaseMap httpHeader; if (cookie) { auto lck = cookie->getLock(); @@ -421,7 +421,7 @@ static void accessFile(TcpSession &sender, const Parser &parser, const MediaInfo } cb(code, HttpFileManager::getContentType(strFile.data()), headerOut, body); }; - invoker.responseFile(parser.getHeader(), httpHeader, strFile); + invoker.responseFile(parser.getHeader(), httpHeader, strFile, !is_hls); }; if (!is_hls) { @@ -576,7 +576,8 @@ HttpResponseInvokerImp::HttpResponseInvokerImp(const HttpResponseInvokerImp::Htt void HttpResponseInvokerImp::responseFile(const StrCaseMap &requestHeader, const StrCaseMap &responseHeader, - const string &filePath) const { + const string &filePath, + bool use_mmap) const { StrCaseMap &httpHeader = const_cast(responseHeader); std::shared_ptr fp(fopen(filePath.data(), "rb"), [](FILE *fp) { if (fp) { @@ -618,7 +619,7 @@ void HttpResponseInvokerImp::responseFile(const StrCaseMap &requestHeader, } //回复文件 - HttpBody::Ptr fileBody = std::make_shared(fp, iRangeStart, iRangeEnd - iRangeStart + 1); + HttpBody::Ptr fileBody = std::make_shared(fp, iRangeStart, iRangeEnd - iRangeStart + 1, use_mmap); (*this)(code, httpHeader, fileBody); } diff --git a/src/Http/HttpFileManager.h b/src/Http/HttpFileManager.h index 07993046..95781888 100644 --- a/src/Http/HttpFileManager.h +++ b/src/Http/HttpFileManager.h @@ -35,7 +35,7 @@ public: void operator()(int code, const StrCaseMap &headerOut, const HttpBody::Ptr &body) const; void operator()(int code, const StrCaseMap &headerOut, const string &body) const; - void responseFile(const StrCaseMap &requestHeader,const StrCaseMap &responseHeader,const string &filePath) const; + void responseFile(const StrCaseMap &requestHeader,const StrCaseMap &responseHeader,const string &filePath, bool use_mmap = true) const; operator bool(); private: HttpResponseInvokerLambda0 _lambad; diff --git a/src/Record/HlsMaker.cpp b/src/Record/HlsMaker.cpp index 84cd1e4d..afdb7357 100644 --- a/src/Record/HlsMaker.cpp +++ b/src/Record/HlsMaker.cpp @@ -132,8 +132,10 @@ void HlsMaker::flushLastSegment(bool eof){ _seg_dur_list.push_back(std::make_tuple(seg_dur, std::move(_last_file_name))); _last_file_name.clear(); delOldSegment(); - makeIndexFile(eof); + //先flush ts切片,否则可能存在ts文件未写入完毕就被访问的情况 onFlushLastSegment(seg_dur); + //然后写m3u8文件 + makeIndexFile(eof); } bool HlsMaker::isLive() { diff --git a/src/Record/HlsMakerImp.cpp b/src/Record/HlsMakerImp.cpp index 569dbac0..04995cb4 100644 --- a/src/Record/HlsMakerImp.cpp +++ b/src/Record/HlsMakerImp.cpp @@ -125,10 +125,11 @@ void HlsMakerImp::onWriteHls(const char *data, size_t len) { } void HlsMakerImp::onFlushLastSegment(uint32_t duration_ms) { + //关闭并flush文件到磁盘 + _file = nullptr; + GET_CONFIG(bool, broadcastRecordTs, Hls::kBroadcastRecordTs); if (broadcastRecordTs) { - //关闭ts文件以便获取正确的文件大小 - _file = nullptr; _info.time_len = duration_ms / 1000.0f; struct stat fileData; stat(_info.file_path.data(), &fileData);