diff options
author | Lars Knoll <lars.knoll@qt.io> | 2021-01-04 12:31:09 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2021-01-22 06:58:14 +0000 |
commit | cfaa21174e72dc00d073f3d6f6ce7f68330afff9 (patch) | |
tree | d925688c02c5e6d9c596ba46be58ff2db6032078 /src/multimedia/video | |
parent | c355d98b045834a494e9fda634388f82c8f625a9 (diff) |
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 <doris.verria@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/multimedia/video')
-rw-r--r-- | src/multimedia/video/qabstractvideobuffer.cpp | 115 | ||||
-rw-r--r-- | src/multimedia/video/qabstractvideobuffer.h | 32 | ||||
-rw-r--r-- | src/multimedia/video/qabstractvideobuffer_p.h | 27 | ||||
-rw-r--r-- | src/multimedia/video/qimagevideobuffer.cpp | 16 | ||||
-rw-r--r-- | src/multimedia/video/qimagevideobuffer_p.h | 2 | ||||
-rw-r--r-- | src/multimedia/video/qmemoryvideobuffer.cpp | 16 | ||||
-rw-r--r-- | src/multimedia/video/qmemoryvideobuffer_p.h | 2 | ||||
-rw-r--r-- | src/multimedia/video/qvideoframe.cpp | 192 |
8 files changed, 120 insertions, 282 deletions
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<uchar *>(d->data.data()); + mapData.nBytes = d->data.size(); + mapData.nPlanes = 1; + mapData.bytesPerLine[0] = d->bytesPerLine; + mapData.data[0] = reinterpret_cast<uchar *>(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; } /*! |