diff --git a/src/voip/CallManager.cpp b/src/voip/CallManager.cpp index 3d795fc1..135d0b6a 100644 --- a/src/voip/CallManager.cpp +++ b/src/voip/CallManager.cpp @@ -193,9 +193,8 @@ CallManager::sendInvite(const QString &roomid, CallType callType, unsigned int w auto roomInfo = cache::singleRoomInfo(roomid.toStdString()); std::string errorMessage; - if (!session_.havePlugins(false, &errorMessage) || - ((callType == CallType::VIDEO || callType == CallType::SCREEN) && - !session_.havePlugins(true, &errorMessage))) { + if (!session_.havePlugins( + callType != CallType::VOICE, callType == CallType::SCREEN, &errorMessage)) { emit ChatPage::instance()->showNotification(QString::fromStdString(errorMessage)); return; } @@ -469,8 +468,8 @@ CallManager::acceptInvite() stopRingtone(); std::string errorMessage; - if (!session_.havePlugins(false, &errorMessage) || - (callType_ == CallType::VIDEO && !session_.havePlugins(true, &errorMessage))) { + if (!session_.havePlugins( + callType_ != CallType::VOICE, callType_ == CallType::SCREEN, &errorMessage)) { emit ChatPage::instance()->showNotification(QString::fromStdString(errorMessage)); hangUp(CallHangUp::Reason::UserMediaFailed); return; diff --git a/src/voip/WebRTCSession.cpp b/src/voip/WebRTCSession.cpp index 7760e2ea..001781e4 100644 --- a/src/voip/WebRTCSession.cpp +++ b/src/voip/WebRTCSession.cpp @@ -580,53 +580,81 @@ getMediaAttributes(const GstSDPMessage *sdp, } bool -WebRTCSession::havePlugins(bool isVideo, std::string *errorMessage) +WebRTCSession::havePlugins(bool isVideo, bool isX11Screenshare, std::string *errorMessage) { if (!initialised_ && !init(errorMessage)) return false; - if (!isVideo && haveVoicePlugins_) - return true; - if (isVideo && haveVideoPlugins_) + if (haveVoicePlugins_ && (!isVideo || haveVideoPlugins_) && + (!isX11Screenshare || haveX11ScreensharePlugins_)) return true; - const gchar *voicePlugins[] = {"audioconvert", - "audioresample", - "autodetect", - "dtls", - "nice", - "opus", - "playback", - "rtpmanager", - "srtp", - "volume", - "webrtc", - nullptr}; + static constexpr std::initializer_list audio_elements = { + "audioconvert", + "audioresample", + "autoaudiosink", + "capsfilter", + "decodebin", + "opusenc", + "queue", + "rtpopuspay", + "volume", + "webrtcbin", + }; - const gchar *videoPlugins[] = { - "compositor", "opengl", "qmlgl", "rtp", "videoconvert", "vpx", nullptr}; + static constexpr std::initializer_list video_elements = { + "compositor", + "glcolorconvert", + "glsinkbin", + "glupload", + "qmlglsink", + "rtpvp8pay", + "tee", + "videoconvert", + "videoscale", + "vp8enc", + }; + static constexpr std::initializer_list screenshare_elements = { + "ximagesink", + "ximagesrc", + }; - std::string strError("Missing GStreamer plugins: "); - const gchar **needed = isVideo ? videoPlugins : voicePlugins; - bool &havePlugins = isVideo ? haveVideoPlugins_ : haveVoicePlugins_; - havePlugins = true; + std::string strError("Missing GStreamer elements: "); GstRegistry *registry = gst_registry_get(); - for (guint i = 0; i < g_strv_length((gchar **)needed); i++) { - GstPlugin *plugin = gst_registry_find_plugin(registry, needed[i]); - if (!plugin) { - havePlugins = false; - strError += std::string(needed[i]) + " "; - continue; + + auto check_plugins = [&strError, + registry](const std::initializer_list &elements) { + bool havePlugins = true; + for (const auto &element : elements) { + GstPluginFeature *plugin = + gst_registry_find_feature(registry, element, GST_TYPE_ELEMENT_FACTORY); + if (!plugin) { + havePlugins = false; + strError += std::string(element) + " "; + continue; + } + gst_object_unref(plugin); } - gst_object_unref(plugin); - } - if (!havePlugins) { + + return havePlugins; + }; + + haveVoicePlugins_ = check_plugins(audio_elements); + + // check both elements at once + if (isVideo) + haveVideoPlugins_ = check_plugins(video_elements); + if (isX11Screenshare) + haveX11ScreensharePlugins_ = check_plugins(screenshare_elements); + + if (!haveVoicePlugins_ || (isVideo && !haveVideoPlugins_) || + (isX11Screenshare && !haveX11ScreensharePlugins_)) { nhlog::ui()->error(strError); if (errorMessage) *errorMessage = strError; return false; } - if (isVideo) { + if (isVideo || isX11Screenshare) { // load qmlglsink to register GStreamer's GstGLVideoItem QML type GstElement *qmlglsink = gst_element_factory_make("qmlglsink", nullptr); gst_object_unref(qmlglsink); diff --git a/src/voip/WebRTCSession.h b/src/voip/WebRTCSession.h index da13e356..911a9b6c 100644 --- a/src/voip/WebRTCSession.h +++ b/src/voip/WebRTCSession.h @@ -54,7 +54,7 @@ public: return instance; } - bool havePlugins(bool isVideo, std::string *errorMessage = nullptr); + bool havePlugins(bool isVideo, bool isX11Screenshare, std::string *errorMessage = nullptr); webrtc::CallType callType() const { return callType_; } webrtc::State state() const { return state_; } bool haveLocalPiP() const; @@ -93,18 +93,19 @@ private: WebRTCSession(); CallDevices &devices_; - bool initialised_ = false; - bool haveVoicePlugins_ = false; - bool haveVideoPlugins_ = false; - webrtc::CallType callType_ = webrtc::CallType::VOICE; - webrtc::State state_ = webrtc::State::DISCONNECTED; - bool isOffering_ = false; - bool isRemoteVideoRecvOnly_ = false; - bool isRemoteVideoSendOnly_ = false; - QQuickItem *videoItem_ = nullptr; - GstElement *pipe_ = nullptr; - GstElement *webrtc_ = nullptr; - unsigned int busWatchId_ = 0; + bool initialised_ = false; + bool haveVoicePlugins_ = false; + bool haveVideoPlugins_ = false; + bool haveX11ScreensharePlugins_ = false; + webrtc::CallType callType_ = webrtc::CallType::VOICE; + webrtc::State state_ = webrtc::State::DISCONNECTED; + bool isOffering_ = false; + bool isRemoteVideoRecvOnly_ = false; + bool isRemoteVideoSendOnly_ = false; + QQuickItem *videoItem_ = nullptr; + GstElement *pipe_ = nullptr; + GstElement *webrtc_ = nullptr; + unsigned int busWatchId_ = 0; std::vector turnServers_; uint32_t shareWindowId_ = 0;