diff options
-rw-r--r-- | src/gsttools/qgstreamerplayersession.cpp | 90 | ||||
-rw-r--r-- | src/gsttools/qgstreamerplayersession_p.h | 3 | ||||
-rw-r--r-- | src/multimedia/configure.json | 17 | ||||
-rw-r--r-- | src/multimediawidgets/qgraphicsvideoitem.h | 9 | ||||
-rw-r--r-- | src/plugins/alsa/alsa.pro | 2 | ||||
-rw-r--r-- | src/plugins/directshow/player/directshowplayercontrol.cpp | 14 | ||||
-rw-r--r-- | src/plugins/gstreamer/camerabin/camerabinsession.cpp | 6 | ||||
-rw-r--r-- | src/plugins/videonode/imx6/imx6.pro | 6 | ||||
-rw-r--r-- | src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp | 12 | ||||
-rw-r--r-- | src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp | 3 | ||||
-rw-r--r-- | tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp | 20 |
11 files changed, 135 insertions, 47 deletions
diff --git a/src/gsttools/qgstreamerplayersession.cpp b/src/gsttools/qgstreamerplayersession.cpp index 10e83342d..b9e1c084f 100644 --- a/src/gsttools/qgstreamerplayersession.cpp +++ b/src/gsttools/qgstreamerplayersession.cpp @@ -113,6 +113,11 @@ static GstStaticCaps static_RawCaps = GST_STATIC_CAPS(DEFAULT_RAW_CAPS); QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) : QObject(parent) { + initPlaybin(); +} + +void QGstreamerPlayerSession::initPlaybin() +{ m_playbin = gst_element_factory_make(QT_GSTREAMER_PLAYBIN_ELEMENT_NAME, NULL); if (m_playbin) { //GST_PLAY_FLAG_NATIVE_VIDEO omits configuration of ffmpegcolorspace and videoscale, @@ -199,9 +204,7 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) if (m_playbin != 0) { // Sort out messages - m_bus = gst_element_get_bus(m_playbin); - m_busHelper = new QGstreamerBusHelper(m_bus, this); - m_busHelper->installMessageFilter(this); + setBus(gst_element_get_bus(m_playbin)); g_object_set(G_OBJECT(m_playbin), "video-sink", m_videoOutputBin, NULL); @@ -237,16 +240,33 @@ QGstreamerPlayerSession::~QGstreamerPlayerSession() removeAudioBufferProbe(); delete m_busHelper; - gst_object_unref(GST_OBJECT(m_bus)); - if (m_playbin) - gst_object_unref(GST_OBJECT(m_playbin)); - gst_object_unref(GST_OBJECT(m_pipeline)); + m_busHelper = nullptr; + resetElements(); + } +} + +template <class T> +static inline void resetGstObject(T *&obj, T *v = nullptr) +{ + if (obj) + gst_object_unref(GST_OBJECT(obj)); + + obj = v; +} + +void QGstreamerPlayerSession::resetElements() +{ + setBus(nullptr); + resetGstObject(m_playbin); + resetGstObject(m_pipeline); #if !GST_CHECK_VERSION(1,0,0) - gst_object_unref(GST_OBJECT(m_colorSpace)); + resetGstObject(m_colorSpace); #endif - gst_object_unref(GST_OBJECT(m_nullVideoSink)); - gst_object_unref(GST_OBJECT(m_videoOutputBin)); - } + resetGstObject(m_nullVideoSink); + resetGstObject(m_videoOutputBin); + + m_volumeElement = nullptr; + m_videoIdentity = nullptr; } GstElement *QGstreamerPlayerSession::playbin() const @@ -336,8 +356,14 @@ void QGstreamerPlayerSession::loadFromUri(const QNetworkRequest &request) bool QGstreamerPlayerSession::parsePipeline() { - if (m_request.url().scheme() != QLatin1String("gst-pipeline")) + if (m_request.url().scheme() != QLatin1String("gst-pipeline")) { + if (!m_playbin) { + resetElements(); + initPlaybin(); + updateVideoRenderer(); + } return false; + } // Set current surface to video sink before creating a pipeline. auto renderer = qobject_cast<QVideoRendererControl *>(m_videoOutput); @@ -384,25 +410,12 @@ bool QGstreamerPlayerSession::setPipeline(GstElement *pipeline) if (!bus) return false; - gst_object_unref(GST_OBJECT(m_pipeline)); - m_pipeline = pipeline; - gst_object_unref(GST_OBJECT(m_bus)); - m_bus = bus; - m_busHelper->deleteLater(); - m_busHelper = new QGstreamerBusHelper(m_bus, this); - m_busHelper->installMessageFilter(this); - - if (m_videoOutput) - m_busHelper->installMessageFilter(m_videoOutput); - - if (m_playbin) { + if (m_playbin) gst_element_set_state(m_playbin, GST_STATE_NULL); - gst_object_unref(GST_OBJECT(m_playbin)); - } - m_playbin = nullptr; - m_volumeElement = nullptr; - m_videoIdentity = nullptr; + resetElements(); + setBus(bus); + m_pipeline = pipeline; if (m_renderer) { gst_foreach(gst_bin_iterate_sinks(GST_BIN(pipeline)), @@ -432,6 +445,25 @@ bool QGstreamerPlayerSession::setPipeline(GstElement *pipeline) return true; } +void QGstreamerPlayerSession::setBus(GstBus *bus) +{ + resetGstObject(m_bus, bus); + + // It might still accept gst messages. + if (m_busHelper) + m_busHelper->deleteLater(); + m_busHelper = nullptr; + + if (!m_bus) + return; + + m_busHelper = new QGstreamerBusHelper(m_bus, this); + m_busHelper->installMessageFilter(this); + + if (m_videoOutput) + m_busHelper->installMessageFilter(m_videoOutput); +} + qint64 QGstreamerPlayerSession::duration() const { return m_duration; diff --git a/src/gsttools/qgstreamerplayersession_p.h b/src/gsttools/qgstreamerplayersession_p.h index 69027eeb2..797229e69 100644 --- a/src/gsttools/qgstreamerplayersession_p.h +++ b/src/gsttools/qgstreamerplayersession_p.h @@ -210,6 +210,9 @@ private: void resumeVideoProbes(); bool parsePipeline(); bool setPipeline(GstElement *pipeline); + void resetElements(); + void initPlaybin(); + void setBus(GstBus *bus); QNetworkRequest m_request; QMediaPlayer::State m_state = QMediaPlayer::StoppedState; diff --git a/src/multimedia/configure.json b/src/multimedia/configure.json index ca2839cea..65d9aee80 100644 --- a/src/multimedia/configure.json +++ b/src/multimedia/configure.json @@ -106,6 +106,18 @@ { "type": "pkgConfig", "args": "gstreamer-gl-1.0" } ] }, + "gstreamer_imxcommon": { + "label": "GStreamer i.MX common", + "export": "gstreamer_imxcommon", + "test": { + "include": "gst/allocators/imx/phys_mem_meta.h" + }, + "use": "gstreamer_1_0", + "sources": [ + { "type": "pkgConfig", + "args": "gstimxcommon" } + ] + }, "libresourceqt5": { "label": "libresourceqt5", "test": "resourcepolicy", @@ -245,6 +257,11 @@ "condition": "features.gstreamer_1_0 && libs.gstreamer_gl_1_0", "output": [ "privateFeature" ] }, + "gstreamer_imxcommon": { + "label": "GStreamer i.MX common", + "condition": "(features.gstreamer_1_0 && libs.gstreamer_imxcommon)", + "output": [ "privateFeature" ] + }, "gpu_vivante": { "label": "Vivante GPU", "condition": "features.gui && features.opengles2 && tests.gpu_vivante", diff --git a/src/multimediawidgets/qgraphicsvideoitem.h b/src/multimediawidgets/qgraphicsvideoitem.h index 3902389d9..5aa3bd75c 100644 --- a/src/multimediawidgets/qgraphicsvideoitem.h +++ b/src/multimediawidgets/qgraphicsvideoitem.h @@ -81,6 +81,15 @@ public: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + enum { Type = 14 }; + int type() const override + { + // Enable the use of qgraphicsitem_cast with this item. + return Type; + } +#endif + Q_SIGNALS: void nativeSizeChanged(const QSizeF &size); diff --git a/src/plugins/alsa/alsa.pro b/src/plugins/alsa/alsa.pro index 56657f100..4012bb8f6 100644 --- a/src/plugins/alsa/alsa.pro +++ b/src/plugins/alsa/alsa.pro @@ -1,7 +1,7 @@ TARGET = qtaudio_alsa QT += multimedia-private -LIBS += -lasound +QMAKE_USE += alsa HEADERS += \ qalsaplugin.h \ diff --git a/src/plugins/directshow/player/directshowplayercontrol.cpp b/src/plugins/directshow/player/directshowplayercontrol.cpp index 7e1413b56..2fe43f21b 100644 --- a/src/plugins/directshow/player/directshowplayercontrol.cpp +++ b/src/plugins/directshow/player/directshowplayercontrol.cpp @@ -89,9 +89,11 @@ void DirectShowPlayerControl::setPosition(qint64 position) emit mediaStatusChanged(m_status); } - if (m_state == QMediaPlayer::StoppedState && m_pendingPosition != position) { - m_pendingPosition = position; - emit positionChanged(m_pendingPosition); + if (m_state == QMediaPlayer::StoppedState) { + if (m_pendingPosition != position) { + m_pendingPosition = position; + emit positionChanged(m_pendingPosition); + } return; } @@ -280,6 +282,9 @@ void DirectShowPlayerControl::emitPropertyChanges() int properties = m_updateProperties; m_updateProperties = 0; + if (properties & StatusProperty) + emit mediaStatusChanged(m_status); + if ((properties & ErrorProperty) && m_error != QMediaPlayer::NoError) emit error(m_error, m_errorString); @@ -300,9 +305,6 @@ void DirectShowPlayerControl::emitPropertyChanges() if (properties & SeekableProperty) emit seekableChanged(m_seekable); - if (properties & StatusProperty) - emit mediaStatusChanged(m_status); - if (properties & StateProperty) emit stateChanged(m_state); } diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.cpp b/src/plugins/gstreamer/camerabin/camerabinsession.cpp index b96ba6792..3e505a413 100644 --- a/src/plugins/gstreamer/camerabin/camerabinsession.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinsession.cpp @@ -1312,6 +1312,9 @@ QList< QPair<int,int> > CameraBinSession::supportedFrameRates(const QSize &frame for (uint i=0; i<gst_caps_get_size(caps); i++) { GstStructure *structure = gst_caps_get_structure(caps, i); gst_structure_set_name(structure, "video/x-raw"); +#if GST_CHECK_VERSION(1,2,0) + gst_caps_set_features(caps, i, NULL); +#endif const GValue *oldRate = gst_structure_get_value(structure, "framerate"); if (!oldRate) continue; @@ -1424,6 +1427,9 @@ QList<QSize> CameraBinSession::supportedResolutions(QPair<int,int> rate, for (uint i=0; i<gst_caps_get_size(caps); i++) { GstStructure *structure = gst_caps_get_structure(caps, i); gst_structure_set_name(structure, "video/x-raw"); +#if GST_CHECK_VERSION(1,2,0) + gst_caps_set_features(caps, i, NULL); +#endif const GValue *oldW = gst_structure_get_value(structure, "width"); const GValue *oldH = gst_structure_get_value(structure, "height"); if (!oldW || !oldH) diff --git a/src/plugins/videonode/imx6/imx6.pro b/src/plugins/videonode/imx6/imx6.pro index c8085a31e..43e17e725 100644 --- a/src/plugins/videonode/imx6/imx6.pro +++ b/src/plugins/videonode/imx6/imx6.pro @@ -2,6 +2,12 @@ TARGET = imx6vivantevideonode QT += multimedia-private qtmultimediaquicktools-private +qtConfig(gstreamer_imxcommon) { + QT += multimediagsttools-private + QMAKE_USE += gstreamer_imxcommon + DEFINES += GST_USE_UNSTABLE_API +} + HEADERS += \ qsgvivantevideonode.h \ qsgvivantevideomaterialshader.h \ diff --git a/src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp b/src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp index 4b68f47a4..e1468fe34 100644 --- a/src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp +++ b/src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp @@ -49,6 +49,11 @@ #include <unistd.h> +#include <QtMultimedia/private/qtmultimediaglobal_p.h> +#if QT_CONFIG(gstreamer_imxcommon) +#include "private/qgstvideobuffer_p.h" +#include <gst/allocators/imx/phys_mem_meta.h> +#endif //#define QT_VIVANTE_VIDEO_DEBUG @@ -224,7 +229,12 @@ GLuint QSGVivanteVideoMaterial::vivanteMapping(QVideoFrame vF) #endif GLuint physical = ~0U; - +#if QT_CONFIG(gstreamer_imxcommon) + auto buffer = reinterpret_cast<QGstVideoBuffer *>(vF.buffer()); + GstImxPhysMemMeta *meta = GST_IMX_PHYS_MEM_META_GET(buffer->buffer()); + if (meta && meta->phys_addr) + physical = meta->phys_addr; +#endif glBindTexture(GL_TEXTURE_2D, tmpTexId); glTexDirectVIVMap_LOCAL(GL_TEXTURE_2D, fullWidth, fullHeight, diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp index 40568d118..863cefa4e 100644 --- a/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp +++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp @@ -163,8 +163,7 @@ void QDeclarativeVideoRendererBackend::scheduleDeleteFilterResources() void QDeclarativeVideoRendererBackend::releaseResources() { // Called on the gui thread when the window is closed or changed. - QMutexLocker lock(&m_frameMutex); - scheduleDeleteFilterResources(); + invalidateSceneGraph(); } void QDeclarativeVideoRendererBackend::invalidateSceneGraph() diff --git a/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp b/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp index 9ec26021f..9cd3b7fa9 100644 --- a/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp +++ b/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp @@ -791,16 +791,18 @@ void tst_QMediaPlayerBackend::seekPauseSeek() player.pause(); QTRY_COMPARE(player.state(), QMediaPlayer::PausedState); // it might take some time for the operation to be completed - QTRY_VERIFY(!surface->m_frameList.isEmpty()); // we must see a frame at position 7000 here + QTRY_VERIFY_WITH_TIMEOUT(!surface->m_frameList.isEmpty(), 10000); // we must see a frame at position 7000 here // Make sure that the frame has a timestamp before testing - not all backends provides this - if (surface->m_frameList.back().startTime() < 0) + if (!surface->m_frameList.back().isValid() || surface->m_frameList.back().startTime() < 0) QSKIP("No timestamp"); { QVideoFrame frame = surface->m_frameList.back(); +#if !QT_CONFIG(directshow) const qint64 elapsed = (frame.startTime() / 1000) - position; // frame.startTime() is microsecond, position is milliseconds. QVERIFY2(qAbs(elapsed) < (qint64)500, QByteArray::number(elapsed).constData()); +#endif QCOMPARE(frame.width(), 160); QCOMPARE(frame.height(), 120); @@ -808,9 +810,9 @@ void tst_QMediaPlayerBackend::seekPauseSeek() QVERIFY(frame.map(QAbstractVideoBuffer::ReadOnly)); QImage image(frame.bits(), frame.width(), frame.height(), QVideoFrame::imageFormatFromPixelFormat(frame.pixelFormat())); QVERIFY(!image.isNull()); - QVERIFY(qRed(image.pixel(0, 0)) >= 240); // conversion from YUV => RGB, that's why it's not 255 - QCOMPARE(qGreen(image.pixel(0, 0)), 0); - QCOMPARE(qBlue(image.pixel(0, 0)), 0); + QVERIFY(qRed(image.pixel(0, 0)) >= 230); // conversion from YUV => RGB, that's why it's not 255 + QVERIFY(qGreen(image.pixel(0, 0)) < 20); + QVERIFY(qBlue(image.pixel(0, 0)) < 20); frame.unmap(); } @@ -824,17 +826,19 @@ void tst_QMediaPlayerBackend::seekPauseSeek() { QVideoFrame frame = surface->m_frameList.back(); +#if !QT_CONFIG(directshow) const qint64 elapsed = (frame.startTime() / 1000) - position; QVERIFY2(qAbs(elapsed) < (qint64)500, QByteArray::number(elapsed).constData()); +#endif QCOMPARE(frame.width(), 160); QCOMPARE(frame.height(), 120); QVERIFY(frame.map(QAbstractVideoBuffer::ReadOnly)); QImage image(frame.bits(), frame.width(), frame.height(), QVideoFrame::imageFormatFromPixelFormat(frame.pixelFormat())); QVERIFY(!image.isNull()); - QCOMPARE(qRed(image.pixel(0, 0)), 0); - QVERIFY(qGreen(image.pixel(0, 0)) >= 240); - QCOMPARE(qBlue(image.pixel(0, 0)), 0); + QVERIFY(qRed(image.pixel(0, 0)) < 20); + QVERIFY(qGreen(image.pixel(0, 0)) >= 230); + QVERIFY(qBlue(image.pixel(0, 0)) < 20); frame.unmap(); } } |