diff --git a/src/Common/config.cpp b/src/Common/config.cpp index 5a538ab4f5..8b7031ae9a 100644 --- a/src/Common/config.cpp +++ b/src/Common/config.cpp @@ -361,6 +361,7 @@ static onceToken token([]() { namespace Client { const string kNetAdapter = "net_adapter"; const string kRtpType = "rtp_type"; +const string kRtspBeatType = "rtsp_beat_type"; const string kRtspUser = "rtsp_user"; const string kRtspPwd = "rtsp_pwd"; const string kRtspPwdIsMD5 = "rtsp_pwd_md5"; diff --git a/src/Common/config.h b/src/Common/config.h index 98ab289ce9..b10fe685dd 100644 --- a/src/Common/config.h +++ b/src/Common/config.h @@ -417,6 +417,9 @@ extern const std::string kNetAdapter; // 设置rtp传输类型,可选项有0(tcp,默认)、1(udp)、2(组播) // 设置方法:player[PlayerBase::kRtpType] = 0/1/2; extern const std::string kRtpType; +// rtsp播放器发送信令心跳还是rtcp心跳,可选项有0(同时发)、1(rtcp心跳)、2(信令心跳) +// 设置方法:player[PlayerBase::kRtspBeatType] = 0/1/2; +extern const std::string kRtspBeatType; // rtsp认证用户名 extern const std::string kRtspUser; // rtsp认证用用户密码,可以是明文也可以是md5,md5密码生成方式 md5(username:realm:password) diff --git a/src/Rtsp/RtspPlayer.cpp b/src/Rtsp/RtspPlayer.cpp index e83cc090f5..876b5f247e 100644 --- a/src/Rtsp/RtspPlayer.cpp +++ b/src/Rtsp/RtspPlayer.cpp @@ -28,6 +28,7 @@ using namespace std; namespace mediakit { enum PlayType { type_play = 0, type_pause, type_seek, type_speed }; +enum class BeatType : uint32_t { both = 0, cmd, rtcp }; RtspPlayer::RtspPlayer(const EventPoller::Ptr &poller) : TcpClient(poller) {} @@ -85,6 +86,8 @@ void RtspPlayer::play(const string &strUrl) { _play_url = url._url; _rtp_type = (Rtsp::eRtpType)(int)(*this)[Client::kRtpType]; + _beat_type = (*this)[Client::kRtspBeatType].as(); + _beat_interval_ms = (*this)[Client::kBeatIntervalMS].as(); DebugL << url._url << " " << (url._user.size() ? url._user : "null") << " " << (url._passwd.size() ? url._passwd : "null") << " " << _rtp_type; weak_ptr weakSelf = static_pointer_cast(shared_from_this()); @@ -642,23 +645,28 @@ void RtspPlayer::onBeforeRtpSorted(const RtpPacket::Ptr &rtp, int track_idx) { rtcp_ctx->onRtp(rtp->getSeq(), rtp->getStamp(), rtp->ntp_stamp, rtp->sample_rate, rtp->size() - RtpPacket::kRtpTcpHeaderSize); auto &ticker = _rtcp_send_ticker[track_idx]; - if (ticker.elapsedTime() < 3 * 1000) { - // 时间未到 + if (ticker.elapsedTime() < _beat_interval_ms) { + // 心跳时间未到 return; } + + // 有些rtsp服务器需要rtcp保活,有些需要发送信令保活; rtcp与rtsp信令轮流心跳,该特性用于兼容issue:#642 auto &rtcp_flag = _send_rtcp[track_idx]; + ticker.resetTime(); - // 每3秒发送一次心跳,rtcp与rtsp信令轮流心跳,该特性用于兼容issue:642 - // 有些rtsp服务器需要rtcp保活,有些需要发送信令保活 + switch ((BeatType)_beat_type) { + case BeatType::cmd: rtcp_flag = false; break; + case BeatType::rtcp: rtcp_flag = true; break; + case BeatType::both: + default: rtcp_flag = !rtcp_flag; break; + } // 发送信令保活 if (!rtcp_flag) { if (track_idx == 0) { + // 两个track无需同时触发发送信令保活 sendKeepAlive(); } - ticker.resetTime(); - // 下次发送rtcp保活 - rtcp_flag = true; return; } @@ -680,9 +688,6 @@ void RtspPlayer::onBeforeRtpSorted(const RtpPacket::Ptr &rtp, int track_idx) { rtcp_sdes->chunks.ssrc = htonl(ssrc); send_rtcp(this, track_idx, std::move(rtcp)); send_rtcp(this, track_idx, RtcpHeader::toBuffer(rtcp_sdes)); - ticker.resetTime(); - // 下次发送信令保活 - rtcp_flag = false; } void RtspPlayer::onPlayResult_l(const SockException &ex, bool handshake_done) { diff --git a/src/Rtsp/RtspPlayer.h b/src/Rtsp/RtspPlayer.h index 66882c206a..c40d72b7eb 100644 --- a/src/Rtsp/RtspPlayer.h +++ b/src/Rtsp/RtspPlayer.h @@ -114,6 +114,11 @@ class RtspPlayer : public PlayerBase, public toolkit::TcpClient, public RtspSpli //轮流发送rtcp与GET_PARAMETER保活 bool _send_rtcp[2] = {true, true}; + // 心跳类型 + uint32_t _beat_type = 0; + // 心跳保护间隔 + uint32_t _beat_interval_ms = 0; + std::string _play_url; std::vector _sdp_track; std::function _on_response;