Don't link avmediagst with gtk3 and qt5

While the VCL plugins are dynamically loaded and therefore just
load their depending toolkit libraries, the GStreamer avmedia
backend now links against Qt and GTK+. The GStreamer API itself
is toolkit agnostic and the toolkit setup just uses a single
GStreamer symbol to create the specific video sink.

So the toolkit binding can simply be moved into the VCL plugin.
At the point of the GStreamer toolkit setup call the GStreamer
library is loaded by avmediagst, so the dlsym lookup should
never fail.

I also dropped the special GtkWidget handling. Using g_object_get
will increase the refcount of the widget. A g_object_unref after
adding it to the container seems to destroy it correctly.

Change-Id: I693947e441bceb4b09bc38920e308e39142d0a35
Reviewed-on: https://gerrit.libreoffice.org/73849
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
This commit is contained in:
Jan-Marek Glogowski
2019-06-13 23:45:09 +02:00
parent 2d36e43d3d
commit a6201725d7
17 changed files with 195 additions and 161 deletions
-20
View File
@@ -21,26 +21,6 @@ $(eval $(call gb_Library_add_libs,avmediagst,\
$(GSTREAMER_1_0_LIBS) \
))
ifneq ($(ENABLE_GTK3),)
$(eval $(call gb_Library_add_cxxflags,avmediagst,\
$$(GTK3_CFLAGS) \
))
$(eval $(call gb_Library_add_libs,avmediagst,\
$(GTK3_LIBS) \
))
endif
ifneq ($(ENABLE_QT5),)
$(eval $(call gb_Library_add_cxxflags,avmediagst,\
$$(QT5_CFLAGS) \
))
$(eval $(call gb_Library_add_libs,avmediagst,\
$(QT5_LIBS) \
))
endif
$(eval $(call gb_Library_use_external,avmediagst,boost_headers))
$(eval $(call gb_Library_use_sdk_api,avmediagst))
+54 -111
View File
@@ -42,10 +42,6 @@
#include "gstframegrabber.hxx"
#include "gstwindow.hxx"
#if ENABLE_QT5
#include <QtWidgets/QWidget>
#endif
#include <gst/video/videooverlay.h>
#define AVMEDIA_GST_PLAYER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.Player_GStreamer"
#define AVMEDIA_GST_PLAYER_SERVICENAME "com.sun.star.media.Player_GStreamer"
@@ -287,9 +283,6 @@ Player::Player() :
GstPlayer_BASE( m_aMutex ),
mpPlaybin( nullptr ),
mpVolumeControl( nullptr ),
#if ENABLE_GTK3
mpGtkWidget( nullptr ),
#endif
mbUseGtkSink( false ),
mbFakeVideo (false ),
mnUnmutedVolume( 0 ),
@@ -347,14 +340,6 @@ void SAL_CALL Player::disposing()
// Release the elements and pipeline
if( mbInitialized )
{
#if ENABLE_GTK3
if (mpGtkWidget)
{
gtk_widget_destroy(mpGtkWidget);
mpGtkWidget = nullptr;
}
#endif
if( mpPlaybin )
{
gst_element_set_state( mpPlaybin, GST_STATE_NULL );
@@ -557,14 +542,6 @@ GstBusSyncReply Player::processSyncMessage( GstMessage *message )
void Player::preparePlaybin( const OUString& rURL, GstElement *pSink )
{
#if ENABLE_GTK3
if (mpGtkWidget)
{
gtk_widget_destroy(mpGtkWidget);
mpGtkWidget = nullptr;
}
#endif
if (mpPlaybin != nullptr)
{
gst_element_set_state( mpPlaybin, GST_STATE_NULL );
@@ -870,98 +847,64 @@ uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( co
if( aSize.Width > 0 && aSize.Height > 0 )
{
::avmedia::gstreamer::Window* pWindow = new ::avmedia::gstreamer::Window;
if (rArguments.getLength() <= 2)
{
xRet = pWindow;
return xRet;
}
sal_IntPtr pIntPtr = 0;
rArguments[ 2 ] >>= pIntPtr;
SystemChildWindow *pParentWindow = reinterpret_cast< SystemChildWindow* >( pIntPtr );
if (!pParentWindow)
return nullptr;
const SystemEnvData* pEnvData = pParentWindow->GetSystemData();
if (!pEnvData)
return nullptr;
OUString aToolkit = OUString::createFromAscii(pEnvData->pToolkit);
OUString aPlatform = OUString::createFromAscii(pEnvData->pPlatformName);
// tdf#124027: the position of embedded window is identical w/ the position
// of media object in all other vclplugs (gtk, kde5, gen), in gtk3 w/o gtksink it
// needs to be translated
if (aToolkit == "gtk3")
{
Point aPoint = pParentWindow->GetPosPixel();
maArea.X = aPoint.getX();
maArea.Y = aPoint.getY();
}
mbUseGtkSink = false;
GstElement *pVideosink = static_cast<GstElement*>(pParentWindow->CreateGStreamerSink());
if (pVideosink)
{
if (aToolkit == "gtk3")
mbUseGtkSink = true;
}
else
{
if (aPlatform == "wayland")
pVideosink = gst_element_factory_make("waylandsink", "video-output");
else
pVideosink = gst_element_factory_make("autovideosink", "video-output");
if (!pVideosink)
return nullptr;
}
xRet = pWindow;
if( rArguments.getLength() > 2 )
{
sal_IntPtr pIntPtr = 0;
rArguments[ 2 ] >>= pIntPtr;
SystemChildWindow *pParentWindow = reinterpret_cast< SystemChildWindow* >( pIntPtr );
g_object_set(G_OBJECT(mpPlaybin), "video-sink", pVideosink, nullptr);
g_object_set(G_OBJECT(mpPlaybin), "force-aspect-ratio", FALSE, nullptr);
const SystemEnvData* pEnvData = pParentWindow ? pParentWindow->GetSystemData() : nullptr;
OSL_ASSERT(pEnvData);
if (pEnvData)
{
OUString aToolkit = OUString::createFromAscii(pEnvData->pToolkit);
OUString aPlatform = OUString::createFromAscii(pEnvData->pPlatformName);
// tdf#124027: the position of embedded window is identical w/ the position
// of media object in all other vclplugs (gtk, kde5, gen), in gtk3 w/o gtksink it
// needs to be translated
if (aToolkit == "gtk3")
{
if (pParentWindow)
{
Point aPoint = pParentWindow->GetPosPixel();
maArea.X = aPoint.getX();
maArea.Y = aPoint.getY();
}
}
GstElement *pVideosink = nullptr;
#if ENABLE_GTK3
pVideosink = (aToolkit == "gtk3") ?
gst_element_factory_make("gtksink", "gtksink") : nullptr;
if (pVideosink)
{
mbUseGtkSink = true;
g_object_get(pVideosink, "widget", &mpGtkWidget, nullptr);
gtk_widget_set_vexpand(mpGtkWidget, true);
gtk_widget_set_hexpand(mpGtkWidget, true);
GtkWidget *pParent = static_cast<GtkWidget*>(pEnvData->pWidget);
gtk_container_add (GTK_CONTAINER(pParent), mpGtkWidget);
g_object_set( G_OBJECT( mpPlaybin ), "video-sink", pVideosink, nullptr);
g_object_set( G_OBJECT( mpPlaybin ), "force-aspect-ratio", FALSE, nullptr);
gtk_widget_show_all (pParent);
}
else
#endif
{
#if ENABLE_QT5
// try to use qwidget5videosink for qt5 on Wayland, which requires the Qt5 packages for QtGStreamer to be installed
if (aToolkit == "qt5" && aPlatform == "wayland")
{
pVideosink = gst_element_factory_make("qwidget5videosink", "qwidget5videosink");
if (pVideosink) {
QWidget* pQWidget = static_cast<QWidget*>(pEnvData->pWidget);
g_object_set(G_OBJECT(pVideosink), "widget", pQWidget, nullptr);
}
else
{
SAL_WARN("avmedia.gstreamer", "Couldn't initialize qwidget5videosink."
" Video playback might not work as expected."
" Please install Qt5 packages for QtGStreamer.");
// with no videosink explicitly set, GStreamer will open its own (misplaced) window(s) to display video
}
}
#endif
if (!pVideosink)
{
if (aPlatform == "wayland")
pVideosink = gst_element_factory_make("waylandsink", "video-output");
else
pVideosink = gst_element_factory_make("autovideosink", "video-output");
}
if (!pVideosink)
{
xRet.clear();
return nullptr;
}
g_object_set(G_OBJECT(mpPlaybin), "video-sink", pVideosink, nullptr);
mbUseGtkSink = false;
mnWindowID = pEnvData->aWindow;
mpDisplay = pEnvData->pDisplay;
SAL_INFO( "avmedia.gstreamer", AVVERSION "set window id to " << static_cast<int>(mnWindowID) << " XOverlay " << mpXOverlay);
gst_element_set_state( mpPlaybin, GST_STATE_PAUSED );
if ( mpXOverlay != nullptr )
gst_video_overlay_set_window_handle( mpXOverlay, mnWindowID );
}
}
}
mnWindowID = pEnvData->aWindow;
mpDisplay = pEnvData->pDisplay;
SAL_INFO( "avmedia.gstreamer", AVVERSION "set window id to " << static_cast<int>(mnWindowID) << " XOverlay " << mpXOverlay);
gst_element_set_state( mpPlaybin, GST_STATE_PAUSED );
if ( mpXOverlay != nullptr )
gst_video_overlay_set_window_handle( mpXOverlay, mnWindowID );
}
return xRet;
-9
View File
@@ -20,8 +20,6 @@
#ifndef INCLUDED_AVMEDIA_SOURCE_GSTREAMER_GSTPLAYER_HXX
#define INCLUDED_AVMEDIA_SOURCE_GSTREAMER_GSTPLAYER_HXX
#include <config_vclplug.h>
#include <osl/conditn.hxx>
#include "gstcommon.hxx"
@@ -29,10 +27,6 @@
#include <cppuhelper/compbase.hxx>
#include <cppuhelper/basemutex.hxx>
#if ENABLE_GTK3
# include <gtk/gtk.h>
#endif
typedef struct _GstVideoOverlay GstVideoOverlay;
namespace avmedia { namespace gstreamer {
@@ -85,9 +79,6 @@ private:
// Add elements and pipeline here
GstElement* mpPlaybin; // the playbin is also a pipeline
GstElement* mpVolumeControl; // the playbin is also a pipeline
#if ENABLE_GTK3
GtkWidget* mpGtkWidget;
#endif
bool mbUseGtkSink;
bool mbFakeVideo;
+3 -3
View File
@@ -466,9 +466,9 @@ export PYTHON_VERSION_MAJOR=@PYTHON_VERSION_MAJOR@
export PYTHON_VERSION_MINOR=@PYTHON_VERSION_MINOR@
export QT5_CFLAGS=$(gb_SPACE)@QT5_CFLAGS@
export QT5_LIBS=$(gb_SPACE)@QT5_LIBS@
export QT5_GLIB_CFLAGS=$(gb_SPACE)@QT5_GLIB_CFLAGS@
export QT5_GLIB_LIBS=$(gb_SPACE)@QT5_GLIB_LIBS@
export QT5_HAVE_GLIB=@QT5_HAVE_GLIB@
export QT5_GOBJECT_CFLAGS=$(gb_SPACE)@QT5_GOBJECT_CFLAGS@
export QT5_GOBJECT_LIBS=$(gb_SPACE)@QT5_GOBJECT_LIBS@
export QT5_HAVE_GOBJECT=@QT5_HAVE_GOBJECT@
export QXP_CFLAGS=$(gb_SPACE)@QXP_CFLAGS@
export QXP_LIBS=$(gb_SPACE)@QXP_LIBS@
export RANLIB=@RANLIB@
+3
View File
@@ -13,4 +13,7 @@ Settings about which desktops have support enabled.
#define ENABLE_KDE5 0
#define ENABLE_QT5 0
#define QT5_HAVE_GOBJECT 0
#define ENABLE_GSTREAMER_1_0 0
#endif
+16 -14
View File
@@ -10512,6 +10512,7 @@ if test "$build_gstreamer_1_0" = "yes"; then
GSTREAMER_1_0_CFLAGS=$(printf '%s' "$GSTREAMER_1_0_CFLAGS" | sed -e "s/-I/${ISYSTEM?}/g")
FilterLibs "${GSTREAMER_1_0_LIBS}"
GSTREAMER_1_0_LIBS="${filteredlibs}"
AC_DEFINE(ENABLE_GSTREAMER_1_0)
else
AC_MSG_RESULT([no])
fi
@@ -11073,9 +11074,9 @@ QT5_CFLAGS=""
QT5_LIBS=""
QMAKE5="qmake"
MOC5="moc"
QT5_GLIB_CFLAGS=""
QT5_GLIB_LIBS=""
QT5_HAVE_GLIB=""
QT5_GOBJECT_CFLAGS=""
QT5_GOBJECT_LIBS=""
QT5_HAVE_GOBJECT=""
if test \( "$test_kde5" = "yes" -a "$ENABLE_KDE5" = "TRUE" \) -o \
\( "$test_qt5" = "yes" -a "$ENABLE_QT5" = "TRUE" \) -o \
\( "$test_gtk3_kde5" = "yes" -a "$ENABLE_GTK3_KDE5" = "TRUE" \)
@@ -11149,21 +11150,22 @@ then
the root of your Qt installation by exporting QT5DIR before running "configure".])
fi
# Glib is needed for properly handling Qt event loop with Qt's Glib integration enabled.
# Sets also QT5_GLIB_CFLAGS/QT5_GLIB_LIBS if successful.
PKG_CHECK_MODULES(QT5_GLIB,[glib-2.0 >= 2.4],
[
QT5_HAVE_GLIB=1
],
AC_MSG_WARN([[No Glib found, Qt5 support will not use native file pickers!]])
)
if test "$build_gstreamer_1_0" = "yes"; then
PKG_CHECK_MODULES(QT5_GOBJECT,[gobject-2.0], [
QT5_HAVE_GOBJECT=1
AC_DEFINE(QT5_HAVE_GOBJECT)
],
AC_MSG_WARN([[No GObject found, can't use QWidget GStreamer sink on wayland!]])
)
fi
fi
AC_SUBST(QT5_CFLAGS)
AC_SUBST(QT5_LIBS)
AC_SUBST(MOC5)
AC_SUBST(QT5_GLIB_CFLAGS)
AC_SUBST(QT5_GLIB_LIBS)
AC_SUBST(QT5_HAVE_GLIB)
AC_SUBST(QT5_GOBJECT_CFLAGS)
AC_SUBST(QT5_GOBJECT_LIBS)
AC_SUBST(QT5_HAVE_GOBJECT)
dnl ===================================================================
dnl KDE5 Integration
+2
View File
@@ -57,6 +57,8 @@ public:
void SetLeaveEnterBackgrounds(const css::uno::Sequence<css::uno::Any>& rLeaveArgs, const css::uno::Sequence<css::uno::Any>& rEnterArgs);
// return the platform specific handle/id of this window;
sal_IntPtr GetParentWindowHandle();
void* CreateGStreamerSink();
};
#endif // INCLUDED_VCL_SYSCHILD_HXX
+1
View File
@@ -28,6 +28,7 @@ $(eval $(call gb_Library_add_cxxflags,vclplug_gtk3, \
$(eval $(call gb_Library_set_include,vclplug_gtk3,\
$$(INCLUDE) \
$$(GTK3_CFLAGS) \
$$(GSTREAMER_1_0_CFLAGS) \
-I$(SRCDIR)/vcl/inc \
-I$(SRCDIR)/vcl/unx \
-I$(SRCDIR)/vcl/unx/gtk3 \
+1
View File
@@ -36,6 +36,7 @@ $(eval $(call gb_Library_add_cxxflags,vclplug_gtk3_kde5,\
$$(INCLUDE) \
$$(GTK3_CFLAGS) \
$(KF5_CFLAGS) \
$$(GSTREAMER_1_0_CFLAGS) \
))
$(eval $(call gb_Library_add_defs,vclplug_gtk3_kde5,\
+4 -3
View File
@@ -25,6 +25,7 @@ $(eval $(call gb_Library_set_include,vclplug_qt5,\
$$(INCLUDE) \
-I$(SRCDIR)/vcl/inc \
-I$(SRCDIR)/vcl/inc/qt5 \
$(GSTREAMER_1_0_CFLAGS) \
))
$(eval $(call gb_Library_add_defs,vclplug_qt5,\
@@ -70,12 +71,12 @@ $(eval $(call gb_Library_add_libs,vclplug_qt5,\
$(QT5_LIBS) \
))
ifneq ($(QT5_HAVE_GLIB),)
ifneq ($(QT5_HAVE_GOBJECT),)
$(eval $(call gb_Library_add_cxxflags,vclplug_qt5,\
$(QT5_GLIB_CFLAGS) \
$(QT5_GOBJECT_CFLAGS) \
))
$(eval $(call gb_Library_add_libs,vclplug_qt5,\
$(QT5_GLIB_LIBS) \
$(QT5_GOBJECT_LIBS) \
))
endif
+2
View File
@@ -151,6 +151,8 @@ public:
virtual css::uno::Reference<css::uno::XInterface> CreateDropTarget() override;
void UpdateStyle(bool bFontsChanged);
void* CreateGStreamerSink(const SystemChildWindow*) override;
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+3
View File
@@ -50,6 +50,7 @@ namespace weld {
class Widget;
class Window;
}
class SystemChildWindow;
struct SystemParentData;
struct SalPrinterQueueInfo;
class ImplJobSetup;
@@ -206,6 +207,8 @@ public:
virtual OUString getOSVersion() { return OUString("-"); }
virtual const cairo_font_options_t* GetCairoFontOptions() { return nullptr; }
virtual void* CreateGStreamerSink(const SystemChildWindow*) { return nullptr; }
};
// called from SVMain
+27
View File
@@ -0,0 +1,27 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
#pragma once
#include <config_vclplug.h>
#if ENABLE_GSTREAMER_1_0
#include <gst/gst.h>
#include <dlfcn.h>
typedef GstElement* (*GstElementFactoryName)(const gchar*, const gchar*);
static GstElementFactoryName gstElementFactoryNameSymbol()
{
return reinterpret_cast<GstElementFactoryName>(dlsym(nullptr, "gst_element_factory_make"));
}
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+4
View File
@@ -254,6 +254,10 @@ public:
std::shared_ptr<vcl::unx::GtkPrintWrapper> const & getPrintWrapper() const;
#if GTK_CHECK_VERSION(3,0,0)
void* CreateGStreamerSink(const SystemChildWindow*) override;
#endif
private:
GtkSalTimer *m_pTimer;
#if GTK_CHECK_VERSION(3,0,0)
+37 -1
View File
@@ -48,7 +48,7 @@
#include <comphelper/flagguard.hxx>
#include <sal/log.hxx>
#include <osl/process.h>
#include <unx/gstsink.hxx>
#include <headless/svpbmp.hxx>
#include <mutex>
@@ -488,6 +488,42 @@ void Qt5Instance::UpdateStyle(bool bFontsChanged)
m_aUpdateStyleTimer.Start();
}
void* Qt5Instance::CreateGStreamerSink(const SystemChildWindow* pWindow)
{
#if ENABLE_GSTREAMER_1_0 && QT5_HAVE_GOBJECT
auto pSymbol = gstElementFactoryNameSymbol();
if (!pSymbol)
return nullptr;
const SystemEnvData* pEnvData = pWindow->GetSystemData();
if (!pEnvData)
return nullptr;
OUString aPlatform = OUString::createFromAscii(pEnvData->pPlatformName);
if (aPlatform != "wayland")
return nullptr;
GstElement* pVideosink = pSymbol("qwidget5videosink", "qwidget5videosink");
if (pVideosink)
{
QWidget* pQWidget = static_cast<QWidget*>(pEnvData->pWidget);
g_object_set(G_OBJECT(pVideosink), "widget", pQWidget, nullptr);
}
else
{
SAL_WARN("vcl.qt5", "Couldn't initialize qwidget5videosink."
" Video playback might not work as expected."
" Please install Qt5 packages for QtGStreamer.");
// with no videosink explicitly set, GStreamer will open it's own (misplaced) window(s) to display video
}
return pVideosink;
#else
(void*)pWindow;
return nullptr;
#endif
}
void Qt5Instance::AllocFakeCmdlineArgs(std::unique_ptr<char* []>& rFakeArgv,
std::unique_ptr<int>& rFakeArgc,
std::vector<FreeableCStr>& rFakeArgvFreeable)
+5
View File
@@ -185,4 +185,9 @@ sal_IntPtr SystemChildWindow::GetParentWindowHandle()
return nRet;
}
void* SystemChildWindow::CreateGStreamerSink()
{
return ImplGetSVData()->mpDefInst->CreateGStreamerSink(this);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+33
View File
@@ -36,6 +36,7 @@
#include <tools/fract.hxx>
#include <tools/stream.hxx>
#include <unotools/resmgr.hxx>
#include <unx/gstsink.hxx>
#include <vcl/ImageTree.hxx>
#include <vcl/i18nhelp.hxx>
#include <vcl/quickselectionengine.hxx>
@@ -10778,4 +10779,36 @@ weld::Window* GtkSalFrame::GetFrameWeld() const
return m_xFrameWeld.get();
}
void* GtkInstance::CreateGStreamerSink(const SystemChildWindow *pWindow)
{
#if ENABLE_GSTREAMER_1_0
auto aSymbol = gstElementFactoryNameSymbol();
if (!aSymbol)
return nullptr;
const SystemEnvData* pEnvData = pWindow->GetSystemData();
if (!pEnvData)
return nullptr;
GstElement* pVideosink = aSymbol("gtksink", "gtksink");
if (!pVideosink)
return nullptr;
GtkWidget *pGstWidget;
g_object_get(pVideosink, "widget", &pGstWidget, nullptr);
gtk_widget_set_vexpand(pGstWidget, true);
gtk_widget_set_hexpand(pGstWidget, true);
GtkWidget *pParent = static_cast<GtkWidget*>(pEnvData->pWidget);
gtk_container_add(GTK_CONTAINER(pParent), pGstWidget);
g_object_unref(pGstWidget);
gtk_widget_show_all(pParent);
return pVideosink;
#else
(void*)pWindow;
return nullptr;
#endif
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */