diff --git a/src/call.h b/src/call.h index e54632a070998ea487c7e41dbe1f2abd11effb8d..f3374befc8d1d96d6304489748ba9ae57711d16a 100644 --- a/src/call.h +++ b/src/call.h @@ -346,7 +346,8 @@ public: // media management virtual void enterConference(const std::string& confId) = 0; virtual void exitConference() = 0; - virtual video::VideoGenerator* getVideoReceiver() = 0; + virtual std::shared_ptr<Observable<std::shared_ptr<MediaFrame>>> + getReceiveVideoFrameActiveWriter() = 0; std::vector<std::map<std::string, std::string>> getConferenceInfos() const { @@ -401,7 +402,6 @@ protected: time_point duration_start_ {time_point::min()}; private: - bool validStateTransition(CallState newState); void checkPendingIM(); diff --git a/src/conference.cpp b/src/conference.cpp index 03640959415507f84b93d0e7a497d580afeef406..c2b283a686016c5a0648946eebdbb9e35c49c61c 100644 --- a/src/conference.cpp +++ b/src/conference.cpp @@ -316,8 +316,7 @@ Conference::setActiveParticipant(const std::string& participant_id) return; } if (auto call = getCallFromPeerID(participant_id)) { - auto videoRecv = reinterpret_cast<Observable<std::shared_ptr<MediaFrame>>*>( - call->getVideoReceiver()); + auto videoRecv = call->getReceiveVideoFrameActiveWriter().get(); videoMixer_->setActiveParticipant(videoRecv); return; } @@ -388,12 +387,12 @@ Conference::sendConferenceInfos() if (!account) continue; - dht::ThreadPool::io().run([call, - confInfo = getConfInfoHostUri(account->getUsername() - + "@ring.dht", - call->getPeerNumber())] { - call->sendConfInfo(confInfo.toString()); - }); + dht::ThreadPool::io().run( + [call, + confInfo = getConfInfoHostUri(account->getUsername() + "@ring.dht", + call->getPeerNumber())] { + call->sendConfInfo(confInfo.toString()); + }); } } @@ -675,7 +674,9 @@ Conference::onConfOrder(const std::string& callId, const std::string& confOrder) if (auto call = Manager::instance().getCallFromCallID(callId)) { auto peerID = string_remove_suffix(call->getPeerNumber(), '@'); if (!isModerator(peerID)) { - JAMI_WARN("Received conference order from a non master (%.*s)", (int) peerID.size(), peerID.data()); + JAMI_WARN("Received conference order from a non master (%.*s)", + (int) peerID.size(), + peerID.data()); return; } @@ -684,7 +685,9 @@ Conference::onConfOrder(const std::string& callId, const std::string& confOrder) Json::CharReaderBuilder rbuilder; auto reader = std::unique_ptr<Json::CharReader>(rbuilder.newCharReader()); if (!reader->parse(confOrder.c_str(), confOrder.c_str() + confOrder.size(), &root, &err)) { - JAMI_WARN("Couldn't parse conference order from %.*s", (int) peerID.size(), peerID.data()); + JAMI_WARN("Couldn't parse conference order from %.*s", + (int) peerID.size(), + peerID.data()); return; } if (root.isMember("layout")) { @@ -981,8 +984,8 @@ Conference::resizeRemoteParticipants(ConfInfo& confInfo, std::string_view peerUR int remoteFrameWidth = confInfo.w; if (remoteFrameHeight == 0 or remoteFrameWidth == 0) { - // get the size of the remote frame from receiveThread - // if the one from confInfo is empty + // get the size of the remote frame from receiveThread + // if the one from confInfo is empty if (auto call = std::dynamic_pointer_cast<SIPCall>( getCallFromPeerID(string_remove_suffix(peerURI, '@')))) { if (auto const& videoRtp = call->getVideoRtp()) { diff --git a/src/media/media_attribute.h b/src/media/media_attribute.h index a6262a6ceb97083b50ce994b400a5b14d2a1816b..8ec8173c44385ddb4cb1ec5dbfe0e2722bf47721 100644 --- a/src/media/media_attribute.h +++ b/src/media/media_attribute.h @@ -34,7 +34,7 @@ public: MediaAttribute(MediaType type = MediaType::MEDIA_NONE, bool muted = false, bool secure = true, - bool enabled = true, + bool enabled = false, std::string_view source = {}, std::string_view label = {}) : type_(type) @@ -80,7 +80,7 @@ public: MediaType type_ {MediaType::MEDIA_NONE}; bool muted_ {false}; bool secure_ {true}; - bool enabled_ {true}; + bool enabled_ {false}; std::string sourceUri_ {}; std::string label_ {}; }; diff --git a/src/media/video/video_rtp_session.cpp b/src/media/video/video_rtp_session.cpp index 94976c7cb7bffea65d500802601912582b9d02cd..d7a8cd17ff5018f96549426553ed92906ba7710d 100644 --- a/src/media/video/video_rtp_session.cpp +++ b/src/media/video/video_rtp_session.cpp @@ -397,6 +397,8 @@ VideoRtpSession::exitConference() if (receiveThread_) { conference_->detachVideo(receiveThread_.get()); receiveThread_->exitConference(); + } else { + conference_->detachVideo(dummyVideoReceive_.get()); } videoMixer_.reset(); diff --git a/src/media/video/video_rtp_session.h b/src/media/video/video_rtp_session.h index 0243a0927c8ea070e305410ea3adf4c1dc38b06f..80ac4a98571094c492a451b9a2da28ee3246e6c5 100644 --- a/src/media/video/video_rtp_session.h +++ b/src/media/video/video_rtp_session.h @@ -104,7 +104,15 @@ public: std::shared_ptr<VideoMixer>& getVideoMixer() { return videoMixer_; } - std::unique_ptr<VideoReceiveThread>& getVideoReceive() { return receiveThread_; } + std::shared_ptr<VideoReceiveThread>& getVideoReceive() { return receiveThread_; } + + std::shared_ptr<VideoFrameActiveWriter> getReceiveVideoFrameActiveWriter() + { + if (isReceiving() && receiveThread_) + return std::static_pointer_cast<VideoFrameActiveWriter>(receiveThread_); + else + return dummyVideoReceive_; + } private: void setupConferenceVideoPipeline(Conference& conference); @@ -117,7 +125,9 @@ private: DeviceParams localVideoParams_; std::unique_ptr<VideoSender> sender_; - std::unique_ptr<VideoReceiveThread> receiveThread_; + std::shared_ptr<VideoReceiveThread> receiveThread_; + std::shared_ptr<VideoFrameActiveWriter> dummyVideoReceive_ + = std::make_shared<VideoFrameActiveWriter>(); Conference* conference_ {nullptr}; std::shared_ptr<VideoMixer> videoMixer_; std::shared_ptr<VideoFrameActiveWriter> videoLocal_; diff --git a/src/sip/sipaccountbase.cpp b/src/sip/sipaccountbase.cpp index 93930760329291e8b7a17a51b9aec7f4af5164f9..c3374d1f4f85b5b1adf11204631c868ad7695bfd 100644 --- a/src/sip/sipaccountbase.cpp +++ b/src/sip/sipaccountbase.cpp @@ -138,10 +138,12 @@ std::string getDisplayed(const std::string& messageId) { // implementing https://tools.ietf.org/rfc/rfc5438.txt - return fmt::format("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" - "<imdn><message-id>{}</message-id>\n" - "<display-notification><status><displayed/></status></display-notification>\n" - "</imdn>", messageId); + return fmt::format( + "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" + "<imdn><message-id>{}</message-id>\n" + "<display-notification><status><displayed/></status></display-notification>\n" + "</imdn>", + messageId); } void @@ -684,13 +686,13 @@ SIPAccountBase::createDefaultMediaList(bool addVideo, bool onHold) // Add audio and DTMF events mediaList.emplace_back( - MediaAttribute(MediaType::MEDIA_AUDIO, onHold, secure, true, "", "main audio")); + MediaAttribute(MediaType::MEDIA_AUDIO, onHold, secure, false, "", "main audio")); #ifdef ENABLE_VIDEO // Add video if allowed. if (isVideoEnabled() and addVideo) { mediaList.emplace_back( - MediaAttribute(MediaType::MEDIA_VIDEO, onHold, secure, true, "", "main video")); + MediaAttribute(MediaType::MEDIA_VIDEO, onHold, secure, false, "", "main video")); } #endif return mediaList; diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp index 1f4c420c369455c3c4d3eacd59002ffed663ed51..b7a18b90c38d79265dedcd7ee1be246549d7f6c0 100644 --- a/src/sip/sipcall.cpp +++ b/src/sip/sipcall.cpp @@ -1412,6 +1412,7 @@ SIPCall::startAllMedia() // reset readyToRecord_ = false; resetMediaReady(); + bool isVideoEnabled = false; for (const auto& slot : slots) { ++slotN; @@ -1453,6 +1454,9 @@ SIPCall::startAllMedia() } // Configure the media. + rtpStream.mediaAttribute_->enabled_ = true; + if (rtpStream.mediaAttribute_->type_ == MEDIA_VIDEO) + isVideoEnabled = true; configureRtpSession(rtpStream.rtpSession_, rtpStream.mediaAttribute_, local, remote); // Not restarting media loop on hold as it's a huge waste of CPU ressources @@ -1487,6 +1491,11 @@ SIPCall::startAllMedia() // Video is muted if all video streams are muted. isVideoMuted_ = iter == rtpStreams_.end(); + + if (!isVideoEnabled && !getConfId().empty()) { + auto conference = Manager::instance().getConferenceFromID(getConfId()); + conference->attachVideo(getReceiveVideoFrameActiveWriter().get(), getCallId()); + } #endif // Media is restarted, we can process the last holding request. diff --git a/src/sip/sipcall.h b/src/sip/sipcall.h index 5dc0de5e06d30c21fcbd3030a2c84d93d599a91d..81ea04ee80daef89742b689f024d341f06ddd60c 100644 --- a/src/sip/sipcall.h +++ b/src/sip/sipcall.h @@ -148,11 +148,12 @@ public: std::map<std::string, std::string> getDetails() const override; void enterConference(const std::string& confId) override; void exitConference() override; - video::VideoGenerator* getVideoReceiver() override + std::shared_ptr<Observable<std::shared_ptr<MediaFrame>>> getReceiveVideoFrameActiveWriter() + override { auto const& videoRtp = getVideoRtp(); if (videoRtp) - return videoRtp->getVideoReceive().get(); + return videoRtp->getReceiveVideoFrameActiveWriter(); return nullptr; }