diff options
author | VaL Doroshchuk <valentyn.doroshchuk@qt.io> | 2019-10-28 12:23:15 +0100 |
---|---|---|
committer | VaL Doroshchuk <valentyn.doroshchuk@qt.io> | 2019-11-06 09:50:28 +0100 |
commit | cb8f5067a2fdf73f4f5b71ab3c7bcc65dc13c387 (patch) | |
tree | 7c4cb1985e23de597a7627d0a360d4a7ed30e130 | |
parent | 59d0683c999bec5612f6ba91867bde4d02185204 (diff) | |
download | qtmultimedia-cb8f5067a2fdf73f4f5b71ab3c7bcc65dc13c387.tar.gz |
Introduce rendering to multiple surfaces
QAbstractVideoSurface is used to retrieve and render video frames
in particular pixel format.
I.e. a backend takes one video surface which asks to provide video frames
in one of the supported formats returned from QAbstractVideoSurface::supportedPixelFormats().
So currently there is one source of the video frames and only one video output possible.
Introducing QMediaPlayer::setVideoOutput(const QVector<QAbstractVideoSurface *> &)
This func takes a list of surfaces, that support at least one shared pixel format,
and presents video frames to all of them at the same time.
Several surfaces, which do not have any shared pixel formats, will fail to work.
Task-number: QTBUG-32939
Change-Id: Ifbdaf692755353fbd5bf3ad74baba1820e3d0237
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
-rw-r--r-- | src/multimedia/playback/qmediaplayer.cpp | 19 | ||||
-rw-r--r-- | src/multimedia/playback/qmediaplayer.h | 1 | ||||
-rw-r--r-- | src/multimedia/video/qvideosurfaces.cpp | 92 | ||||
-rw-r--r-- | src/multimedia/video/qvideosurfaces_p.h | 77 | ||||
-rw-r--r-- | src/multimedia/video/video.pri | 6 | ||||
-rw-r--r-- | tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp | 28 |
6 files changed, 221 insertions, 2 deletions
diff --git a/src/multimedia/playback/qmediaplayer.cpp b/src/multimedia/playback/qmediaplayer.cpp index 48db0335e..e8bb352f7 100644 --- a/src/multimedia/playback/qmediaplayer.cpp +++ b/src/multimedia/playback/qmediaplayer.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qmediaplayer.h" +#include "qvideosurfaces_p.h" #include "qvideosurfaceoutput_p.h" #include "qmediaobject_p.h" @@ -1168,6 +1169,24 @@ void QMediaPlayer::setVideoOutput(QAbstractVideoSurface *surface) } } +/*! + \since 5.15 + Sets multiple video surfaces as the video output of a media player. + This allows the media player to render video frames on different surfaces. + + All video surfaces must support at least one shared \c QVideoFrame::PixelFormat. + + If a video output has already been set on the media player the new surfaces + will replace it. + + \sa QAbstractVideoSurface::supportedPixelFormats +*/ + +void QMediaPlayer::setVideoOutput(const QVector<QAbstractVideoSurface *> &surfaces) +{ + setVideoOutput(new QVideoSurfaces(surfaces, this)); +} + /*! \reimp */ QMultimedia::AvailabilityStatus QMediaPlayer::availability() const { diff --git a/src/multimedia/playback/qmediaplayer.h b/src/multimedia/playback/qmediaplayer.h index 5d9a393e1..7ebed84da 100644 --- a/src/multimedia/playback/qmediaplayer.h +++ b/src/multimedia/playback/qmediaplayer.h @@ -131,6 +131,7 @@ public: void setVideoOutput(QVideoWidget *); void setVideoOutput(QGraphicsVideoItem *); void setVideoOutput(QAbstractVideoSurface *surface); + void setVideoOutput(const QVector<QAbstractVideoSurface *> &surfaces); QMediaContent media() const; const QIODevice *mediaStream() const; diff --git a/src/multimedia/video/qvideosurfaces.cpp b/src/multimedia/video/qvideosurfaces.cpp new file mode 100644 index 000000000..c7de5ea12 --- /dev/null +++ b/src/multimedia/video/qvideosurfaces.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qvideosurfaces_p.h" + +QT_BEGIN_NAMESPACE + +QVideoSurfaces::QVideoSurfaces(const QVector<QAbstractVideoSurface *> &s, QObject *parent) + : QAbstractVideoSurface(parent) + , m_surfaces(s) +{ +} + +QVideoSurfaces::~QVideoSurfaces() +{ +} + +QList<QVideoFrame::PixelFormat> QVideoSurfaces::supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const +{ + QList<QVideoFrame::PixelFormat> result; + QMap<QVideoFrame::PixelFormat, int> formats; + for (auto &s : m_surfaces) { + for (auto &p : s->supportedPixelFormats(type)) { + if (++formats[p] == m_surfaces.size()) + result << p; + } + } + + return result; +} + +bool QVideoSurfaces::start(const QVideoSurfaceFormat &format) +{ + bool result = true; + for (auto &s : m_surfaces) + result &= s->start(format); + + return result; +} + +void QVideoSurfaces::stop() +{ + for (auto &s : m_surfaces) + s->stop(); +} + +bool QVideoSurfaces::present(const QVideoFrame &frame) +{ + bool result = true; + for (auto &s : m_surfaces) + result &= s->present(frame); + + return result; +} + +QT_END_NAMESPACE diff --git a/src/multimedia/video/qvideosurfaces_p.h b/src/multimedia/video/qvideosurfaces_p.h new file mode 100644 index 000000000..67831e74e --- /dev/null +++ b/src/multimedia/video/qvideosurfaces_p.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVIDEOSURFACES_P_H +#define QVIDEOSURFACES_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QAbstractVideoSurface> +#include <QVector> + +QT_BEGIN_NAMESPACE + +class QVideoSurfaces : public QAbstractVideoSurface +{ +public: + QVideoSurfaces(const QVector<QAbstractVideoSurface *> &surfaces, QObject *parent = nullptr); + ~QVideoSurfaces(); + + QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const override; + bool start(const QVideoSurfaceFormat &format) override; + void stop() override; + bool present(const QVideoFrame &frame) override; + +private: + QVector<QAbstractVideoSurface *> m_surfaces; + Q_DISABLE_COPY(QVideoSurfaces) +}; + +QT_END_NAMESPACE + +#endif // QVIDEOSURFACES_P_H diff --git a/src/multimedia/video/video.pri b/src/multimedia/video/video.pri index 3a73c5045..a3668ba4a 100644 --- a/src/multimedia/video/video.pri +++ b/src/multimedia/video/video.pri @@ -15,7 +15,8 @@ PRIVATE_HEADERS += \ video/qmemoryvideobuffer_p.h \ video/qvideooutputorientationhandler_p.h \ video/qvideosurfaceoutput_p.h \ - video/qvideoframeconversionhelper_p.h + video/qvideoframeconversionhelper_p.h \ + video/qvideosurfaces_p.h SOURCES += \ video/qabstractvideobuffer.cpp \ @@ -28,7 +29,8 @@ SOURCES += \ video/qvideosurfaceoutput.cpp \ video/qvideoprobe.cpp \ video/qabstractvideofilter.cpp \ - video/qvideoframeconversionhelper.cpp + video/qvideoframeconversionhelper.cpp \ + video/qvideosurfaces.cpp SSE2_SOURCES += video/qvideoframeconversionhelper_sse2.cpp SSSE3_SOURCES += video/qvideoframeconversionhelper_ssse3.cpp diff --git a/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp b/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp index 9cd3b7fa9..f1be070e8 100644 --- a/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp +++ b/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp @@ -78,6 +78,7 @@ private slots: void playlistObject(); void surfaceTest_data(); void surfaceTest(); + void multipleSurfaces(); void metadata(); void playerStateAtEOS(); @@ -1393,6 +1394,33 @@ void tst_QMediaPlayerBackend::surfaceTest() QVERIFY2(surface.m_totalFrames >= 25, qPrintable(QString("Expected >= 25, got %1").arg(surface.m_totalFrames))); } +void tst_QMediaPlayerBackend::multipleSurfaces() +{ + if (localVideoFile.isNull()) + QSKIP("No supported video file"); + + QList<QVideoFrame::PixelFormat> formats1; + formats1 << QVideoFrame::Format_RGB32 + << QVideoFrame::Format_ARGB32; + QList<QVideoFrame::PixelFormat> formats2; + formats2 << QVideoFrame::Format_YUV420P + << QVideoFrame::Format_RGB32; + + TestVideoSurface surface1(false); + surface1.setSupportedFormats(formats1); + TestVideoSurface surface2(false); + surface2.setSupportedFormats(formats2); + + QMediaPlayer player; + player.setVideoOutput(QVector<QAbstractVideoSurface *>() << &surface1 << &surface2); + player.setMedia(localVideoFile); + player.play(); + QTRY_VERIFY(player.position() >= 1000); + QVERIFY2(surface1.m_totalFrames >= 25, qPrintable(QString("Expected >= 25, got %1").arg(surface1.m_totalFrames))); + QVERIFY2(surface2.m_totalFrames >= 25, qPrintable(QString("Expected >= 25, got %1").arg(surface2.m_totalFrames))); + QCOMPARE(surface1.m_totalFrames, surface2.m_totalFrames); +} + void tst_QMediaPlayerBackend::metadata() { if (localFileWithMetadata.isNull()) |