diff --git a/src/media/video/video_mixer.cpp b/src/media/video/video_mixer.cpp index 279a15ee8791c6e3dbafb31e6e518b4fa3af0420..f41ea02064c041bf0e0ff9852b815f5a5f6a9de9 100644 --- a/src/media/video/video_mixer.cpp +++ b/src/media/video/video_mixer.cpp @@ -114,6 +114,11 @@ VideoMixer::switchInput(const std::string& input) videoLocal_ = getVideoCamera(); } + if (input.empty()) { + JAMI_DBG("Input is empty, don't add it in the mixer"); + return; + } + // Re-attach videoInput to mixer if (videoLocal_) { if (auto localInput = std::dynamic_pointer_cast<VideoInput>(videoLocal_)) { diff --git a/src/media/video/video_rtp_session.cpp b/src/media/video/video_rtp_session.cpp index 34ab180936cbdb01a3883e9372b39a808f3b9a80..d757817fe61af27f58135b9203fb06c90daa82ea 100644 --- a/src/media/video/video_rtp_session.cpp +++ b/src/media/video/video_rtp_session.cpp @@ -145,12 +145,21 @@ VideoRtpSession::startSender() try { sender_.reset(); socketPair_->stopSendOp(false); + MediaStream ms = !conference_ ? + MediaStream("video sender", + AV_PIX_FMT_YUV420P, + 1 / static_cast<rational<int>>(localVideoParams_.framerate), + localVideoParams_.width, + localVideoParams_.height, + send_.bitrate, + static_cast<rational<int>>(localVideoParams_.framerate)) : + conference_->getVideoMixer()->getStream("Video Sender"); sender_.reset(new VideoSender(getRemoteRtpUri(), - localVideoParams_, - send_, - *socketPair_, - initSeqVal_ + 1, - mtu_)); + ms, + send_, + *socketPair_, + initSeqVal_ + 1, + mtu_)); if (changeOrientationCallback_) sender_->setChangeOrientationCallback(changeOrientationCallback_); if (socketPair_) @@ -340,12 +349,17 @@ VideoRtpSession::enterConference(Conference* conference) // TODO is this correct? The video Mixer should be enabled for a detached conference even if we // are not sending values videoMixer_ = conference->getVideoMixer(); + auto conf_res = split_string_to_unsigned(jami::Manager::instance().videoPreferences.getConferenceResolution(), 'x'); + if (conf_res.size() != 2 or conf_res[0] <= 0 or conf_res[1] <= 0) { + JAMI_ERR("Conference resolution is invalid"); + return; + } #if defined(__APPLE__) && TARGET_OS_MAC - videoMixer_->setParameters(localVideoParams_.width, - localVideoParams_.height, - av_get_pix_fmt(localVideoParams_.pixel_format.c_str())); + videoMixer_->setParameters(conf_res[0], + conf_res[1], + AV_PIX_FMT_NV12); #else - videoMixer_->setParameters(localVideoParams_.width, localVideoParams_.height); + videoMixer_->setParameters(conf_res[0], conf_res[1]); #endif if (send_.enabled or receiveThread_) { setupConferenceVideoPipeline(*conference_); diff --git a/src/media/video/video_sender.cpp b/src/media/video/video_sender.cpp index f643046bbd25145032f7ca78ed3772ccc8c7e799..f0dae6f56349eb5017cd90bfa2c5397fb8d866d5 100644 --- a/src/media/video/video_sender.cpp +++ b/src/media/video/video_sender.cpp @@ -43,7 +43,7 @@ namespace video { using std::string; VideoSender::VideoSender(const std::string& dest, - const DeviceParams& dev, + const MediaStream& opts, const MediaDescription& args, SocketPair& socketPair, const uint16_t seqVal, @@ -51,15 +51,8 @@ VideoSender::VideoSender(const std::string& dest, : muxContext_(socketPair.createIOContext(mtu)) , videoEncoder_(new MediaEncoder) { - keyFrameFreq_ = dev.framerate.numerator() * KEY_FRAME_PERIOD; + keyFrameFreq_ = opts.frameRate.numerator() * KEY_FRAME_PERIOD; videoEncoder_->openOutput(dest, "rtp"); - auto opts = MediaStream("video sender", - AV_PIX_FMT_YUV420P, - 1 / (rational<int>) dev.framerate, - dev.width, - dev.height, - args.bitrate, - (rational<int>) dev.framerate); videoEncoder_->setOptions(opts); videoEncoder_->setOptions(args); videoEncoder_->addStream(args.codec->systemCodecInfo); @@ -70,7 +63,7 @@ VideoSender::VideoSender(const std::string& dest, Smartools::getInstance().setLocalVideoCodec(videoEncoder_->getVideoCodec()); // Send the resolution in smartInfo - Smartools::getInstance().setResolution("local", dev.width, dev.height); + Smartools::getInstance().setResolution("local", opts.width, opts.height); } VideoSender::~VideoSender() diff --git a/src/media/video/video_sender.h b/src/media/video/video_sender.h index fb8afb6deb96263151b5e5a1f5c707a40ebf74a4..fb077cb1518463eb511cf12d609ea0416bf3787c 100644 --- a/src/media/video/video_sender.h +++ b/src/media/video/video_sender.h @@ -44,7 +44,7 @@ class VideoSender : public VideoFramePassiveReader { public: VideoSender(const std::string& dest, - const DeviceParams& dev, + const MediaStream& opts, const MediaDescription& args, SocketPair& socketPair, const uint16_t seqVal, diff --git a/src/preferences.cpp b/src/preferences.cpp index ff31d7e6f1244f65713867b227ca2da9ca0394cd..4b105e1c0827dc967543bda44576c6721dc5dfac 100644 --- a/src/preferences.cpp +++ b/src/preferences.cpp @@ -78,6 +78,7 @@ using yaml_utils::parseValue; constexpr const char* const Preferences::CONFIG_LABEL; const char* const Preferences::DFT_ZONE = "North America"; const char* const Preferences::REGISTRATION_EXPIRE_KEY = "registrationexpire"; +constexpr std::string_view DEFAULT_CONFERENCE_RESOLUTION {"1280x720"}; // general preferences static constexpr const char* ORDER_KEY {"order"}; @@ -136,6 +137,7 @@ static constexpr const char* DECODING_ACCELERATED_KEY {"decodingAccelerated"}; static constexpr const char* ENCODING_ACCELERATED_KEY {"encodingAccelerated"}; static constexpr const char* RECORD_PREVIEW_KEY {"recordPreview"}; static constexpr const char* RECORD_QUALITY_KEY {"recordQuality"}; +static constexpr const char* CONFERENCE_RESOLUTION_KEY {"conferenceResolution"}; #endif #ifdef ENABLE_PLUGIN @@ -561,6 +563,7 @@ VideoPreferences::VideoPreferences() , encodingAccelerated_(false) , recordPreview_(true) , recordQuality_(0) + , conferenceResolution_(DEFAULT_CONFERENCE_RESOLUTION) {} void @@ -573,6 +576,7 @@ VideoPreferences::serialize(YAML::Emitter& out) const out << YAML::Key << DECODING_ACCELERATED_KEY << YAML::Value << decodingAccelerated_; out << YAML::Key << ENCODING_ACCELERATED_KEY << YAML::Value << encodingAccelerated_; #endif + out << YAML::Key << CONFERENCE_RESOLUTION_KEY << YAML::Value << conferenceResolution_; getVideoDeviceMonitor().serialize(out); out << YAML::EndMap; } @@ -598,6 +602,11 @@ VideoPreferences::unserialize(const YAML::Node& in) encodingAccelerated_ = false; } #endif + try { + parseValue(node, CONFERENCE_RESOLUTION_KEY, conferenceResolution_); + } catch (...) { + conferenceResolution_ = DEFAULT_CONFERENCE_RESOLUTION; + } getVideoDeviceMonitor().unserialize(in); } #endif // ENABLE_VIDEO diff --git a/src/preferences.h b/src/preferences.h index 3fcb49ad4053bc3520f3b6dbfcd9222dc83a6b50..6ef611226da84e844507dc8fe963faaf32aea3ad 100644 --- a/src/preferences.h +++ b/src/preferences.h @@ -339,11 +339,16 @@ public: void setRecordQuality(int rec) { recordQuality_ = rec; } + const std::string& getConferenceResolution() const { return conferenceResolution_; } + + void setConferenceResolution(const std::string& res) { conferenceResolution_ = res; } + private: bool decodingAccelerated_; bool encodingAccelerated_; bool recordPreview_; int recordQuality_; + std::string conferenceResolution_; constexpr static const char* const CONFIG_LABEL = "video"; }; #endif // ENABLE_VIDEO