[vlc-devel] [PATCH 05/16] qt: don't release vout window when the interface has already been destroyed
Pierre Lamot
pierre at videolabs.io
Thu Aug 6 09:43:51 CEST 2020
---
modules/gui/qt/maininterface/compositor.hpp | 3 +-
.../gui/qt/maininterface/compositor_dcomp.cpp | 41 ++++++++++++++-----
.../gui/qt/maininterface/compositor_dcomp.hpp | 2 +-
.../gui/qt/maininterface/compositor_dummy.cpp | 2 +-
.../gui/qt/maininterface/compositor_dummy.hpp | 2 +-
modules/gui/qt/qt.cpp | 25 ++++++++++-
6 files changed, 60 insertions(+), 15 deletions(-)
diff --git a/modules/gui/qt/maininterface/compositor.hpp b/modules/gui/qt/maininterface/compositor.hpp
index aef4e11a32..7e74ffb593 100644
--- a/modules/gui/qt/maininterface/compositor.hpp
+++ b/modules/gui/qt/maininterface/compositor.hpp
@@ -34,13 +34,14 @@ namespace vlc {
class Compositor {
public:
+ typedef bool (*VoutDestroyCb)(vout_window_t *p_wnd);
virtual ~Compositor() = default;
virtual MainInterface* makeMainInterface() = 0;
virtual void destroyMainInterface() = 0;
- virtual bool setupVoutWindow(vout_window_t *p_wnd) = 0;
+ virtual bool setupVoutWindow(vout_window_t *p_wnd, VoutDestroyCb destroyCb) = 0;
//factory
static Compositor* createCompositor(intf_thread_t *p_intf);
diff --git a/modules/gui/qt/maininterface/compositor_dcomp.cpp b/modules/gui/qt/maininterface/compositor_dcomp.cpp
index 23b0612a9e..b3b95aa8f1 100644
--- a/modules/gui/qt/maininterface/compositor_dcomp.cpp
+++ b/modules/gui/qt/maininterface/compositor_dcomp.cpp
@@ -40,6 +40,11 @@
namespace vlc {
+struct VoutWindowPriv {
+ CompositorDirectComposition* that = nullptr;
+ CompositorDirectComposition::VoutDestroyCb voutDestroyCb = nullptr;
+};
+
using namespace Microsoft::WRL;
//Signature for DCompositionCreateDevice
@@ -47,7 +52,8 @@ typedef HRESULT (*DCompositionCreateDeviceFun)(IDXGIDevice *dxgiDevice, REFIID i
int CompositorDirectComposition::window_enable(struct vout_window_t * p_wnd, const vout_window_cfg_t *)
{
- CompositorDirectComposition* that = static_cast<CompositorDirectComposition*>(p_wnd->sys);
+ VoutWindowPriv* sys = static_cast<VoutWindowPriv*>(p_wnd->sys);
+ CompositorDirectComposition* that = sys->that;
msg_Dbg(that->m_intf, "window_enable");
if (!that->m_videoVisual)
{
@@ -71,7 +77,8 @@ int CompositorDirectComposition::window_enable(struct vout_window_t * p_wnd, con
void CompositorDirectComposition::window_disable(struct vout_window_t * p_wnd)
{
- CompositorDirectComposition* that = static_cast<CompositorDirectComposition*>(p_wnd->sys);
+ VoutWindowPriv* sys = static_cast<VoutWindowPriv*>(p_wnd->sys);
+ CompositorDirectComposition* that = sys->that;
try
{
that->m_qmlVideoSurfaceProvider->disable();
@@ -89,14 +96,20 @@ void CompositorDirectComposition::window_disable(struct vout_window_t * p_wnd)
void CompositorDirectComposition::window_resize(struct vout_window_t * p_wnd, unsigned width, unsigned height)
{
- CompositorDirectComposition* that = static_cast<CompositorDirectComposition*>(p_wnd->sys);
+ VoutWindowPriv* sys = static_cast<VoutWindowPriv*>(p_wnd->sys);
+ CompositorDirectComposition* that = sys->that;
msg_Dbg(that->m_intf, "window_resize %ux%u", width, height);
that->m_rootWindow->requestResizeVideo(width, height);
}
void CompositorDirectComposition::window_destroy(struct vout_window_t * p_wnd)
{
- CompositorDirectComposition* that = static_cast<CompositorDirectComposition*>(p_wnd->sys);
+ VoutWindowPriv* sys = static_cast<VoutWindowPriv*>(p_wnd->sys);
+ CompositorDirectComposition* that = sys->that;
+ bool canRelease = sys->voutDestroyCb(p_wnd);
+ delete sys;
+ if (!canRelease)
+ return;
msg_Dbg(that->m_intf, "window_destroy");
that->m_window = nullptr;
that->m_videoVisual.Reset();
@@ -104,21 +117,24 @@ void CompositorDirectComposition::window_destroy(struct vout_window_t * p_wnd)
void CompositorDirectComposition::window_set_state(struct vout_window_t * p_wnd, unsigned state)
{
- CompositorDirectComposition* that = static_cast<CompositorDirectComposition*>(p_wnd->sys);
+ VoutWindowPriv* sys = static_cast<VoutWindowPriv*>(p_wnd->sys);
+ CompositorDirectComposition* that = sys->that;
msg_Dbg(that->m_intf, "window_set_state");
that->m_rootWindow->requestVideoState(static_cast<vout_window_state>(state));
}
void CompositorDirectComposition::window_unset_fullscreen(struct vout_window_t * p_wnd)
{
- CompositorDirectComposition* that = static_cast<CompositorDirectComposition*>(p_wnd->sys);
+ VoutWindowPriv* sys = static_cast<VoutWindowPriv*>(p_wnd->sys);
+ CompositorDirectComposition* that = sys->that;
msg_Dbg(that->m_intf, "window_unset_fullscreen");
that->m_rootWindow->requestVideoWindowed();
}
void CompositorDirectComposition::window_set_fullscreen(struct vout_window_t * p_wnd, const char *id)
{
- CompositorDirectComposition* that = static_cast<CompositorDirectComposition*>(p_wnd->sys);
+ VoutWindowPriv* sys = static_cast<VoutWindowPriv*>(p_wnd->sys);
+ CompositorDirectComposition* that = sys->that;
msg_Dbg(that->m_intf, "window_set_fullscreen");
that->m_rootWindow->requestVideoFullScreen(id);
}
@@ -263,7 +279,7 @@ void CompositorDirectComposition::destroyMainInterface()
}
}
-bool CompositorDirectComposition::setupVoutWindow(vout_window_t *p_wnd)
+bool CompositorDirectComposition::setupVoutWindow(vout_window_t *p_wnd, VoutDestroyCb destroyCb)
{
//Only the first video is embedded
if (m_videoVisual.Get())
@@ -275,7 +291,6 @@ bool CompositorDirectComposition::setupVoutWindow(vout_window_t *p_wnd)
msg_Err(p_wnd, "create to create DComp video visual");
return false;
}
-
static const struct vout_window_operations ops = {
CompositorDirectComposition::window_enable,
CompositorDirectComposition::window_disable,
@@ -286,7 +301,13 @@ bool CompositorDirectComposition::setupVoutWindow(vout_window_t *p_wnd)
CompositorDirectComposition::window_set_fullscreen,
nullptr, //window_set_title
};
- p_wnd->sys = this;
+
+ VoutWindowPriv* sys = new VoutWindowPriv();
+ //destructor callback
+ sys->voutDestroyCb = destroyCb;
+ sys->that = this;
+
+ p_wnd->sys = sys;
p_wnd->type = VOUT_WINDOW_TYPE_DCOMP;
p_wnd->display.dcomp_device = m_dcompDevice.Get();
p_wnd->handle.dcomp_visual = m_videoVisual.Get();
diff --git a/modules/gui/qt/maininterface/compositor_dcomp.hpp b/modules/gui/qt/maininterface/compositor_dcomp.hpp
index 7deaf92127..41d5678bea 100644
--- a/modules/gui/qt/maininterface/compositor_dcomp.hpp
+++ b/modules/gui/qt/maininterface/compositor_dcomp.hpp
@@ -48,7 +48,7 @@ public:
MainInterface *makeMainInterface() override;
void destroyMainInterface() override;
- bool setupVoutWindow(vout_window_t *p_wnd) override;
+ bool setupVoutWindow(vout_window_t *p_wnd, VoutDestroyCb destroyCb) override;
private:
static int window_enable(struct vout_window_t *, const vout_window_cfg_t *);
diff --git a/modules/gui/qt/maininterface/compositor_dummy.cpp b/modules/gui/qt/maininterface/compositor_dummy.cpp
index 16012e1c34..c645552bf7 100644
--- a/modules/gui/qt/maininterface/compositor_dummy.cpp
+++ b/modules/gui/qt/maininterface/compositor_dummy.cpp
@@ -52,7 +52,7 @@ void CompositorDummy::destroyMainInterface()
}
}
-bool CompositorDummy::setupVoutWindow(vout_window_t*)
+bool CompositorDummy::setupVoutWindow(vout_window_t*, VoutDestroyCb )
{
//dummy compositor doesn't handle window intergration
return false;
diff --git a/modules/gui/qt/maininterface/compositor_dummy.hpp b/modules/gui/qt/maininterface/compositor_dummy.hpp
index bcaa9672a0..521700418d 100644
--- a/modules/gui/qt/maininterface/compositor_dummy.hpp
+++ b/modules/gui/qt/maininterface/compositor_dummy.hpp
@@ -39,7 +39,7 @@ public:
MainInterface *makeMainInterface() override;
virtual void destroyMainInterface() override;
- bool setupVoutWindow(vout_window_t *p_wnd) override;
+ bool setupVoutWindow(vout_window_t *p_wnd, VoutDestroyCb destroyCb) override;
private:
diff --git a/modules/gui/qt/qt.cpp b/modules/gui/qt/qt.cpp
index 804a8a9408..f0d361c9ee 100644
--- a/modules/gui/qt/qt.cpp
+++ b/modules/gui/qt/qt.cpp
@@ -796,6 +796,29 @@ static void ShowDialog( intf_thread_t *p_intf, int i_dialog_event, int i_arg,
QApplication::postEvent( THEDP, event );
}
+static bool WindowClose( vout_window_t *p_wnd )
+{
+ MainInterface *p_mi = (MainInterface *)p_wnd->sys;
+ vlc::threads::mutex_locker locker (lock);
+
+ /* Normally, the interface terminates after the video. In the contrary, the
+ * Qt main loop is gone, so we cannot send any event to the user interface
+ * widgets. Ideally, we would keep the Qt main loop running until after
+ * the video window is released. But it is far simpler to just have the Qt
+ * thread destroy the window early, and to turn this function into a stub.
+ *
+ * That assumes the video output will behave sanely if it window is
+ * destroyed asynchronously.
+ * XCB and Xlib-XCB are fine with that. Plain Xlib wouldn't, */
+ if (unlikely(open_state != OPEN_STATE_OPENED))
+ {
+ msg_Warn (p_wnd, "video already released");
+ return false;
+ }
+ msg_Dbg (p_wnd, "releasing video...");
+ return true;
+}
+
/**
* Video output window provider
*/
@@ -826,6 +849,6 @@ static int WindowOpen( vout_window_t *p_wnd )
if (unlikely(open_state != OPEN_STATE_OPENED))
return VLC_EGENERIC;
- return p_intf->p_sys->p_compositor->setupVoutWindow( p_wnd ) ? VLC_SUCCESS : VLC_EGENERIC;
+ return p_intf->p_sys->p_compositor->setupVoutWindow( p_wnd, WindowClose ) ? VLC_SUCCESS : VLC_EGENERIC;
}
--
2.25.1
More information about the vlc-devel
mailing list