From fc7937c73d5729066079484c32a9785bddd74bc5 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Wed, 8 Feb 2023 00:54:02 +0100 Subject: [PATCH] Fix required plugin check on gstreamer 1.22 GStreamer 1.22 merged the videoscale plugin into the videoconvertscale plugin. So we should check if the Element is still loadable instead of checking the plugin name. fixes #1352 --- src/voip/CallManager.cpp | 9 ++-- src/voip/WebRTCSession.cpp | 92 +++++++++++++++++++++++++------------- src/voip/WebRTCSession.h | 27 +++++------ 3 files changed, 78 insertions(+), 50 deletions(-) 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;