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.weghorn@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.weghorn@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.weghorn@posteo.de>
(cherry picked from commit
08533ca4e2526644b803c40c0c3d3c96f43762af)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184918
Reviewed-by: Adolfo Jayme Barrientos <fitojb@ubuntu.com>
Gbp-Pq: Name avmedia-qt-use-gstreamer-frame-grabber-by-default.diff
#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>
#include <vcl/timer.hxx>
#include <gstwindow.hxx>
+#include <mediamisc.hxx>
#include "QtFrameGrabber.hxx"
#include "QtPlayer.hxx"
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()