diff options
Diffstat (limited to 'src/multimedia')
-rw-r--r-- | src/multimedia/platform/gstreamer/common/qgstreamervideosink.cpp | 20 | ||||
-rw-r--r-- | src/multimedia/platform/gstreamer/common/qgstutils.cpp | 8 | ||||
-rw-r--r-- | src/multimedia/video/qvideoframe.cpp | 160 | ||||
-rw-r--r-- | src/multimedia/video/qvideoframe.h | 1 | ||||
-rw-r--r-- | src/multimedia/video/qvideoframeconversionhelper.cpp | 318 | ||||
-rw-r--r-- | src/multimedia/video/qvideoframeconversionhelper_p.h | 18 |
6 files changed, 409 insertions, 116 deletions
diff --git a/src/multimedia/platform/gstreamer/common/qgstreamervideosink.cpp b/src/multimedia/platform/gstreamer/common/qgstreamervideosink.cpp index 7d61c813b..4c86483bf 100644 --- a/src/multimedia/platform/gstreamer/common/qgstreamervideosink.cpp +++ b/src/multimedia/platform/gstreamer/common/qgstreamervideosink.cpp @@ -61,17 +61,31 @@ public: QList<QVideoFrame::PixelFormat> supportedPixelFormats( QVideoFrame::HandleType /*type*/) const override { + // All the formats that both we and gstreamer support return QList<QVideoFrame::PixelFormat>() - << QVideoFrame::Format_ABGR32 - << QVideoFrame::Format_RGB32 << QVideoFrame::Format_YUV420P << QVideoFrame::Format_YUV422P << QVideoFrame::Format_YV12 << QVideoFrame::Format_UYVY << QVideoFrame::Format_YUYV << QVideoFrame::Format_NV12 + << QVideoFrame::Format_NV21 + << QVideoFrame::Format_AYUV444 + << QVideoFrame::Format_YUV444 << QVideoFrame::Format_P010LE - << QVideoFrame::Format_P010BE; + << QVideoFrame::Format_P010BE + << QVideoFrame::Format_Y8 + << QVideoFrame::Format_RGB32 + << QVideoFrame::Format_BGR32 + << QVideoFrame::Format_ARGB32 + << QVideoFrame::Format_ABGR32 + << QVideoFrame::Format_BGRA32 + << QVideoFrame::Format_RGB555 + << QVideoFrame::Format_BGR555 + << QVideoFrame::Format_Y16 + << QVideoFrame::Format_RGB24 + << QVideoFrame::Format_BGR24 + << QVideoFrame::Format_RGB565; } bool present(const QVideoFrame &frame) override { diff --git a/src/multimedia/platform/gstreamer/common/qgstutils.cpp b/src/multimedia/platform/gstreamer/common/qgstutils.cpp index c5068ffdd..443a45e7e 100644 --- a/src/multimedia/platform/gstreamer/common/qgstutils.cpp +++ b/src/multimedia/platform/gstreamer/common/qgstutils.cpp @@ -179,20 +179,28 @@ static const VideoFormat qt_videoFormatLookup[] = { QVideoFrame::Format_NV12 , GST_VIDEO_FORMAT_NV12 }, { QVideoFrame::Format_NV21 , GST_VIDEO_FORMAT_NV21 }, { QVideoFrame::Format_AYUV444, GST_VIDEO_FORMAT_AYUV }, + { QVideoFrame::Format_YUV444, GST_VIDEO_FORMAT_Y444 }, { QVideoFrame::Format_P010LE , GST_VIDEO_FORMAT_P010_10LE }, { QVideoFrame::Format_P010BE , GST_VIDEO_FORMAT_P010_10BE }, + { QVideoFrame::Format_Y8 , GST_VIDEO_FORMAT_GRAY8 }, #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN { QVideoFrame::Format_RGB32 , GST_VIDEO_FORMAT_BGRx }, { QVideoFrame::Format_BGR32 , GST_VIDEO_FORMAT_RGBx }, { QVideoFrame::Format_ARGB32, GST_VIDEO_FORMAT_BGRA }, { QVideoFrame::Format_ABGR32, GST_VIDEO_FORMAT_RGBA }, { QVideoFrame::Format_BGRA32, GST_VIDEO_FORMAT_ARGB }, + { QVideoFrame::Format_RGB555 , GST_VIDEO_FORMAT_BGR15 }, + { QVideoFrame::Format_BGR555 , GST_VIDEO_FORMAT_RGB15 }, + { QVideoFrame::Format_Y16 , GST_VIDEO_FORMAT_GRAY16_LE }, #else { QVideoFrame::Format_RGB32 , GST_VIDEO_FORMAT_xRGB }, { QVideoFrame::Format_BGR32 , GST_VIDEO_FORMAT_xBGR }, { QVideoFrame::Format_ARGB32, GST_VIDEO_FORMAT_ARGB }, { QVideoFrame::Format_ABGR32, GST_VIDEO_FORMAT_ABGR }, { QVideoFrame::Format_BGRA32, GST_VIDEO_FORMAT_BGRA }, + { QVideoFrame::Format_RGB555 , GST_VIDEO_FORMAT_RGB15 }, + { QVideoFrame::Format_BGR555 , GST_VIDEO_FORMAT_BGR15 }, + { QVideoFrame::Format_Y16 , GST_VIDEO_FORMAT_GRAY16_BE }, #endif { QVideoFrame::Format_RGB24 , GST_VIDEO_FORMAT_RGB }, { QVideoFrame::Format_BGR24 , GST_VIDEO_FORMAT_BGR }, 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 |