From 188e087fc247452895b69881952a94f14dc19496 Mon Sep 17 00:00:00 2001 From: wxf Date: Sun, 13 Sep 2020 14:08:05 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20hls=20ts=20=E5=88=87?= =?UTF-8?q?=E7=89=87=E5=BD=95=E5=88=B6=E5=AE=8C=E6=88=90=E9=80=9A=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/WebHook.cpp | 22 ++++++++++++++++++++++ src/Common/config.cpp | 1 + src/Common/config.h | 4 ++++ src/Record/HlsMaker.cpp | 5 +++++ src/Record/HlsMaker.h | 20 ++++++++++++++++++++ src/Record/HlsMakerImp.cpp | 25 +++++++++++++++++++++++++ src/Record/HlsMakerImp.h | 2 ++ 7 files changed, 79 insertions(+) diff --git a/server/WebHook.cpp b/server/WebHook.cpp index 05943403..64c084e0 100644 --- a/server/WebHook.cpp +++ b/server/WebHook.cpp @@ -53,6 +53,7 @@ const string kOnRtspAuth = HOOK_FIELD"on_rtsp_auth"; const string kOnStreamChanged = HOOK_FIELD"on_stream_changed"; const string kOnStreamNotFound = HOOK_FIELD"on_stream_not_found"; const string kOnRecordMp4 = HOOK_FIELD"on_record_mp4"; +const string kOnRecordTs = HOOK_FIELD"on_record_ts"; const string kOnShellLogin = HOOK_FIELD"on_shell_login"; const string kOnStreamNoneReader = HOOK_FIELD"on_stream_none_reader"; const string kOnHttpAccess = HOOK_FIELD"on_http_access"; @@ -70,6 +71,7 @@ onceToken token([](){ mINI::Instance()[kOnStreamChanged] = "https://127.0.0.1/index/hook/on_stream_changed"; mINI::Instance()[kOnStreamNotFound] = "https://127.0.0.1/index/hook/on_stream_not_found"; mINI::Instance()[kOnRecordMp4] = "https://127.0.0.1/index/hook/on_record_mp4"; + mINI::Instance()[kOnRecordTs] = "https://127.0.0.1/index/hook/on_record_ts"; mINI::Instance()[kOnShellLogin] = "https://127.0.0.1/index/hook/on_shell_login"; mINI::Instance()[kOnStreamNoneReader] = "https://127.0.0.1/index/hook/on_stream_none_reader"; mINI::Instance()[kOnHttpAccess] = "https://127.0.0.1/index/hook/on_http_access"; @@ -190,6 +192,7 @@ void installWebHook(){ GET_CONFIG(string,hook_stream_chaned,Hook::kOnStreamChanged); GET_CONFIG(string,hook_stream_not_found,Hook::kOnStreamNotFound); GET_CONFIG(string,hook_record_mp4,Hook::kOnRecordMp4); + GET_CONFIG(string,hook_record_ts,Hook::kOnRecordTs); GET_CONFIG(string,hook_shell_login,Hook::kOnShellLogin); GET_CONFIG(string,hook_stream_none_reader,Hook::kOnStreamNoneReader); GET_CONFIG(string,hook_http_access,Hook::kOnHttpAccess); @@ -361,6 +364,25 @@ void installWebHook(){ }); #endif //ENABLE_MP4 + NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastRecordTs, [](BroadcastRecordTsArgs) { + if (!hook_enable || hook_record_ts.empty()) { + return; + } + ArgsType body; + body["start_time"] = (Json::UInt64)info.ui64StartedTime; + body["time_len"] = (Json::UInt64)info.ui64TimeLen; + body["file_size"] = (Json::UInt64)info.ui64FileSize; + body["file_path"] = info.strFilePath; + body["file_name"] = info.strFileName; + body["folder"] = info.strFolder; + body["url"] = info.strUrl; + body["app"] = info.strAppName; + body["stream"] = info.strStreamId; + body["vhost"] = info.strVhost; + // 执行 hook + do_http_hook(hook_record_ts, body, nullptr); + }); + NoticeCenter::Instance().addListener(nullptr,Broadcast::kBroadcastShellLogin,[](BroadcastShellLoginArgs){ if(!hook_enable || hook_shell_login.empty() || sender.get_peer_ip() == "127.0.0.1"){ invoker(""); diff --git a/src/Common/config.cpp b/src/Common/config.cpp index 69e7ed42..79520970 100644 --- a/src/Common/config.cpp +++ b/src/Common/config.cpp @@ -40,6 +40,7 @@ bool loadIniConfig(const char *ini_path){ namespace Broadcast { const string kBroadcastMediaChanged = "kBroadcastMediaChanged"; const string kBroadcastRecordMP4 = "kBroadcastRecordMP4"; +const string kBroadcastRecordTs = "kBroadcastRecoredTs"; const string kBroadcastHttpRequest = "kBroadcastHttpRequest"; const string kBroadcastHttpAccess = "kBroadcastHttpAccess"; const string kBroadcastOnGetRtspRealm = "kBroadcastOnGetRtspRealm"; diff --git a/src/Common/config.h b/src/Common/config.h index 0ebdf980..c3cf643b 100644 --- a/src/Common/config.h +++ b/src/Common/config.h @@ -60,6 +60,10 @@ extern const string kBroadcastMediaChanged; extern const string kBroadcastRecordMP4; #define BroadcastRecordMP4Args const MP4Info &info +// 录制 ts 文件后广播 +extern const string kBroadcastRecordTs; +#define BroadcastRecordTsArgs const TsInfo &info + //收到http api请求广播 extern const string kBroadcastHttpRequest; #define BroadcastHttpRequestArgs const Parser &parser,const HttpSession::HttpResponseInvoker &invoker,bool &consumed,SockInfo &sender diff --git a/src/Record/HlsMaker.cpp b/src/Record/HlsMaker.cpp index ff8ead52..f24a4308 100644 --- a/src/Record/HlsMaker.cpp +++ b/src/Record/HlsMaker.cpp @@ -120,6 +120,11 @@ void HlsMaker::flushLastSegment(uint32_t timestamp, bool eof){ delOldSegment(); makeIndexFile(eof); _last_file_name.clear(); + + onFlushLastSegment(seg_dur); +} + +void HlsMaker::onFlushLastSegment(uint32_t) { } bool HlsMaker::isLive() { diff --git a/src/Record/HlsMaker.h b/src/Record/HlsMaker.h index 37666b93..6b0e82d3 100644 --- a/src/Record/HlsMaker.h +++ b/src/Record/HlsMaker.h @@ -22,6 +22,20 @@ using namespace toolkit; namespace mediakit { +class TsInfo { +public: + time_t ui64StartedTime; // GMT 标准时间,单位秒 + time_t ui64TimeLen; // 录像长度,单位毫秒 + off_t ui64FileSize; // 文件大小,单位 BYTE + string strFilePath; // 文件路径 + string strFileName; // 文件名称 + string strFolder; // 文件夹路径 + string strUrl; // 播放路径 + string strAppName; // 应用名称 + string strStreamId; // 流 ID + string strVhost; // vhost +}; + class HlsMaker { public: /** @@ -85,6 +99,12 @@ protected: */ void flushLastSegment(uint32_t timestamp, bool eof = false); + /** + * 上一个 ts 切片写入完成, 可在这里进行通知处理 + * @param duration 上一个 ts 切片的时长, 单位为毫秒 + */ + virtual void onFlushLastSegment(uint32_t duration); + private: /** * 生成m3u8文件 diff --git a/src/Record/HlsMakerImp.cpp b/src/Record/HlsMakerImp.cpp index 4893687b..f3ac9bb6 100644 --- a/src/Record/HlsMakerImp.cpp +++ b/src/Record/HlsMakerImp.cpp @@ -8,7 +8,10 @@ * may be found in the AUTHORS file in the root of the source tree. */ +#include +#include #include "HlsMakerImp.h" +#include "Thread/WorkThreadPool.h" #include "Util/util.h" #include "Util/uv_errno.h" @@ -28,6 +31,8 @@ HlsMakerImp::HlsMakerImp(const string &m3u8_file, _file_buf.reset(new char[bufSize], [](char *ptr) { delete[] ptr; }); + + _info.strFolder = _path_prefix; } HlsMakerImp::~HlsMakerImp() { @@ -59,6 +64,12 @@ string HlsMakerImp::onOpenSegment(int index) { } } _file = makeFile(segment_path, true); + + _info.ui64StartedTime = ::time(NULL); + _info.strFileName = segment_name; + _info.strFilePath = segment_path; + _info.strUrl = _info.strAppName + "/" + _info.strStreamId + "/" + segment_name; + if (!_file) { WarnL << "create file failed," << segment_path << " " << get_uv_errmsg(); } @@ -97,6 +108,17 @@ void HlsMakerImp::onWriteHls(const char *data, int len) { //DebugL << "\r\n" << string(data,len); } +void HlsMakerImp::onFlushLastSegment(uint32_t duration) { + auto info = _info; + info.ui64TimeLen = duration; + WorkThreadPool::Instance().getExecutor()->async([info]() { + struct stat fileData; + stat(info.strFilePath.data(), &fileData); + const_cast(info).ui64FileSize = fileData.st_size; + NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastRecordTs, info); + }); +} + std::shared_ptr HlsMakerImp::makeFile(const string &file, bool setbuf) { auto file_buf = _file_buf; @@ -113,6 +135,9 @@ std::shared_ptr HlsMakerImp::makeFile(const string &file, bool setbuf) { void HlsMakerImp::setMediaSource(const string &vhost, const string &app, const string &stream_id) { _media_src = std::make_shared(vhost, app, stream_id); + _info.strAppName = app; + _info.strStreamId = stream_id; + _info.strVhost = vhost; } HlsMediaSource::Ptr HlsMakerImp::getMediaSource() const { diff --git a/src/Record/HlsMakerImp.h b/src/Record/HlsMakerImp.h index 7764644f..c914b89f 100644 --- a/src/Record/HlsMakerImp.h +++ b/src/Record/HlsMakerImp.h @@ -54,6 +54,7 @@ protected: void onDelSegment(int index) override; void onWriteSegment(const char *data, int len) override; void onWriteHls(const char *data, int len) override; + void onFlushLastSegment(uint32_t duration) override; private: std::shared_ptr makeFile(const string &file,bool setbuf = false); @@ -66,6 +67,7 @@ private: std::shared_ptr _file; std::shared_ptr _file_buf; HlsMediaSource::Ptr _media_src; + TsInfo _info; map _segment_file_paths; };