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()

Reply via email to