diff --git a/src/media/socket_pair.cpp b/src/media/socket_pair.cpp index 04234e36e77b28e9285075567db0a3fc349bb323..3f6cb1555cf545f1caddcb330f063170a9f6bf52 100644 --- a/src/media/socket_pair.cpp +++ b/src/media/socket_pair.cpp @@ -457,6 +457,9 @@ SocketPair::readCallback(uint8_t* buf, int buf_size) // SRTP decrypt if (not fromRTCP and srtpContext_ and srtpContext_->srtp_in.aes) { auto err = ff_srtp_decrypt(&srtpContext_->srtp_in, buf, &len); + if(packetLossCallback_ and (buf[2] << 8 | buf[3]) != lastSeqNum_+1) + packetLossCallback_(); + lastSeqNum_ = buf[2] << 8 | buf[3]; if (err < 0) JAMI_WARN("decrypt error %d", err); } @@ -581,4 +584,10 @@ SocketPair::getLastLatency() return -1; } +void +SocketPair::setPacketLossCallback(std::function<void(void)> cb) +{ + packetLossCallback_ = std::move(cb); +} + } // namespace jami diff --git a/src/media/socket_pair.h b/src/media/socket_pair.h index e620202e9fd6027875d37b870c740d3363d433ad..593996cd97e4fbaef4804cf65923fa24cee56a1e 100644 --- a/src/media/socket_pair.h +++ b/src/media/socket_pair.h @@ -45,7 +45,7 @@ using socklen_t = int; #include <list> #include <vector> #include <condition_variable> - +#include <functional> namespace jami { @@ -136,6 +136,8 @@ class SocketPair { bool waitForRTCP(std::chrono::seconds interval); double getLastLatency(); + void setPacketLossCallback(std::function<void (void)> cb); + private: NON_COPYABLE(SocketPair); @@ -163,6 +165,7 @@ class SocketPair { std::atomic_bool interrupted_ {false}; std::atomic_bool noWrite_ {false}; std::unique_ptr<SRTPProtoContext> srtpContext_; + std::function<void(void)> packetLossCallback_; std::list<rtcpRRHeader> listRtcpHeader_; std::mutex rtcpInfo_mutex_; @@ -176,6 +179,7 @@ class SocketPair { std::list<double> histoLatency_; std::chrono::steady_clock::time_point lastRR_time; + uint16_t lastSeqNum_ {0}; }; diff --git a/src/media/video/video_rtp_session.cpp b/src/media/video/video_rtp_session.cpp index 8ae0146f6ac9d13c41ed8417e9b28d55bff61350..2a28e1b52fee3842b54c7848ad8a32c9741ec317 100644 --- a/src/media/video/video_rtp_session.cpp +++ b/src/media/video/video_rtp_session.cpp @@ -75,7 +75,10 @@ VideoRtpSession::updateMedia(const MediaDescription& send, const MediaDescriptio void VideoRtpSession::setRequestKeyFrameCallback(std::function<void(void)> cb) { - requestKeyFrameCallback_ = std::move(cb); + if(socketPair_) + socketPair_->setPacketLossCallback(std::move(cb)); + else + JAMI_ERR("No socket pair, keyframe request callback not possible"); } void VideoRtpSession::startSender() diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp index f9ac13590ee7e1a07d7a1c69bf8a57bf7a4d62e9..71e5dccc19e7b8c1cc61cad4293dab2746a47318 100644 --- a/src/sip/sipcall.cpp +++ b/src/sip/sipcall.cpp @@ -69,6 +69,7 @@ getVideoSettings() static constexpr std::chrono::seconds DEFAULT_ICE_INIT_TIMEOUT {35}; // seconds static constexpr std::chrono::seconds DEFAULT_ICE_NEGO_TIMEOUT {60}; // seconds +static constexpr std::chrono::milliseconds MS_BETWEEN_2_KEYFRAME_REQUEST {1000}; // SDP media Ids static constexpr int SDP_AUDIO_MEDIA_ID {0}; @@ -271,18 +272,22 @@ SIPCall::sendSIPInfo(const char *const body, const char *const subtype) void SIPCall::requestKeyframe() { - constexpr const char * const BODY = - "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" - "<media_control><vc_primitive><to_encoder>" - "<picture_fast_update/>" - "</to_encoder></vc_primitive></media_control>"; + auto now = clock::now(); + if ((now - lastKeyFrameReq_) < MS_BETWEEN_2_KEYFRAME_REQUEST and lastKeyFrameReq_ != time_point::min()) + return; + constexpr const char * const BODY = + "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" + "<media_control><vc_primitive><to_encoder>" + "<picture_fast_update/>" + "</to_encoder></vc_primitive></media_control>"; JAMI_DBG("Sending video keyframe request via SIP INFO"); try { sendSIPInfo(BODY, "media_control+xml"); } catch (const std::exception& e) { JAMI_ERR("Error sending video keyframe request: %s", e.what()); } + lastKeyFrameReq_ = now; } void @@ -907,21 +912,6 @@ SIPCall::startAllMedia() bool peer_holding {true}; int slotN = -1; -#ifdef ENABLE_VIDEO - videortp_->setRequestKeyFrameCallback([wthis = weak()] { - runOnMainThread([wthis] { - if (auto this_ = wthis.lock()) - this_->requestKeyframe(); - }); - }); - videortp_->setChangeOrientationCallback([wthis = weak()] (int angle) { - runOnMainThread([wthis, angle] { - if (auto this_ = wthis.lock()) - this_->setVideoOrientation(angle); - }); - }); -#endif - for (const auto& slot : slots) { ++slotN; const auto& local = slot.first; @@ -1001,6 +991,21 @@ SIPCall::startAllMedia() } } +#ifdef ENABLE_VIDEO + videortp_->setRequestKeyFrameCallback([wthis = weak()] { + runOnMainThread([wthis] { + if (auto this_ = wthis.lock()) + this_->requestKeyframe(); + }); + }); + videortp_->setChangeOrientationCallback([wthis = weak()] (int angle) { + runOnMainThread([wthis, angle] { + if (auto this_ = wthis.lock()) + this_->setVideoOrientation(angle); + }); + }); +#endif + if (not isSubcall() and peerHolding_ != peer_holding) { peerHolding_ = peer_holding; emitSignal<DRing::CallSignal::PeerHold>(getCallId(), peerHolding_); diff --git a/src/sip/sipcall.h b/src/sip/sipcall.h index ab44cab6d88170da15d4a05820f6c156c8dc7c17..44a4ef82c05fc3bdbb14533a39cf2717e07be9c2 100644 --- a/src/sip/sipcall.h +++ b/src/sip/sipcall.h @@ -246,6 +246,9 @@ public: // NOT SIP RELATED (good candidates to be moved elsewhere) void rtpSetupSuccess(MediaType type); private: + using clock = std::chrono::steady_clock; + using time_point = clock::time_point; + NON_COPYABLE(SIPCall); void setCallMediaLocal(); @@ -338,6 +341,8 @@ private: bool readyToRecord_ {false}; bool pendingRecord_ {false}; + + time_point lastKeyFrameReq_ {time_point::min()}; }; // Helpers