summaryrefslogtreecommitdiffstats
path: root/src/multimedia/video
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2021-03-17 14:44:11 +0100
committerLars Knoll <lars.knoll@qt.io>2021-04-06 08:06:31 +0000
commit76aa4e1dd1921441fd34a3907a90e633a2f74911 (patch)
tree654616d8b20172f16970d8c2634db2659ab43554 /src/multimedia/video
parent591395e7dc0bd5afc273d843101862168ede81c9 (diff)
Various improvements to QVideoFrame->QImage conversion
* Implement support for missing pixel formats, we are now able to convert all supported pixel formats to a QImage. * Ensure we always convert to a RGB32 or ARGB32_Premultiplied image * Add missing mappings to gstreamer formats Change-Id: I8816e0a42ced73c96dfff03f131d7a749b55ae36 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/qvideoframe.cpp160
-rw-r--r--src/multimedia/video/qvideoframe.h1
-rw-r--r--src/multimedia/video/qvideoframeconversionhelper.cpp318
-rw-r--r--src/multimedia/video/qvideoframeconversionhelper_p.h18
4 files changed, 384 insertions, 113 deletions
diff --git a/src/multimedia/video/qvideoframe.cpp b/src/multimedia/video/qvideoframe.cpp
index f1c4dc453..3545c1cc3 100644
--- a/src/multimedia/video/qvideoframe.cpp
+++ b/src/multimedia/video/qvideoframe.cpp
@@ -52,6 +52,51 @@
#include <QDebug>
QT_BEGIN_NAMESPACE
+static bool pixelFormatHasAlpha[QVideoFrame::NPixelFormats] =
+{
+ false, //Format_Invalid,
+ true, //Format_ARGB32,
+ true, //Format_ARGB32_Premultiplied,
+ false, //Format_RGB32,
+ false, //Format_RGB24,
+ false, //Format_RGB565,
+ false, //Format_RGB555,
+ true, //Format_ARGB8565_Premultiplied,
+ true, //Format_BGRA32,
+ true, //Format_BGRA32_Premultiplied,
+ true, //Format_ABGR32,
+ false, //Format_BGR32,
+ false, //Format_BGR24,
+ false, //Format_BGR565,
+ false, //Format_BGR555,
+ true, //Format_BGRA5658_Premultiplied,
+
+ true, //Format_AYUV444,
+ true, //Format_AYUV444_Premultiplied,
+ false, //Format_YUV444,
+ false, //Format_YUV420P,
+ false, //Format_YUV422P,
+ false, //Format_YV12,
+ false, //Format_UYVY,
+ false, //Format_YUYV,
+ false, //Format_NV12,
+ false, //Format_NV21,
+ false, //Format_IMC1,
+ false, //Format_IMC2,
+ false, //Format_IMC3,
+ false, //Format_IMC4,
+ false, //Format_Y8,
+ false, //Format_Y16,
+
+ false, //Format_P010LE,
+ false, //Format_P010BE,
+ false, //Format_P016LE,
+ false, //Format_P016BE,
+
+ false, //Format_Jpeg,
+
+};
+
class QVideoFramePrivate : public QSharedData
{
@@ -884,6 +929,10 @@ QVideoFrame::PixelFormat QVideoFrame::pixelFormatFromImageFormat(QImage::Format
return Format_RGB555;
case QImage::Format_RGB888:
return Format_RGB24;
+ case QImage::Format_Grayscale8:
+ return Format_Y8;
+ case QImage::Format_Grayscale16:
+ return Format_Y16;
default:
return Format_Invalid;
}
@@ -899,8 +948,6 @@ QVideoFrame::PixelFormat QVideoFrame::pixelFormatFromImageFormat(QImage::Format
QImage::Format QVideoFrame::imageFormatFromPixelFormat(PixelFormat format)
{
switch (format) {
- case Format_Invalid:
- return QImage::Format_Invalid;
case Format_ARGB32:
return QImage::Format_ARGB32;
case Format_ARGB32_Premultiplied:
@@ -915,11 +962,15 @@ QImage::Format QVideoFrame::imageFormatFromPixelFormat(PixelFormat format)
return QImage::Format_RGB555;
case Format_ARGB8565_Premultiplied:
return QImage::Format_ARGB8565_Premultiplied;
+ case Format_Y8:
+ return QImage::Format_Grayscale8;
+ case Format_Y16:
+ return QImage::Format_Grayscale16;
+ case Format_ABGR32:
case Format_BGRA32:
case Format_BGRA32_Premultiplied:
case Format_BGR32:
case Format_BGR24:
- return QImage::Format_Invalid;
case Format_BGR565:
case Format_BGR555:
case Format_BGRA5658_Premultiplied:
@@ -937,100 +988,18 @@ QImage::Format QVideoFrame::imageFormatFromPixelFormat(PixelFormat format)
case Format_IMC2:
case Format_IMC3:
case Format_IMC4:
- case Format_Y8:
- case Format_Y16:
+ case Format_P010LE:
+ case Format_P010BE:
+ case Format_P016LE:
+ case Format_P016BE:
case Format_Jpeg:
- return QImage::Format_Invalid;
- default:
+ case Format_Invalid:
return QImage::Format_Invalid;
}
return QImage::Format_Invalid;
}
-extern void QT_FASTCALL qt_convert_BGRA32_to_ARGB32(const QVideoFrame&, uchar*);
-extern void QT_FASTCALL qt_convert_BGR24_to_ARGB32(const QVideoFrame&, uchar*);
-extern void QT_FASTCALL qt_convert_BGR565_to_ARGB32(const QVideoFrame&, uchar*);
-extern void QT_FASTCALL qt_convert_BGR555_to_ARGB32(const QVideoFrame&, uchar*);
-extern void QT_FASTCALL qt_convert_AYUV444_to_ARGB32(const QVideoFrame&, uchar*);
-extern void QT_FASTCALL qt_convert_YUV444_to_ARGB32(const QVideoFrame&, uchar*);
-extern void QT_FASTCALL qt_convert_YUV420P_to_ARGB32(const QVideoFrame&, uchar*);
-extern void QT_FASTCALL qt_convert_YV12_to_ARGB32(const QVideoFrame&, uchar*);
-extern void QT_FASTCALL qt_convert_UYVY_to_ARGB32(const QVideoFrame&, uchar*);
-extern void QT_FASTCALL qt_convert_YUYV_to_ARGB32(const QVideoFrame&, uchar*);
-extern void QT_FASTCALL qt_convert_NV12_to_ARGB32(const QVideoFrame&, uchar*);
-extern void QT_FASTCALL qt_convert_NV21_to_ARGB32(const QVideoFrame&, uchar*);
-extern void QT_FASTCALL qt_convert_P016LE_to_ARGB32(const QVideoFrame &, uchar*);
-extern void QT_FASTCALL qt_convert_P016BE_to_ARGB32(const QVideoFrame &, uchar*);
-
-static VideoFrameConvertFunc qConvertFuncs[QVideoFrame::NPixelFormats] = {
- /* Format_Invalid */ nullptr, // Not needed
- /* Format_ARGB32 */ nullptr, // Not needed
- /* Format_ARGB32_Premultiplied */ nullptr, // Not needed
- /* Format_RGB32 */ nullptr, // Not needed
- /* Format_RGB24 */ nullptr, // Not needed
- /* Format_RGB565 */ nullptr, // Not needed
- /* Format_RGB555 */ nullptr, // Not needed
- /* Format_ARGB8565_Premultiplied */ nullptr, // Not needed
- /* Format_BGRA32 */ qt_convert_BGRA32_to_ARGB32,
- /* Format_BGRA32_Premultiplied */ qt_convert_BGRA32_to_ARGB32,
- /* Format_ABGR32 */ nullptr,
- /* Format_BGR32 */ qt_convert_BGRA32_to_ARGB32,
- /* Format_BGR24 */ qt_convert_BGR24_to_ARGB32,
- /* Format_BGR565 */ qt_convert_BGR565_to_ARGB32,
- /* Format_BGR555 */ qt_convert_BGR555_to_ARGB32,
- /* Format_BGRA5658_Premultiplied */ nullptr,
- /* Format_AYUV444 */ qt_convert_AYUV444_to_ARGB32,
- /* Format_AYUV444_Premultiplied */ nullptr,
- /* Format_YUV444 */ qt_convert_YUV444_to_ARGB32,
- /* Format_YUV420P */ qt_convert_YUV420P_to_ARGB32,
- /* Format_YUV422P */ nullptr,
- /* Format_YV12 */ qt_convert_YV12_to_ARGB32,
- /* Format_UYVY */ qt_convert_UYVY_to_ARGB32,
- /* Format_YUYV */ qt_convert_YUYV_to_ARGB32,
- /* Format_NV12 */ qt_convert_NV12_to_ARGB32,
- /* Format_NV21 */ qt_convert_NV21_to_ARGB32,
- /* Format_IMC1 */ nullptr,
- /* Format_IMC2 */ nullptr,
- /* Format_IMC3 */ nullptr,
- /* Format_IMC4 */ nullptr,
- /* Format_Y8 */ nullptr,
- /* Format_Y16 */ nullptr,
- /* Format_P010LE */ qt_convert_P016LE_to_ARGB32,
- /* Format_P010BE */ qt_convert_P016BE_to_ARGB32,
- /* Format_P016LE */ qt_convert_P016LE_to_ARGB32,
- /* Format_P016BE */ qt_convert_P016BE_to_ARGB32,
- /* Format_Jpeg */ nullptr, // Not needed
-};
-
-static void qInitConvertFuncsAsm()
-{
-#ifdef QT_COMPILER_SUPPORTS_SSE2
- extern void QT_FASTCALL qt_convert_BGRA32_to_ARGB32_sse2(const QVideoFrame&, uchar*);
- if (qCpuHasFeature(SSE2)){
- qConvertFuncs[QVideoFrame::Format_BGRA32] = qt_convert_BGRA32_to_ARGB32_sse2;
- qConvertFuncs[QVideoFrame::Format_BGRA32_Premultiplied] = qt_convert_BGRA32_to_ARGB32_sse2;
- qConvertFuncs[QVideoFrame::Format_BGR32] = qt_convert_BGRA32_to_ARGB32_sse2;
- }
-#endif
-#ifdef QT_COMPILER_SUPPORTS_SSSE3
- extern void QT_FASTCALL qt_convert_BGRA32_to_ARGB32_ssse3(const QVideoFrame&, uchar*);
- if (qCpuHasFeature(SSSE3)){
- qConvertFuncs[QVideoFrame::Format_BGRA32] = qt_convert_BGRA32_to_ARGB32_ssse3;
- qConvertFuncs[QVideoFrame::Format_BGRA32_Premultiplied] = qt_convert_BGRA32_to_ARGB32_ssse3;
- qConvertFuncs[QVideoFrame::Format_BGR32] = qt_convert_BGRA32_to_ARGB32_ssse3;
- }
-#endif
-#ifdef QT_COMPILER_SUPPORTS_AVX2
- extern void QT_FASTCALL qt_convert_BGRA32_to_ARGB32_avx2(const QVideoFrame&, uchar*);
- if (qCpuHasFeature(AVX2)){
- qConvertFuncs[QVideoFrame::Format_BGRA32] = qt_convert_BGRA32_to_ARGB32_avx2;
- qConvertFuncs[QVideoFrame::Format_BGRA32_Premultiplied] = qt_convert_BGRA32_to_ARGB32_avx2;
- qConvertFuncs[QVideoFrame::Format_BGR32] = qt_convert_BGRA32_to_ARGB32_avx2;
- }
-#endif
-}
-
/*!
Based on the pixel format converts current video frame to image.
\since 5.15
@@ -1043,7 +1012,6 @@ QImage QVideoFrame::image() const
if (!frame.isValid() || !frame.map(QVideoFrame::ReadOnly))
return result;
- qDebug() << "converting video frame:" << frame.pixelFormat();
// Formats supported by QImage don't need conversion
QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(frame.pixelFormat());
if (imageFormat != QImage::Format_Invalid) {
@@ -1057,16 +1025,12 @@ QImage QVideoFrame::image() const
// Need conversion
else {
- static bool initAsmFuncsDone = false;
- if (!initAsmFuncsDone) {
- qInitConvertFuncsAsm();
- initAsmFuncsDone = true;
- }
- VideoFrameConvertFunc convert = qConvertFuncs[frame.pixelFormat()];
+ VideoFrameConvertFunc convert = qConverterForFormat(frame.pixelFormat());
if (!convert) {
qWarning() << Q_FUNC_INFO << ": unsupported pixel format" << frame.pixelFormat();
} else {
- result = QImage(frame.width(), frame.height(), QImage::Format_ARGB32_Premultiplied);
+ auto format = pixelFormatHasAlpha[frame.pixelFormat()] ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
+ result = QImage(frame.width(), frame.height(), format);
convert(frame, result.bits());
}
}
diff --git a/src/multimedia/video/qvideoframe.h b/src/multimedia/video/qvideoframe.h
index 9628045cc..185291e82 100644
--- a/src/multimedia/video/qvideoframe.h
+++ b/src/multimedia/video/qvideoframe.h
@@ -94,7 +94,6 @@ public:
Format_P010LE,
Format_P010BE,
-
Format_P016LE,
Format_P016BE,
diff --git a/src/multimedia/video/qvideoframeconversionhelper.cpp b/src/multimedia/video/qvideoframeconversionhelper.cpp
index 919e150df..b2d724703 100644
--- a/src/multimedia/video/qvideoframeconversionhelper.cpp
+++ b/src/multimedia/video/qvideoframeconversionhelper.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qvideoframeconversionhelper_p.h"
+#include "qrgb.h"
QT_BEGIN_NAMESPACE
@@ -94,9 +95,41 @@ static inline void planarYUV420_to_ARGB32(const uchar *y, int yStride,
}
}
+static inline void planarYUV422_to_ARGB32(const uchar *y, int yStride,
+ const uchar *u, int uStride,
+ const uchar *v, int vStride,
+ int uvPixelStride,
+ quint32 *rgb,
+ int width, int height)
+{
+ quint32 *rgb0 = rgb;
+ quint32 *rgb1 = rgb + width;
+
+ for (int j = 0; j < height; ++j) {
+ const uchar *lineY0 = y;
+ const uchar *lineU = u;
+ const uchar *lineV = v;
+
+ for (int i = 0; i < width; i += 2) {
+ EXPAND_UV(*lineU, *lineV);
+ lineU += uvPixelStride;
+ lineV += uvPixelStride;
+
+ *rgb0++ = qYUVToARGB32(*lineY0++, rv, guv, bu);
+ *rgb0++ = qYUVToARGB32(*lineY0++, rv, guv, bu);
+ }
+
+ y += yStride << 1; // stride * 2
+ u += uStride;
+ v += vStride;
+ rgb0 += width;
+ rgb1 += width;
+ }
+}
-void QT_FASTCALL qt_convert_YUV420P_to_ARGB32(const QVideoFrame &frame, uchar *output)
+
+static void QT_FASTCALL qt_convert_YUV420P_to_ARGB32(const QVideoFrame &frame, uchar *output)
{
FETCH_INFO_TRIPLANAR(frame)
planarYUV420_to_ARGB32(plane1, plane1Stride,
@@ -107,7 +140,19 @@ void QT_FASTCALL qt_convert_YUV420P_to_ARGB32(const QVideoFrame &frame, uchar *o
width, height);
}
-void QT_FASTCALL qt_convert_YV12_to_ARGB32(const QVideoFrame &frame, uchar *output)
+static void QT_FASTCALL qt_convert_YUV422P_to_ARGB32(const QVideoFrame &frame, uchar *output)
+{
+ FETCH_INFO_TRIPLANAR(frame)
+ planarYUV422_to_ARGB32(plane1, plane1Stride,
+ plane2, plane2Stride,
+ plane3, plane3Stride,
+ 1,
+ reinterpret_cast<quint32*>(output),
+ width, height);
+}
+
+
+static void QT_FASTCALL qt_convert_YV12_to_ARGB32(const QVideoFrame &frame, uchar *output)
{
FETCH_INFO_TRIPLANAR(frame)
planarYUV420_to_ARGB32(plane1, plane1Stride,
@@ -118,7 +163,32 @@ void QT_FASTCALL qt_convert_YV12_to_ARGB32(const QVideoFrame &frame, uchar *outp
width, height);
}
-void QT_FASTCALL qt_convert_AYUV444_to_ARGB32(const QVideoFrame &frame, uchar *output)
+static void QT_FASTCALL qt_convert_AYUV444_to_ARGB32(const QVideoFrame &frame, uchar *output)
+{
+ FETCH_INFO_PACKED(frame)
+ MERGE_LOOPS(width, height, stride, 4)
+
+ quint32 *rgb = reinterpret_cast<quint32*>(output);
+
+ for (int i = 0; i < height; ++i) {
+ const uchar *lineSrc = src;
+
+ for (int j = 0; j < width; ++j) {
+ int a = *lineSrc++;
+ int y = *lineSrc++;
+ int u = *lineSrc++;
+ int v = *lineSrc++;
+
+ EXPAND_UV(u, v);
+
+ *rgb++ = qPremultiply(qYUVToARGB32(y, rv, guv, bu, a));
+ }
+
+ src += stride;
+ }
+}
+
+static void QT_FASTCALL qt_convert_AYUV444_Premultiplied_to_ARGB32(const QVideoFrame &frame, uchar *output)
{
FETCH_INFO_PACKED(frame)
MERGE_LOOPS(width, height, stride, 4)
@@ -143,7 +213,7 @@ void QT_FASTCALL qt_convert_AYUV444_to_ARGB32(const QVideoFrame &frame, uchar *o
}
}
-void QT_FASTCALL qt_convert_YUV444_to_ARGB32(const QVideoFrame &frame, uchar *output)
+static void QT_FASTCALL qt_convert_YUV444_to_ARGB32(const QVideoFrame &frame, uchar *output)
{
FETCH_INFO_PACKED(frame)
MERGE_LOOPS(width, height, stride, 3)
@@ -167,7 +237,7 @@ void QT_FASTCALL qt_convert_YUV444_to_ARGB32(const QVideoFrame &frame, uchar *ou
}
}
-void QT_FASTCALL qt_convert_UYVY_to_ARGB32(const QVideoFrame &frame, uchar *output)
+static void QT_FASTCALL qt_convert_UYVY_to_ARGB32(const QVideoFrame &frame, uchar *output)
{
FETCH_INFO_PACKED(frame)
MERGE_LOOPS(width, height, stride, 2)
@@ -193,7 +263,7 @@ void QT_FASTCALL qt_convert_UYVY_to_ARGB32(const QVideoFrame &frame, uchar *outp
}
}
-void QT_FASTCALL qt_convert_YUYV_to_ARGB32(const QVideoFrame &frame, uchar *output)
+static void QT_FASTCALL qt_convert_YUYV_to_ARGB32(const QVideoFrame &frame, uchar *output)
{
FETCH_INFO_PACKED(frame)
MERGE_LOOPS(width, height, stride, 2)
@@ -219,7 +289,7 @@ void QT_FASTCALL qt_convert_YUYV_to_ARGB32(const QVideoFrame &frame, uchar *outp
}
}
-void QT_FASTCALL qt_convert_NV12_to_ARGB32(const QVideoFrame &frame, uchar *output)
+static void QT_FASTCALL qt_convert_NV12_to_ARGB32(const QVideoFrame &frame, uchar *output)
{
FETCH_INFO_BIPLANAR(frame)
planarYUV420_to_ARGB32(plane1, plane1Stride,
@@ -230,7 +300,7 @@ void QT_FASTCALL qt_convert_NV12_to_ARGB32(const QVideoFrame &frame, uchar *outp
width, height);
}
-void QT_FASTCALL qt_convert_NV21_to_ARGB32(const QVideoFrame &frame, uchar *output)
+static void QT_FASTCALL qt_convert_NV21_to_ARGB32(const QVideoFrame &frame, uchar *output)
{
FETCH_INFO_BIPLANAR(frame)
planarYUV420_to_ARGB32(plane1, plane1Stride,
@@ -241,7 +311,88 @@ void QT_FASTCALL qt_convert_NV21_to_ARGB32(const QVideoFrame &frame, uchar *outp
width, height);
}
-void QT_FASTCALL qt_convert_BGRA32_to_ARGB32(const QVideoFrame &frame, uchar *output)
+static void QT_FASTCALL qt_convert_IMC1_to_ARGB32(const QVideoFrame &frame, uchar *output)
+{
+ FETCH_INFO_TRIPLANAR(frame)
+ Q_ASSERT(plane1Stride == plane2Stride);
+ Q_ASSERT(plane1Stride == plane3Stride);
+
+ planarYUV420_to_ARGB32(plane1, plane1Stride,
+ plane3, plane3Stride,
+ plane2, plane2Stride,
+ 1,
+ reinterpret_cast<quint32*>(output),
+ width, height);
+}
+
+static void QT_FASTCALL qt_convert_IMC2_to_ARGB32(const QVideoFrame &frame, uchar *output)
+{
+ FETCH_INFO_BIPLANAR(frame)
+ Q_ASSERT(plane1Stride == plane2Stride);
+
+ planarYUV420_to_ARGB32(plane1, plane1Stride,
+ plane2 + (plane1Stride >> 1), plane1Stride,
+ plane2, plane1Stride,
+ 1,
+ reinterpret_cast<quint32*>(output),
+ width, height);
+}
+
+static void QT_FASTCALL qt_convert_IMC3_to_ARGB32(const QVideoFrame &frame, uchar *output)
+{
+ FETCH_INFO_TRIPLANAR(frame)
+ Q_ASSERT(plane1Stride == plane2Stride);
+ Q_ASSERT(plane1Stride == plane3Stride);
+
+ planarYUV420_to_ARGB32(plane1, plane1Stride,
+ plane2, plane2Stride,
+ plane3, plane3Stride,
+ 1,
+ reinterpret_cast<quint32*>(output),
+ width, height);
+}
+
+static void QT_FASTCALL qt_convert_IMC4_to_ARGB32(const QVideoFrame &frame, uchar *output)
+{
+ FETCH_INFO_BIPLANAR(frame)
+ Q_ASSERT(plane1Stride == plane2Stride);
+
+ planarYUV420_to_ARGB32(plane1, plane1Stride,
+ plane2, plane1Stride,
+ plane2 + (plane1Stride >> 1), plane1Stride,
+ 1,
+ reinterpret_cast<quint32*>(output),
+ width, height);
+}
+
+
+static void QT_FASTCALL qt_convert_BGRA32_to_ARGB32(const QVideoFrame &frame, uchar *output)
+{
+ FETCH_INFO_PACKED(frame)
+ MERGE_LOOPS(width, height, stride, 4)
+
+ quint32 *argb = reinterpret_cast<quint32*>(output);
+
+ for (int y = 0; y < height; ++y) {
+ const quint32 *bgra = reinterpret_cast<const quint32*>(src);
+
+ int x = 0;
+ for (; x < width - 3; x += 4) {
+ *argb++ = qPremultiply(qConvertBGRA32ToARGB32(*bgra++));
+ *argb++ = qPremultiply(qConvertBGRA32ToARGB32(*bgra++));
+ *argb++ = qPremultiply(qConvertBGRA32ToARGB32(*bgra++));
+ *argb++ = qPremultiply(qConvertBGRA32ToARGB32(*bgra++));
+ }
+
+ // leftovers
+ for (; x < width; ++x)
+ *argb++ = qPremultiply(qConvertBGRA32ToARGB32(*bgra++));
+
+ src += stride;
+ }
+}
+
+static void QT_FASTCALL qt_convert_BGRA32_Premultiplied_to_ARGB32(const QVideoFrame &frame, uchar *output)
{
FETCH_INFO_PACKED(frame)
MERGE_LOOPS(width, height, stride, 4)
@@ -267,7 +418,33 @@ void QT_FASTCALL qt_convert_BGRA32_to_ARGB32(const QVideoFrame &frame, uchar *ou
}
}
-void QT_FASTCALL qt_convert_BGR24_to_ARGB32(const QVideoFrame &frame, uchar *output)
+static void QT_FASTCALL qt_convert_ABGR32_to_ARGB32(const QVideoFrame &frame, uchar *output)
+{
+ FETCH_INFO_PACKED(frame)
+ MERGE_LOOPS(width, height, stride, 4)
+
+ quint32 *argb = reinterpret_cast<quint32*>(output);
+
+ for (int y = 0; y < height; ++y) {
+ const quint32 *abgr = reinterpret_cast<const quint32*>(src);
+
+ int x = 0;
+ for (; x < width - 3; x += 4) {
+ *argb++ = qConvertABGR32ToARGB32(*abgr++);
+ *argb++ = qConvertABGR32ToARGB32(*abgr++);
+ *argb++ = qConvertABGR32ToARGB32(*abgr++);
+ *argb++ = qConvertABGR32ToARGB32(*abgr++);
+ }
+
+ // leftovers
+ for (; x < width; ++x)
+ *argb++ = qConvertABGR32ToARGB32(*abgr++);
+
+ src += stride;
+ }
+}
+
+static void QT_FASTCALL qt_convert_BGR24_to_ARGB32(const QVideoFrame &frame, uchar *output)
{
FETCH_INFO_PACKED(frame)
MERGE_LOOPS(width, height, stride, 3)
@@ -299,7 +476,7 @@ void QT_FASTCALL qt_convert_BGR24_to_ARGB32(const QVideoFrame &frame, uchar *out
}
}
-void QT_FASTCALL qt_convert_BGR565_to_ARGB32(const QVideoFrame &frame, uchar *output)
+static void QT_FASTCALL qt_convert_BGR565_to_ARGB32(const QVideoFrame &frame, uchar *output)
{
FETCH_INFO_PACKED(frame)
MERGE_LOOPS(width, height, stride, 2)
@@ -325,7 +502,7 @@ void QT_FASTCALL qt_convert_BGR565_to_ARGB32(const QVideoFrame &frame, uchar *ou
}
}
-void QT_FASTCALL qt_convert_BGR555_to_ARGB32(const QVideoFrame &frame, uchar *output)
+static void QT_FASTCALL qt_convert_BGR555_to_ARGB32(const QVideoFrame &frame, uchar *output)
{
FETCH_INFO_PACKED(frame)
MERGE_LOOPS(width, height, stride, 2)
@@ -351,6 +528,39 @@ void QT_FASTCALL qt_convert_BGR555_to_ARGB32(const QVideoFrame &frame, uchar *ou
}
}
+static void QT_FASTCALL qt_convert_BGRA5658_to_ARGB32(const QVideoFrame &frame, uchar *output)
+{
+ FETCH_INFO_PACKED(frame)
+ MERGE_LOOPS(width, height, stride, 3)
+
+ quint32 *argb = reinterpret_cast<quint32*>(output);
+
+ for (int y = 0; y < height; ++y) {
+ const uchar *bgr = src;
+
+ int x = 0;
+ for (; x < width - 3; x += 4) {
+ *argb++ = qConvertBGRA5658ToARGB32(bgr);
+ bgr += 3;
+ *argb++ = qConvertBGRA5658ToARGB32(bgr);
+ bgr += 3;
+ *argb++ = qConvertBGRA5658ToARGB32(bgr);
+ bgr += 3;
+ *argb++ = qConvertBGRA5658ToARGB32(bgr);
+ bgr += 3;
+ }
+
+ // leftovers
+ for (; x < width; ++x) {
+ *argb++ = qConvertBGRA5658ToARGB32(bgr);
+ bgr += 3;
+ }
+
+ src += stride;
+ }
+}
+
+
static inline void planarYUV420_16bit_to_ARGB32(const uchar *y, int yStride,
const uchar *u, int uStride,
const uchar *v, int vStride,
@@ -390,7 +600,7 @@ static inline void planarYUV420_16bit_to_ARGB32(const uchar *y, int yStride,
}
}
-void QT_FASTCALL qt_convert_P016LE_to_ARGB32(const QVideoFrame &frame, uchar *output)
+static void QT_FASTCALL qt_convert_P016LE_to_ARGB32(const QVideoFrame &frame, uchar *output)
{
FETCH_INFO_BIPLANAR(frame)
planarYUV420_16bit_to_ARGB32(plane1 + 1, plane1Stride,
@@ -402,7 +612,7 @@ void QT_FASTCALL qt_convert_P016LE_to_ARGB32(const QVideoFrame &frame, uchar *ou
}
-void QT_FASTCALL qt_convert_P016BE_to_ARGB32(const QVideoFrame &frame, uchar *output)
+static void QT_FASTCALL qt_convert_P016BE_to_ARGB32(const QVideoFrame &frame, uchar *output)
{
FETCH_INFO_BIPLANAR(frame)
planarYUV420_16bit_to_ARGB32(plane1, plane1Stride,
@@ -414,4 +624,84 @@ void QT_FASTCALL qt_convert_P016BE_to_ARGB32(const QVideoFrame &frame, uchar *ou
}
+static VideoFrameConvertFunc qConvertFuncs[QVideoFrame::NPixelFormats] = {
+ /* Format_Invalid */ nullptr, // Not needed
+ /* Format_ARGB32 */ nullptr, // Not needed
+ /* Format_ARGB32_Premultiplied */ nullptr, // Not needed
+ /* Format_RGB32 */ nullptr, // Not needed
+ /* Format_RGB24 */ nullptr, // Not needed
+ /* Format_RGB565 */ nullptr, // Not needed
+ /* Format_RGB555 */ nullptr, // Not needed
+ /* Format_ARGB8565_Premultiplied */ nullptr, // Not needed
+ /* Format_BGRA32 */ qt_convert_BGRA32_to_ARGB32,
+ /* Format_BGRA32_Premultiplied */ qt_convert_BGRA32_Premultiplied_to_ARGB32,
+ /* Format_ABGR32 */ qt_convert_ABGR32_to_ARGB32,
+ /* Format_BGR32 */ qt_convert_BGRA32_Premultiplied_to_ARGB32,
+ /* Format_BGR24 */ qt_convert_BGR24_to_ARGB32,
+ /* Format_BGR565 */ qt_convert_BGR565_to_ARGB32,
+ /* Format_BGR555 */ qt_convert_BGR555_to_ARGB32,
+ /* Format_BGRA5658_Premultiplied */ qt_convert_BGRA5658_to_ARGB32,
+ /* Format_AYUV444 */ qt_convert_AYUV444_to_ARGB32,
+ /* Format_AYUV444_Premultiplied */ qt_convert_AYUV444_Premultiplied_to_ARGB32,
+ /* Format_YUV444 */ qt_convert_YUV444_to_ARGB32,
+ /* Format_YUV420P */ qt_convert_YUV420P_to_ARGB32,
+ /* Format_YUV422P */ qt_convert_YUV422P_to_ARGB32,
+ /* Format_YV12 */ qt_convert_YV12_to_ARGB32,
+ /* Format_UYVY */ qt_convert_UYVY_to_ARGB32,
+ /* Format_YUYV */ qt_convert_YUYV_to_ARGB32,
+ /* Format_NV12 */ qt_convert_NV12_to_ARGB32,
+ /* Format_NV21 */ qt_convert_NV21_to_ARGB32,
+ /* Format_IMC1 */ qt_convert_IMC1_to_ARGB32,
+ /* Format_IMC2 */ qt_convert_IMC2_to_ARGB32,
+ /* Format_IMC3 */ qt_convert_IMC3_to_ARGB32,
+ /* Format_IMC4 */ qt_convert_IMC4_to_ARGB32,
+ /* Format_Y8 */ nullptr, // Not needed
+ /* Format_Y16 */ nullptr, // Not needed
+ /* Format_P010LE */ qt_convert_P016LE_to_ARGB32,
+ /* Format_P010BE */ qt_convert_P016BE_to_ARGB32,
+ /* Format_P016LE */ qt_convert_P016LE_to_ARGB32,
+ /* Format_P016BE */ qt_convert_P016BE_to_ARGB32,
+ /* Format_Jpeg */ nullptr, // Not needed
+};
+
+static void qInitConvertFuncsAsm()
+{
+#ifdef QT_COMPILER_SUPPORTS_SSE2
+ extern void QT_FASTCALL qt_convert_BGRA32_to_ARGB32_sse2(const QVideoFrame&, uchar*);
+ if (qCpuHasFeature(SSE2)){
+ qConvertFuncs[QVideoFrame::Format_BGRA32] = qt_convert_BGRA32_to_ARGB32_sse2;
+ qConvertFuncs[QVideoFrame::Format_BGRA32_Premultiplied] = qt_convert_BGRA32_to_ARGB32_sse2;
+ qConvertFuncs[QVideoFrame::Format_BGR32] = qt_convert_BGRA32_to_ARGB32_sse2;
+ }
+#endif
+#ifdef QT_COMPILER_SUPPORTS_SSSE3
+ extern void QT_FASTCALL qt_convert_BGRA32_to_ARGB32_ssse3(const QVideoFrame&, uchar*);
+ if (qCpuHasFeature(SSSE3)){
+ qConvertFuncs[QVideoFrame::Format_BGRA32] = qt_convert_BGRA32_to_ARGB32_ssse3;
+ qConvertFuncs[QVideoFrame::Format_BGRA32_Premultiplied] = qt_convert_BGRA32_to_ARGB32_ssse3;
+ qConvertFuncs[QVideoFrame::Format_BGR32] = qt_convert_BGRA32_to_ARGB32_ssse3;
+ }
+#endif
+#ifdef QT_COMPILER_SUPPORTS_AVX2
+ extern void QT_FASTCALL qt_convert_BGRA32_to_ARGB32_avx2(const QVideoFrame&, uchar*);
+ if (qCpuHasFeature(AVX2)){
+ qConvertFuncs[QVideoFrame::Format_BGRA32] = qt_convert_BGRA32_to_ARGB32_avx2;
+ qConvertFuncs[QVideoFrame::Format_BGRA32_Premultiplied] = qt_convert_BGRA32_to_ARGB32_avx2;
+ qConvertFuncs[QVideoFrame::Format_BGR32] = qt_convert_BGRA32_to_ARGB32_avx2;
+ }
+#endif
+}
+
+VideoFrameConvertFunc qConverterForFormat(QVideoFrame::PixelFormat format)
+{
+ static bool initAsmFuncsDone = false;
+ if (!initAsmFuncsDone) {
+ qInitConvertFuncsAsm();
+ initAsmFuncsDone = true;
+ }
+ VideoFrameConvertFunc convert = qConvertFuncs[format];
+ return convert;
+}
+
+
QT_END_NAMESPACE
diff --git a/src/multimedia/video/qvideoframeconversionhelper_p.h b/src/multimedia/video/qvideoframeconversionhelper_p.h
index b7837db2a..0fdcbf8a3 100644
--- a/src/multimedia/video/qvideoframeconversionhelper_p.h
+++ b/src/multimedia/video/qvideoframeconversionhelper_p.h
@@ -54,8 +54,11 @@
#include <qvideoframe.h>
#include <private/qsimd_p.h>
+// Converts to RGB32 or ARGB32_Premultiplied
typedef void (QT_FASTCALL *VideoFrameConvertFunc)(const QVideoFrame &frame, uchar *output);
+VideoFrameConvertFunc qConverterForFormat(QVideoFrame::PixelFormat format);
+
inline quint32 qConvertBGRA32ToARGB32(quint32 bgra)
{
return (((bgra & 0xFF000000) >> 24)
@@ -64,11 +67,26 @@ inline quint32 qConvertBGRA32ToARGB32(quint32 bgra)
| ((bgra & 0x000000FF) << 24));
}
+inline quint32 qConvertABGR32ToARGB32(quint32 abgr)
+{
+ return ((abgr & 0xFF000000)
+ | ((abgr & 0x00FF0000) >> 16)
+ | (abgr & 0x0000FF00)
+ | ((abgr & 0x000000FF) << 16));
+}
+
inline quint32 qConvertBGR24ToARGB32(const uchar *bgr)
{
return 0xFF000000 | bgr[0] | bgr[1] << 8 | bgr[2] << 16;
}
+inline quint32 qConvertBGRA5658ToARGB32(const uchar *bgr)
+{
+ return (bgr[0] & 0xf8) | (quint32(bgr[0] & 7) << 13) |
+ (quint32(bgr[1] & 0xe0) << 5) | (quint32(bgr[1] & 0x1f) << 3) |
+ bgr[2] << 24;
+}
+
inline quint32 qConvertBGR565ToARGB32(quint16 bgr)
{
return 0xff000000