From 861be27ef89e0fac562324a7765f136d983131a6 Mon Sep 17 00:00:00 2001 From: ljx0305 Date: Tue, 26 Mar 2024 15:05:14 +0800 Subject: [PATCH 1/5] Fix compilation error issues (#3412) --- server/WebApi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/WebApi.cpp b/server/WebApi.cpp index edbf90bc..29fc773d 100755 --- a/server/WebApi.cpp +++ b/server/WebApi.cpp @@ -1918,7 +1918,7 @@ void installWebApi() { api_regist("/index/api/stack/start", [](API_ARGS_JSON_ASYNC) { CHECK_SECRET(); - auto ret = VideoStackManager::Instance().startVideoStack(allArgs.getArgs()); + auto ret = VideoStackManager::Instance().startVideoStack(allArgs.args()); val["code"] = ret; val["msg"] = ret ? "failed" : "success"; invoker(200, headerOut, val.toStyledString()); From ecc05dae282d4b5b1d72e8b1cac8caffa70efa7e Mon Sep 17 00:00:00 2001 From: xia-chu <771730766@qq.com> Date: Sat, 30 Mar 2024 14:04:32 +0800 Subject: [PATCH 2/5] BugFix: fix the issue where modifying the default secret resulted in HTTP api authentication failures --- server/main.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/server/main.cpp b/server/main.cpp index 8449f102..f418f2f8 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -258,6 +258,15 @@ int start_main(int argc,char *argv[]) { //加载配置文件,如果配置文件不存在就创建一个 loadIniConfig(g_ini_file.data()); + auto &secret = mINI::Instance()[API::kSecret]; + if (secret == "035c73f7-bb6b-4889-a715-d9eb2d1925cc" || secret.empty()) { + // 使用默认secret被禁止启动 + secret = makeRandStr(32, true); + mINI::Instance().dumpFile(g_ini_file); + WarnL << "The " << API::kSecret << " is invalid, modified it to: " << secret + << ", saved config file: " << g_ini_file; + } + if (!File::is_dir(ssl_file)) { // 不是文件夹,加载证书,证书包含公钥和私钥 SSL_Initor::Instance().loadCertificate(ssl_file.data()); @@ -352,14 +361,6 @@ int start_main(int argc,char *argv[]) { InfoL << "已启动http hook 接口"; try { - auto &secret = mINI::Instance()[API::kSecret]; - if (secret == "035c73f7-bb6b-4889-a715-d9eb2d1925cc" || secret.empty()) { - // 使用默认secret被禁止启动 - secret = makeRandStr(32, true); - mINI::Instance().dumpFile(g_ini_file); - WarnL << "The " << API::kSecret << " is invalid, modified it to: " << secret - << ", saved config file: " << g_ini_file; - } //rtsp服务器,端口默认554 if (rtspPort) { rtspSrv->start(rtspPort); } //rtsps服务器,端口默认322 From 390c3740869fb9d1164719cc6ed9967183fa9d8a Mon Sep 17 00:00:00 2001 From: xia-chu <771730766@qq.com> Date: Sat, 30 Mar 2024 14:41:20 +0800 Subject: [PATCH 3/5] Optimize the code 1. change param_strs to params 2. move params from MediaInfo to MediaTuple 3. passing MediaTuple as a parameter for some functions --- api/source/mk_events_objects.cpp | 2 +- server/WebHook.cpp | 6 +++--- src/Common/MediaSource.cpp | 9 +++++---- src/Common/MediaSource.h | 1 - src/Record/HlsMakerImp.cpp | 6 ++---- src/Record/HlsMakerImp.h | 5 +---- src/Record/HlsRecorder.h | 2 +- src/Record/MP4Recorder.cpp | 6 ++---- src/Record/MP4Recorder.h | 2 +- src/Record/Recorder.cpp | 6 ++---- src/Record/Recorder.h | 1 + srt/SrtTransportImp.cpp | 12 ++++++------ tests/test_server.cpp | 12 ++++++------ 13 files changed, 31 insertions(+), 39 deletions(-) diff --git a/api/source/mk_events_objects.cpp b/api/source/mk_events_objects.cpp index c30fd0cd..3f5bf711 100644 --- a/api/source/mk_events_objects.cpp +++ b/api/source/mk_events_objects.cpp @@ -130,7 +130,7 @@ API_EXPORT const char* API_CALL mk_parser_get_content(const mk_parser ctx, size_ API_EXPORT const char* API_CALL mk_media_info_get_params(const mk_media_info ctx){ assert(ctx); MediaInfo *info = (MediaInfo *)ctx; - return info->param_strs.c_str(); + return info->params.c_str(); } API_EXPORT const char* API_CALL mk_media_info_get_schema(const mk_media_info ctx){ diff --git a/server/WebHook.cpp b/server/WebHook.cpp index aa99a94c..aacee038 100755 --- a/server/WebHook.cpp +++ b/server/WebHook.cpp @@ -225,7 +225,7 @@ static ArgsType make_json(const MediaInfo &args) { ArgsType body; body["schema"] = args.schema; dumpMediaTuple(args, body); - body["params"] = args.param_strs; + body["params"] = args.params; return body; } @@ -286,7 +286,7 @@ static string getPullUrl(const string &origin_fmt, const MediaInfo &info) { return ""; } // 告知源站这是来自边沿站的拉流请求,如果未找到流请立即返回拉流失败 - return string(url) + '?' + kEdgeServerParam + '&' + VHOST_KEY + '=' + info.vhost + '&' + info.param_strs; + return string(url) + '?' + kEdgeServerParam + '&' + VHOST_KEY + '=' + info.vhost + '&' + info.params; } static void pullStreamFromOrigin(const vector &urls, size_t index, size_t failed_cnt, const MediaInfo &args, const function &closePlayer) { @@ -498,7 +498,7 @@ void installWebHook() { return; } - if (start_with(args.param_strs, kEdgeServerParam)) { + if (start_with(args.params, kEdgeServerParam)) { // 源站收到来自边沿站的溯源请求,流不存在时立即返回拉流失败 closePlayer(); return; diff --git a/src/Common/MediaSource.cpp b/src/Common/MediaSource.cpp index 184550e0..96ae22f5 100644 --- a/src/Common/MediaSource.cpp +++ b/src/Common/MediaSource.cpp @@ -583,7 +583,7 @@ void MediaInfo::parse(const std::string &url_in){ auto url = url_in; auto pos = url.find("?"); if (pos != string::npos) { - param_strs = url.substr(pos + 1); + params = url.substr(pos + 1); url.erase(pos); } @@ -616,9 +616,10 @@ void MediaInfo::parse(const std::string &url_in){ stream = stream_id; } - auto params = Parser::parseArgs(param_strs); - if (params.find(VHOST_KEY) != params.end()) { - vhost = params[VHOST_KEY]; + auto kv = Parser::parseArgs(params); + auto it = kv.find(VHOST_KEY); + if (it != kv.end()) { + vhost = it->second; } GET_CONFIG(bool, enableVhost, General::kEnableVhost); diff --git a/src/Common/MediaSource.h b/src/Common/MediaSource.h index b156954c..49f16dd4 100644 --- a/src/Common/MediaSource.h +++ b/src/Common/MediaSource.h @@ -299,7 +299,6 @@ public: std::string full_url; std::string schema; std::string host; - std::string param_strs; }; bool equalMediaTuple(const MediaTuple& a, const MediaTuple& b); diff --git a/src/Record/HlsMakerImp.cpp b/src/Record/HlsMakerImp.cpp index d62c4398..cbd19fb7 100644 --- a/src/Record/HlsMakerImp.cpp +++ b/src/Record/HlsMakerImp.cpp @@ -195,10 +195,8 @@ std::shared_ptr HlsMakerImp::makeFile(const string &file, bool setbuf) { return ret; } -void HlsMakerImp::setMediaSource(const string &vhost, const string &app, const string &stream_id) { - _info.app = app; - _info.stream = stream_id; - _info.vhost = vhost; +void HlsMakerImp::setMediaSource(const MediaTuple& tuple) { + static_cast(_info) = tuple; _media_src = std::make_shared(isFmp4() ? HLS_FMP4_SCHEMA : HLS_SCHEMA, _info); } diff --git a/src/Record/HlsMakerImp.h b/src/Record/HlsMakerImp.h index b3bf77b9..1485e8d3 100644 --- a/src/Record/HlsMakerImp.h +++ b/src/Record/HlsMakerImp.h @@ -27,11 +27,8 @@ public: /** * 设置媒体信息 - * @param vhost 虚拟主机 - * @param app 应用名 - * @param stream_id 流id */ - void setMediaSource(const std::string &vhost, const std::string &app, const std::string &stream_id); + void setMediaSource(const MediaTuple& tuple); /** * 获取MediaSource diff --git a/src/Record/HlsRecorder.h b/src/Record/HlsRecorder.h index f6e84bfb..26894ccf 100644 --- a/src/Record/HlsRecorder.h +++ b/src/Record/HlsRecorder.h @@ -34,7 +34,7 @@ public: } void setMediaSource(const MediaTuple& tuple) { - _hls->setMediaSource(tuple.vhost, tuple.app, tuple.stream); + _hls->setMediaSource(tuple); } void setListener(const std::weak_ptr &listener) { diff --git a/src/Record/MP4Recorder.cpp b/src/Record/MP4Recorder.cpp index c8cee016..4e40bab3 100644 --- a/src/Record/MP4Recorder.cpp +++ b/src/Record/MP4Recorder.cpp @@ -22,12 +22,10 @@ using namespace toolkit; namespace mediakit { -MP4Recorder::MP4Recorder(const string &path, const string &vhost, const string &app, const string &stream_id, size_t max_second) { +MP4Recorder::MP4Recorder(const MediaTuple &tuple, const string &path, size_t max_second) { _folder_path = path; /////record 业务逻辑////// - _info.app = app; - _info.stream = stream_id; - _info.vhost = vhost; + static_cast(_info) = tuple; _info.folder = path; GET_CONFIG(uint32_t, s_max_second, Protocol::kMP4MaxSecond); _max_second = max_second ? max_second : s_max_second; diff --git a/src/Record/MP4Recorder.h b/src/Record/MP4Recorder.h index 7b9deb65..e1258029 100644 --- a/src/Record/MP4Recorder.h +++ b/src/Record/MP4Recorder.h @@ -26,7 +26,7 @@ class MP4Recorder final : public MediaSinkInterface { public: using Ptr = std::shared_ptr; - MP4Recorder(const std::string &path, const std::string &vhost, const std::string &app, const std::string &stream_id, size_t max_second); + MP4Recorder(const MediaTuple &tuple, const std::string &path, size_t max_second); ~MP4Recorder() override; /** diff --git a/src/Record/Recorder.cpp b/src/Record/Recorder.cpp index 2d67fd16..51b9e031 100644 --- a/src/Record/Recorder.cpp +++ b/src/Record/Recorder.cpp @@ -68,8 +68,7 @@ string Recorder::getRecordPath(Recorder::type type, const MediaTuple& tuple, con } return File::absolutePath(m3u8FilePath, hlsPath); } - default: - return ""; + default: return ""; } } @@ -85,13 +84,12 @@ std::shared_ptr Recorder::createRecorder(type type, const Me #else throw std::invalid_argument("hls相关功能未打开,请开启ENABLE_HLS宏后编译再测试"); #endif - } case Recorder::type_mp4: { #if defined(ENABLE_MP4) auto path = Recorder::getRecordPath(type, tuple, option.mp4_save_path); - return std::make_shared(path, tuple.vhost, tuple.app, tuple.stream, option.mp4_max_second); + return std::make_shared(tuple, path, option.mp4_max_second); #else throw std::invalid_argument("mp4相关功能未打开,请开启ENABLE_MP4宏后编译再测试"); #endif diff --git a/src/Record/Recorder.h b/src/Record/Recorder.h index 57f439cd..ea924618 100644 --- a/src/Record/Recorder.h +++ b/src/Record/Recorder.h @@ -22,6 +22,7 @@ struct MediaTuple { std::string vhost; std::string app; std::string stream; + std::string params; std::string shortUrl() const { return vhost + '/' + app + '/' + stream; } diff --git a/srt/SrtTransportImp.cpp b/srt/SrtTransportImp.cpp index 8f818655..60c0b59b 100644 --- a/srt/SrtTransportImp.cpp +++ b/srt/SrtTransportImp.cpp @@ -63,8 +63,8 @@ void SrtTransportImp::onHandShakeFinished(std::string &streamid, struct sockaddr return; } - auto params = Parser::parseArgs(_media_info.param_strs); - if (params["m"] == "publish") { + auto kv = Parser::parseArgs(_media_info.params); + if (kv["m"] == "publish") { _is_pusher = true; _decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, this); emitOnPublish(); @@ -98,10 +98,10 @@ bool SrtTransportImp::parseStreamid(std::string &streamid) { app = tmps[0]; stream_name = tmps[1]; } else { - if (_media_info.param_strs.empty()) { - _media_info.param_strs = it.first + "=" + it.second; + if (_media_info.params.empty()) { + _media_info.params = it.first + "=" + it.second; } else { - _media_info.param_strs += "&" + it.first + "=" + it.second; + _media_info.params += "&" + it.first + "=" + it.second; } } } @@ -118,7 +118,7 @@ bool SrtTransportImp::parseStreamid(std::string &streamid) { _media_info.app = app; _media_info.stream = stream_name; - TraceL << " mediainfo=" << _media_info.shortUrl() << " params=" << _media_info.param_strs; + TraceL << " mediainfo=" << _media_info.shortUrl() << " params=" << _media_info.params; return true; } diff --git a/tests/test_server.cpp b/tests/test_server.cpp index d94ccbeb..0b3c93ef 100644 --- a/tests/test_server.cpp +++ b/tests/test_server.cpp @@ -90,7 +90,7 @@ void initEventListener() { static onceToken s_token([]() { //监听kBroadcastOnGetRtspRealm事件决定rtsp链接是否需要鉴权(传统的rtsp鉴权方案)才能访问 NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastOnGetRtspRealm, [](BroadcastOnGetRtspRealmArgs) { - DebugL << "RTSP是否需要鉴权事件:" << args.getUrl() << " " << args.param_strs; + DebugL << "RTSP是否需要鉴权事件:" << args.getUrl() << " " << args.params; if (string("1") == args.stream) { // live/1需要认证 //该流需要认证,并且设置realm @@ -104,7 +104,7 @@ void initEventListener() { //监听kBroadcastOnRtspAuth事件返回正确的rtsp鉴权用户密码 NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastOnRtspAuth, [](BroadcastOnRtspAuthArgs) { - DebugL << "RTSP播放鉴权:" << args.getUrl() << " " << args.param_strs; + DebugL << "RTSP播放鉴权:" << args.getUrl() << " " << args.params; DebugL << "RTSP用户:" << user_name << (must_no_encrypt ? " Base64" : " MD5") << " 方式登录"; string user = user_name; //假设我们异步读取数据库 @@ -134,14 +134,14 @@ void initEventListener() { //监听rtsp/rtmp推流事件,返回结果告知是否有推流权限 NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastMediaPublish, [](BroadcastMediaPublishArgs) { - DebugL << "推流鉴权:" << args.getUrl() << " " << args.param_strs; + DebugL << "推流鉴权:" << args.getUrl() << " " << args.params; invoker("", ProtocolOption());//鉴权成功 //invoker("this is auth failed message");//鉴权失败 }); //监听rtsp/rtsps/rtmp/http-flv播放事件,返回结果告知是否有播放权限(rtsp通过kBroadcastOnRtspAuth或此事件都可以实现鉴权) NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastMediaPlayed, [](BroadcastMediaPlayedArgs) { - DebugL << "播放鉴权:" << args.getUrl() << " " << args.param_strs; + DebugL << "播放鉴权:" << args.getUrl() << " " << args.params; invoker("");//鉴权成功 //invoker("this is auth failed message");//鉴权失败 }); @@ -183,13 +183,13 @@ void initEventListener() { * 你可以在这个事件触发时再去拉流,这样就可以实现按需拉流 * 拉流成功后,ZLMediaKit会把其立即转发给播放器(最大等待时间约为5秒,如果5秒都未拉流成功,播放器会播放失败) */ - DebugL << "未找到流事件:" << args.getUrl() << " " << args.param_strs; + DebugL << "未找到流事件:" << args.getUrl() << " " << args.params; }); //监听播放或推流结束时消耗流量事件 NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastFlowReport, [](BroadcastFlowReportArgs) { - DebugL << "播放器(推流器)断开连接事件:" << args.getUrl() << " " << args.param_strs << "\r\n使用流量:" << totalBytes << " bytes,连接时长:" << totalDuration << "秒"; + DebugL << "播放器(推流器)断开连接事件:" << args.getUrl() << " " << args.params << "\r\n使用流量:" << totalBytes << " bytes,连接时长:" << totalDuration << "秒"; }); From 0602cc0c0b23e8ee816616633562dca9c5faa960 Mon Sep 17 00:00:00 2001 From: xia-chu <771730766@qq.com> Date: Sat, 30 Mar 2024 14:46:39 +0800 Subject: [PATCH 4/5] Add 'params' field to MediaSource tuple information --- server/WebApi.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/server/WebApi.cpp b/server/WebApi.cpp index 29fc773d..034db359 100755 --- a/server/WebApi.cpp +++ b/server/WebApi.cpp @@ -389,6 +389,7 @@ void dumpMediaTuple(const MediaTuple &tuple, Json::Value& item) { item[VHOST_KEY] = tuple.vhost; item["app"] = tuple.app; item["stream"] = tuple.stream; + item["params"] = tuple.params; } Value makeMediaSourceJson(MediaSource &media){ From af3ef996b0ae265e000344e7faf753577f9abf4e Mon Sep 17 00:00:00 2001 From: xia-chu <771730766@qq.com> Date: Sat, 30 Mar 2024 14:59:28 +0800 Subject: [PATCH 5/5] Avoid build warnings in the main code --- CMakeLists.txt | 2 +- api/include/mk_events_objects.h | 10 +++++----- api/source/mk_events_objects.cpp | 10 +++++----- server/WebApi.cpp | 4 ++-- src/Common/MediaSource.cpp | 2 +- src/Record/MP4Reader.cpp | 2 +- src/Record/MP4Recorder.cpp | 2 +- tests/test_flv.cpp | 2 +- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1adefab1..72a4544e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,7 +191,7 @@ if(UNIX) set(COMPILE_OPTIONS_DEFAULT "-fPIC" "-Wall;-Wextra" - "-Wno-unused-function;-Wno-unused-parameter;-Wno-unused-variable" + "-Wno-unused-function;-Wno-unused-parameter;-Wno-unused-variable;-Wno-deprecated-declarations" "-Wno-error=extra;-Wno-error=missing-field-initializers;-Wno-error=type-limits") if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") diff --git a/api/include/mk_events_objects.h b/api/include/mk_events_objects.h index d44ed666..ddbaf87d 100644 --- a/api/include/mk_events_objects.h +++ b/api/include/mk_events_objects.h @@ -142,11 +142,11 @@ API_EXPORT void API_CALL mk_media_source_find(const char *schema, void *user_data, on_mk_media_source_find_cb cb); -API_EXPORT const mk_media_source API_CALL mk_media_source_find2(const char *schema, - const char *vhost, - const char *app, - const char *stream, - int from_mp4); +API_EXPORT mk_media_source API_CALL mk_media_source_find2(const char *schema, + const char *vhost, + const char *app, + const char *stream, + int from_mp4); //MediaSource::for_each_media() API_EXPORT void API_CALL mk_media_source_for_each(void *user_data, on_mk_media_source_find_cb cb, const char *schema, const char *vhost, const char *app, const char *stream); diff --git a/api/source/mk_events_objects.cpp b/api/source/mk_events_objects.cpp index 3f5bf711..7046f1ab 100644 --- a/api/source/mk_events_objects.cpp +++ b/api/source/mk_events_objects.cpp @@ -278,11 +278,11 @@ API_EXPORT void API_CALL mk_media_source_find(const char *schema, cb(user_data, (mk_media_source)src.get()); } -API_EXPORT const mk_media_source API_CALL mk_media_source_find2(const char *schema, - const char *vhost, - const char *app, - const char *stream, - int from_mp4) { +API_EXPORT mk_media_source API_CALL mk_media_source_find2(const char *schema, + const char *vhost, + const char *app, + const char *stream, + int from_mp4) { assert(schema && vhost && app && stream); auto src = MediaSource::find(schema, vhost, app, stream, from_mp4); return (mk_media_source)src.get(); diff --git a/server/WebApi.cpp b/server/WebApi.cpp index 034db359..faac203d 100755 --- a/server/WebApi.cpp +++ b/server/WebApi.cpp @@ -1564,7 +1564,7 @@ void installWebApi() { api_regist("/index/api/deleteRecordDirectory", [](API_ARGS_MAP) { CHECK_SECRET(); CHECK_ARGS("vhost", "app", "stream", "period"); - auto tuple = MediaTuple{allArgs["vhost"], allArgs["app"], allArgs["stream"]}; + auto tuple = MediaTuple{allArgs["vhost"], allArgs["app"], allArgs["stream"], ""}; auto record_path = Recorder::getRecordPath(Recorder::type_mp4, tuple, allArgs["customized_path"]); auto period = allArgs["period"]; record_path = record_path + period + "/"; @@ -1603,7 +1603,7 @@ void installWebApi() { api_regist("/index/api/getMP4RecordFile", [](API_ARGS_MAP){ CHECK_SECRET(); CHECK_ARGS("vhost", "app", "stream"); - auto tuple = MediaTuple{allArgs["vhost"], allArgs["app"], allArgs["stream"]}; + auto tuple = MediaTuple{allArgs["vhost"], allArgs["app"], allArgs["stream"], ""}; auto record_path = Recorder::getRecordPath(Recorder::type_mp4, tuple, allArgs["customized_path"]); auto period = allArgs["period"]; diff --git a/src/Common/MediaSource.cpp b/src/Common/MediaSource.cpp index 96ae22f5..8de8202a 100644 --- a/src/Common/MediaSource.cpp +++ b/src/Common/MediaSource.cpp @@ -113,7 +113,7 @@ ProtocolOption::ProtocolOption() { ////////////////////////////////////////////////////////////////////////////////////////////////////////////// struct MediaSourceNull : public MediaSource { - MediaSourceNull() : MediaSource("schema", MediaTuple{"vhost", "app", "stream"}) {}; + MediaSourceNull() : MediaSource("schema", MediaTuple{"vhost", "app", "stream", ""}) {}; int readerCount() override { return 0; } }; diff --git a/src/Record/MP4Reader.cpp b/src/Record/MP4Reader.cpp index e70f9fe8..6437fcff 100644 --- a/src/Record/MP4Reader.cpp +++ b/src/Record/MP4Reader.cpp @@ -38,7 +38,7 @@ MP4Reader::MP4Reader(const std::string &vhost, const std::string &app, const std void MP4Reader::setup(const std::string &vhost, const std::string &app, const std::string &stream_id, const std::string &file_path, const ProtocolOption &option, toolkit::EventPoller::Ptr poller) { //读写文件建议放在后台线程 - auto tuple = MediaTuple{vhost, app, stream_id}; + auto tuple = MediaTuple{vhost, app, stream_id, ""}; _poller = poller ? std::move(poller) : WorkThreadPool::Instance().getPoller(); _file_path = file_path; if (_file_path.empty()) { diff --git a/src/Record/MP4Recorder.cpp b/src/Record/MP4Recorder.cpp index 4e40bab3..cd55d30a 100644 --- a/src/Record/MP4Recorder.cpp +++ b/src/Record/MP4Recorder.cpp @@ -118,7 +118,7 @@ bool MP4Recorder::inputFrame(const Frame::Ptr &frame) { //b帧情况下dts时间戳可能回退 _last_dts = MAX(frame->dts(), _last_dts); } - auto duration = 5; // 默认至少一帧5ms + auto duration = 5u; // 默认至少一帧5ms if (frame->dts() > 0 && frame->dts() > _last_dts) { duration = MAX(duration, frame->dts() - _last_dts); } diff --git a/tests/test_flv.cpp b/tests/test_flv.cpp index 49b78865..cf838822 100644 --- a/tests/test_flv.cpp +++ b/tests/test_flv.cpp @@ -27,7 +27,7 @@ using namespace mediakit; class FlvSplitterImp : public FlvSplitter { public: FlvSplitterImp() { - _src = std::make_shared(MediaTuple{DEFAULT_VHOST, "live", "test"}); + _src = std::make_shared(MediaTuple{DEFAULT_VHOST, "live", "test", ""}); } ~FlvSplitterImp() override = default;