tdf#145735 qt avmedia: Don't deadlock with QGstreamerMediaPlayer
While opending a slide with a video worked fine for me with the qt6 VCL plugin and a local Qt development build on Debian testing (qtbase as of 8915ae3a75c4a356d94962dd9b31e1458f2a506f, qtwayland as of deae8b9ce9f551b29ef98d0bb827a8543af2797e, qtmultimedia as of 235ba5f273fbb7dfed8ba3736e4444a85aee5770), this resulted in a freeze when using Debian's system-provided Qt packages instead (libqt6multimedia6:amd64 6.4.2-11+b2). While the self-compiled Qt dev is using `QFFmpegMediaPlayer` which asynchronously loads media, the system QtMultimedia is using `QGstreamerMediaPlayer` (s. frame 37 in below backtrace) that apparently doesn't use multiple threads. Therefore, using `Qt::BlockingQueuedConnection` is problematic, as its documentation [1] says: > Same as Qt::QueuedConnection, except that the signalling thread blocks > until the slot returns. This connection must not be used if the receiver > lives in the signalling thread, or else the application will deadlock. Use `Qt::AutoConnection` (= 0, the default) instead and specify the `Qt::SingleShotConnection` flag in addition to ensure the slot gets called only once: > This is a flag that can be combined with any one of the above connection > types, using a bitwise OR. When Qt::SingleShotConnection is set, the > slot is going to be called only once; the connection will be > automatically broken when the signal is emitted. This flag was > introduced in Qt 6.0. Drop the now no longer needed manual disconnect. This makes the scenario work with both, the custom-compiled Qt dev using `QFFmpegMediaPlayer` and the system-provided Qt 6.4.2 using `QGstreamerMediaPlayer`. Side note: Unrelated to the issue addressed here, using the system-provided Qt with `QGstreamerMediaPlayer` results in a crash when started via the soffice shell script wrapper with a LibreOffice debug build or when using soffice.bin directly and manually setting `MALLOC_PERTURB_=153`, which indicates some memory issue. That could be within Qt, though, haven't analyzed that further. Backtrace of deadlock: 1 syscall syscall.S 38 0x7f40a83249f9 2 QSemaphore::acquire(int) 0x7f40948714e2 3 ?? 0x7f409477fede 4 QVideoSink::videoFrameChanged(QVideoFrame const&) const 0x7f4095195376 5 ?? 0x7f405c219f5c 6 ?? 0x7f405c21a25b 7 QApplicationPrivate::notify_helper(QObject *, QEvent *) 0x7f4093782d62 8 QCoreApplication::notifyInternal2(QObject *, QEvent *) 0x7f40947356d8 9 QCoreApplicationPrivate::sendPostedEvents(QObject *, int, QThreadData *) 0x7f40947358b7 10 ?? 0x7f4094925257 11 ?? 0x7f409ab0de3f 12 ?? 0x7f409ab0fec7 13 g_main_context_iteration 0x7f409ab104e0 14 QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) 0x7f4094922f60 15 QtInstance::ImplYield QtInstance.cxx 455 0x7f4094e534e0 16 QtInstance::DoYield QtInstance.cxx 464 0x7f4094e568a5 17 ImplYield svapp.cxx 384 0x7f409f3c48cc 18 Scheduler::ProcessEventsToIdle svapp.cxx 419 0x7f409f3c4bc8 19 avmedia::qt::QtFrameGrabber::grabFrame QtFrameGrabber.cxx 106 0x7f405cac5524 20 non-virtual thunk to avmedia::qt::QtFrameGrabber::grabFrame(double) 0x7f405cac564e 21 avmedia::MediaWindow::grabFrame mediawindow.cxx 385 0x7f40a03e41ad 22 SdrMediaObj::getSnapshot() const::$_0::operator()(com::sun:⭐:uno::Reference<com::sun:⭐:media::XPlayer> const&) const svdomedia.cxx 195 0x7f40a249e5b5 23 std::__invoke_impl<void, SdrMediaObj::getSnapshot() const::$_0&, com::sun:⭐:uno::Reference<com::sun:⭐:media::XPlayer> const&>(std::__invoke_other, SdrMediaObj::getSnapshot() const::$_0&, com::sun:⭐:uno::Reference<com::sun:⭐:media::XPlayer> const&) invoke.h 61 0x7f40a249e52d 24 std::__invoke_r<void, SdrMediaObj::getSnapshot() const::$_0&, com::sun:⭐:uno::Reference<com::sun:⭐:media::XPlayer> const&>(SdrMediaObj::getSnapshot() const::$_0&, com::sun:⭐:uno::Reference<com::sun:⭐:media::XPlayer> const&) invoke.h 111 0x7f40a249e4dd 25 std::_Function_handler<void (com::sun:⭐:uno::Reference<com::sun:⭐:media::XPlayer> const&), SdrMediaObj::getSnapshot() const::$_0>::_M_invoke(std::_Any_data const&, com::sun:⭐:uno::Reference<com::sun:⭐:media::XPlayer> const&) std_function.h 290 0x7f40a249e345 26 std::function<void (com::sun:⭐:uno::Reference<com::sun:⭐:media::XPlayer> const&)>::operator()(com::sun:⭐:uno::Reference<com::sun:⭐:media::XPlayer> const&) const std_function.h 591 0x7f40a03e96cd 27 avmedia::PlayerListener::callPlayerWindowSizeAvailable mediawindow.hxx 76 0x7f40a03e6bf1 28 avmedia::PlayerListener::preferredPlayerWindowSizeAvailable mediawindow.cxx 496 0x7f40a03e5055 29 avmedia::qt::QtPlayer::notifyListeners QtPlayer.cxx 395 0x7f405cacfd53 30 avmedia::qt::QtPlayer::notifyIfReady QtPlayer.cxx 326 0x7f405cacfb42 31 QtPrivate::FunctorCall<QtPrivate::IndexesList<0>, QtPrivate::List<QMediaPlayer::MediaStatus>, void, void (avmedia::qt::QtPlayer:: *)(QMediaPlayer::MediaStatus)>::call qobjectdefs_impl.h 135 0x7f405cad477b 32 QtPrivate::FunctionPointer<void (avmedia::qt::QtPlayer:: *)(QMediaPlayer::MediaStatus)>::call<QtPrivate::List<QMediaPlayer::MediaStatus>, void> qobjectdefs_impl.h 172 0x7f405cad46cd 33 QtPrivate::QSlotObject<void (avmedia::qt::QtPlayer:: *)(QMediaPlayer::MediaStatus), QtPrivate::List<QMediaPlayer::MediaStatus>, void>::impl qobjectdefs_impl.h 383 0x7f405cad4612 34 ?? 0x7f409477fbbe 35 QMediaPlayer::mediaStatusChanged(QMediaPlayer::MediaStatus) 0x7f4095184a05 36 ?? 0x7f405c210740 37 non-virtual thunk to QGstreamerMediaPlayer::processBusMessage(QGstreamerMessage const&) 0x7f405c2009f7 38 ?? 0x7f405c21aa94 39 QObject::event(QEvent *) 0x7f40947723e0 40 QApplicationPrivate::notify_helper(QObject *, QEvent *) 0x7f4093782d62 41 QCoreApplication::notifyInternal2(QObject *, QEvent *) 0x7f40947356d8 42 QCoreApplicationPrivate::sendPostedEvents(QObject *, int, QThreadData *) 0x7f40947358b7 43 ?? 0x7f4094925257 44 ?? 0x7f409ab0de3f 45 ?? 0x7f409ab0fec7 46 g_main_context_iteration 0x7f409ab104e0 47 QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) 0x7f4094922f60 48 QtInstance::ImplYield QtInstance.cxx 455 0x7f4094e534e0 49 QtInstance::DoYield QtInstance.cxx 464 0x7f4094e568a5 50 ImplYield svapp.cxx 384 0x7f409f3c48cc 51 Scheduler::ProcessEventsToIdle svapp.cxx 419 0x7f409f3c4bc8 52 avmedia::qt::QtFrameGrabber::grabFrame QtFrameGrabber.cxx 106 0x7f405cac5524 53 non-virtual thunk to avmedia::qt::QtFrameGrabber::grabFrame(double) 0x7f405cac564e 54 avmedia::MediaWindow::grabFrame mediawindow.cxx 385 0x7f40a03e41ad 55 SdrMediaObj::getSnapshot() const::$_0::operator()(com::sun:⭐:uno::Reference<com::sun:⭐:media::XPlayer> const&) const svdomedia.cxx 195 0x7f40a249e5b5 56 std::__invoke_impl<void, SdrMediaObj::getSnapshot() const::$_0&, com::sun:⭐:uno::Reference<com::sun:⭐:media::XPlayer> const&>(std::__invoke_other, SdrMediaObj::getSnapshot() const::$_0&, com::sun:⭐:uno::Reference<com::sun:⭐:media::XPlayer> const&) invoke.h 61 0x7f40a249e52d 57 std::__invoke_r<void, SdrMediaObj::getSnapshot() const::$_0&, com::sun:⭐:uno::Reference<com::sun:⭐:media::XPlayer> const&>(SdrMediaObj::getSnapshot() const::$_0&, com::sun:⭐:uno::Reference<com::sun:⭐:media::XPlayer> const&) invoke.h 111 0x7f40a249e4dd 58 std::_Function_handler<void (com::sun:⭐:uno::Reference<com::sun:⭐:media::XPlayer> const&), SdrMediaObj::getSnapshot() const::$_0>::_M_invoke(std::_Any_data const&, com::sun:⭐:uno::Reference<com::sun:⭐:media::XPlayer> const&) std_function.h 290 0x7f40a249e345 59 std::function<void (com::sun:⭐:uno::Reference<com::sun:⭐:media::XPlayer> const&)>::operator()(com::sun:⭐:uno::Reference<com::sun:⭐:media::XPlayer> const&) const std_function.h 591 0x7f40a03e96cd 60 avmedia::PlayerListener::callPlayerWindowSizeAvailable mediawindow.hxx 76 0x7f40a03e6bf1 61 avmedia::PlayerListener::preferredPlayerWindowSizeAvailable mediawindow.cxx 496 0x7f40a03e5055 62 avmedia::qt::QtPlayer::notifyListeners QtPlayer.cxx 395 0x7f405cacfd53 63 avmedia::qt::QtPlayer::notifyIfReady QtPlayer.cxx 326 0x7f405cacfb42 64 QtPrivate::FunctorCall<QtPrivate::IndexesList<0>, QtPrivate::List<QMediaPlayer::MediaStatus>, void, void (avmedia::qt::QtPlayer:: *)(QMediaPlayer::MediaStatus)>::call qobjectdefs_impl.h 135 0x7f405cad477b 65 QtPrivate::FunctionPointer<void (avmedia::qt::QtPlayer:: *)(QMediaPlayer::MediaStatus)>::call<QtPrivate::List<QMediaPlayer::MediaStatus>, void> qobjectdefs_impl.h 172 0x7f405cad46cd 66 QtPrivate::QSlotObject<void (avmedia::qt::QtPlayer:: *)(QMediaPlayer::MediaStatus), QtPrivate::List<QMediaPlayer::MediaStatus>, void>::impl qobjectdefs_impl.h 383 0x7f405cad4612 [1] https://doc.qt.io/qt-6/qt.html#ConnectionType-enum Change-Id: Ia8bfd19b0c0c4f970a5eb200c2a0b45784ef25fd Reviewed-on: https://gerrit.libreoffice.org/c/core/+/169036 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
This commit is contained in:
parent
12c4b7ee91
commit
4df2a30c57
1 changed files with 2 additions and 5 deletions
|
@ -55,7 +55,7 @@ QtFrameGrabber::QtFrameGrabber(const QUrl& rSourceUrl)
|
|||
m_xMediaPlayer->setVideoSink(m_xVideoSink.get());
|
||||
|
||||
connect(m_xMediaPlayer.get(), &QMediaPlayer::errorOccurred, this,
|
||||
&QtFrameGrabber::onErrorOccured, Qt::BlockingQueuedConnection);
|
||||
&QtFrameGrabber::onErrorOccured, Qt::SingleShotConnection);
|
||||
}
|
||||
|
||||
void QtFrameGrabber::onErrorOccured(QMediaPlayer::Error eError, const QString& rErrorString)
|
||||
|
@ -72,9 +72,6 @@ void QtFrameGrabber::onVideoFrameChanged(const QVideoFrame& rFrame)
|
|||
{
|
||||
std::lock_guard aLock(m_aMutex);
|
||||
|
||||
disconnect(m_xVideoSink.get(), &QVideoSink::videoFrameChanged, this,
|
||||
&QtFrameGrabber::onVideoFrameChanged);
|
||||
|
||||
const QImage aImage = rFrame.toImage();
|
||||
m_xGraphic = toXGraphic(aImage);
|
||||
m_bWaitingForFrame = false;
|
||||
|
@ -90,7 +87,7 @@ css::uno::Reference<css::graphic::XGraphic> SAL_CALL QtFrameGrabber::grabFrame(d
|
|||
// until the first frame has been received
|
||||
m_bWaitingForFrame = true;
|
||||
connect(m_xVideoSink.get(), &QVideoSink::videoFrameChanged, this,
|
||||
&QtFrameGrabber::onVideoFrameChanged, Qt::BlockingQueuedConnection);
|
||||
&QtFrameGrabber::onVideoFrameChanged, Qt::SingleShotConnection);
|
||||
m_xMediaPlayer->play();
|
||||
while (m_bWaitingForFrame)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue