avmedia/source/qt6/QtPlayer.cxx | 51 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-)
New commits: commit 4bda0a68ef81a3f3eb5233b35ea046aca5352c88 Author: Michael Weghorn <m.wegh...@posteo.de> AuthorDate: Fri May 2 17:52:19 2025 +0200 Commit: Adolfo Jayme Barrientos <fit...@ubuntu.com> CommitDate: Sat May 3 14:10:17 2025 +0200 tdf#166055 avmedia qt: Use GStreamer frame grabber by default As described in tdf#166055, QtFrameGrabber currently still causes issues (freezes or crashes). The QtMultimedia API does not provide a simple way to synchronously retrieve a video frame, so the current approach is to connect to the QVideoSink::videoFrameChanged signal and start playing the video until the first frame arrives. There are various QtMultimedia plugins/backends (at least GStreamer and ffmpeg for Linux). Some use multiple threads internally. Some logic needs to be run in the main thread however, so it's not possible to move things to a separate thread/event loop to decouple it from the main thread. As a consequence, there is a need to trigger event processing while waiting for the frame, as QVideoSink::videoFrameChanged would otherwise never be called. Triggering event processing can have bad side-effects however, as seen in tdf#166055, e.g. leading to endless recursion or crashes when processing LO events. See also commit 697405b533a8ae5b6a8f5bd184b9344a96f71c69 Author: Michael Weghorn <m.wegh...@posteo.de> Date: Wed Apr 9 09:42:45 2025 +0200 tdf#166055 qt avmedia: Provide media/player size right away for more background and some thoughts. For now, avoid the problem by using the GStreamer based frame grabber even with QtPlayer by default. This means that the QtMultimedia framework is still used for video playback with the qt6 VCL plugin, where LO's GStreamer implementation doesn't work properly, see commit 441d8ed9be0e7f831b455a69b8688dcb79a8bc00 Author: Michael Weghorn <m.wegh...@posteo.de> Date: Mon May 20 16:25:09 2024 +0200 tdf#145735 avmedia qt: Use QtMultimedia for Qt 6 media playback . However, in order to preview images (that are e.g. shown in Impress when not in presentation mode) the LO GStreamer backend is used now. (That works fine, no UI interaction is needed for that.) Adjust QtPlayer::createFrameGrabber accordingly to return the LO default platform player/frame grabber implementation (which is the GStreamer one on Linux), see also MediaWindowImpl::createPlayer. Use the service to avoid having to link GStreamer libraries. However, allow to force the use of QtFrameGrabber by setting environment variable SAL_VCL_QT_USE_QT_FRAME_GRABBER. Change-Id: Ibe5c42adf6e8f699f33e5f089bd2f6076c3de4f7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184912 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.wegh...@posteo.de> (cherry picked from commit 08533ca4e2526644b803c40c0c3d3c96f43762af) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184918 Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com> diff --git a/avmedia/source/qt6/QtPlayer.cxx b/avmedia/source/qt6/QtPlayer.cxx index 1be226b248dd..dc0dea9fb05a 100644 --- a/avmedia/source/qt6/QtPlayer.cxx +++ b/avmedia/source/qt6/QtPlayer.cxx @@ -17,6 +17,9 @@ #include <QtWidgets/QLabel> #include <QtWidgets/QLayout> +#include <com/sun/star/media/XManager.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <comphelper/processfactory.hxx> #include <cppuhelper/supportsservice.hxx> #include <sal/log.hxx> #include <rtl/string.hxx> @@ -30,6 +33,7 @@ #include <vcl/timer.hxx> #include <gstwindow.hxx> +#include <mediamisc.hxx> #include "QtFrameGrabber.hxx" #include "QtPlayer.hxx" @@ -245,12 +249,55 @@ uno::Reference<::media::XPlayerWindow> return xRet; } +namespace +{ +// see also MediaWindowImpl::createPlayer +uno::Reference<media::XFrameGrabber> createPlatformFrameGrabber(const OUString& rUrl) +{ + const uno::Reference<uno::XComponentContext>& xContext + = comphelper::getProcessComponentContext(); + try + { + uno::Reference<css::media::XManager> xManager( + xContext->getServiceManager()->createInstanceWithContext(AVMEDIA_MANAGER_SERVICE_NAME, + xContext), + uno::UNO_QUERY); + if (!xManager.is()) + return nullptr; + + uno::Reference<media::XPlayer> xPlayer = xManager->createPlayer(rUrl); + if (!xPlayer.is()) + return nullptr; + + return xPlayer->createFrameGrabber(); + } + catch (const uno::Exception&) + { + SAL_WARN("avmedia", "Exception in createPlatformFrameGrabber"); + } + + return nullptr; +} +} + uno::Reference<media::XFrameGrabber> SAL_CALL QtPlayer::createFrameGrabber() { osl::MutexGuard aGuard(m_aMutex); - rtl::Reference<QtFrameGrabber> xFrameGrabber = new QtFrameGrabber(m_xMediaPlayer->source()); - return xFrameGrabber; + // use the default platform frame grabber (GStreamer on Linux) by default + // instead of using QtFrameGrabber for now unless overriden by env variable, + // as QtFrameGrabber has issues (see e.g. tdf#166055) + static const bool bPreferQtFrameGrabber + = (getenv("SAL_VCL_QT_USE_QT_FRAME_GRABBER") != nullptr); + if (!bPreferQtFrameGrabber) + { + uno::Reference<media::XFrameGrabber> xFrameGrabber + = createPlatformFrameGrabber(toOUString(m_xMediaPlayer->source().url())); + if (xFrameGrabber.is()) + return xFrameGrabber; + } + + return new QtFrameGrabber(m_xMediaPlayer->source()); } OUString SAL_CALL QtPlayer::getImplementationName()