QML MediaPlayer Segmentation Fault
-
Running on an i.MX6, I immediately get a "Segmentation Fault" anytime that I try to use "MediaPlayer" from "QtMultimedia". Even the following simple QML results in a "Segmentation Fault":
import QtQuick 2.15 import QtQuick.Window 2.15 import QtMultimedia 5.15 Window { id: mainWindow width: 480 height: 272 visible: true title: qsTr("Test") Rectangle { border.color: "red" border.width: 5 anchors.fill: parent MediaPlayer { id: mediaPlayer videoOutput: videoOutput } VideoOutput { id: videoOutput anchors.top: parent.top anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right anchors.margins: 5 } } }
Remove the MediaPlayer / VideoOutput and it works fine.
I found the following bug report, which is marked as "fixed", but I can't seem to see what the "fix" is:
https://bugreports.qt.io/browse/QTBUG-89796How do I debug/fix this?
-
Running on an i.MX6, I immediately get a "Segmentation Fault" anytime that I try to use "MediaPlayer" from "QtMultimedia". Even the following simple QML results in a "Segmentation Fault":
import QtQuick 2.15 import QtQuick.Window 2.15 import QtMultimedia 5.15 Window { id: mainWindow width: 480 height: 272 visible: true title: qsTr("Test") Rectangle { border.color: "red" border.width: 5 anchors.fill: parent MediaPlayer { id: mediaPlayer videoOutput: videoOutput } VideoOutput { id: videoOutput anchors.top: parent.top anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right anchors.margins: 5 } } }
Remove the MediaPlayer / VideoOutput and it works fine.
I found the following bug report, which is marked as "fixed", but I can't seem to see what the "fix" is:
https://bugreports.qt.io/browse/QTBUG-89796How do I debug/fix this?
Mediaplayer
does not containvideoOutput
you should usesource
MediaPlayer { id: mediaPlayer //videoOutput: videoOutput source: videoOutput } VideoOutput { id: videoOutput anchors.top: parent.top anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right anchors.margins: 5 } } }
-
Mediaplayer
does not containvideoOutput
you should usesource
MediaPlayer { id: mediaPlayer //videoOutput: videoOutput source: videoOutput } VideoOutput { id: videoOutput anchors.top: parent.top anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right anchors.margins: 5 } } }
@Markkyboy Thanks for the response :-). I've tried that but it unfortunately made no difference (still get Segmentation Fault).
I've also tried with just "Video":
import QtQuick 2.15 import QtQuick.Window 2.15 import QtMultimedia 5.15 Window { id: mainWindow width: 480 height: 272 visible: true title: qsTr("Test") Rectangle { border.color: "red" border.width: 5 anchors.fill: parent Video { id: video anchors.top: parent.top anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right anchors.margins: 5 } } }
which also makes no difference (results in Segmentation Fault).
I have tried running the QML with just qmlscene, so this is really about as basic as it can get.
-
I have now reduced this to simply:
import QtQuick 2.15 import QtMultimedia 5.15 Video { id: video width: 480 height: 272 }
which still results in "Segmentation Fault" (launching with qmlscene).
Really looks like this is something in Qt rather than the QML code? -
I have put together a C++ only test and that works fine.
#include "dialog.h" #include <QApplication> #include <QMediaPlayer> #include <QVideoWidget> #include <QDebug> int main(int argc, char *argv[]) { QApplication a(argc, argv); //Dialog w; //w.show(); QMediaPlayer* player = new QMediaPlayer; QVideoWidget* vw = new QVideoWidget; player->setVideoOutput(vw); player->setMedia(QUrl::fromLocalFile("/root/vid_480.avi")); vw->setGeometry(0,0,480,272); vw->show(); player->play(); qDebug() << player->state(); return a.exec(); }
So seems like this is specifically QML related? Is there a potential workaround doing most of the application in QML but only the video player in C++?
Interestingly, vw->setGeometry() does not seem to have any effect. I have tried for example
vw->setGeometry(160,32,320,240);
however the video still just plays full screen.
-
I am having trouble debugging C++ on the embedded target, as per https://forum.qt.io/topic/33262/this-does-not-seem-to-be-a-debug-build/14, however if I do try the debugger then upon the Segmentation Fault it does seem to break somewhere with a sort of stack trace (apologies, I am new to Qt and Qt Creator), which stack trace includes "QDeclarativeVideoOutput::createBackend(QMediaService*)" - so not sure if that info helps at all.
-
I now have the debugging working and have managed to trace the cause of the fault.
In qtmultimediaquicktools/qdeclarativevideooutput.cpp (Qt 5.15), the initialiser forQDeclarativeVideoOutput
callscreateBackend(nullptr)
:QDeclarativeVideoOutput::QDeclarativeVideoOutput(QQuickItem *parent) : QQuickItem(parent), m_sourceType(NoSource), m_fillMode(PreserveAspectFit), m_geometryDirty(true), m_orientation(0), m_autoOrientation(false), m_screenOrientationHandler(0) { initResource(); setFlag(ItemHasContents, true); qInfo() << Q_FUNC_INFO << "createBackend(nullptr);"; //! createBackend(nullptr); }
createBackend()
looks like this:bool QDeclarativeVideoOutput::createBackend(QMediaService *service) { bool backendAvailable = false; const auto instances = videoBackendFactoryLoader()->instances(QLatin1String("declarativevideobackend")); for (QObject *instance : instances) { if (QDeclarativeVideoBackendFactoryInterface *plugin = qobject_cast<QDeclarativeVideoBackendFactoryInterface*>(instance)) { if (!m_backend) m_backend.reset(plugin->create(this)); if (m_backend && m_backend->init(service)) { backendAvailable = true; break; } } } #if QT_CONFIG(opengl) if (!backendAvailable) { if (!m_backend) m_backend.reset(new QDeclarativeVideoRendererBackend(this)); if (m_backend->init(service)) backendAvailable = true; } #endif // QDeclarativeVideoWindowBackend only works when there is a service with a QVideoWindowControl. // Without service, the QDeclarativeVideoRendererBackend should always work. if (!backendAvailable) { Q_ASSERT(service); m_backend.reset(new QDeclarativeVideoWindowBackend(this)); if (m_backend->init(service)) backendAvailable = true; } if (backendAvailable) { // Since new backend has been created needs to update its geometry. m_geometryDirty = true; m_backend->clearFilters(); for (int i = 0; i < m_filters.count(); ++i) m_backend->appendFilter(m_filters[i]); } else { qWarning() << Q_FUNC_INFO << "Media service has neither renderer nor window control available."; m_backend.reset(); } return backendAvailable; }
the important part here is the
#if QT_CONFIG(opengl)
preprocessor conditional. On my desktop computer, which has OpenGL available, execution enters here and callsm_backend.reset(new QDeclarativeVideoRendererBackend(this));
before callingm_backend->init(service)
(service
is null at this point).
QDeclarativeVideoRendererBackend::init
looks like this:bool QDeclarativeVideoRendererBackend::init(QMediaService *service) { // When there is no service, the source is an object with a "videoSurface" property, which // doesn't require a QVideoRendererControl and therefore always works if (!service) return true; if (QMediaControl *control = service->requestControl(QVideoRendererControl_iid)) { if ((m_rendererControl = qobject_cast<QVideoRendererControl *>(control))) { m_rendererControl->setSurface(m_surface); m_service = service; return true; } } return false; }
because
service
is null, this function simply returnstrue
, which back inQDeclarativeVideoOutput::createBackend
then results in settingbackendAvailable = true;
which then results in the nextif
statement not executing.On the embedded machine, which is an i.MX6ULL with no GPU (and therefore no OpenGL), the preprocessor section is removed, and so the
if
statement after it executes. This results in a call tom_backend.reset(new QDeclarativeVideoWindowBackend(this));
and thenm_backend->init(service)
.QDeclarativeVideoWindowBackend::init
(qtmultimediaquicktools/qdeclarativevideooutput_window.cpp) looks like this:bool QDeclarativeVideoWindowBackend::init(QMediaService *service) { if (QMediaControl *control = service->requestControl(QVideoWindowControl_iid)) { if ((m_videoWindowControl = qobject_cast<QVideoWindowControl *>(control))) { if (q->window()) m_videoWindowControl->setWinId(q->window()->winId()); m_service = service; QObject::connect(m_videoWindowControl.data(), SIGNAL(nativeSizeChanged()), q, SLOT(_q_updateNativeSize())); return true; } } return false; }
so it will try call
service->requestControl
, but becauseservice
is null this results in a segmentation fault.So overall, the reason for the error is that the i.MX6ULL doesn't have OpenGL, which then results in running into this bug .
I've tried a few guessy workarounds so far, however this then results in the line of code
qWarning() << Q_FUNC_INFO << "Media service has neither renderer nor window control available.";
being hit and things not working (qtvideosink doesn't get registered). I haven't dug further enough into this yet to understand exactly why that is happening. I will submit a bug report now however, hopefully the developers can resolve this fairly quickly :-).
-
-
OK I've now added software OpenGL (Buildroot BR2_PACKAGE_MESA3D + BR2_PACKAGE_MESA3D_GALLIUM_DRIVER_SWRAST + BR2_PACKAGE_MESA3D_OPENGL_ES). This solves the Segmentation Fault problem, however I am still getting nothing on the display.
source: "gst-pipeline: videotestsrc ! qtvideosink"
results in nothing.
source: "gst-pipeline: videotestsrc ! fbdevsink"
works, but obviously it's rendering directly to the frame-buffer (full screen) and not the Qt control (qtvideosink).
There are no errors or warnings reported, it just doesn't work.Any ideas / suggestions welcome!