From 99333986146e5b29ca6555a0d2a5584e9a8dd297 Mon Sep 17 00:00:00 2001 From: waken <33921191+mc373906408@users.noreply.github.com> Date: Wed, 13 Dec 2023 17:41:57 +0800 Subject: [PATCH 01/25] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E5=85=B3=E9=97=ADGB28181=E6=97=B6=E5=BC=95=E5=8F=91=E7=9A=84?= =?UTF-8?q?=E5=B4=A9=E6=BA=83=E9=97=AE=E9=A2=98=20=20(#3118)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix #3116 #3115 --- postman/ZLMediaKit.postman_collection.json | 2 +- src/Extension/Factory.cpp | 3 +++ src/Rtp/Decoder.cpp | 4 ++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/postman/ZLMediaKit.postman_collection.json b/postman/ZLMediaKit.postman_collection.json index 1111850f..59840416 100644 --- a/postman/ZLMediaKit.postman_collection.json +++ b/postman/ZLMediaKit.postman_collection.json @@ -2252,4 +2252,4 @@ "value": "__defaultVhost__" } ] -} \ No newline at end of file +} diff --git a/src/Extension/Factory.cpp b/src/Extension/Factory.cpp index f69eead7..9904a784 100644 --- a/src/Extension/Factory.cpp +++ b/src/Extension/Factory.cpp @@ -205,6 +205,9 @@ Frame::Ptr Factory::getFrameFromPtr(CodecId codec, const char *data, size_t byte Frame::Ptr Factory::getFrameFromBuffer(CodecId codec, Buffer::Ptr data, uint64_t dts, uint64_t pts) { auto frame = Factory::getFrameFromPtr(codec, data->data(), data->size(), dts, pts); + if(!frame){ + return nullptr; + } return std::make_shared(frame, false, std::move(data)); } diff --git a/src/Rtp/Decoder.cpp b/src/Rtp/Decoder.cpp index 65dc655c..dacd3ab5 100644 --- a/src/Rtp/Decoder.cpp +++ b/src/Rtp/Decoder.cpp @@ -110,6 +110,10 @@ void DecoderImp::onDecode(int stream, int codecid, int flags, int64_t pts, int64 if (!ref.first) { onTrack(stream, Factory::getTrackByCodecId(codec, 8000, 1, 16)); } + if (!ref.first) { + WarnL << "not support codec :" << getCodecName(codec); + return; + } auto frame = Factory::getFrameFromPtr(codec, (char *)data, bytes, dts, pts); if (getTrackType(codec) != TrackVideo) { onFrame(stream, frame); From 07f3c6dde4cb4b8e68e1bce59e061ceb874823cb Mon Sep 17 00:00:00 2001 From: PioLing <964472638@qq.com> Date: Thu, 14 Dec 2023 14:14:50 +0800 Subject: [PATCH 02/25] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E4=B8=8D=E6=94=AF=E6=8C=81codec=E7=9A=84frame=20(#3126)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Extension/Factory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Extension/Factory.cpp b/src/Extension/Factory.cpp index 9904a784..49feeb94 100644 --- a/src/Extension/Factory.cpp +++ b/src/Extension/Factory.cpp @@ -197,8 +197,8 @@ AMFValue Factory::getAmfByCodecId(CodecId codecId) { Frame::Ptr Factory::getFrameFromPtr(CodecId codec, const char *data, size_t bytes, uint64_t dts, uint64_t pts) { auto it = s_plugins.find(codec); if (it == s_plugins.end()) { - WarnL << "Unsupported codec: " << getCodecName(codec); - return nullptr; + // 创建不支持codec的frame + return std::make_shared(codec, (char *)data, bytes, dts, pts); } return it->second->getFrameFromPtr(data, bytes, dts, pts); } From c0bb7db4762c11db98b620f5172e30b0344b8e08 Mon Sep 17 00:00:00 2001 From: xia-chu <771730766@qq.com> Date: Thu, 14 Dec 2023 17:28:21 +0800 Subject: [PATCH 03/25] BugFix: crash when FrameMerger::flush In a lambda expression, temporary stack variables should not be captured; otherwise, the variables may have become invalid when FrameMerger::flush is called. --- src/Record/MP4Muxer.cpp | 2 +- src/Record/MPEG.cpp | 2 +- src/Rtp/Decoder.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Record/MP4Muxer.cpp b/src/Record/MP4Muxer.cpp index 37c6cfd7..5d40be1d 100644 --- a/src/Record/MP4Muxer.cpp +++ b/src/Record/MP4Muxer.cpp @@ -104,7 +104,7 @@ bool MP4MuxerInterface::inputFrame(const Frame::Ptr &frame) { case CodecH264: case CodecH265: { // 这里的代码逻辑是让SPS、PPS、IDR这些时间戳相同的帧打包到一起当做一个帧处理, - track.merger.inputFrame(frame, [&](uint64_t dts, uint64_t pts, const Buffer::Ptr &buffer, bool have_idr) { + track.merger.inputFrame(frame, [this, &track](uint64_t dts, uint64_t pts, const Buffer::Ptr &buffer, bool have_idr) { int64_t dts_out, pts_out; track.stamp.revise(dts, pts, dts_out, pts_out); mp4_writer_write(_mov_writter.get(), track.track_id, buffer->data(), buffer->size(), pts_out, dts_out, have_idr ? MOV_AV_FLAG_KEYFREAME : 0); diff --git a/src/Record/MPEG.cpp b/src/Record/MPEG.cpp index ef844277..bca086dc 100644 --- a/src/Record/MPEG.cpp +++ b/src/Record/MPEG.cpp @@ -55,7 +55,7 @@ bool MpegMuxer::inputFrame(const Frame::Ptr &frame) { case CodecH264: case CodecH265: { // 这里的代码逻辑是让SPS、PPS、IDR这些时间戳相同的帧打包到一起当做一个帧处理, - return track.merger.inputFrame(frame, [&](uint64_t dts, uint64_t pts, const Buffer::Ptr &buffer, bool have_idr) { + return track.merger.inputFrame(frame, [this, &track](uint64_t dts, uint64_t pts, const Buffer::Ptr &buffer, bool have_idr) { _key_pos = have_idr; // 取视频时间戳为TS的时间戳 _timestamp = dts; diff --git a/src/Rtp/Decoder.cpp b/src/Rtp/Decoder.cpp index dacd3ab5..ca4b20b7 100644 --- a/src/Rtp/Decoder.cpp +++ b/src/Rtp/Decoder.cpp @@ -111,7 +111,7 @@ void DecoderImp::onDecode(int stream, int codecid, int flags, int64_t pts, int64 onTrack(stream, Factory::getTrackByCodecId(codec, 8000, 1, 16)); } if (!ref.first) { - WarnL << "not support codec :" << getCodecName(codec); + WarnL << "Unsupported codec :" << getCodecName(codec); return; } auto frame = Factory::getFrameFromPtr(codec, (char *)data, bytes, dts, pts); @@ -119,7 +119,7 @@ void DecoderImp::onDecode(int stream, int codecid, int flags, int64_t pts, int64 onFrame(stream, frame); return; } - ref.second.inputFrame(frame, [&](uint64_t dts, uint64_t pts, const Buffer::Ptr &buffer, bool) { + ref.second.inputFrame(frame, [this, stream, codec](uint64_t dts, uint64_t pts, const Buffer::Ptr &buffer, bool) { onFrame(stream, Factory::getFrameFromBuffer(codec, buffer, dts, pts)); }); } From a72d87cca7d836a1850aaa22bfb4e003fb8ff0b9 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Fri, 15 Dec 2023 16:46:43 +0800 Subject: [PATCH 04/25] BugFix: MediaSource unregister after 3 seconds after calling close_streams (#3132) To avoid frequent creation and destruction of UdpSession, RtpSession will be destructed 3 seconds after triggering onError. --- src/Rtp/RtpSession.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Rtp/RtpSession.cpp b/src/Rtp/RtpSession.cpp index 85f0c2fb..40db50f3 100644 --- a/src/Rtp/RtpSession.cpp +++ b/src/Rtp/RtpSession.cpp @@ -46,11 +46,7 @@ RtpSession::RtpSession(const Socket::Ptr &sock) } } -RtpSession::~RtpSession() { - if (_process) { - RtpSelector::Instance().delProcess(_stream_id, _process.get()); - } -} +RtpSession::~RtpSession() = default; void RtpSession::onRecv(const Buffer::Ptr &data) { if (_is_udp) { @@ -62,6 +58,9 @@ void RtpSession::onRecv(const Buffer::Ptr &data) { void RtpSession::onError(const SockException &err) { WarnP(this) << _stream_id << " " << err; + if (_process) { + RtpSelector::Instance().delProcess(_stream_id, _process.get()); + } } void RtpSession::onManager() { From 189f787746a2dd4a626dca8742ea66369cf975ae Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sun, 17 Dec 2023 18:10:47 +0800 Subject: [PATCH 05/25] Disable enhanced-rtmp H265 default --- conf/config.ini | 2 +- src/Common/config.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/config.ini b/conf/config.ini index d1d8246c..d690b1f8 100644 --- a/conf/config.ini +++ b/conf/config.ini @@ -289,7 +289,7 @@ sslport=0 # rtmp是否直接代理模式 directProxy=1 #h265 rtmp打包采用增强型rtmp标准还是国内拓展标准 -enhanced=1 +enhanced=0 [rtp] #音频mtu大小,该参数限制rtp最大字节数,推荐不要超过1400 diff --git a/src/Common/config.cpp b/src/Common/config.cpp index 82b3feca..c345350d 100644 --- a/src/Common/config.cpp +++ b/src/Common/config.cpp @@ -242,7 +242,7 @@ static onceToken token([]() { mINI::Instance()[kHandshakeSecond] = 15; mINI::Instance()[kKeepAliveSecond] = 15; mINI::Instance()[kDirectProxy] = 1; - mINI::Instance()[kEnhanced] = 1; + mINI::Instance()[kEnhanced] = 0; }); } // namespace Rtmp From f1923f0076f8d28e308d011f0fe0b7630602135e Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sun, 17 Dec 2023 18:13:51 +0800 Subject: [PATCH 06/25] Ignore the http connection which calling kick_sessions http api --- server/WebApi.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/server/WebApi.cpp b/server/WebApi.cpp index 44da3e5c..aa3df337 100755 --- a/server/WebApi.cpp +++ b/server/WebApi.cpp @@ -944,25 +944,29 @@ void installWebApi() { //批量断开tcp连接,比如说可以断开rtsp、rtmp播放器等 //测试url http://127.0.0.1/index/api/kick_sessions?local_port=1935 - api_regist("/index/api/kick_sessions",[](API_ARGS_MAP){ + api_regist("/index/api/kick_sessions", [](API_ARGS_MAP) { CHECK_SECRET(); uint16_t local_port = allArgs["local_port"].as(); string peer_ip = allArgs["peer_ip"]; size_t count_hit = 0; list session_list; - SessionMap::Instance().for_each_session([&](const string &id,const Session::Ptr &session){ - if(local_port != 0 && local_port != session->get_local_port()){ + SessionMap::Instance().for_each_session([&](const string &id, const Session::Ptr &session) { + if (local_port != 0 && local_port != session->get_local_port()) { return; } - if(!peer_ip.empty() && peer_ip != session->get_peer_ip()){ + if (!peer_ip.empty() && peer_ip != session->get_peer_ip()) { + return; + } + if (session->getIdentifier() == sender.getIdentifier()) { + // 忽略本http链接 return; } session_list.emplace_back(session); ++count_hit; }); - for(auto &session : session_list){ + for (auto &session : session_list) { session->safeShutdown(); } val["count_hit"] = (Json::UInt64)count_hit; From e593ef5fefb5f2861fd43228788f847ed5368abc Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sun, 17 Dec 2023 18:22:58 +0800 Subject: [PATCH 07/25] Change av_image_fill_arrays align size from 1 to 32 To avoid crash in some cases --- src/Codec/Transcode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Codec/Transcode.cpp b/src/Codec/Transcode.cpp index aaa641fe..c1878216 100644 --- a/src/Codec/Transcode.cpp +++ b/src/Codec/Transcode.cpp @@ -673,7 +673,7 @@ FFmpegFrame::Ptr FFmpegSws::inputFrame(const FFmpegFrame::Ptr &frame, int &ret, auto out = std::make_shared(); if (!out->get()->data[0]) { if (data) { - av_image_fill_arrays(out->get()->data, out->get()->linesize, data, _target_format, target_width, target_height, 1); + av_image_fill_arrays(out->get()->data, out->get()->linesize, data, _target_format, target_width, target_height, 32); } else { out->fillPicture(_target_format, target_width, target_height); } From c7f2f9e883731f7fc6afd5570dd3e77183efd564 Mon Sep 17 00:00:00 2001 From: PioLing <964472638@qq.com> Date: Mon, 18 Dec 2023 16:28:00 +0800 Subject: [PATCH 08/25] Change fillPicture (av_image_fill_arrays() ) align size from 1 to 32 (#3142) --- src/Codec/Transcode.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Codec/Transcode.cpp b/src/Codec/Transcode.cpp index c1878216..daffe5ac 100644 --- a/src/Codec/Transcode.cpp +++ b/src/Codec/Transcode.cpp @@ -244,8 +244,8 @@ AVFrame *FFmpegFrame::get() const { void FFmpegFrame::fillPicture(AVPixelFormat target_format, int target_width, int target_height) { assert(_data == nullptr); - _data = new char[av_image_get_buffer_size(target_format, target_width, target_height, 1)]; - av_image_fill_arrays(_frame->data, _frame->linesize, (uint8_t *) _data, target_format, target_width, target_height,1); + _data = new char[av_image_get_buffer_size(target_format, target_width, target_height, 32)]; + av_image_fill_arrays(_frame->data, _frame->linesize, (uint8_t *) _data, target_format, target_width, target_height, 32); } /////////////////////////////////////////////////////////////////////////// From a17b950b21d6dfddead07a14c09cf53998c8d69c Mon Sep 17 00:00:00 2001 From: chdahuzi Date: Wed, 20 Dec 2023 19:32:49 +0800 Subject: [PATCH 09/25] Install http api and hook before starting the service listener (#3149) We have found that sometimes, when starting zlmediakit, stream push requests may be received before the hook is ready. --- server/main.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/server/main.cpp b/server/main.cpp index 1b2f4b1a..c946beab 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -346,6 +346,11 @@ int start_main(int argc,char *argv[]) { uint16_t srtPort = mINI::Instance()[SRT::kPort]; #endif //defined(ENABLE_SRT) + installWebApi(); + InfoL << "已启动http api 接口"; + installWebHook(); + InfoL << "已启动http hook 接口"; + try { auto &secret = mINI::Instance()[API::kSecret]; if (secret == "035c73f7-bb6b-4889-a715-d9eb2d1925cc" || secret.empty()) { @@ -403,11 +408,6 @@ int start_main(int argc,char *argv[]) { return -1; } - installWebApi(); - InfoL << "已启动http api 接口"; - installWebHook(); - InfoL << "已启动http hook 接口"; - //设置退出信号处理函数 static semaphore sem; signal(SIGINT, [](int) { From 8f4e76406c6a9339f41f5b6122f5b73c0570b280 Mon Sep 17 00:00:00 2001 From: snysmtx Date: Fri, 22 Dec 2023 17:40:42 +0800 Subject: [PATCH 10/25] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=BC=96=E8=AF=91=20rp?= =?UTF-8?q?m=20=E6=97=B6=E8=8E=B7=E5=8F=96=E8=B0=83=E8=AF=95=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E5=A4=B1=E8=B4=A5=E9=97=AE=E9=A2=98=20(#3151)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Release 8.0 之后, 编译 rpm 会出现获取调试信息失败问题, 导致 rpm 打包失败 虽然说可以禁用调试包生成来规避问题, 但个人认为在编译 DEBUG 版本时生成调试信息包还是有必要的 --- CMakeLists.txt | 6 ++++++ package/rpm/ZLMediaKit.spec | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b9dbfa64..64157b7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -193,6 +193,12 @@ if(UNIX) "-Wall;-Wextra" "-Wno-unused-function;-Wno-unused-parameter;-Wno-unused-variable" "-Wno-error=extra;-Wno-error=missing-field-initializers;-Wno-error=type-limits") + + if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") + set(COMPILE_OPTIONS_DEFAULT ${COMPILE_OPTIONS_DEFAULT} "-g3") + else() + set(COMPILE_OPTIONS_DEFAULT ${COMPILE_OPTIONS_DEFAULT} "-g0") + endif() elseif(WIN32) if (MSVC) set(COMPILE_OPTIONS_DEFAULT diff --git a/package/rpm/ZLMediaKit.spec b/package/rpm/ZLMediaKit.spec index 9ff902d6..f26aba10 100644 --- a/package/rpm/ZLMediaKit.spec +++ b/package/rpm/ZLMediaKit.spec @@ -18,7 +18,7 @@ %bcond_with cxx_api Name: ZLMediaKit -Version: 5.0.0 +Version: 8.0.0 Release: 1%{?dist} Summary: A lightweight, high performance and stable stream server and client framework based on C++11. From 9d68b668fce86cf5174630ef88e4c894f7eab8da Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Sat, 23 Dec 2023 21:27:28 +0800 Subject: [PATCH 11/25] Add http pipelining request support (#3154) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support recv multi http request before reponse it. Co-authored-by: 夏楚 <771730766@qq.com> --- src/Http/HttpSession.cpp | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/src/Http/HttpSession.cpp b/src/Http/HttpSession.cpp index 38eb5473..a593cc62 100644 --- a/src/Http/HttpSession.cpp +++ b/src/Http/HttpSession.cpp @@ -124,29 +124,18 @@ ssize_t HttpSession::onRecvHeader(const char *header, size_t len) { } //// body size明确指定且小于最大值的情况 //// - auto body = std::make_shared(); - // 预留一定的内存buffer,防止频繁的内存拷贝 - body->reserve(content_len); - - _on_recv_body = [this, body, content_len, it](const char *data, size_t len) mutable { - body->append(data, len); - if (body->size() < content_len) { - // 未收满数据 - return true; - } - + _on_recv_body = [this, it](const char *data, size_t len) mutable { // 收集body完毕 - _parser.setContent(std::move(*body)); + _parser.setContent(std::string(data, len)); (this->*(it->second))(); _parser.clear(); - // 后续是header - setContentLen(0); + // _on_recv_body置空 return false; }; - // 声明后续都是body;Http body在本对象缓冲,不通过HttpRequestSplitter保存 - return -1; + // 声明body长度,通过HttpRequestSplitter缓存然后一次性回调到_on_recv_body + return content_len; } void HttpSession::onRecvContent(const char *data, size_t len) { From bcf0c719f103d86d0c9c92e5b297808a76dfa1ff Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sat, 23 Dec 2023 21:32:24 +0800 Subject: [PATCH 12/25] Update ZLToolKit --- 3rdpart/ZLToolKit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdpart/ZLToolKit b/3rdpart/ZLToolKit index 9a545d7d..6a8bdfc8 160000 --- a/3rdpart/ZLToolKit +++ b/3rdpart/ZLToolKit @@ -1 +1 @@ -Subproject commit 9a545d7d09fc4b570c1d29a798622c7923111735 +Subproject commit 6a8bdfc80db3930d2ba8067d06db467dad8baddf From 7c42ac4d79d310f52f40673b31d3499fc8cd5518 Mon Sep 17 00:00:00 2001 From: Dw9 Date: Fri, 29 Dec 2023 10:53:47 +0800 Subject: [PATCH 13/25] Set the default port for WebRTC (#3175) Set the default port for WebRTC to 8000 to prevent the generated default configuration file from disabling WebRTC features. --- webrtc/WebRtcTransport.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/webrtc/WebRtcTransport.cpp b/webrtc/WebRtcTransport.cpp index 685e9f89..7fc8816e 100644 --- a/webrtc/WebRtcTransport.cpp +++ b/webrtc/WebRtcTransport.cpp @@ -59,8 +59,8 @@ static onceToken token([]() { mINI::Instance()[kTimeOutSec] = 15; mINI::Instance()[kExternIP] = ""; mINI::Instance()[kRembBitRate] = 0; - mINI::Instance()[kPort] = 0; - mINI::Instance()[kTcpPort] = 0; + mINI::Instance()[kPort] = 8000; + mINI::Instance()[kTcpPort] = 8000; mINI::Instance()[kStartBitrate] = 0; mINI::Instance()[kMaxBitrate] = 0; @@ -1380,4 +1380,4 @@ static onceToken s_rtc_auto_register([]() { }); }); -}// namespace mediakit \ No newline at end of file +}// namespace mediakit From a106f8dfc00e04ff5f677fb62ee7be1e54ed65ac Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sun, 31 Dec 2023 22:10:13 +0800 Subject: [PATCH 14/25] Avoid blocking the poller thread --- tests/test_rtp.cpp | 139 ++++++++++++++++++++++----------------------- 1 file changed, 68 insertions(+), 71 deletions(-) diff --git a/tests/test_rtp.cpp b/tests/test_rtp.cpp index 5bdffa12..9bb7e4bc 100644 --- a/tests/test_rtp.cpp +++ b/tests/test_rtp.cpp @@ -10,11 +10,8 @@ #include #include -#include "Util/MD5.h" -#include "Util/File.h" -#include "Util/logger.h" -#include "Util/SSLBox.h" #include "Util/util.h" +#include "Util/logger.h" #include "Network/TcpServer.h" #include "Common/config.h" #include "Rtsp/RtspSession.h" @@ -29,102 +26,102 @@ using namespace mediakit; static semaphore sem; #if defined(ENABLE_RTPPROXY) -static bool loadFile(const char *path, const EventPoller::Ptr &poller){ - FILE *fp = fopen(path, "rb"); +static bool loadFile(const char *path, const EventPoller::Ptr &poller) { + std::shared_ptr fp(fopen(path, "rb"), [](FILE *fp) { + sem.post(); + if (fp) { + fclose(fp); + } + }); if (!fp) { WarnL << "open file failed:" << path; return false; } - uint64_t timeStamp_last = 0; - uint16_t len; - char rtp[0xFFFF]; struct sockaddr_storage addr; memset(&addr, 0, sizeof(addr)); addr.ss_family = AF_INET; auto sock = Socket::createSocket(poller); - size_t total_size = 0; - RtpProcess::Ptr process; - uint32_t ssrc = 0; - while (true) { - if (2 != fread(&len, 1, 2, fp)) { - WarnL; - break; - } - len = ntohs(len); - if (len < 12 || len > sizeof(rtp)) { - WarnL << len; - break; - } + auto process = RtpSelector::Instance().getProcess("test", true); - if (len != fread(rtp, 1, len, fp)) { - WarnL; - break; - } - total_size += len; - uint64_t timeStamp = 0; - - if (!process) { - if (!RtpSelector::getSSRC(rtp, len, ssrc)) { - WarnL << "get ssrc from rtp failed:" << len; - return false; + uint64_t stamp_last = 0; + auto total_size = std::make_shared(0); + auto do_read = [fp, total_size, sock, addr, process, stamp_last]() mutable -> int { + uint16_t len; + char rtp[0xFFFF]; + while (true) { + if (2 != fread(&len, 1, 2, fp.get())) { + WarnL << "Read rtp size failed"; + // 重新播放 + fseek(fp.get(), 0, SEEK_SET); + return 1; } - process = RtpSelector::Instance().getProcess(printSSRC(ssrc), true); - } - if (process) { + len = ntohs(len); + if (len < 12 || len > sizeof(rtp)) { + WarnL << "Invalid rtp size: " << len; + return 0; + } + + if (len != fread(rtp, 1, len, fp.get())) { + WarnL << "Read rtp data failed"; + return 0; + } + (*total_size) += len; + uint64_t stamp = 0; try { - process->inputRtp(true, sock, rtp, len, (struct sockaddr *)&addr, &timeStamp); - } catch (...) { - RtpSelector::Instance().delProcess(printSSRC(ssrc), process.get()); - throw; + process->inputRtp(true, sock, rtp, len, (struct sockaddr *)&addr, &stamp); + } catch (std::exception &ex) { + WarnL << "Input rtp failed: " << ex.what(); + return 0; + } + + auto diff = stamp - stamp_last; + if (diff < 0 || diff > 500) { + diff = 1; + } + if (diff) { + stamp_last = stamp; + return diff; } } - - auto diff = timeStamp - timeStamp_last; - if (diff > 0 && diff < 500) { - usleep(diff * 1000); - } else { - usleep(1 * 1000); + }; + poller->doDelayTask(1, [do_read, total_size, process]() mutable { + auto ret = do_read(); + if (!ret) { + WarnL << *total_size / 1024 << "KB"; + RtpSelector::Instance().delProcess("test", process.get()); } - timeStamp_last = timeStamp; - } - WarnL << total_size / 1024 << "KB"; - fclose(fp); + return ret; + }); + return true; } -#endif//#if defined(ENABLE_RTPPROXY) +#endif // #if defined(ENABLE_RTPPROXY) -int main(int argc,char *argv[]) { - //设置日志 +int main(int argc, char *argv[]) { + // 设置日志 Logger::Instance().add(std::make_shared("ConsoleChannel")); #if defined(ENABLE_RTPPROXY) - //启动异步日志线程 + // 启动异步日志线程 Logger::Instance().setWriter(std::make_shared()); loadIniConfig((exeDir() + "config.ini").data()); TcpServer::Ptr rtspSrv(new TcpServer()); TcpServer::Ptr rtmpSrv(new TcpServer()); TcpServer::Ptr httpSrv(new TcpServer()); - rtspSrv->start(554);//默认554 - rtmpSrv->start(1935);//默认1935 - httpSrv->start(80);//默认80 - //此处选择是否导出调试文件 -// mINI::Instance()[RtpProxy::kDumpDir] = "/Users/xzl/Desktop/"; + rtspSrv->start(554); // 默认554 + rtmpSrv->start(1935); // 默认1935 + httpSrv->start(80); // 默认80 + // 此处选择是否导出调试文件 + // mINI::Instance()[RtpProxy::kDumpDir] = "/Users/xzl/Desktop/"; - if (argc == 2){ - auto poller = EventPollerPool::Instance().getPoller(); - poller->async_first([poller,argv](){ - loadFile(argv[1],poller); - sem.post(); - }); + if (argc == 2) { + loadFile(argv[1], EventPollerPool::Instance().getPoller()); sem.wait(); - sleep(1); + } else { + ErrorL << "parameter error."; } - else - ErrorL << "parameter error."; #else ErrorL << "please ENABLE_RTPPROXY and then test"; -#endif//#if defined(ENABLE_RTPPROXY) +#endif // #if defined(ENABLE_RTPPROXY) return 0; } - - From f382f1fa958139abfdeea080a43c2122dbcb83ce Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sun, 31 Dec 2023 22:14:58 +0800 Subject: [PATCH 15/25] Replacing switch case with codec map Prevent the occurrence of multiple case with same value --- src/Extension/Frame.cpp | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/Extension/Frame.cpp b/src/Extension/Frame.cpp index c58ea84b..6daafda5 100644 --- a/src/Extension/Frame.cpp +++ b/src/Extension/Frame.cpp @@ -69,12 +69,16 @@ CodecId getCodecByMovId(int object_id) { if (object_id == MOV_OBJECT_NONE) { return CodecInvalid; } - switch (object_id) { -#define XX(name, type, value, str, mpeg_id, mp4_id) case mp4_id : return name; - CODEC_MAP(XX) + +#define XX(name, type, value, str, mpeg_id, mp4_id) { mp4_id, name }, + static map s_map = { CODEC_MAP(XX) }; #undef XX - default : WarnL << "Unsupported mov: " << object_id; return CodecInvalid; + auto it = s_map.find(object_id); + if (it == s_map.end()) { + WarnL << "Unsupported mov: " << object_id; + return CodecInvalid; } + return it->second; } #endif @@ -89,17 +93,20 @@ int getMpegIdByCodec(CodecId codec) { } CodecId getCodecByMpegId(int mpeg_id) { - if (mpeg_id == PSI_STREAM_RESERVED) { + if (mpeg_id == PSI_STREAM_RESERVED || mpeg_id == 0xBD) { + // 海康的 PS 流中会有0xBD 的包 return CodecInvalid; } - switch (mpeg_id) { -#define XX(name, type, value, str, mpeg_id, mp4_id) case mpeg_id : return name; - CODEC_MAP(XX) + +#define XX(name, type, value, str, mpeg_id, mp4_id) { mpeg_id, name }, + static map s_map = { CODEC_MAP(XX) }; #undef XX - // 海康的 PS 流中会有0xBD 的包 - case 0xBD: return CodecInvalid; - default : WarnL << "Unsupported mpeg: " << mpeg_id; return CodecInvalid; + auto it = s_map.find(mpeg_id); + if (it == s_map.end()) { + WarnL << "Unsupported mpeg: " << mpeg_id; + return CodecInvalid; } + return it->second; } #endif From 519cce8c29638f95c921d70cb1fa092f2b74b121 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sun, 31 Dec 2023 22:15:51 +0800 Subject: [PATCH 16/25] Add data alignment declaration --- src/Rtcp/RtcpFCI.cpp | 6 ++++-- src/Rtcp/RtcpFCI.h | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Rtcp/RtcpFCI.cpp b/src/Rtcp/RtcpFCI.cpp index 9683f46f..843798df 100644 --- a/src/Rtcp/RtcpFCI.cpp +++ b/src/Rtcp/RtcpFCI.cpp @@ -210,7 +210,7 @@ string FCI_NACK::dumpString() const { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - +#pragma pack(push, 1) class RunLengthChunk { public: static size_t constexpr kSize = 2; @@ -241,6 +241,7 @@ public: // 打印本对象 string dumpString() const; }; +#pragma pack(pop) RunLengthChunk::RunLengthChunk(SymbolStatus status, uint16_t run_length) { type = 0; @@ -261,7 +262,7 @@ string RunLengthChunk::dumpString() const { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - +#pragma pack(push, 1) class StatusVecChunk { public: static size_t constexpr kSize = 2; @@ -292,6 +293,7 @@ public: // 打印本对象 string dumpString() const; }; +#pragma pack(pop) StatusVecChunk::StatusVecChunk(bool symbol_bit, const vector &status) { CHECK(status.size() << symbol_bit <= 14); diff --git a/src/Rtcp/RtcpFCI.h b/src/Rtcp/RtcpFCI.h index 10d2f558..43c45487 100644 --- a/src/Rtcp/RtcpFCI.h +++ b/src/Rtcp/RtcpFCI.h @@ -14,6 +14,7 @@ #include "Rtcp.h" namespace mediakit { +#pragma pack(push, 1) /////////////////////////////////////////// PSFB //////////////////////////////////////////////////// @@ -375,6 +376,6 @@ private: // feedback packet count,反馈包号,本包是第几个transport-cc包,每次加1 | uint8_t fb_pkt_count; }; - +#pragma pack(pop) } // namespace mediakit #endif // ZLMEDIAKIT_RTCPFCI_H From bb2d4820562e703b39239933989cbc639277d5ba Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sun, 31 Dec 2023 22:16:05 +0800 Subject: [PATCH 17/25] Update ZLToolKit --- 3rdpart/ZLToolKit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdpart/ZLToolKit b/3rdpart/ZLToolKit index 6a8bdfc8..0dbf6c8d 160000 --- a/3rdpart/ZLToolKit +++ b/3rdpart/ZLToolKit @@ -1 +1 @@ -Subproject commit 6a8bdfc80db3930d2ba8067d06db467dad8baddf +Subproject commit 0dbf6c8d727c9f905458c81043f8fbad07ca5c58 From b6cbbb4339c26e6d6fff8daa15240b317c2a3170 Mon Sep 17 00:00:00 2001 From: SetoKaiba Date: Wed, 3 Jan 2024 09:05:15 +0800 Subject: [PATCH 18/25] Add hls_delay feature (#3158) --- conf/config.ini | 2 ++ src/Common/config.cpp | 2 ++ src/Common/config.h | 2 ++ src/Record/HlsMaker.cpp | 49 +++++++++++++++++++++++++++++++------- src/Record/HlsMaker.h | 4 ++-- src/Record/HlsMakerImp.cpp | 17 ++++++++++--- src/Record/HlsMakerImp.h | 3 ++- 7 files changed, 64 insertions(+), 15 deletions(-) diff --git a/conf/config.ini b/conf/config.ini index d690b1f8..302fb295 100644 --- a/conf/config.ini +++ b/conf/config.ini @@ -135,6 +135,8 @@ segDur=2 #m3u8索引中,hls保留切片个数(实际保留切片个数大2~3个) #如果设置为0,则不删除切片,而是保存为点播 segNum=3 +#HLS切片延迟个数,大于0将生成hls_delay.m3u8文件,0则不生成 +segDelay=0 #HLS切片从m3u8文件中移除后,继续保留在磁盘上的个数 segRetain=5 #是否广播 hls切片(ts/fmp4)完成通知(on_record_ts) diff --git a/src/Common/config.cpp b/src/Common/config.cpp index c345350d..357a9689 100644 --- a/src/Common/config.cpp +++ b/src/Common/config.cpp @@ -307,6 +307,7 @@ namespace Hls { const string kSegmentDuration = HLS_FIELD "segDur"; const string kSegmentNum = HLS_FIELD "segNum"; const string kSegmentKeep = HLS_FIELD "segKeep"; +const string kSegmentDelay = HLS_FIELD "segDelay"; const string kSegmentRetain = HLS_FIELD "segRetain"; const string kFileBufSize = HLS_FIELD "fileBufSize"; const string kBroadcastRecordTs = HLS_FIELD "broadcastRecordTs"; @@ -317,6 +318,7 @@ static onceToken token([]() { mINI::Instance()[kSegmentDuration] = 2; mINI::Instance()[kSegmentNum] = 3; mINI::Instance()[kSegmentKeep] = false; + mINI::Instance()[kSegmentDelay] = 0; mINI::Instance()[kSegmentRetain] = 5; mINI::Instance()[kFileBufSize] = 64 * 1024; mINI::Instance()[kBroadcastRecordTs] = false; diff --git a/src/Common/config.h b/src/Common/config.h index 7f9073d9..a6d7af4d 100644 --- a/src/Common/config.h +++ b/src/Common/config.h @@ -349,6 +349,8 @@ extern const std::string kSegmentDuration; extern const std::string kSegmentNum; // 如果设置为0,则不保留切片,设置为1则一直保留切片 extern const std::string kSegmentKeep; +// HLS切片延迟个数,大于0将生成hls_delay.m3u8文件,0则不生成 +extern const std::string kSegmentDelay; // HLS切片从m3u8文件中移除后,继续保留在磁盘上的个数 extern const std::string kSegmentRetain; // HLS文件写缓存大小 diff --git a/src/Record/HlsMaker.cpp b/src/Record/HlsMaker.cpp index 2b074e1b..11d5190a 100644 --- a/src/Record/HlsMaker.cpp +++ b/src/Record/HlsMaker.cpp @@ -24,15 +24,40 @@ HlsMaker::HlsMaker(bool is_fmp4, float seg_duration, uint32_t seg_number, bool s _seg_keep = seg_keep; } -void HlsMaker::makeIndexFile(bool eof) { +void HlsMaker::makeIndexFile(bool include_delay, bool eof) { + GET_CONFIG(uint32_t, segDelay, Hls::kSegmentDelay); + GET_CONFIG(uint32_t, segRetain, Hls::kSegmentRetain); + std::deque> temp(_seg_dur_list); + if (!include_delay) { + while (temp.size() > _seg_number) { + temp.pop_front(); + } + } int maxSegmentDuration = 0; - for (auto &tp : _seg_dur_list) { + for (auto &tp : temp) { int dur = std::get<0>(tp); if (dur > maxSegmentDuration) { maxSegmentDuration = dur; } } - auto index_seq = _seg_number ? (_file_index > _seg_number ? _file_index - _seg_number : 0LL) : 0LL; + uint64_t index_seq; + if (_seg_number) { + if (include_delay) { + if (_file_index > _seg_number + segDelay) { + index_seq = _file_index - _seg_number - segDelay; + } else { + index_seq = 0LL; + } + } else { + if (_file_index > _seg_number) { + index_seq = _file_index - _seg_number; + } else { + index_seq = 0LL; + } + } + } else { + index_seq = 0LL; + } string index_str; index_str.reserve(2048); @@ -50,7 +75,7 @@ void HlsMaker::makeIndexFile(bool eof) { } stringstream ss; - for (auto &tp : _seg_dur_list) { + for (auto &tp : temp) { ss << "#EXTINF:" << std::setprecision(3) << std::get<0>(tp) / 1000.0 << ",\n" << std::get<1>(tp) << "\n"; } index_str += ss.str(); @@ -58,7 +83,7 @@ void HlsMaker::makeIndexFile(bool eof) { if (eof) { index_str += "#EXT-X-ENDLIST\n"; } - onWriteHls(index_str); + onWriteHls(index_str, include_delay); } void HlsMaker::inputInitSegment(const char *data, size_t len) { @@ -91,12 +116,13 @@ void HlsMaker::inputData(const char *data, size_t len, uint64_t timestamp, bool } void HlsMaker::delOldSegment() { + GET_CONFIG(uint32_t, segDelay, Hls::kSegmentDelay); if (_seg_number == 0) { //如果设置为保留0个切片,则认为是保存为点播 return; } //在hls m3u8索引文件中,我们保存的切片个数跟_seg_number相关设置一致 - if (_file_index > _seg_number) { + if (_file_index > _seg_number + segDelay) { _seg_dur_list.pop_front(); } //如果设置为一直保存,就不删除 @@ -105,8 +131,8 @@ void HlsMaker::delOldSegment() { } GET_CONFIG(uint32_t, segRetain, Hls::kSegmentRetain); //但是实际保存的切片个数比m3u8所述多若干个,这样做的目的是防止播放器在切片删除前能下载完毕 - if (_file_index > _seg_number + segRetain) { - onDelSegment(_file_index - _seg_number - segRetain - 1); + if (_file_index > _seg_number + segDelay + segRetain) { + onDelSegment(_file_index - _seg_number - segDelay - segRetain - 1); } } @@ -125,6 +151,7 @@ void HlsMaker::addNewSegment(uint64_t stamp) { } void HlsMaker::flushLastSegment(bool eof){ + GET_CONFIG(uint32_t, segDelay, Hls::kSegmentDelay); if (_last_file_name.empty()) { //不存在上个切片 return; @@ -139,7 +166,11 @@ void HlsMaker::flushLastSegment(bool eof){ //先flush ts切片,否则可能存在ts文件未写入完毕就被访问的情况 onFlushLastSegment(seg_dur); //然后写m3u8文件 - makeIndexFile(eof); + makeIndexFile(false, eof); + //写入切片延迟的m3u8文件 + if (segDelay) { + makeIndexFile(true, eof); + } } bool HlsMaker::isLive() const { diff --git a/src/Record/HlsMaker.h b/src/Record/HlsMaker.h index c06117e7..a95e2296 100644 --- a/src/Record/HlsMaker.h +++ b/src/Record/HlsMaker.h @@ -96,7 +96,7 @@ protected: /** * 写m3u8文件回调 */ - virtual void onWriteHls(const std::string &data) = 0; + virtual void onWriteHls(const std::string &data, bool include_delay) = 0; /** * 上一个 ts 切片写入完成, 可在这里进行通知处理 @@ -115,7 +115,7 @@ private: * 生成m3u8文件 * @param eof true代表点播 */ - void makeIndexFile(bool eof = false); + void makeIndexFile(bool include_delay, bool eof = false); /** * 删除旧的ts切片 diff --git a/src/Record/HlsMakerImp.cpp b/src/Record/HlsMakerImp.cpp index 7fc2b000..519b3d50 100644 --- a/src/Record/HlsMakerImp.cpp +++ b/src/Record/HlsMakerImp.cpp @@ -21,11 +21,20 @@ using namespace toolkit; namespace mediakit { +std::string getDelayPath(const std::string& originalPath) { + std::size_t pos = originalPath.find(".m3u8"); + if (pos != std::string::npos) { + return originalPath.substr(0, pos) + "_delay.m3u8"; + } + return originalPath; +} + HlsMakerImp::HlsMakerImp(bool is_fmp4, const string &m3u8_file, const string ¶ms, uint32_t bufSize, float seg_duration, uint32_t seg_number, bool seg_keep) : HlsMaker(is_fmp4, seg_duration, seg_number, seg_keep) { _poller = EventPollerPool::Instance().getPoller(); _path_prefix = m3u8_file.substr(0, m3u8_file.rfind('/')); _path_hls = m3u8_file; + _path_hls_delay = getDelayPath(m3u8_file); _params = params; _buf_size = bufSize; _file_buf.reset(new char[bufSize], [](char *ptr) { delete[] ptr; }); @@ -62,6 +71,7 @@ void HlsMakerImp::clearCache(bool immediately, bool eof) { { std::list lst; lst.emplace_back(_path_hls); + lst.emplace_back(_path_hls_delay); if (!_path_init.empty()) { lst.emplace_back(_path_init); } @@ -146,8 +156,9 @@ void HlsMakerImp::onWriteSegment(const char *data, size_t len) { } } -void HlsMakerImp::onWriteHls(const std::string &data) { - auto hls = makeFile(_path_hls); +void HlsMakerImp::onWriteHls(const std::string &data, bool include_delay) { + auto path = include_delay ? _path_hls_delay : _path_hls; + auto hls = makeFile(path); if (hls) { fwrite(data.data(), data.size(), 1, hls.get()); hls.reset(); @@ -155,7 +166,7 @@ void HlsMakerImp::onWriteHls(const std::string &data) { _media_src->setIndexFile(data); } } else { - WarnL << "Create hls file failed," << _path_hls << " " << get_uv_errmsg(); + WarnL << "Create hls file failed," << path << " " << get_uv_errmsg(); } } diff --git a/src/Record/HlsMakerImp.h b/src/Record/HlsMakerImp.h index 7d268a53..b3bf77b9 100644 --- a/src/Record/HlsMakerImp.h +++ b/src/Record/HlsMakerImp.h @@ -49,7 +49,7 @@ protected: void onDelSegment(uint64_t index) override; void onWriteInitSegment(const char *data, size_t len) override; void onWriteSegment(const char *data, size_t len) override; - void onWriteHls(const std::string &data) override; + void onWriteHls(const std::string &data, bool include_delay) override; void onFlushLastSegment(uint64_t duration_ms) override; private: @@ -60,6 +60,7 @@ private: int _buf_size; std::string _params; std::string _path_hls; + std::string _path_hls_delay; std::string _path_init; std::string _path_prefix; RecordInfo _info; From aeda47ec8c653b466d42542c6defc69296246099 Mon Sep 17 00:00:00 2001 From: sandro-qiang <44429952+sandro-qiang@users.noreply.github.com> Date: Fri, 5 Jan 2024 15:33:51 +0800 Subject: [PATCH 19/25] =?UTF-8?q?=E4=BF=AE=E6=AD=A3SctpAssociation.cpp?= =?UTF-8?q?=E7=9A=84=E8=AE=BF=E9=97=AE=E8=B6=8A=E7=95=8C=20(#3182)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ZLMediaKit/ZLMediaKit#3181 --- CMakeLists.txt | 2 +- webrtc/SctpAssociation.cpp | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 64157b7f..96e79890 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -370,7 +370,7 @@ if(ENABLE_JEMALLOC_STATIC) set(ENABLE_JEMALLOC_STAT OFF) endif () include(Jemalloc) - include_directories(SYSTEM ${DEP_ROOT_DIR}/${JEMALLOC_NAME}/include/jemalloc) + include_directories(SYSTEM ${DEP_ROOT_DIR}/${JEMALLOC_NAME}/include) link_directories(${DEP_ROOT_DIR}/${JEMALLOC_NAME}/lib) # 用于影响后续查找过程 # Used to affect subsequent lookup process diff --git a/webrtc/SctpAssociation.cpp b/webrtc/SctpAssociation.cpp index 84a2c04f..1b5d2782 100644 --- a/webrtc/SctpAssociation.cpp +++ b/webrtc/SctpAssociation.cpp @@ -677,9 +677,9 @@ namespace RTC if (notification->sn_header.sn_length > 0) { static const size_t BufferSize{ 1024 }; - static char buffer[BufferSize]; + thread_local static char buffer[BufferSize]; - uint32_t len = notification->sn_header.sn_length; + uint32_t len = notification->sn_assoc_change.sac_length - sizeof(struct sctp_assoc_change); for (uint32_t i{ 0 }; i < len; ++i) { @@ -745,9 +745,9 @@ namespace RTC if (notification->sn_header.sn_length > 0) { static const size_t BufferSize{ 1024 }; - static char buffer[BufferSize]; + thread_local static char buffer[BufferSize]; - uint32_t len = notification->sn_header.sn_length; + uint32_t len = notification->sn_assoc_change.sac_length - sizeof(struct sctp_assoc_change); for (uint32_t i{ 0 }; i < len; ++i) { @@ -786,7 +786,7 @@ namespace RTC case SCTP_REMOTE_ERROR: { static const size_t BufferSize{ 1024 }; - static char buffer[BufferSize]; + thread_local static char buffer[BufferSize]; uint32_t len = notification->sn_remote_error.sre_length - sizeof(struct sctp_remote_error); @@ -822,7 +822,7 @@ namespace RTC case SCTP_SEND_FAILED_EVENT: { static const size_t BufferSize{ 1024 }; - static char buffer[BufferSize]; + thread_local static char buffer[BufferSize]; uint32_t len = notification->sn_send_failed_event.ssfe_length - sizeof(struct sctp_send_failed_event); @@ -1004,4 +1004,4 @@ namespace RTC } // namespace RTC -#endif //ENABLE_SCTP \ No newline at end of file +#endif //ENABLE_SCTP From 77400832ac79bfe572b0d660cf14e69ee3f8c8b3 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sat, 6 Jan 2024 17:47:43 +0800 Subject: [PATCH 20/25] Update ZLToolKit --- 3rdpart/ZLToolKit | 2 +- tests/test_bench_forward.cpp | 2 +- tests/test_bench_pull.cpp | 2 +- tests/test_bench_push.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/3rdpart/ZLToolKit b/3rdpart/ZLToolKit index 0dbf6c8d..45d35704 160000 --- a/3rdpart/ZLToolKit +++ b/3rdpart/ZLToolKit @@ -1 +1 @@ -Subproject commit 0dbf6c8d727c9f905458c81043f8fbad07ca5c58 +Subproject commit 45d3570498f420bd7ef5fa97ef0a35a67f31a3be diff --git a/tests/test_bench_forward.cpp b/tests/test_bench_forward.cpp index eb6df202..a71994d1 100644 --- a/tests/test_bench_forward.cpp +++ b/tests/test_bench_forward.cpp @@ -180,7 +180,7 @@ int main(int argc, char *argv[]) { auto pusher = std::make_shared(src); pusher->setOnCreateSocket([](const EventPoller::Ptr &poller) { //socket关闭互斥锁,提高性能 - return std::make_shared(poller, false); + return Socket::createSocket(poller, false); }); //设置推流失败监听 pusher->setOnPublished([&mtx, &pusher_map, index](const SockException &ex) { diff --git a/tests/test_bench_pull.cpp b/tests/test_bench_pull.cpp index c16de46a..dd455f8e 100644 --- a/tests/test_bench_pull.cpp +++ b/tests/test_bench_pull.cpp @@ -123,7 +123,7 @@ int main(int argc, char *argv[]) { auto tag = player.get(); player->setOnCreateSocket([](const EventPoller::Ptr &poller) { //socket关闭互斥锁,提高性能 - return std::make_shared(poller, false); + return Socket::createSocket(poller, false); }); //设置播放失败监听 player->setOnPlayResult([&mtx, &player_map, tag](const SockException &ex) { diff --git a/tests/test_bench_push.cpp b/tests/test_bench_push.cpp index 604ad76f..ee07f0c2 100644 --- a/tests/test_bench_push.cpp +++ b/tests/test_bench_push.cpp @@ -166,7 +166,7 @@ int main(int argc, char *argv[]) { auto tag = pusher.get(); pusher->setOnCreateSocket([](const EventPoller::Ptr &poller) { //socket关闭互斥锁,提高性能 - return std::make_shared(poller, false); + return Socket::createSocket(poller, false); }); //设置推流失败监听 pusher->setOnPublished([&mtx, &pusher_map, tag](const SockException &ex) { From 8048cd886be6ad6b2b1a29e08c9b471560f0f5af Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sat, 6 Jan 2024 18:17:51 +0800 Subject: [PATCH 21/25] Fix typo error of VideoTrackImp --- src/Extension/Track.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Extension/Track.h b/src/Extension/Track.h index 8264b3a8..ba101282 100644 --- a/src/Extension/Track.h +++ b/src/Extension/Track.h @@ -129,8 +129,8 @@ public: _fps = fps; } - int getVideoHeight() const override { return _width; } - int getVideoWidth() const override { return _height; } + int getVideoWidth() const override { return _width; } + int getVideoHeight() const override { return _height; } float getVideoFps() const override { return _fps; } bool ready() const override { return true; } From 27217cb1e68b00469110e5fd272965e3ba661362 Mon Sep 17 00:00:00 2001 From: Seto <61304189@qq.com> Date: Sat, 6 Jan 2024 18:30:42 +0800 Subject: [PATCH 22/25] Fix _media_src setIndexFile by mistake for include_delay. --- src/Record/HlsMakerImp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Record/HlsMakerImp.cpp b/src/Record/HlsMakerImp.cpp index 519b3d50..e987f820 100644 --- a/src/Record/HlsMakerImp.cpp +++ b/src/Record/HlsMakerImp.cpp @@ -162,7 +162,7 @@ void HlsMakerImp::onWriteHls(const std::string &data, bool include_delay) { if (hls) { fwrite(data.data(), data.size(), 1, hls.get()); hls.reset(); - if (_media_src) { + if (_media_src && !include_delay) { _media_src->setIndexFile(data); } } else { From 473228a12885d5d4de413392d14eb4cd6f8363ef Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sat, 6 Jan 2024 23:22:47 +0800 Subject: [PATCH 23/25] Update ZLToolKit --- 3rdpart/ZLToolKit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdpart/ZLToolKit b/3rdpart/ZLToolKit index 45d35704..e5535a71 160000 --- a/3rdpart/ZLToolKit +++ b/3rdpart/ZLToolKit @@ -1 +1 @@ -Subproject commit 45d3570498f420bd7ef5fa97ef0a35a67f31a3be +Subproject commit e5535a7164f55eb9062213f40ddc68c0294e6f57 From dfda93a4c46af621bd035e768cc7b37b9c93e90f Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Mon, 15 Jan 2024 20:32:06 +0800 Subject: [PATCH 24/25] Ignore invalid H264/H265 rtmp packet instead of throwing an error --- ext-codec/H264Rtmp.cpp | 12 ++++++++++-- ext-codec/H265Rtmp.cpp | 16 ++++++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/ext-codec/H264Rtmp.cpp b/ext-codec/H264Rtmp.cpp index 05098779..30bf10eb 100644 --- a/ext-codec/H264Rtmp.cpp +++ b/ext-codec/H264Rtmp.cpp @@ -14,16 +14,24 @@ using namespace std; using namespace toolkit; +#define CHECK_RET(...) \ + try { \ + CHECK(__VA_ARGS__); \ + } catch (AssertFailedException & ex) { \ + WarnL << ex.what(); \ + return; \ + } + namespace mediakit { void H264RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) { if (pkt->isConfigFrame()) { - CHECK(pkt->size() > 5); + CHECK_RET(pkt->size() > 5); getTrack()->setExtraData((uint8_t *)pkt->data() + 5, pkt->size() - 5); return; } - CHECK(pkt->size() > 9); + CHECK_RET(pkt->size() > 9); uint8_t *cts_ptr = (uint8_t *)(pkt->buffer.data() + 2); int32_t cts = (((cts_ptr[0] << 16) | (cts_ptr[1] << 8) | (cts_ptr[2])) + 0xff800000) ^ 0xff800000; auto pts = pkt->time_stamp + cts; diff --git a/ext-codec/H265Rtmp.cpp b/ext-codec/H265Rtmp.cpp index 9799849d..2b88795d 100644 --- a/ext-codec/H265Rtmp.cpp +++ b/ext-codec/H265Rtmp.cpp @@ -18,6 +18,14 @@ using namespace std; using namespace toolkit; +#define CHECK_RET(...) \ + try { \ + CHECK(__VA_ARGS__); \ + } catch (AssertFailedException & ex) { \ + WarnL << ex.what(); \ + return; \ + } + namespace mediakit { void H265RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) { @@ -44,7 +52,7 @@ void H265RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) { auto data = (uint8_t *)pkt->data() + RtmpPacketInfo::kEnhancedRtmpHeaderSize; auto size = pkt->size() - RtmpPacketInfo::kEnhancedRtmpHeaderSize; auto pts = pkt->time_stamp; - CHECK(size > 3); + CHECK_RET(size > 3); if (RtmpPacketType::PacketTypeCodedFrames == _info.video.pkt_type) { // SI24 = [CompositionTime Offset] int32_t cts = (((data[0] << 16) | (data[1] << 8) | (data[2])) + 0xff800000) ^ 0xff800000; @@ -52,7 +60,7 @@ void H265RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) { data += 3; size -= 3; } - CHECK(size > 4); + CHECK_RET(size > 4); splitFrame(data, size, pkt->time_stamp, pts); break; } @@ -63,12 +71,12 @@ void H265RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) { // 国内扩展(12) H265 rtmp if (pkt->isConfigFrame()) { - CHECK(pkt->size() > 5); + CHECK_RET(pkt->size() > 5); getTrack()->setExtraData((uint8_t *)pkt->data() + 5, pkt->size() - 5); return; } - CHECK(pkt->size() > 9); + CHECK_RET(pkt->size() > 9); uint8_t *cts_ptr = (uint8_t *)(pkt->buffer.data() + 2); int32_t cts = (((cts_ptr[0] << 16) | (cts_ptr[1] << 8) | (cts_ptr[2])) + 0xff800000) ^ 0xff800000; auto pts = pkt->time_stamp + cts; From 6514be74f1c08262f3eaeb375c371da3870cf436 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Mon, 15 Jan 2024 20:34:17 +0800 Subject: [PATCH 25/25] Prevent access to nullptr when cloning a track --- src/Common/MediaSink.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Common/MediaSink.cpp b/src/Common/MediaSink.cpp index 3fc5a9ea..837024af 100644 --- a/src/Common/MediaSink.cpp +++ b/src/Common/MediaSink.cpp @@ -37,6 +37,7 @@ bool MediaSink::addTrack(const Track::Ptr &track_in) { } // 克隆Track,只拷贝其数据,不拷贝其数据转发关系 auto track = track_in->clone(); + CHECK(track, "Clone track failed: ", track_in->getCodecName()); auto index = track->getIndex(); if (!_track_map.emplace(index, std::make_pair(track, false)).second) { WarnL << "Already add a same track: " << track->getIndex() << ", codec: " << track->getCodecName();