From 3d8f015f5dbe34a475c6fe8c2dce86e86be3bc14 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sat, 14 Nov 2020 23:11:28 +0800 Subject: [PATCH 1/5] =?UTF-8?q?GB28181=E6=8E=A8=E6=B5=81=EF=BC=8C=E6=97=A0?= =?UTF-8?q?=E4=BA=BA=E8=A7=82=E7=9C=8B=E6=97=B6=E4=B8=8D=E8=A7=A3=E5=A4=8D?= =?UTF-8?q?=E7=94=A8=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Rtp/RtpProcess.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Rtp/RtpProcess.cpp b/src/Rtp/RtpProcess.cpp index 64a4b197..9769b71d 100644 --- a/src/Rtp/RtpProcess.cpp +++ b/src/Rtp/RtpProcess.cpp @@ -101,6 +101,14 @@ bool RtpProcess::inputRtp(bool is_udp, const Socket::Ptr &sock, const char *data if (!_process) { _process = std::make_shared(_media_info, this); } + + GET_CONFIG(string, dump_dir, RtpProxy::kDumpDir); + if (!_muxer->isEnabled() && !dts_out && dump_dir.empty()) { + //无人访问、且不取时间戳、不导出调试文件时,我们可以直接丢弃数据 + _last_frame_time.resetTime(); + return false; + } + bool ret = _process ? _process->inputRtp(is_udp, data, len) : false; if (dts_out) { *dts_out = _dts; From ebbe124d0015195478164ba48db42f2c739b302d Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sun, 15 Nov 2020 00:00:22 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=8D=E8=83=BD?= =?UTF-8?q?=E7=AB=8B=E5=8D=B3=E5=85=B3=E9=97=AD=E6=8B=89=E6=B5=81=E4=BB=A3?= =?UTF-8?q?=E7=90=86=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=9A#559?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Player/PlayerProxy.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Player/PlayerProxy.cpp b/src/Player/PlayerProxy.cpp index 03e4b8cf..ee81e952 100644 --- a/src/Player/PlayerProxy.cpp +++ b/src/Player/PlayerProxy.cpp @@ -169,10 +169,10 @@ bool PlayerProxy::close(MediaSource &sender,bool force) { strongSelf->_muxer.reset(); strongSelf->setMediaSource(nullptr); strongSelf->teardown(); - if (strongSelf->_on_close) { - strongSelf->_on_close(); - } }); + if (_on_close) { + _on_close(); + } WarnL << sender.getSchema() << "/" << sender.getVhost() << "/" << sender.getApp() << "/" << sender.getId() << " " << force; return true; } From bb9b39d8216696d919401145872fe32430fd51ac Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sun, 15 Nov 2020 00:40:46 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=8C=89=E9=9C=80?= =?UTF-8?q?=E8=BD=AC=E5=8D=8F=E8=AE=AE=E5=BC=80=E5=85=B3=EF=BC=8C=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E4=B8=80=E7=9B=B4=E8=BD=AC=E5=8D=8F=E8=AE=AE=EF=BC=9A?= =?UTF-8?q?#569?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conf/config.ini | 15 +++++++++++++++ src/Common/config.cpp | 5 +++++ src/Common/config.h | 6 ++++++ src/FMP4/FMP4MediaSourceMuxer.h | 13 ++++++++----- src/Record/HlsRecorder.h | 15 +++++++++------ src/Rtmp/RtmpMediaSourceMuxer.h | 13 ++++++++----- src/Rtsp/RtspMediaSourceMuxer.h | 13 ++++++++----- src/TS/TSMediaSourceMuxer.h | 13 ++++++++----- 8 files changed, 67 insertions(+), 26 deletions(-) diff --git a/conf/config.ini b/conf/config.ini index 2e407739..8043f750 100644 --- a/conf/config.ini +++ b/conf/config.ini @@ -55,6 +55,21 @@ modifyStamp=0 #服务器唯一id,用于触发hook时区别是哪台服务器 mediaServerId=your_server_id +###### 以下是按需转协议的开关,在测试ZLMediaKit的接收推流性能时,请关闭以下全部开关 +###### 如果某种协议你用不到,你可以把以下开关置1以便节省资源(但是还是可以播放,只是第一个播放者体验稍微差点), +###### 如果某种协议你想获取最好的用户体验,请置1(第一个播放者可以秒开,且不花屏) + +#hls协议是否按需生成,如果hls.segNum配置为0(意味着hls录制),那么hls将一直生成(不管此开关) +hls_demand=0 +#rtsp[s]协议是否按需生成 +rtsp_demand=0 +#rtmp[s]、http[s]-flv、ws[s]-flv协议是否按需生成 +rtmp_demand=0 +#http[s]-ts协议是否按需生成 +ts_demand=0 +#http[s]-fmp4、ws[s]-fmp4协议是否按需生成 +fmp4_demand=0 + [hls] #hls写文件的buf大小,调整参数可以提高文件io性能 fileBufSize=65536 diff --git a/src/Common/config.cpp b/src/Common/config.cpp index 38091f0b..8dbadda6 100644 --- a/src/Common/config.cpp +++ b/src/Common/config.cpp @@ -69,6 +69,11 @@ const string kPublishToHls = GENERAL_FIELD"publishToHls"; const string kPublishToMP4 = GENERAL_FIELD"publishToMP4"; const string kMergeWriteMS = GENERAL_FIELD"mergeWriteMS"; const string kModifyStamp = GENERAL_FIELD"modifyStamp"; +const string kHlsDemand = GENERAL_FIELD"hls_demand"; +const string kRtspDemand = GENERAL_FIELD"rtsp_demand"; +const string kRtmpDemand = GENERAL_FIELD"rtmp_demand"; +const string kTSDemand = GENERAL_FIELD"ts_demand"; +const string kFMP4Demand = GENERAL_FIELD"fmp4_demand"; onceToken token([](){ mINI::Instance()[kFlowThreshold] = 1024; diff --git a/src/Common/config.h b/src/Common/config.h index bc11d9b6..4c41e1f9 100644 --- a/src/Common/config.h +++ b/src/Common/config.h @@ -181,6 +181,12 @@ extern const string kPublishToMP4 ; extern const string kMergeWriteMS ; //全局的时间戳覆盖开关,在转协议时,对frame进行时间戳覆盖 extern const string kModifyStamp; +//按需转协议的开关 +extern const string kHlsDemand; +extern const string kRtspDemand; +extern const string kRtmpDemand; +extern const string kTSDemand; +extern const string kFMP4Demand; }//namespace General diff --git a/src/FMP4/FMP4MediaSourceMuxer.h b/src/FMP4/FMP4MediaSourceMuxer.h index 3d8482a0..6d133db5 100644 --- a/src/FMP4/FMP4MediaSourceMuxer.h +++ b/src/FMP4/FMP4MediaSourceMuxer.h @@ -41,26 +41,29 @@ public: } void onReaderChanged(MediaSource &sender, int size) override { - _enabled = size; - if (!size) { + GET_CONFIG(bool, fmp4_demand, General::kFMP4Demand); + _enabled = fmp4_demand ? size : true; + if (!size && fmp4_demand) { _clear_cache = true; } MediaSourceEventInterceptor::onReaderChanged(sender, size); } void inputFrame(const Frame::Ptr &frame) override { - if (_clear_cache) { + GET_CONFIG(bool, fmp4_demand, General::kFMP4Demand); + if (_clear_cache && fmp4_demand) { _clear_cache = false; _media_src->clearCache(); } - if (_enabled) { + if (_enabled || !fmp4_demand) { MP4MuxerMemory::inputFrame(frame); } } bool isEnabled() { + GET_CONFIG(bool, fmp4_demand, General::kFMP4Demand); //缓存尚未清空时,还允许触发inputFrame函数,以便及时清空缓存 - return _clear_cache ? true : _enabled; + return fmp4_demand ? (_clear_cache ? true : _enabled) : true; } void onAllTrackReady() { diff --git a/src/Record/HlsRecorder.h b/src/Record/HlsRecorder.h index 465a4199..5b076d36 100644 --- a/src/Record/HlsRecorder.h +++ b/src/Record/HlsRecorder.h @@ -45,9 +45,10 @@ public: } void onReaderChanged(MediaSource &sender, int size) override { + GET_CONFIG(bool, hls_demand, General::kHlsDemand); //hls保留切片个数为0时代表为hls录制(不删除切片),那么不管有无观看者都一直生成hls - _enabled = _hls->isLive() ? size : true; - if (!size && _hls->isLive()) { + _enabled = hls_demand ? (_hls->isLive() ? size : true) : true; + if (!size && _hls->isLive() && hls_demand) { //hls直播时,如果无人观看就删除视频缓存,目的是为了防止视频跳跃 _clear_cache = true; } @@ -55,16 +56,18 @@ public: } bool isEnabled() { + GET_CONFIG(bool, hls_demand, General::kHlsDemand); //缓存尚未清空时,还允许触发inputFrame函数,以便及时清空缓存 - return _clear_cache ? true : _enabled; + return hls_demand ? (_clear_cache ? true : _enabled) : true; } - void inputFrame(const Frame::Ptr &frame) override{ - if (_clear_cache) { + void inputFrame(const Frame::Ptr &frame) override { + GET_CONFIG(bool, hls_demand, General::kHlsDemand); + if (_clear_cache && hls_demand) { _clear_cache = false; _hls->clearCache(); } - if (_enabled) { + if (_enabled || !hls_demand) { TsMuxer::inputFrame(frame); } } diff --git a/src/Rtmp/RtmpMediaSourceMuxer.h b/src/Rtmp/RtmpMediaSourceMuxer.h index c8ef9652..f998a3a2 100644 --- a/src/Rtmp/RtmpMediaSourceMuxer.h +++ b/src/Rtmp/RtmpMediaSourceMuxer.h @@ -50,26 +50,29 @@ public: } void onReaderChanged(MediaSource &sender, int size) override { - _enabled = size; - if (!size) { + GET_CONFIG(bool, rtmp_demand, General::kRtmpDemand); + _enabled = rtmp_demand ? size : true; + if (!size && rtmp_demand) { _clear_cache = true; } MediaSourceEventInterceptor::onReaderChanged(sender, size); } void inputFrame(const Frame::Ptr &frame) override { - if (_clear_cache) { + GET_CONFIG(bool, rtmp_demand, General::kRtmpDemand); + if (_clear_cache && rtmp_demand) { _clear_cache = false; _media_src->clearCache(); } - if (_enabled) { + if (_enabled || !rtmp_demand) { RtmpMuxer::inputFrame(frame); } } bool isEnabled() { + GET_CONFIG(bool, rtmp_demand, General::kRtmpDemand); //缓存尚未清空时,还允许触发inputFrame函数,以便及时清空缓存 - return _clear_cache ? true : _enabled; + return rtmp_demand ? (_clear_cache ? true : _enabled) : true; } private: diff --git a/src/Rtsp/RtspMediaSourceMuxer.h b/src/Rtsp/RtspMediaSourceMuxer.h index eb2a4bd4..18059910 100644 --- a/src/Rtsp/RtspMediaSourceMuxer.h +++ b/src/Rtsp/RtspMediaSourceMuxer.h @@ -49,26 +49,29 @@ public: } void onReaderChanged(MediaSource &sender, int size) override { - _enabled = size; - if (!size) { + GET_CONFIG(bool, rtsp_demand, General::kRtspDemand); + _enabled = rtsp_demand ? size : true; + if (!size && rtsp_demand) { _clear_cache = true; } MediaSourceEventInterceptor::onReaderChanged(sender, size); } void inputFrame(const Frame::Ptr &frame) override { - if (_clear_cache) { + GET_CONFIG(bool, rtsp_demand, General::kRtspDemand); + if (_clear_cache && rtsp_demand) { _clear_cache = false; _media_src->clearCache(); } - if (_enabled) { + if (_enabled || !rtsp_demand) { RtspMuxer::inputFrame(frame); } } bool isEnabled() { + GET_CONFIG(bool, rtsp_demand, General::kRtspDemand); //缓存尚未清空时,还允许触发inputFrame函数,以便及时清空缓存 - return _clear_cache ? true : _enabled; + return rtsp_demand ? (_clear_cache ? true : _enabled) : true; } private: diff --git a/src/TS/TSMediaSourceMuxer.h b/src/TS/TSMediaSourceMuxer.h index 34051808..a8cf9efc 100644 --- a/src/TS/TSMediaSourceMuxer.h +++ b/src/TS/TSMediaSourceMuxer.h @@ -40,26 +40,29 @@ public: } void onReaderChanged(MediaSource &sender, int size) override { - _enabled = size; - if (!size) { + GET_CONFIG(bool, ts_demand, General::kTSDemand); + _enabled = ts_demand ? size : true; + if (!size && ts_demand) { _clear_cache = true; } MediaSourceEventInterceptor::onReaderChanged(sender, size); } void inputFrame(const Frame::Ptr &frame) override { - if (_clear_cache) { + GET_CONFIG(bool, ts_demand, General::kTSDemand); + if (_clear_cache && ts_demand) { _clear_cache = false; _media_src->clearCache(); } - if (_enabled) { + if (_enabled || !ts_demand) { TsMuxer::inputFrame(frame); } } bool isEnabled() { + GET_CONFIG(bool, ts_demand, General::kTSDemand); //缓存尚未清空时,还允许触发inputFrame函数,以便及时清空缓存 - return _clear_cache ? true : _enabled; + return ts_demand ? (_clear_cache ? true : _enabled) : true; } protected: From 0f5435181193092ffc876dbdcb5316e320d1e810 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sun, 15 Nov 2020 00:43:42 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E6=8C=89=E9=9C=80=E8=BD=AC=E5=8D=8F?= =?UTF-8?q?=E8=AE=AE=E9=BB=98=E8=AE=A4=E5=85=B3=E9=97=AD(=E6=84=8F?= =?UTF-8?q?=E5=8D=B3=E4=B8=80=E7=9B=B4=E8=BD=AC=E5=8D=8F=E8=AE=AE)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Common/config.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Common/config.cpp b/src/Common/config.cpp index 8dbadda6..d4fd3887 100644 --- a/src/Common/config.cpp +++ b/src/Common/config.cpp @@ -87,6 +87,12 @@ onceToken token([](){ mINI::Instance()[kMergeWriteMS] = 0; mINI::Instance()[kModifyStamp] = 0; mINI::Instance()[kMediaServerId] = makeRandStr(16); + mINI::Instance()[kHlsDemand] = 0; + mINI::Instance()[kRtspDemand] = 0; + mINI::Instance()[kRtmpDemand] = 0; + mINI::Instance()[kTSDemand] = 0; + mINI::Instance()[kFMP4Demand] = 0; + },nullptr); }//namespace General From 1cc3add97f98761d116d3035e17ec45c40f05926 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sun, 15 Nov 2020 00:59:31 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E6=8F=90=E5=8D=87=E6=8C=89=E9=9C=80?= =?UTF-8?q?=E8=BD=AC=E5=8D=8F=E8=AE=AE=E6=80=A7=E8=83=BD=E4=B8=8E=E4=BD=93?= =?UTF-8?q?=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Common/MultiMediaSourceMuxer.cpp | 15 +++++++++++++-- src/Common/MultiMediaSourceMuxer.h | 2 ++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Common/MultiMediaSourceMuxer.cpp b/src/Common/MultiMediaSourceMuxer.cpp index 5774f45c..f3d44352 100644 --- a/src/Common/MultiMediaSourceMuxer.cpp +++ b/src/Common/MultiMediaSourceMuxer.cpp @@ -9,6 +9,7 @@ */ #include +#include "Common/config.h" #include "MultiMediaSourceMuxer.h" namespace mediakit { @@ -450,11 +451,21 @@ void MultiMediaSourceMuxer::inputFrame(const Frame::Ptr &frame_in) { } bool MultiMediaSourceMuxer::isEnabled(){ + GET_CONFIG(uint32_t, stream_none_reader_delay_ms, General::kStreamNoneReaderDelayMS); + if (!_is_enable || _last_check.elapsedTime() > stream_none_reader_delay_ms) { + //无人观看时,每次检查是否真的无人观看 + //有人观看时,则延迟一定时间检查一遍是否无人观看了(节省性能) #if defined(ENABLE_RTPPROXY) - return (_muxer->isEnabled() || _rtp_sender); + _is_enable = (_muxer->isEnabled() || _rtp_sender); #else - return _muxer->isEnabled(); + _is_enable = _muxer->isEnabled(); #endif //ENABLE_RTPPROXY + if (_is_enable) { + //无人观看时,不刷新计时器,因为无人观看时每次都会检查一遍,所以刷新计数器无意义且浪费cpu + _last_check.resetTime(); + } + } + return _is_enable; } diff --git a/src/Common/MultiMediaSourceMuxer.h b/src/Common/MultiMediaSourceMuxer.h index 11ef0e81..36729447 100644 --- a/src/Common/MultiMediaSourceMuxer.h +++ b/src/Common/MultiMediaSourceMuxer.h @@ -183,6 +183,8 @@ public: void onAllTrackReady() override; private: + bool _is_enable = false; + Ticker _last_check; Stamp _stamp[2]; MultiMuxerPrivate::Ptr _muxer; std::weak_ptr _track_listener;