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
This commit is contained in:
Nicolas Werner 2023-02-08 00:54:02 +01:00
parent 50f5fc6637
commit fc7937c73d
No known key found for this signature in database
GPG key ID: C8D75E610773F2D9
3 changed files with 78 additions and 50 deletions

View file

@ -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;

View file

@ -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<const char *> 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<const char *> video_elements = {
"compositor",
"glcolorconvert",
"glsinkbin",
"glupload",
"qmlglsink",
"rtpvp8pay",
"tee",
"videoconvert",
"videoscale",
"vp8enc",
};
static constexpr std::initializer_list<const char *> 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<const char *> &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);

View file

@ -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<std::string> turnServers_;
uint32_t shareWindowId_ = 0;