From aa9bd56c5a79f0bc804b99b7797672dd9d0ac015 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Mon, 27 Apr 2020 09:18:46 +0800 Subject: [PATCH 01/11] =?UTF-8?q?=E5=9B=9E=E8=B0=83=E5=8F=AF=E4=BB=A5?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E7=A9=BA=E6=8C=87=E9=92=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/source/mk_player.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/source/mk_player.cpp b/api/source/mk_player.cpp index f4b6bf7c..a3dd4b9f 100755 --- a/api/source/mk_player.cpp +++ b/api/source/mk_player.cpp @@ -178,7 +178,7 @@ API_EXPORT void API_CALL mk_player_seekto(mk_player ctx, float progress) { } static void mk_player_set_on_event(mk_player ctx, on_mk_play_event cb, void *user_data, int type) { - assert(ctx && cb); + assert(ctx); MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *)ctx); obj.setOnEvent(cb,user_data, type); } @@ -192,7 +192,7 @@ API_EXPORT void API_CALL mk_player_set_on_shutdown(mk_player ctx, on_mk_play_eve } API_EXPORT void API_CALL mk_player_set_on_data(mk_player ctx, on_mk_play_data cb, void *user_data) { - assert(ctx && cb); + assert(ctx); MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *)ctx); obj.setOnData(cb,user_data); } From 0eb97d5471779b37e7f06f27fadfa3be9258afb8 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Tue, 28 Apr 2020 09:40:47 +0800 Subject: [PATCH 02/11] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=8D=E8=83=BD?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E5=BD=95=E5=88=B6=E8=B7=AF=E5=BE=84=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=9A#279?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Record/Recorder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Record/Recorder.cpp b/src/Record/Recorder.cpp index 38d6b98a..2ab341b7 100644 --- a/src/Record/Recorder.cpp +++ b/src/Record/Recorder.cpp @@ -56,7 +56,7 @@ string Recorder::getRecordPath(Recorder::type type, const string &vhost, const s } std::shared_ptr Recorder::createRecorder(type type, const string &vhost, const string &app, const string &stream_id, const string &customized_path){ - auto path = Recorder::getRecordPath(type, vhost, app, stream_id); + auto path = Recorder::getRecordPath(type, vhost, app, stream_id, customized_path); switch (type) { case Recorder::type_hls: { #if defined(ENABLE_HLS) From 7565a20695ecfc9594644d8fb07c94e2f41d50df Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Tue, 28 Apr 2020 15:24:08 +0800 Subject: [PATCH 03/11] startRecord API with "customized_path" #279 --- src/Common/MultiMediaSourceMuxer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Common/MultiMediaSourceMuxer.cpp b/src/Common/MultiMediaSourceMuxer.cpp index 0f56ddbe..6047062e 100644 --- a/src/Common/MultiMediaSourceMuxer.cpp +++ b/src/Common/MultiMediaSourceMuxer.cpp @@ -77,8 +77,8 @@ int MultiMuxerPrivate::totalReaderCount() const { return (_rtsp ? _rtsp->readerCount() : 0) + (_rtmp ? _rtmp->readerCount() : 0) + (hls_src ? hls_src->readerCount() : 0); } -static std::shared_ptr makeRecorder(const vector &tracks, Recorder::type type, MediaSource &sender){ - auto recorder = Recorder::createRecorder(type, sender.getVhost(), sender.getApp(), sender.getId()); +static std::shared_ptr makeRecorder(const vector &tracks, Recorder::type type, const string &custom_path, MediaSource &sender){ + auto recorder = Recorder::createRecorder(type, sender.getVhost(), sender.getApp(), sender.getId(), custom_path); for (auto &track : tracks) { recorder->addTrack(track); } @@ -91,7 +91,7 @@ bool MultiMuxerPrivate::setupRecord(MediaSource &sender, Recorder::type type, bo case Recorder::type_hls : { if (start && !_hls) { //开始录制 - _hls = makeRecorder(getTracks(true), type, sender); + _hls = makeRecorder(getTracks(true), type, custom_path, sender); auto hls_src = getHlsMediaSource(); if (hls_src) { //设置HlsMediaSource的事件监听器 @@ -107,7 +107,7 @@ bool MultiMuxerPrivate::setupRecord(MediaSource &sender, Recorder::type type, bo case Recorder::type_mp4 : { if (start && !_mp4) { //开始录制 - _mp4 = makeRecorder(getTracks(true), type, sender);; + _mp4 = makeRecorder(getTracks(true), type, custom_path, sender); } else if (!start && _mp4) { //停止录制 _mp4 = nullptr; From 163b0875cfd9ac730c9d0be20e6ed0d82b185649 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Tue, 28 Apr 2020 22:24:31 +0800 Subject: [PATCH 04/11] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dh264=20split=E5=90=8E?= =?UTF-8?q?=E5=8F=AF=E8=83=BD=E5=A4=9A=E4=B8=AA=E5=AD=97=E8=8A=82=E7=9A=84?= =?UTF-8?q?bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Extension/H264.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Extension/H264.cpp b/src/Extension/H264.cpp index d1f66f9a..7cfb086a 100644 --- a/src/Extension/H264.cpp +++ b/src/Extension/H264.cpp @@ -50,6 +50,9 @@ void splitH264(const char *ptr, int len, const std::function Date: Wed, 29 Apr 2020 10:01:56 +0800 Subject: [PATCH 05/11] =?UTF-8?q?h265=E6=96=B0=E5=A2=9E=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E4=B8=A4=E7=A7=8D=E7=B1=BB=E5=9E=8B=E7=9A=84=E5=85=B3=E9=94=AE?= =?UTF-8?q?=E5=B8=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Extension/H265.h | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/Extension/H265.h b/src/Extension/H265.h index 71069d11..fca162c3 100644 --- a/src/Extension/H265.h +++ b/src/Extension/H265.h @@ -46,6 +46,9 @@ public: NAL_IDR_W_RADL = 19, NAL_IDR_N_LP = 20, NAL_CRA_NUT = 21, + NAL_RSV_IRAP_VCL22 = 22, + NAL_RSV_IRAP_VCL23 = 23, + NAL_VPS = 32, NAL_SPS = 33, NAL_PPS = 34, @@ -101,17 +104,7 @@ public: } static bool isKeyFrame(int type) { - switch (type) { - case NAL_BLA_N_LP: - case NAL_BLA_W_LP: - case NAL_BLA_W_RADL: - case NAL_CRA_NUT: - case NAL_IDR_N_LP: - case NAL_IDR_W_RADL: - return true; - default: - return false; - } + return type >= NAL_BLA_W_LP && type <= NAL_RSV_IRAP_VCL23; } public: From f9df7f521701c1f44c5217db748afc77faa24c65 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Wed, 29 Apr 2020 11:08:43 +0800 Subject: [PATCH 06/11] =?UTF-8?q?=E5=8E=BB=E9=99=A4ultraLowDelay=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conf/config.ini | 6 ++---- src/Common/MediaSource.cpp | 3 +-- src/Common/config.cpp | 4 +--- src/Common/config.h | 4 +--- src/Http/HttpSession.cpp | 4 ++-- src/Rtmp/RtmpPusher.cpp | 4 ++-- src/Rtmp/RtmpSession.cpp | 4 ++-- src/Rtsp/RtspPusher.cpp | 4 ++-- src/Rtsp/RtspSession.cpp | 4 ++-- 9 files changed, 15 insertions(+), 22 deletions(-) diff --git a/conf/config.ini b/conf/config.ini index accde647..44aca9e6 100644 --- a/conf/config.ini +++ b/conf/config.ini @@ -29,8 +29,6 @@ maxStreamWaitMS=15000 #某个流无人观看时,触发hook.on_stream_none_reader事件的最大等待时间,单位毫秒 #在配合hook.on_stream_none_reader事件时,可以做到无人观看自动停止拉流或停止接收推流 streamNoneReaderDelayMS=20000 -#是否开启低延时模式,该模式下禁用MSG_MORE,启用TCP_NODEALY,延时将降低,但数据发送性能将降低 -ultraLowDelay=1 #拉流代理是否添加静音音频(直接拉流模式本协议无效) addMuteAudio=1 #拉流代理时如果断流再重连成功是否删除前一次的媒体流数据,如果删除将重新开始, @@ -43,8 +41,8 @@ publishToHls=1 #是否默认推流时mp4录像,hook接口(on_publish)中可以覆盖该设置 publishToMP4=0 #合并写缓存大小(单位毫秒),合并写指服务器缓存一定的数据后才会一次性写入socket,这样能提高性能,但是会提高延时 -#在开启低延时模式后,该参数不起作用 -mergeWriteMS=300 +#开启后会同时关闭TCP_NODELAY并开启MSG_MORE +mergeWriteMS=0 [hls] #hls写文件的buf大小,调整参数可以提高文件io性能 diff --git a/src/Common/MediaSource.cpp b/src/Common/MediaSource.cpp index 3c41c0ec..fafb13dd 100644 --- a/src/Common/MediaSource.cpp +++ b/src/Common/MediaSource.cpp @@ -516,9 +516,8 @@ static bool isFlushAble_merge(bool is_audio, uint32_t last_stamp, uint32_t new_s bool FlushPolicy::isFlushAble(uint32_t new_stamp, int cache_size) { bool ret = false; - GET_CONFIG(bool, ultraLowDelay, General::kUltraLowDelay); GET_CONFIG(int, mergeWriteMS, General::kMergeWriteMS); - if (ultraLowDelay || mergeWriteMS <= 0) { + if (mergeWriteMS <= 0) { //关闭了合并写或者合并写阈值小于等于0 ret = isFlushAble_default(_is_audio, _last_stamp, new_stamp, cache_size); } else { diff --git a/src/Common/config.cpp b/src/Common/config.cpp index 819901fb..8a22bea1 100644 --- a/src/Common/config.cpp +++ b/src/Common/config.cpp @@ -61,7 +61,6 @@ const string kFlowThreshold = GENERAL_FIELD"flowThreshold"; const string kStreamNoneReaderDelayMS = GENERAL_FIELD"streamNoneReaderDelayMS"; const string kMaxStreamWaitTimeMS = GENERAL_FIELD"maxStreamWaitMS"; const string kEnableVhost = GENERAL_FIELD"enableVhost"; -const string kUltraLowDelay = GENERAL_FIELD"ultraLowDelay"; const string kAddMuteAudio = GENERAL_FIELD"addMuteAudio"; const string kResetWhenRePlay = GENERAL_FIELD"resetWhenRePlay"; const string kPublishToRtxp = GENERAL_FIELD"publishToRtxp"; @@ -74,13 +73,12 @@ onceToken token([](){ mINI::Instance()[kStreamNoneReaderDelayMS] = 20 * 1000; mINI::Instance()[kMaxStreamWaitTimeMS] = 15 * 1000; mINI::Instance()[kEnableVhost] = 0; - mINI::Instance()[kUltraLowDelay] = 1; mINI::Instance()[kAddMuteAudio] = 1; mINI::Instance()[kResetWhenRePlay] = 1; mINI::Instance()[kPublishToRtxp] = 1; mINI::Instance()[kPublishToHls] = 1; mINI::Instance()[kPublishToMP4] = 0; - mINI::Instance()[kMergeWriteMS] = 300; + mINI::Instance()[kMergeWriteMS] = 0; },nullptr); }//namespace General diff --git a/src/Common/config.h b/src/Common/config.h index aa42acaa..3948879f 100644 --- a/src/Common/config.h +++ b/src/Common/config.h @@ -160,8 +160,6 @@ extern const string kStreamNoneReaderDelayMS; extern const string kMaxStreamWaitTimeMS; //是否启动虚拟主机 extern const string kEnableVhost; -//超低延时模式,默认打开,打开后会降低延时但是转发性能会稍差 -extern const string kUltraLowDelay; //拉流代理时是否添加静音音频 extern const string kAddMuteAudio; //拉流代理时如果断流再重连成功是否删除前一次的媒体流数据,如果删除将重新开始, @@ -174,7 +172,7 @@ extern const string kPublishToHls ; //是否默认推流时mp4录像,hook接口(on_publish)中可以覆盖该设置 extern const string kPublishToMP4 ; //合并写缓存大小(单位毫秒),合并写指服务器缓存一定的数据后才会一次性写入socket,这样能提高性能,但是会提高延时 -//在开启低延时模式后,该参数不起作用 +//开启后会同时关闭TCP_NODELAY并开启MSG_MORE extern const string kMergeWriteMS ; }//namespace General diff --git a/src/Http/HttpSession.cpp b/src/Http/HttpSession.cpp index 26056ed0..65ed9b3a 100644 --- a/src/Http/HttpSession.cpp +++ b/src/Http/HttpSession.cpp @@ -606,8 +606,8 @@ void HttpSession::sendNotFound(bool bClose) { } void HttpSession::setSocketFlags(){ - GET_CONFIG(bool,ultraLowDelay,General::kUltraLowDelay); - if(!ultraLowDelay) { + GET_CONFIG(int, mergeWriteMS, General::kMergeWriteMS); + if(mergeWriteMS > 0) { //推流模式下,关闭TCP_NODELAY会增加推流端的延时,但是服务器性能将提高 SockUtil::setNoDelay(_sock->rawFD(), false); //播放模式下,开启MSG_MORE会增加延时,但是能提高发送性能 diff --git a/src/Rtmp/RtmpPusher.cpp b/src/Rtmp/RtmpPusher.cpp index 3722e23d..725868b5 100644 --- a/src/Rtmp/RtmpPusher.cpp +++ b/src/Rtmp/RtmpPusher.cpp @@ -228,8 +228,8 @@ inline void RtmpPusher::send_metaData(){ } void RtmpPusher::setSocketFlags(){ - GET_CONFIG(bool,ultraLowDelay,General::kUltraLowDelay); - if(!ultraLowDelay) { + GET_CONFIG(int, mergeWriteMS, General::kMergeWriteMS); + if(mergeWriteMS > 0) { //提高发送性能 setSendFlags(SOCKET_DEFAULE_FLAGS | FLAG_MORE); SockUtil::setNoDelay(_sock->rawFD(), false); diff --git a/src/Rtmp/RtmpSession.cpp b/src/Rtmp/RtmpSession.cpp index d606f118..a062c5d6 100644 --- a/src/Rtmp/RtmpSession.cpp +++ b/src/Rtmp/RtmpSession.cpp @@ -529,8 +529,8 @@ int RtmpSession::totalReaderCount(MediaSource &sender) { } void RtmpSession::setSocketFlags(){ - GET_CONFIG(bool,ultraLowDelay,General::kUltraLowDelay); - if(!ultraLowDelay) { + GET_CONFIG(int, mergeWriteMS, General::kMergeWriteMS); + if(mergeWriteMS > 0) { //推流模式下,关闭TCP_NODELAY会增加推流端的延时,但是服务器性能将提高 SockUtil::setNoDelay(_sock->rawFD(), false); //播放模式下,开启MSG_MORE会增加延时,但是能提高发送性能 diff --git a/src/Rtsp/RtspPusher.cpp b/src/Rtsp/RtspPusher.cpp index 5243be4c..f259a0d6 100644 --- a/src/Rtsp/RtspPusher.cpp +++ b/src/Rtsp/RtspPusher.cpp @@ -392,8 +392,8 @@ void RtspPusher::sendRecord() { } void RtspPusher::setSocketFlags(){ - GET_CONFIG(bool,ultraLowDelay,General::kUltraLowDelay); - if(!ultraLowDelay) { + GET_CONFIG(int, mergeWriteMS, General::kMergeWriteMS); + if(mergeWriteMS > 0) { //提高发送性能 setSendFlags(SOCKET_DEFAULE_FLAGS | FLAG_MORE); SockUtil::setNoDelay(_sock->rawFD(), false); diff --git a/src/Rtsp/RtspSession.cpp b/src/Rtsp/RtspSession.cpp index f8591e6c..a9cbcffb 100644 --- a/src/Rtsp/RtspSession.cpp +++ b/src/Rtsp/RtspSession.cpp @@ -1236,8 +1236,8 @@ void RtspSession::sendSenderReport(bool overTcp,int iTrackIndex) { } void RtspSession::setSocketFlags(){ - GET_CONFIG(bool,ultraLowDelay,General::kUltraLowDelay); - if(!ultraLowDelay) { + GET_CONFIG(int, mergeWriteMS, General::kMergeWriteMS); + if(mergeWriteMS > 0) { //推流模式下,关闭TCP_NODELAY会增加推流端的延时,但是服务器性能将提高 SockUtil::setNoDelay(_sock->rawFD(), false); //播放模式下,开启MSG_MORE会增加延时,但是能提高发送性能 From 7e85be76543b402f69e0bda1eebac12505a63b66 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Wed, 29 Apr 2020 11:25:15 +0800 Subject: [PATCH 07/11] =?UTF-8?q?=E6=B7=BB=E5=8A=A0rtmps=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/main.cpp | 48 ++++++++++++++++++++++++++++-------------- src/Rtmp/RtmpSession.h | 6 ++++++ 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/server/main.cpp b/server/main.cpp index 55ea061e..cd1ee8a0 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -75,8 +75,10 @@ onceToken token1([](){ namespace Rtmp { #define RTMP_FIELD "rtmp." const string kPort = RTMP_FIELD"port"; +const string kSSLPort = RTMP_FIELD"sslport"; onceToken token1([](){ mINI::Instance()[kPort] = 1935; + mINI::Instance()[kSSLPort] = 19350; },nullptr); } //namespace RTMP @@ -255,9 +257,10 @@ int start_main(int argc,char *argv[]) { uint16_t rtspPort = mINI::Instance()[Rtsp::kPort]; uint16_t rtspsPort = mINI::Instance()[Rtsp::kSSLPort]; uint16_t rtmpPort = mINI::Instance()[Rtmp::kPort]; + uint16_t rtmpsPort = mINI::Instance()[Rtmp::kSSLPort]; uint16_t httpPort = mINI::Instance()[Http::kPort]; uint16_t httpsPort = mINI::Instance()[Http::kSSLPort]; - uint16_t rtp_proxy = mINI::Instance()[RtpProxy::kPort]; + uint16_t rtpPort = mINI::Instance()[RtpProxy::kPort]; //设置poller线程数,该函数必须在使用ZLToolKit网络相关对象之前调用才能生效 EventPollerPool::setPoolSize(threads); @@ -265,38 +268,51 @@ int start_main(int argc,char *argv[]) { //简单的telnet服务器,可用于服务器调试,但是不能使用23端口,否则telnet上了莫名其妙的现象 //测试方法:telnet 127.0.0.1 9000 TcpServer::Ptr shellSrv(new TcpServer()); + + //rtsp[s]服务器, 可用于诸如亚马逊echo show这样的设备访问 TcpServer::Ptr rtspSrv(new TcpServer()); - TcpServer::Ptr rtmpSrv(new TcpServer()); - TcpServer::Ptr httpSrv(new TcpServer()); - //如果支持ssl,还可以开启https服务器 - TcpServer::Ptr httpsSrv(new TcpServer()); - //支持ssl加密的rtsp服务器,可用于诸如亚马逊echo show这样的设备访问 TcpServer::Ptr rtspSSLSrv(new TcpServer()); + //rtmp[s]服务器 + TcpServer::Ptr rtmpSrv(new TcpServer()); + TcpServer::Ptr rtmpsSrv(new TcpServer()); + + //http[s]服务器 + TcpServer::Ptr httpSrv(new TcpServer()); + TcpServer::Ptr httpsSrv(new TcpServer()); + #if defined(ENABLE_RTPPROXY) + //GB28181 rtp推流端口,支持UDP/TCP UdpRecver recver; TcpServer::Ptr tcpRtpServer(new TcpServer()); #endif//defined(ENABLE_RTPPROXY) try { //rtsp服务器,端口默认554 - rtspSrv->start(rtspPort);//默认554 + if(rtspPort) { rtspSrv->start(rtspPort); } //rtsps服务器,端口默认322 - rtspSSLSrv->start(rtspsPort); + if(rtspsPort) { rtspSSLSrv->start(rtspsPort); } + //rtmp服务器,端口默认1935 - rtmpSrv->start(rtmpPort); + if(rtmpPort) { rtmpSrv->start(rtmpPort); } + //rtmps服务器,端口默认19350 + if(rtmpsPort) { rtmpsSrv->start(rtmpsPort); } + //http服务器,端口默认80 - httpSrv->start(httpPort); + if(httpPort) { httpSrv->start(httpPort); } //https服务器,端口默认443 - httpsSrv->start(httpsPort); + if(httpsPort) { httpsSrv->start(httpsPort); } + //telnet远程调试服务器 - shellSrv->start(shellPort); + if(shellPort) { shellSrv->start(shellPort); } #if defined(ENABLE_RTPPROXY) - //创建rtp udp服务器 - recver.initSock(rtp_proxy); - //创建rtp tcp服务器 - tcpRtpServer->start(rtp_proxy); + if(rtpPort){ + //创建rtp udp服务器 + recver.initSock(rtpPort); + //创建rtp tcp服务器 + tcpRtpServer->start(rtpPort); + } #endif//defined(ENABLE_RTPPROXY) }catch (std::exception &ex){ diff --git a/src/Rtmp/RtmpSession.h b/src/Rtmp/RtmpSession.h index da76c627..f88d2eb6 100644 --- a/src/Rtmp/RtmpSession.h +++ b/src/Rtmp/RtmpSession.h @@ -91,6 +91,12 @@ private: }; + +/** + * 支持ssl加密的rtmp服务器 + */ +typedef TcpSessionWithSSL RtmpSessionWithSSL; + } /* namespace mediakit */ #endif /* SRC_RTMP_RTMPSESSION_H_ */ From 02700579079b12e13574ea3806bbcd3907a269a6 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Wed, 29 Apr 2020 11:30:06 +0800 Subject: [PATCH 08/11] =?UTF-8?q?=E6=96=B0=E5=A2=9Ertmps=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E7=AB=AF=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conf/config.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/conf/config.ini b/conf/config.ini index 44aca9e6..02fc096c 100644 --- a/conf/config.ini +++ b/conf/config.ini @@ -148,6 +148,8 @@ keepAliveSecond=15 modifyStamp=0 #rtmp服务器监听端口 port=1935 +#rtmps服务器监听地址 +sslport=19350 [rtp] #音频mtu大小,该参数限制rtp最大字节数,推荐不要超过1400 From 3630839bc9778b05419d968dbf88d0bda000d123 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Wed, 29 Apr 2020 11:59:45 +0800 Subject: [PATCH 09/11] =?UTF-8?q?=E5=85=B3=E9=97=AD=E8=BD=AC=E5=8D=8F?= =?UTF-8?q?=E8=AE=AE=E5=90=8E=EF=BC=8C=E5=B0=86=E5=85=B3=E9=97=AD=E8=A7=A3?= =?UTF-8?q?=E5=A4=8D=E7=94=A8=E4=BB=A5=E6=8F=90=E4=BE=9B=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Common/MultiMediaSourceMuxer.cpp | 18 ++++++++++++++++-- src/Common/MultiMediaSourceMuxer.h | 8 ++++++++ src/Rtmp/RtmpMediaSourceImp.h | 11 ++++++++++- src/Rtsp/RtspMediaSourceImp.h | 11 ++++++++++- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/Common/MultiMediaSourceMuxer.cpp b/src/Common/MultiMediaSourceMuxer.cpp index 6047062e..58217d2b 100644 --- a/src/Common/MultiMediaSourceMuxer.cpp +++ b/src/Common/MultiMediaSourceMuxer.cpp @@ -22,17 +22,21 @@ MultiMuxerPrivate::MultiMuxerPrivate(const string &vhost, bool enable_mp4) { if (enable_rtmp) { _rtmp = std::make_shared(vhost, app, stream, std::make_shared(dur_sec)); + _enable_rtxp = true; } if (enable_rtsp) { _rtsp = std::make_shared(vhost, app, stream, std::make_shared(dur_sec)); + _enable_rtxp = true; } if (enable_hls) { _hls = Recorder::createRecorder(Recorder::type_hls, vhost, app, stream); + _enable_record = true; } if (enable_mp4) { _mp4 = Recorder::createRecorder(Recorder::type_mp4, vhost, app, stream); + _enable_record = true; } } @@ -102,6 +106,7 @@ bool MultiMuxerPrivate::setupRecord(MediaSource &sender, Recorder::type type, bo //停止录制 _hls = nullptr; } + _enable_record = _hls || _mp4; return true; } case Recorder::type_mp4 : { @@ -112,10 +117,10 @@ bool MultiMuxerPrivate::setupRecord(MediaSource &sender, Recorder::type type, bo //停止录制 _mp4 = nullptr; } + _enable_record = _hls || _mp4; return true; } - default: - return false; + default : return false; } } @@ -163,6 +168,10 @@ void MultiMuxerPrivate::onTrackReady(const Track::Ptr &track) { } } +bool MultiMuxerPrivate::isEnabled(){ + return _enable_rtxp || _enable_record; +} + void MultiMuxerPrivate::onTrackFrame(const Frame::Ptr &frame) { if (_rtmp) { _rtmp->inputFrame(frame); @@ -293,4 +302,9 @@ void MultiMediaSourceMuxer::inputFrame(const Frame::Ptr &frame) { _muxer->inputFrame(frame); } +bool MultiMediaSourceMuxer::isEnabled(){ + return _muxer->isEnabled(); +} + + }//namespace mediakit \ No newline at end of file diff --git a/src/Common/MultiMediaSourceMuxer.h b/src/Common/MultiMediaSourceMuxer.h index 5ba6b8fe..04109745 100644 --- a/src/Common/MultiMediaSourceMuxer.h +++ b/src/Common/MultiMediaSourceMuxer.h @@ -45,6 +45,7 @@ private: void setTrackListener(Listener *listener); bool setupRecord(MediaSource &sender, Recorder::type type, bool start, const string &custom_path); bool isRecording(MediaSource &sender, Recorder::type type); + bool isEnabled(); private: void onTrackReady(const Track::Ptr & track) override; void onTrackFrame(const Frame::Ptr &frame) override; @@ -57,6 +58,8 @@ private: MediaSinkInterface::Ptr _mp4; Listener *_listener = nullptr; std::weak_ptr _meida_listener; + bool _enable_rtxp = false; + bool _enable_record = false; }; class MultiMediaSourceMuxer : public MediaSourceEvent, public MediaSinkInterface, public TrackSource, public std::enable_shared_from_this{ @@ -167,6 +170,11 @@ public: * @param frame 帧 */ void inputFrame(const Frame::Ptr &frame) override; + + /** + * 判断是否生效(是否正在转其他协议) + */ + bool isEnabled(); private: MultiMuxerPrivate::Ptr _muxer; std::weak_ptr _listener; diff --git a/src/Rtmp/RtmpMediaSourceImp.h b/src/Rtmp/RtmpMediaSourceImp.h index 954180b9..e78f1286 100644 --- a/src/Rtmp/RtmpMediaSourceImp.h +++ b/src/Rtmp/RtmpMediaSourceImp.h @@ -57,7 +57,14 @@ public: * 输入rtmp并解析 */ void onWrite(const RtmpPacket::Ptr &pkt,bool key_pos = true) override { - key_pos = _demuxer->inputRtmp(pkt); + if(_all_track_ready && !_muxer->isEnabled()){ + //获取到所有Track后,并且未开启转协议,那么不需要解复用rtmp + key_pos = pkt->isVideoKeyFrame(); + }else{ + //需要解复用rtmp + key_pos = _demuxer->inputRtmp(pkt); + } + RtmpMediaSource::onWrite(pkt,key_pos); } @@ -138,10 +145,12 @@ public: */ void onAllTrackReady() override{ setTrackSource(_muxer); + _all_track_ready = true; } private: RtmpDemuxer::Ptr _demuxer; MultiMediaSourceMuxer::Ptr _muxer; + bool _all_track_ready = false; }; } /* namespace mediakit */ diff --git a/src/Rtsp/RtspMediaSourceImp.h b/src/Rtsp/RtspMediaSourceImp.h index 495158f3..91a97992 100644 --- a/src/Rtsp/RtspMediaSourceImp.h +++ b/src/Rtsp/RtspMediaSourceImp.h @@ -48,7 +48,14 @@ public: * 输入rtp并解析 */ void onWrite(const RtpPacket::Ptr &rtp, bool key_pos) override { - key_pos = _demuxer->inputRtp(rtp); + if(_all_track_ready && !_muxer->isEnabled()){ + //获取到所有Track后,并且未开启转协议,那么不需要解复用rtp + //在关闭rtp解复用后,无法知道是否为关键帧,这样会导致无法秒开,或者开播花屏 + key_pos = rtp->type == TrackVideo; + }else{ + //需要解复用rtp + key_pos = _demuxer->inputRtp(rtp); + } RtspMediaSource::onWrite(rtp, key_pos); } @@ -129,10 +136,12 @@ public: */ void onAllTrackReady() override{ setTrackSource(_muxer); + _all_track_ready = true; } private: RtspDemuxer::Ptr _demuxer; MultiMediaSourceMuxer::Ptr _muxer; + bool _all_track_ready = false; }; } /* namespace mediakit */ From 9d9f6e304eb4fcf7fc45020aecb3fffe7a807282 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Wed, 29 Apr 2020 18:05:29 +0800 Subject: [PATCH 10/11] =?UTF-8?q?=E5=AE=8C=E5=96=84dts=E8=AE=A1=E7=AE=97?= =?UTF-8?q?=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Common/Stamp.cpp | 30 +++++++++++++++++++++++++++--- src/Extension/H264Rtp.cpp | 17 ++++------------- src/Extension/H265Rtp.cpp | 16 ++++------------ 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/Common/Stamp.cpp b/src/Common/Stamp.cpp index e184dcdb..b537e8fe 100644 --- a/src/Common/Stamp.cpp +++ b/src/Common/Stamp.cpp @@ -95,7 +95,7 @@ int64_t Stamp::getRelativeStamp() const { bool DtsGenerator::getDts(uint32_t pts, uint32_t &dts){ bool ret = false; if(pts == _last_pts){ - //pts未变,返回上次结果 + //pts未变,说明dts也不会变,返回上次dts if(_last_dts){ dts = _last_dts; ret = true; @@ -105,44 +105,68 @@ bool DtsGenerator::getDts(uint32_t pts, uint32_t &dts){ ret = getDts_l(pts,dts); if(ret){ - //保存本次结果 + //获取到了dts,保存本次结果 _last_dts = dts; + }else{ + //pts排序列队长度还不知道,也就是不知道有没有B帧, + //那么先强制dts == pts,这样可能导致有B帧的情况下,起始画面有几帧回退 + dts = pts; } //记录上次pts _last_pts = pts; return ret; } +//该算法核心思想是对pts进行排序,排序好的pts就是dts。 +//排序有一定的滞后性,那么需要加上排序导致的时间戳偏移量 bool DtsGenerator::getDts_l(uint32_t pts, uint32_t &dts){ if(_sorter_max_size == 1){ - //没有B帧 + //没有B帧,dts就等于pts dts = pts; return true; } if(!_sorter_max_size){ + //尚未计算出pts排序列队长度(也就是P帧间B帧个数) if(pts > _last_max_pts){ + //pts时间戳增加了,那么说明这帧画面不是B帧(说明是P帧或关键帧) if(_frames_since_last_max_pts && _count_sorter_max_size++ > 0){ + //已经出现多次非B帧的情况,那么我们就能知道P帧间B帧的个数 _sorter_max_size = _frames_since_last_max_pts; + //我们记录P帧间时间间隔(也就是多个B帧时间戳增量累计) _dts_pts_offset = (pts - _last_max_pts) / 2; } + //遇到P帧或关键帧,连续B帧计数清零 _frames_since_last_max_pts = 0; + //记录上次非B帧的pts时间戳(同时也是dts),用于统计连续B帧时间戳增量 _last_max_pts = pts; } + //如果pts时间戳小于上一个P帧,那么断定这个是B帧,我们记录B帧连续个数 ++_frames_since_last_max_pts; } + //pts放入排序缓存列队,缓存列队最大等于连续B帧个数 _pts_sorter.emplace(pts); + if(_sorter_max_size && _pts_sorter.size() > _sorter_max_size){ + //如果启用了pts排序(意味着存在B帧),并且pts排序缓存列队长度大于连续B帧个数, + //意味着后续的pts都会比最早的pts大,那么说明可以取出最早的pts了,这个pts将当做该帧的dts基准 auto it = _pts_sorter.begin(); + + //由于该pts是前面偏移了个_sorter_max_size帧的pts(也就是那帧画面的dts), + //那么我们加上时间戳偏移量,基本等于该帧的dts dts = *it + _dts_pts_offset; if(dts > pts){ //dts不能大于pts(基本不可能到达这个逻辑) dts = pts; } + + //pts排序缓存出列 _pts_sorter.erase(it); return true; } + + //排序缓存尚未满 return false; } diff --git a/src/Extension/H264Rtp.cpp b/src/Extension/H264Rtp.cpp index 1a3f08a8..d9b4b9f6 100644 --- a/src/Extension/H264Rtp.cpp +++ b/src/Extension/H264Rtp.cpp @@ -191,19 +191,10 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) { } void H264RtpDecoder::onGetH264(const H264Frame::Ptr &frame) { - auto flag = _dts_generator.getDts(frame->_pts,frame->_dts); - if(!flag){ - if(frame->configFrame() || frame->keyFrame()){ - flag = true; - frame->_dts = frame->_pts; - } - } - - //根据pts计算dts - if(flag){ - //写入环形缓存 - RtpCodec::inputFrame(frame); - } + //rtsp没有dts,那么根据pts排序算法生成dts + _dts_generator.getDts(frame->_pts,frame->_dts); + //写入环形缓存 + RtpCodec::inputFrame(frame); _h264frame = obtainFrame(); } diff --git a/src/Extension/H265Rtp.cpp b/src/Extension/H265Rtp.cpp index b41b4cfa..daa190a0 100644 --- a/src/Extension/H265Rtp.cpp +++ b/src/Extension/H265Rtp.cpp @@ -127,18 +127,10 @@ bool H265RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) { } void H265RtpDecoder::onGetH265(const H265Frame::Ptr &frame) { - //计算dts - auto flag = _dts_generator.getDts(frame->_pts,frame->_dts); - if(!flag){ - if(frame->configFrame() || frame->keyFrame()){ - flag = true; - frame->_dts = frame->_pts; - } - } - if(flag){ - //写入环形缓存 - RtpCodec::inputFrame(frame); - } + //rtsp没有dts,那么根据pts排序算法生成dts + _dts_generator.getDts(frame->_pts,frame->_dts); + //写入环形缓存 + RtpCodec::inputFrame(frame); _h265frame = obtainFrame(); } From 1067c5a2d3a7c75439574cd8d095a0a6ba966ccb Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Wed, 29 Apr 2020 18:19:51 +0800 Subject: [PATCH 11/11] =?UTF-8?q?=E5=86=8D=E4=BC=98=E5=8C=96dts=E8=8E=B7?= =?UTF-8?q?=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Common/Stamp.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/Common/Stamp.cpp b/src/Common/Stamp.cpp index b537e8fe..ecc52e81 100644 --- a/src/Common/Stamp.cpp +++ b/src/Common/Stamp.cpp @@ -91,27 +91,29 @@ int64_t Stamp::getRelativeStamp() const { return _relativeStamp; } - bool DtsGenerator::getDts(uint32_t pts, uint32_t &dts){ bool ret = false; - if(pts == _last_pts){ + if (pts == _last_pts) { //pts未变,说明dts也不会变,返回上次dts - if(_last_dts){ + if (_last_dts) { dts = _last_dts; ret = true; } - return ret; + } else { + //pts变了,尝试计算dts + ret = getDts_l(pts, dts); + if (ret) { + //获取到了dts,保存本次结果 + _last_dts = dts; + } } - ret = getDts_l(pts,dts); - if(ret){ - //获取到了dts,保存本次结果 - _last_dts = dts; - }else{ + if (!ret) { //pts排序列队长度还不知道,也就是不知道有没有B帧, //那么先强制dts == pts,这样可能导致有B帧的情况下,起始画面有几帧回退 dts = pts; } + //记录上次pts _last_pts = pts; return ret;