From cfaa21174e72dc00d073f3d6f6ce7f68330afff9 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 4 Jan 2021 12:31:09 +0100 Subject: Merge QAbstractPlanarVideoOutput into QAbstractVideoOutput And while we're at it, sanitize the signature of the virtual map() method. Change-Id: I8feb09e1dd6abdd9f480e202568ff84e6c3c08a9 Reviewed-by: Doris Verria Reviewed-by: Lars Knoll --- .../video/qmlvideofilter_opencl/rgbframehelper.h | 2 +- src/gsttools/qgstvideobuffer.cpp | 31 ++-- src/gsttools/qgstvideobuffer_p.h | 4 +- src/multimedia/video/qabstractvideobuffer.cpp | 115 +----------- src/multimedia/video/qabstractvideobuffer.h | 32 ++-- src/multimedia/video/qabstractvideobuffer_p.h | 27 +-- src/multimedia/video/qimagevideobuffer.cpp | 16 +- src/multimedia/video/qimagevideobuffer_p.h | 2 +- src/multimedia/video/qmemoryvideobuffer.cpp | 16 +- src/multimedia/video/qmemoryvideobuffer_p.h | 2 +- src/multimedia/video/qvideoframe.cpp | 192 ++++++++++----------- .../android/src/common/qandroidvideooutput.cpp | 24 ++- .../camera/avfcamerarenderercontrol.mm | 46 +++-- .../mediaplayer/avfvideorenderercontrol.mm | 2 +- src/plugins/common/evr/evrd3dpresentengine.cpp | 23 ++- .../mmrendererplayervideorenderercontrol.cpp | 11 +- src/plugins/wmf/player/mfvideorenderercontrol.cpp | 20 +-- .../tst_qabstractvideobuffer.cpp | 2 +- .../tst_qpaintervideosurface.cpp | 4 +- tests/auto/unit/qvideoframe/tst_qvideoframe.cpp | 42 ++--- 20 files changed, 218 insertions(+), 395 deletions(-) diff --git a/examples/multimedia/video/qmlvideofilter_opencl/rgbframehelper.h b/examples/multimedia/video/qmlvideofilter_opencl/rgbframehelper.h index 1c8dbd857..638337ea4 100644 --- a/examples/multimedia/video/qmlvideofilter_opencl/rgbframehelper.h +++ b/examples/multimedia/video/qmlvideofilter_opencl/rgbframehelper.h @@ -113,7 +113,7 @@ class TextureBuffer : public QAbstractVideoBuffer public: TextureBuffer(uint id) : QAbstractVideoBuffer(GLTextureHandle), m_id(id) { } MapMode mapMode() const { return NotMapped; } - uchar *map(MapMode, int *, int *) { return 0; } + virtual MapData map(MapMode mode) { return {}; } void unmap() { } QVariant handle() const { return QVariant::fromValue(m_id); } diff --git a/src/gsttools/qgstvideobuffer.cpp b/src/gsttools/qgstvideobuffer.cpp index 49c8efaed..58738ffa0 100644 --- a/src/gsttools/qgstvideobuffer.cpp +++ b/src/gsttools/qgstvideobuffer.cpp @@ -42,7 +42,7 @@ QT_BEGIN_NAMESPACE QGstVideoBuffer::QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info) - : QAbstractPlanarVideoBuffer(NoHandle) + : QAbstractVideoBuffer(NoHandle) , m_videoInfo(info) , m_buffer(buffer) { @@ -52,7 +52,7 @@ QGstVideoBuffer::QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info) QGstVideoBuffer::QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info, QGstVideoBuffer::HandleType handleType, const QVariant &handle) - : QAbstractPlanarVideoBuffer(handleType) + : QAbstractVideoBuffer(handleType) , m_videoInfo(info) , m_buffer(buffer) , m_handle(handle) @@ -73,39 +73,36 @@ QAbstractVideoBuffer::MapMode QGstVideoBuffer::mapMode() const return m_mode; } -int QGstVideoBuffer::map(MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4]) +QAbstractVideoBuffer::MapData QGstVideoBuffer::map(MapMode mode) { const GstMapFlags flags = GstMapFlags(((mode & ReadOnly) ? GST_MAP_READ : 0) | ((mode & WriteOnly) ? GST_MAP_WRITE : 0)); + MapData mapData; if (mode == NotMapped || m_mode != NotMapped) - return 0; + return mapData; if (m_videoInfo.finfo->n_planes == 0) { // Encoded if (gst_buffer_map(m_buffer, &m_frame.map[0], flags)) { - if (numBytes) - *numBytes = m_frame.map[0].size; - bytesPerLine[0] = -1; - data[0] = static_cast(m_frame.map[0].data); + mapData.nBytes = m_frame.map[0].size; + mapData.nPlanes = 1; + mapData.bytesPerLine[0] = -1; + mapData.data[0] = static_cast(m_frame.map[0].data); m_mode = mode; - - return 1; } } else if (gst_video_frame_map(&m_frame, &m_videoInfo, m_buffer, flags)) { - if (numBytes) - *numBytes = m_frame.info.size; + mapData.nBytes = m_frame.info.size; + mapData.nPlanes = m_frame.info.finfo->n_planes; for (guint i = 0; i < m_frame.info.finfo->n_planes; ++i) { - bytesPerLine[i] = m_frame.info.stride[i]; - data[i] = static_cast(m_frame.data[i]); + mapData.bytesPerLine[i] = m_frame.info.stride[i]; + mapData.data[i] = static_cast(m_frame.data[i]); } m_mode = mode; - - return m_frame.info.finfo->n_planes; } - return 0; + return mapData; } void QGstVideoBuffer::unmap() diff --git a/src/gsttools/qgstvideobuffer_p.h b/src/gsttools/qgstvideobuffer_p.h index 5f026ebc5..4dc45a370 100644 --- a/src/gsttools/qgstvideobuffer_p.h +++ b/src/gsttools/qgstvideobuffer_p.h @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE -class Q_GSTTOOLS_EXPORT QGstVideoBuffer : public QAbstractPlanarVideoBuffer +class Q_GSTTOOLS_EXPORT QGstVideoBuffer : public QAbstractVideoBuffer { public: QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info); @@ -72,7 +72,7 @@ public: GstBuffer *buffer() const { return m_buffer; } MapMode mapMode() const override; - int map(MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4]) override; + MapData map(MapMode mode) override; void unmap() override; QVariant handle() const override { return m_handle; } diff --git a/src/multimedia/video/qabstractvideobuffer.cpp b/src/multimedia/video/qabstractvideobuffer.cpp index 40493412b..0a56902b0 100644 --- a/src/multimedia/video/qabstractvideobuffer.cpp +++ b/src/multimedia/video/qabstractvideobuffer.cpp @@ -54,16 +54,6 @@ static void qRegisterAbstractVideoBufferMetaTypes() Q_CONSTRUCTOR_FUNCTION(qRegisterAbstractVideoBufferMetaTypes) -int QAbstractVideoBufferPrivate::map( - QAbstractVideoBuffer::MapMode mode, - int *numBytes, - int bytesPerLine[4], - uchar *data[4]) -{ - data[0] = q_ptr->map(mode, numBytes, bytesPerLine); - return data[0] ? 1 : 0; -} - /*! \class QAbstractVideoBuffer \brief The QAbstractVideoBuffer class is an abstraction for video data. @@ -127,8 +117,7 @@ int QAbstractVideoBufferPrivate::map( Constructs an abstract video buffer of the given \a type. */ QAbstractVideoBuffer::QAbstractVideoBuffer(HandleType type) - : d_ptr(nullptr) - , m_type(type) + : m_type(type) { } @@ -181,36 +170,8 @@ QAbstractVideoBuffer::HandleType QAbstractVideoBuffer::handleType() const \sa map() */ -/*! - \fn QAbstractVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine) - - Maps the contents of a video buffer to memory. - - In some cases the video buffer might be stored in video memory or otherwise inaccessible - memory, so it is necessary to map the buffer before accessing the pixel data. This may involve - copying the contents around, so avoid mapping and unmapping unless required. - - The map \a mode indicates whether the contents of the mapped memory should be read from and/or - written to the buffer. If the map mode includes the \c QAbstractVideoBuffer::ReadOnly flag the - mapped memory will be populated with the content of the buffer when initially mapped. If the map - mode includes the \c QAbstractVideoBuffer::WriteOnly flag the content of the possibly modified - mapped memory will be written back to the buffer when unmapped. - - When access to the data is no longer needed be sure to call the unmap() function to release the - mapped memory and possibly update the buffer contents. - - Returns a pointer to the mapped memory region, or a null pointer if the mapping failed. The - size in bytes of the mapped memory region is returned in \a numBytes, and the line stride in \a - bytesPerLine. - - \note Writing to memory that is mapped as read-only is undefined, and may result in changes - to shared data or crashes. - - \sa unmap(), mapMode() -*/ - +/*! \fn uchar *QAbstractVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine) -/*! Independently maps the planes of a video buffer to memory. The map \a mode indicates whether the contents of the mapped memory should be read from and/or @@ -236,15 +197,6 @@ QAbstractVideoBuffer::HandleType QAbstractVideoBuffer::handleType() const \since 5.4 */ -int QAbstractVideoBuffer::mapPlanes(MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4]) -{ - if (d_ptr) - return d_ptr->map(mode, numBytes, bytesPerLine, data); - - data[0] = map(mode, numBytes, bytesPerLine); - - return data[0] ? 1 : 0; -} /*! \fn QAbstractVideoBuffer::unmap() @@ -269,69 +221,6 @@ QVariant QAbstractVideoBuffer::handle() const return QVariant(); } - -int QAbstractPlanarVideoBufferPrivate::map( - QAbstractVideoBuffer::MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4]) -{ - return q_func()->map(mode, numBytes, bytesPerLine, data); -} - -/*! - \class QAbstractPlanarVideoBuffer - \brief The QAbstractPlanarVideoBuffer class is an abstraction for planar video data. - \inmodule QtMultimedia - \ingroup QtMultimedia - \ingroup multimedia - \ingroup multimedia_video - - QAbstractPlanarVideoBuffer extends QAbstractVideoBuffer to support mapping - non-continuous planar video data. Implement this instead of QAbstractVideoBuffer when the - abstracted video data stores planes in separate buffers or includes padding between planes - which would interfere with calculating offsets from the bytes per line and frame height. - - \sa QAbstractVideoBuffer::mapPlanes() - \since 5.4 -*/ - -/*! - Constructs an abstract planar video buffer of the given \a type. -*/ -QAbstractPlanarVideoBuffer::QAbstractPlanarVideoBuffer(HandleType type) - : QAbstractVideoBuffer(*new QAbstractPlanarVideoBufferPrivate, type) -{ -} - -/*! - \internal -*/ -QAbstractPlanarVideoBuffer::QAbstractPlanarVideoBuffer( - QAbstractPlanarVideoBufferPrivate &dd, HandleType type) - : QAbstractVideoBuffer(dd, type) -{ -} -/*! - Destroys an abstract planar video buffer. -*/ -QAbstractPlanarVideoBuffer::~QAbstractPlanarVideoBuffer() -{ -} - -/*! - \internal -*/ -uchar *QAbstractPlanarVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine) -{ - uchar *data[4]; - int strides[4]; - if (map(mode, numBytes, strides, data) > 0) { - if (bytesPerLine) - *bytesPerLine = strides[0]; - return data[0]; - } - - return nullptr; -} - /*! \fn int QAbstractPlanarVideoBuffer::map(MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4]) diff --git a/src/multimedia/video/qabstractvideobuffer.h b/src/multimedia/video/qabstractvideobuffer.h index b3f31b377..6572db9c3 100644 --- a/src/multimedia/video/qabstractvideobuffer.h +++ b/src/multimedia/video/qabstractvideobuffer.h @@ -82,10 +82,16 @@ public: HandleType handleType() const; - virtual MapMode mapMode() const = 0; + struct MapData + { + qsizetype nBytes = 0; + int nPlanes = 0; + int bytesPerLine[4] = {}; + uchar *data[4] = {}; + }; - virtual uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) = 0; - int mapPlanes(MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4]); + virtual MapMode mapMode() const = 0; + virtual MapData map(MapMode mode) = 0; virtual void unmap() = 0; virtual QVariant handle() const; @@ -93,31 +99,13 @@ public: protected: QAbstractVideoBuffer(QAbstractVideoBufferPrivate &dd, HandleType type); - QAbstractVideoBufferPrivate *d_ptr; // For expansion, not used currently + QAbstractVideoBufferPrivate *d_ptr = nullptr; // currently unused HandleType m_type; private: - Q_DECLARE_PRIVATE(QAbstractVideoBuffer) Q_DISABLE_COPY(QAbstractVideoBuffer) }; -class QAbstractPlanarVideoBufferPrivate; -class Q_MULTIMEDIA_EXPORT QAbstractPlanarVideoBuffer : public QAbstractVideoBuffer -{ -public: - QAbstractPlanarVideoBuffer(HandleType type); - virtual ~QAbstractPlanarVideoBuffer(); - - uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) override; - virtual int map(MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4]) = 0; - -protected: - QAbstractPlanarVideoBuffer(QAbstractPlanarVideoBufferPrivate &dd, HandleType type); - -private: - Q_DISABLE_COPY(QAbstractPlanarVideoBuffer) -}; - #ifndef QT_NO_DEBUG_STREAM Q_MULTIMEDIA_EXPORT QDebug operator<<(QDebug, QAbstractVideoBuffer::HandleType); Q_MULTIMEDIA_EXPORT QDebug operator<<(QDebug, QAbstractVideoBuffer::MapMode); diff --git a/src/multimedia/video/qabstractvideobuffer_p.h b/src/multimedia/video/qabstractvideobuffer_p.h index 4877d3120..ff3f5e0ba 100644 --- a/src/multimedia/video/qabstractvideobuffer_p.h +++ b/src/multimedia/video/qabstractvideobuffer_p.h @@ -63,32 +63,7 @@ QT_BEGIN_NAMESPACE class QAbstractVideoBufferPrivate { public: - QAbstractVideoBufferPrivate() - : q_ptr(nullptr) - {} - - virtual ~QAbstractVideoBufferPrivate() - {} - - virtual int map( - QAbstractVideoBuffer::MapMode mode, - int *numBytes, - int bytesPerLine[4], - uchar *data[4]); - - QAbstractVideoBuffer *q_ptr; -}; - -class QAbstractPlanarVideoBufferPrivate : QAbstractVideoBufferPrivate -{ -public: - QAbstractPlanarVideoBufferPrivate() - {} - - int map(QAbstractVideoBuffer::MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4]) override; - -private: - Q_DECLARE_PUBLIC(QAbstractPlanarVideoBuffer) + QAbstractVideoBuffer *q_ptr = nullptr; }; QT_END_NAMESPACE diff --git a/src/multimedia/video/qimagevideobuffer.cpp b/src/multimedia/video/qimagevideobuffer.cpp index ad2de82e6..2602d7d9e 100644 --- a/src/multimedia/video/qimagevideobuffer.cpp +++ b/src/multimedia/video/qimagevideobuffer.cpp @@ -76,23 +76,21 @@ QAbstractVideoBuffer::MapMode QImageVideoBuffer::mapMode() const return d_func()->mapMode; } -uchar *QImageVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine) +QImageVideoBuffer::MapData QImageVideoBuffer::map(MapMode mode) { Q_D(QImageVideoBuffer); + MapData mapData; if (d->mapMode == NotMapped && d->image.bits() && mode != NotMapped) { d->mapMode = mode; - if (numBytes) - *numBytes = int(d->image.sizeInBytes()); - - if (bytesPerLine) - *bytesPerLine = d->image.bytesPerLine(); - - return d->image.bits(); + mapData.nBytes = int(d->image.sizeInBytes()); + mapData.nPlanes = 1; + mapData.bytesPerLine[0] = d->image.bytesPerLine(); + mapData.data[0] = d->image.bits(); } - return nullptr; + return mapData; } void QImageVideoBuffer::unmap() diff --git a/src/multimedia/video/qimagevideobuffer_p.h b/src/multimedia/video/qimagevideobuffer_p.h index f2b88dd9b..ba980a3fb 100644 --- a/src/multimedia/video/qimagevideobuffer_p.h +++ b/src/multimedia/video/qimagevideobuffer_p.h @@ -69,7 +69,7 @@ public: MapMode mapMode() const override; - uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) override; + MapData map(MapMode mode) override; void unmap() override; }; diff --git a/src/multimedia/video/qmemoryvideobuffer.cpp b/src/multimedia/video/qmemoryvideobuffer.cpp index caab74e58..164aa6ebc 100644 --- a/src/multimedia/video/qmemoryvideobuffer.cpp +++ b/src/multimedia/video/qmemoryvideobuffer.cpp @@ -91,23 +91,21 @@ QAbstractVideoBuffer::MapMode QMemoryVideoBuffer::mapMode() const /*! \reimp */ -uchar *QMemoryVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine) +QAbstractVideoBuffer::MapData QMemoryVideoBuffer::map(MapMode mode) { Q_D(QMemoryVideoBuffer); + MapData mapData; if (d->mapMode == NotMapped && d->data.size() && mode != NotMapped) { d->mapMode = mode; - if (numBytes) - *numBytes = d->data.size(); - - if (bytesPerLine) - *bytesPerLine = d->bytesPerLine; - - return reinterpret_cast(d->data.data()); + mapData.nBytes = d->data.size(); + mapData.nPlanes = 1; + mapData.bytesPerLine[0] = d->bytesPerLine; + mapData.data[0] = reinterpret_cast(d->data.data()); } - return nullptr; + return mapData; } /*! diff --git a/src/multimedia/video/qmemoryvideobuffer_p.h b/src/multimedia/video/qmemoryvideobuffer_p.h index e1b1f83a9..5251b4979 100644 --- a/src/multimedia/video/qmemoryvideobuffer_p.h +++ b/src/multimedia/video/qmemoryvideobuffer_p.h @@ -67,7 +67,7 @@ public: MapMode mapMode() const override; - uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) override; + MapData map(MapMode mode) override; void unmap() override; }; diff --git a/src/multimedia/video/qvideoframe.cpp b/src/multimedia/video/qvideoframe.cpp index 6adbbdeb1..d7ddfb5e0 100644 --- a/src/multimedia/video/qvideoframe.cpp +++ b/src/multimedia/video/qvideoframe.cpp @@ -67,16 +67,12 @@ class QVideoFramePrivate : public QSharedData public: QVideoFramePrivate() { - memset(data, 0, sizeof(data)); - memset(bytesPerLine, 0, sizeof(bytesPerLine)); } QVideoFramePrivate(const QSize &size, QVideoFrame::PixelFormat format) : size(size) , pixelFormat(format) { - memset(data, 0, sizeof(data)); - memset(bytesPerLine, 0, sizeof(bytesPerLine)); } ~QVideoFramePrivate() @@ -88,10 +84,7 @@ public: QSize size; qint64 startTime = -1; qint64 endTime = -1; - uchar *data[4]; - int bytesPerLine[4]; - int mappedBytes = 0; - int planeCount = 0; + QAbstractVideoBuffer::MapData mapData; QVideoFrame::PixelFormat pixelFormat = QVideoFrame::Format_Invalid; QAbstractVideoBuffer *buffer = nullptr; int mappedCount = 0; @@ -553,89 +546,90 @@ bool QVideoFrame::map(QAbstractVideoBuffer::MapMode mode) return false; } - Q_ASSERT(d->data[0] == nullptr); - Q_ASSERT(d->bytesPerLine[0] == 0); - Q_ASSERT(d->planeCount == 0); - Q_ASSERT(d->mappedBytes == 0); + Q_ASSERT(d->mapData.data[0] == nullptr); + Q_ASSERT(d->mapData.bytesPerLine[0] == 0); + Q_ASSERT(d->mapData.nPlanes == 0); + Q_ASSERT(d->mapData.nBytes == 0); - d->planeCount = d->buffer->mapPlanes(mode, &d->mappedBytes, d->bytesPerLine, d->data); - if (d->planeCount == 0) + d->mapData = d->buffer->map(mode); + if (d->mapData.nPlanes == 0) return false; - if (d->planeCount > 1) { - // If the plane count is derive the additional planes for planar formats. - } else switch (d->pixelFormat) { - case Format_Invalid: - case Format_ARGB32: - case Format_ARGB32_Premultiplied: - case Format_RGB32: - case Format_RGB24: - case Format_RGB565: - case Format_RGB555: - case Format_ARGB8565_Premultiplied: - case Format_BGRA32: - case Format_BGRA32_Premultiplied: - case Format_ABGR32: - case Format_BGR32: - case Format_BGR24: - case Format_BGR565: - case Format_BGR555: - case Format_BGRA5658_Premultiplied: - case Format_AYUV444: - case Format_AYUV444_Premultiplied: - case Format_YUV444: - case Format_UYVY: - case Format_YUYV: - case Format_Y8: - case Format_Y16: - case Format_Jpeg: - case Format_CameraRaw: - case Format_AdobeDng: - case Format_User: - // Single plane or opaque format. - break; - case Format_YUV420P: - case Format_YUV422P: - case Format_YV12: { - // The UV stride is usually half the Y stride and is 32-bit aligned. - // However it's not always the case, at least on Windows where the - // UV planes are sometimes not aligned. - // We calculate the stride using the UV byte count to always - // have a correct stride. - const int height = d->size.height(); - const int yStride = d->bytesPerLine[0]; - const int uvHeight = d->pixelFormat == Format_YUV422P ? height : height / 2; - const int uvStride = (d->mappedBytes - (yStride * height)) / uvHeight / 2; - - // Three planes, the second and third vertically (and horizontally for other than Format_YUV422P formats) subsampled. - d->planeCount = 3; - d->bytesPerLine[2] = d->bytesPerLine[1] = uvStride; - d->data[1] = d->data[0] + (yStride * height); - d->data[2] = d->data[1] + (uvStride * uvHeight); - break; - } - case Format_NV12: - case Format_NV21: - case Format_IMC2: - case Format_IMC4: { - // Semi planar, Full resolution Y plane with interleaved subsampled U and V planes. - d->planeCount = 2; - d->bytesPerLine[1] = d->bytesPerLine[0]; - d->data[1] = d->data[0] + (d->bytesPerLine[0] * d->size.height()); - break; - } - case Format_IMC1: - case Format_IMC3: { - // Three planes, the second and third vertically and horizontally subsumpled, - // but with lines padded to the width of the first plane. - d->planeCount = 3; - d->bytesPerLine[2] = d->bytesPerLine[1] = d->bytesPerLine[0]; - d->data[1] = d->data[0] + (d->bytesPerLine[0] * d->size.height()); - d->data[2] = d->data[1] + (d->bytesPerLine[1] * d->size.height() / 2); - break; - } - default: - break; + if (d->mapData.nPlanes == 1) { + // If the plane count is 1 derive the additional planes for planar formats. + switch (d->pixelFormat) { + case Format_Invalid: + case Format_ARGB32: + case Format_ARGB32_Premultiplied: + case Format_RGB32: + case Format_RGB24: + case Format_RGB565: + case Format_RGB555: + case Format_ARGB8565_Premultiplied: + case Format_BGRA32: + case Format_BGRA32_Premultiplied: + case Format_ABGR32: + case Format_BGR32: + case Format_BGR24: + case Format_BGR565: + case Format_BGR555: + case Format_BGRA5658_Premultiplied: + case Format_AYUV444: + case Format_AYUV444_Premultiplied: + case Format_YUV444: + case Format_UYVY: + case Format_YUYV: + case Format_Y8: + case Format_Y16: + case Format_Jpeg: + case Format_CameraRaw: + case Format_AdobeDng: + case Format_User: + // Single plane or opaque format. + break; + case Format_YUV420P: + case Format_YUV422P: + case Format_YV12: { + // The UV stride is usually half the Y stride and is 32-bit aligned. + // However it's not always the case, at least on Windows where the + // UV planes are sometimes not aligned. + // We calculate the stride using the UV byte count to always + // have a correct stride. + const int height = d->size.height(); + const int yStride = d->mapData.bytesPerLine[0]; + const int uvHeight = d->pixelFormat == Format_YUV422P ? height : height / 2; + const int uvStride = (d->mapData.nBytes - (yStride * height)) / uvHeight / 2; + + // Three planes, the second and third vertically (and horizontally for other than Format_YUV422P formats) subsampled. + d->mapData.nPlanes = 3; + d->mapData.bytesPerLine[2] = d->mapData.bytesPerLine[1] = uvStride; + d->mapData.data[1] = d->mapData.data[0] + (yStride * height); + d->mapData.data[2] = d->mapData.data[1] + (uvStride * uvHeight); + break; + } + case Format_NV12: + case Format_NV21: + case Format_IMC2: + case Format_IMC4: { + // Semi planar, Full resolution Y plane with interleaved subsampled U and V planes. + d->mapData.nPlanes = 2; + d->mapData.bytesPerLine[1] = d->mapData.bytesPerLine[0]; + d->mapData.data[1] = d->mapData.data[0] + (d->mapData.bytesPerLine[0] * d->size.height()); + break; + } + case Format_IMC1: + case Format_IMC3: { + // Three planes, the second and third vertically and horizontally subsumpled, + // but with lines padded to the width of the first plane. + d->mapData.nPlanes = 3; + d->mapData.bytesPerLine[2] = d->mapData.bytesPerLine[1] = d->mapData.bytesPerLine[0]; + d->mapData.data[1] = d->mapData.data[0] + (d->mapData.bytesPerLine[0] * d->size.height()); + d->mapData.data[2] = d->mapData.data[1] + (d->mapData.bytesPerLine[1] * d->size.height() / 2); + break; + } + default: + break; + } } d->mappedCount++; @@ -667,11 +661,7 @@ void QVideoFrame::unmap() d->mappedCount--; if (d->mappedCount == 0) { - d->mappedBytes = 0; - d->planeCount = 0; - memset(d->bytesPerLine, 0, sizeof(d->bytesPerLine)); - memset(d->data, 0, sizeof(d->data)); - + d->mapData = {}; d->buffer->unmap(); } } @@ -688,7 +678,7 @@ void QVideoFrame::unmap() */ int QVideoFrame::bytesPerLine() const { - return d->bytesPerLine[0]; + return d->mapData.bytesPerLine[0]; } /*! @@ -702,7 +692,7 @@ int QVideoFrame::bytesPerLine() const int QVideoFrame::bytesPerLine(int plane) const { - return plane >= 0 && plane < d->planeCount ? d->bytesPerLine[plane] : 0; + return plane >= 0 && plane < d->mapData.nPlanes ? d->mapData.bytesPerLine[plane] : 0; } /*! @@ -718,7 +708,7 @@ int QVideoFrame::bytesPerLine(int plane) const */ uchar *QVideoFrame::bits() { - return d->data[0]; + return d->mapData.data[0]; } /*! @@ -735,7 +725,7 @@ uchar *QVideoFrame::bits() */ uchar *QVideoFrame::bits(int plane) { - return plane >= 0 && plane < d->planeCount ? d->data[plane] : nullptr; + return plane >= 0 && plane < d->mapData.nPlanes ? d->mapData.data[plane] : nullptr; } /*! @@ -750,7 +740,7 @@ uchar *QVideoFrame::bits(int plane) */ const uchar *QVideoFrame::bits() const { - return d->data[0]; + return d->mapData.data[0]; } /*! @@ -766,7 +756,7 @@ const uchar *QVideoFrame::bits() const */ const uchar *QVideoFrame::bits(int plane) const { - return plane >= 0 && plane < d->planeCount ? d->data[plane] : nullptr; + return plane >= 0 && plane < d->mapData.nPlanes ? d->mapData.data[plane] : nullptr; } /*! @@ -778,7 +768,7 @@ const uchar *QVideoFrame::bits(int plane) const */ int QVideoFrame::mappedBytes() const { - return d->mappedBytes; + return d->mapData.nBytes; } /*! @@ -792,7 +782,7 @@ int QVideoFrame::mappedBytes() const int QVideoFrame::planeCount() const { - return d->planeCount; + return d->mapData.nPlanes; } /*! diff --git a/src/plugins/android/src/common/qandroidvideooutput.cpp b/src/plugins/android/src/common/qandroidvideooutput.cpp index 27cea76ad..3c6472482 100644 --- a/src/plugins/android/src/common/qandroidvideooutput.cpp +++ b/src/plugins/android/src/common/qandroidvideooutput.cpp @@ -103,33 +103,31 @@ public: virtual ~AndroidTextureVideoBuffer() {} - MapMode mapMode() const { return m_mapMode; } + MapMode mapMode() const override { return m_mapMode; } - uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) + MapData map(MapMode mode) override { + MapData mapData; if (m_mapMode == NotMapped && mode == ReadOnly && updateFrame()) { m_mapMode = mode; m_image = m_output->m_fbo->toImage(); - if (numBytes) - *numBytes = static_cast(m_image.sizeInBytes()); - - if (bytesPerLine) - *bytesPerLine = m_image.bytesPerLine(); - - return m_image.bits(); - } else { - return 0; + mapData.nBytes = static_cast(m_image.sizeInBytes()); + mapData.nPlanes = 1; + mapData.bytesPerLine[0] = m_image.bytesPerLine(); + mapData.data[0] = m_image.bits(); } + + return mapData; } - void unmap() + void unmap() override { m_image = QImage(); m_mapMode = NotMapped; } - QVariant handle() const + QVariant handle() const override { AndroidTextureVideoBuffer *that = const_cast(this); if (!that->updateFrame()) diff --git a/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm b/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm index 98cbf3df4..b77aa21ec 100644 --- a/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm +++ b/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm @@ -55,16 +55,16 @@ QT_USE_NAMESPACE -class CVImageVideoBuffer : public QAbstractPlanarVideoBuffer +class CVImageVideoBuffer : public QAbstractVideoBuffer { public: CVImageVideoBuffer(CVImageBufferRef buffer, AVFCameraRendererControl *renderer) #ifndef Q_OS_IOS - : QAbstractPlanarVideoBuffer(NoHandle) + : QAbstractVideoBuffer(NoHandle) #else - : QAbstractPlanarVideoBuffer(renderer->supportsTextures() - && CVPixelBufferGetPixelFormatType(buffer) == kCVPixelFormatType_32BGRA - ? GLTextureHandle : NoHandle) + : QAbstractVideoBuffer(renderer->supportsTextures() + && CVPixelBufferGetPixelFormatType(buffer) == kCVPixelFormatType_32BGRA + ? GLTextureHandle : NoHandle) , m_texture(nullptr) , m_renderer(renderer) #endif @@ -89,16 +89,19 @@ public: MapMode mapMode() const { return m_mode; } - int map(QAbstractVideoBuffer::MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4]) + MapData map(QAbstractVideoBuffer::MapMode mode) { + MapData mapData; + // We only support RGBA or NV12 (or Apple's version of NV12), // they are either 0 planes or 2. - const size_t nPlanes = CVPixelBufferGetPlaneCount(m_buffer); - Q_ASSERT(nPlanes <= 2); + mapData.nPlanes = CVPixelBufferGetPlaneCount(m_buffer); + Q_ASSERT(mapData.nPlanes <= 2); - if (!nPlanes) { - data[0] = map(mode, numBytes, bytesPerLine); - return data[0] ? 1 : 0; + if (!mapData.nPlanes) { + mapData.data[0] = map(mode, &mapData.nBytes, &mapData.bytesPerLine[0]); + mapData.nPlanes = mapData.data[0] ? 1 : 0; + return mapData; } // For a bi-planar format we have to set the parameters correctly: @@ -107,27 +110,22 @@ public: ? kCVPixelBufferLock_ReadOnly : 0); - if (numBytes) - *numBytes = CVPixelBufferGetDataSize(m_buffer); + mapData.nBytes = CVPixelBufferGetDataSize(m_buffer); - if (bytesPerLine) { - // At the moment we handle only bi-planar format. - bytesPerLine[0] = CVPixelBufferGetBytesPerRowOfPlane(m_buffer, 0); - bytesPerLine[1] = CVPixelBufferGetBytesPerRowOfPlane(m_buffer, 1); - } + // At the moment we handle only bi-planar format. + mapData.bytesPerLine[0] = CVPixelBufferGetBytesPerRowOfPlane(m_buffer, 0); + mapData.bytesPerLine[1] = CVPixelBufferGetBytesPerRowOfPlane(m_buffer, 1); - if (data) { - data[0] = static_cast(CVPixelBufferGetBaseAddressOfPlane(m_buffer, 0)); - data[1] = static_cast(CVPixelBufferGetBaseAddressOfPlane(m_buffer, 1)); - } + mapData.data[0] = static_cast(CVPixelBufferGetBaseAddressOfPlane(m_buffer, 0)); + mapData.data[1] = static_cast(CVPixelBufferGetBaseAddressOfPlane(m_buffer, 1)); m_mode = mode; } - return nPlanes; + return mapData; } - uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) + uchar *map(MapMode mode, qsizetype *numBytes, int *bytesPerLine) { if (mode != NotMapped && m_mode == NotMapped) { CVPixelBufferLockBaseAddress(m_buffer, mode == QAbstractVideoBuffer::ReadOnly diff --git a/src/plugins/avfoundation/mediaplayer/avfvideorenderercontrol.mm b/src/plugins/avfoundation/mediaplayer/avfvideorenderercontrol.mm index 726dc5193..6e5b6a15e 100644 --- a/src/plugins/avfoundation/mediaplayer/avfvideorenderercontrol.mm +++ b/src/plugins/avfoundation/mediaplayer/avfvideorenderercontrol.mm @@ -71,7 +71,7 @@ public: } MapMode mapMode() const { return NotMapped; } - uchar *map(MapMode, int*, int*) { return 0; } + MapData map(MapMode mode) override { return {}; } void unmap() {} QVariant handle() const diff --git a/src/plugins/common/evr/evrd3dpresentengine.cpp b/src/plugins/common/evr/evrd3dpresentengine.cpp index 964504e48..51f8b1a39 100644 --- a/src/plugins/common/evr/evrd3dpresentengine.cpp +++ b/src/plugins/common/evr/evrd3dpresentengine.cpp @@ -90,7 +90,7 @@ public: QVariant handle() const override; MapMode mapMode() const override { return m_mapMode; } - uchar *map(MapMode, int*, int*) override; + MapData map(MapMode mode) override; void unmap() override; private: @@ -101,28 +101,27 @@ private: mutable unsigned int m_textureId = 0; }; -uchar *IMFSampleVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine) +IMFSampleVideoBuffer::MapData IMFSampleVideoBuffer::map(MapMode mode) { if (!m_surface || m_mapMode != NotMapped) - return 0; + return {}; D3DSURFACE_DESC desc; if (FAILED(m_surface->GetDesc(&desc))) - return 0; + return {}; D3DLOCKED_RECT rect; if (FAILED(m_surface->LockRect(&rect, NULL, mode == ReadOnly ? D3DLOCK_READONLY : 0))) - return 0; + return {}; m_mapMode = mode; - if (numBytes) - *numBytes = (int)(rect.Pitch * desc.Height); - - if (bytesPerLine) - *bytesPerLine = (int)rect.Pitch; - - return reinterpret_cast(rect.pBits); + MapData mapData; + mapData.nBytes = (int)(rect.Pitch * desc.Height); + mapData.nPlanes = 1; + mapData.bytesPerLine[0] = (int)rect.Pitch; + mapData.data[0] = reinterpret_cast(rect.pBits); + return mapData; } void IMFSampleVideoBuffer::unmap() diff --git a/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp index 3b5715157..68cb47c3c 100644 --- a/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp +++ b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp @@ -154,15 +154,8 @@ public: MapMode mapMode() const { return QAbstractVideoBuffer::ReadWrite; } - void unmap() { - - } - uchar *map(MapMode mode, int * numBytes, int * bytesPerLine) { - Q_UNUSED(mode); - Q_UNUSED(numBytes); - Q_UNUSED(bytesPerLine); - return 0; - } + void unmap() {} + MapData map(MapMode mode) override { return {}; } QVariant handle() const { if (!m_handle) { const_cast(this)->m_handle = m_windowGrabber->getNextTextureId(); diff --git a/src/plugins/wmf/player/mfvideorenderercontrol.cpp b/src/plugins/wmf/player/mfvideorenderercontrol.cpp index 7b121255f..212533009 100644 --- a/src/plugins/wmf/player/mfvideorenderercontrol.cpp +++ b/src/plugins/wmf/player/mfvideorenderercontrol.cpp @@ -74,29 +74,27 @@ namespace m_buffer->Release(); } - uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) + MapData map(MapMode mode) override { + MapData mapData; if (m_mapMode == NotMapped && mode != NotMapped) { BYTE *bytes; DWORD length; HRESULT hr = m_buffer->Lock(&bytes, NULL, &length); if (SUCCEEDED(hr)) { - if (numBytes) - *numBytes = int(length); - - if (bytesPerLine) - *bytesPerLine = m_bytesPerLine; - + mapData.nBytes = qsizetype(length); + mapData.nPlanes = 1; + mapData.bytesPerLine[0] = m_bytesPerLine; + mapData.data[0] = reinterpret_cast(bytes); m_mapMode = mode; - return reinterpret_cast(bytes); } else { qWarning("Faild to lock mf buffer!"); } } - return 0; + return mapData; } - void unmap() + void unmap() override { if (m_mapMode == NotMapped) return; @@ -104,7 +102,7 @@ namespace m_buffer->Unlock(); } - MapMode mapMode() const + MapMode mapMode() const override { return m_mapMode; } diff --git a/tests/auto/unit/qabstractvideobuffer/tst_qabstractvideobuffer.cpp b/tests/auto/unit/qabstractvideobuffer/tst_qabstractvideobuffer.cpp index 146b26d30..e11fd6ac0 100644 --- a/tests/auto/unit/qabstractvideobuffer/tst_qabstractvideobuffer.cpp +++ b/tests/auto/unit/qabstractvideobuffer/tst_qabstractvideobuffer.cpp @@ -67,7 +67,7 @@ public: [[nodiscard]] MapMode mapMode() const override { return QAbstractVideoBuffer::ReadWrite; } - uchar *map(MapMode, int *, int *) override { return nullptr; } + MapData map(MapMode) override { return {}; } void unmap() override {} }; diff --git a/tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp b/tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp index aea3e0e61..14f9309db 100644 --- a/tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp +++ b/tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp @@ -101,7 +101,7 @@ public: [[nodiscard]] QVariant handle() const override { return m_textureId; } - uchar *map(MapMode, int *, int *) override { return nullptr; } + MapData map(MapMode) override { return {}; } void unmap() override {} [[nodiscard]] MapMode mapMode() const override { return NotMapped; } @@ -118,7 +118,7 @@ public: : QAbstractVideoBuffer(UserHandle) {} - uchar *map(MapMode, int *, int *) override { return nullptr; } + MapData map(MapMode) override { return {}; } void unmap() override {} [[nodiscard]] MapMode mapMode() const override { return NotMapped; } }; diff --git a/tests/auto/unit/qvideoframe/tst_qvideoframe.cpp b/tests/auto/unit/qvideoframe/tst_qvideoframe.cpp index 6fcae820b..1eac0bed2 100644 --- a/tests/auto/unit/qvideoframe/tst_qvideoframe.cpp +++ b/tests/auto/unit/qvideoframe/tst_qvideoframe.cpp @@ -96,42 +96,44 @@ private slots: Q_DECLARE_METATYPE(QImage::Format) -class QtTestVideoBuffer : public QObject, public QAbstractVideoBuffer +class QtTestDummyVideoBuffer : public QObject, public QAbstractVideoBuffer { Q_OBJECT public: - QtTestVideoBuffer() + QtTestDummyVideoBuffer() : QAbstractVideoBuffer(NoHandle) {} - explicit QtTestVideoBuffer(QAbstractVideoBuffer::HandleType type) + explicit QtTestDummyVideoBuffer(QAbstractVideoBuffer::HandleType type) : QAbstractVideoBuffer(type) {} [[nodiscard]] MapMode mapMode() const override { return NotMapped; } - uchar *map(MapMode, int *, int *) override { return nullptr; } + MapData map(MapMode) override { return {}; } void unmap() override {} }; -class QtTestPlanarVideoBuffer : public QAbstractPlanarVideoBuffer +class QtTestVideoBuffer : public QAbstractVideoBuffer { public: - QtTestPlanarVideoBuffer() - : QAbstractPlanarVideoBuffer(NoHandle) + QtTestVideoBuffer() + : QAbstractVideoBuffer(NoHandle) {} - explicit QtTestPlanarVideoBuffer(QAbstractVideoBuffer::HandleType type) - : QAbstractPlanarVideoBuffer(type) + explicit QtTestVideoBuffer(QAbstractVideoBuffer::HandleType type) + : QAbstractVideoBuffer(type) {} [[nodiscard]] MapMode mapMode() const override { return m_mapMode; } - int map(MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4]) override { + MapData map(MapMode mode) override + { m_mapMode = mode; - if (numBytes) - *numBytes = m_numBytes; + MapData mapData; + mapData.nBytes = m_numBytes; + mapData.nPlanes = m_planeCount; for (int i = 0; i < m_planeCount; ++i) { - data[i] = m_data[i]; - bytesPerLine[i] = m_bytesPerLine[i]; + mapData.data[i] = m_data[i]; + mapData.bytesPerLine[i] = m_bytesPerLine[i]; } - return m_planeCount; + return mapData; } void unmap() override { m_mapMode = NotMapped; } @@ -270,7 +272,7 @@ void tst_QVideoFrame::createFromBuffer() QFETCH(QSize, size); QFETCH(QVideoFrame::PixelFormat, pixelFormat); - QVideoFrame frame(new QtTestVideoBuffer(handleType), size, pixelFormat); + QVideoFrame frame(new QtTestDummyVideoBuffer(handleType), size, pixelFormat); QVERIFY(frame.isValid()); QCOMPARE(frame.handleType(), handleType); @@ -386,7 +388,7 @@ void tst_QVideoFrame::createNull() void tst_QVideoFrame::destructor() { - QPointer buffer = new QtTestVideoBuffer; + QPointer buffer = new QtTestDummyVideoBuffer; { QVideoFrame frame(buffer, QSize(4, 1), QVideoFrame::Format_ARGB32); @@ -443,7 +445,7 @@ void tst_QVideoFrame::copy() QFETCH(qint64, startTime); QFETCH(qint64, endTime); - QPointer buffer = new QtTestVideoBuffer(handleType); + QPointer buffer = new QtTestDummyVideoBuffer(handleType); { QVideoFrame frame(buffer, size, pixelFormat); @@ -532,7 +534,7 @@ void tst_QVideoFrame::assign() QFETCH(qint64, startTime); QFETCH(qint64, endTime); - QPointer buffer = new QtTestVideoBuffer(handleType); + QPointer buffer = new QtTestDummyVideoBuffer(handleType); QVideoFrame frame; { @@ -734,7 +736,7 @@ void tst_QVideoFrame::mapPlanes_data() static uchar bufferData[1024]; - QtTestPlanarVideoBuffer *planarBuffer = new QtTestPlanarVideoBuffer; + QtTestVideoBuffer *planarBuffer = new QtTestVideoBuffer; planarBuffer->m_data[0] = bufferData; planarBuffer->m_data[1] = bufferData + 512; planarBuffer->m_data[2] = bufferData + 765; -- cgit v1.2.3