summaryrefslogtreecommitdiffstats
path: root/src/multimedia
diff options
context:
space:
mode:
Diffstat (limited to 'src/multimedia')
-rw-r--r--src/multimedia/doc/qtmultimedia.qdocconf2
-rw-r--r--src/multimedia/gsttools_headers/qgstutils_p.h2
-rw-r--r--src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h5
-rw-r--r--src/multimedia/multimedia.pro2
-rw-r--r--src/multimedia/video/qvideoframe.cpp126
-rw-r--r--src/multimedia/video/qvideoframe.h3
-rw-r--r--src/multimedia/video/qvideoframe_p.h57
-rw-r--r--src/multimedia/video/qvideoframeconversionhelper.cpp348
-rw-r--r--src/multimedia/video/qvideoframeconversionhelper_avx2.cpp83
-rw-r--r--src/multimedia/video/qvideoframeconversionhelper_p.h106
-rw-r--r--src/multimedia/video/qvideoframeconversionhelper_sse2.cpp83
-rw-r--r--src/multimedia/video/qvideoframeconversionhelper_ssse3.cpp82
-rw-r--r--src/multimedia/video/qvideooutputorientationhandler_p.h4
-rw-r--r--src/multimedia/video/video.pri11
14 files changed, 909 insertions, 5 deletions
diff --git a/src/multimedia/doc/qtmultimedia.qdocconf b/src/multimedia/doc/qtmultimedia.qdocconf
index d917062a2..a32043b39 100644
--- a/src/multimedia/doc/qtmultimedia.qdocconf
+++ b/src/multimedia/doc/qtmultimedia.qdocconf
@@ -32,7 +32,7 @@ exampledirs += ../../../examples/multimedia \
snippets
# Specify example install dir under QT_INSTALL_EXAMPLES
-examplesinstallpath = multimedia
+examplesinstallpath = qtmultimedia/multimedia
headerdirs += ../..
diff --git a/src/multimedia/gsttools_headers/qgstutils_p.h b/src/multimedia/gsttools_headers/qgstutils_p.h
index 31fb85847..cf677c321 100644
--- a/src/multimedia/gsttools_headers/qgstutils_p.h
+++ b/src/multimedia/gsttools_headers/qgstutils_p.h
@@ -150,6 +150,8 @@ gboolean qt_gst_element_query_position(GstElement *element, GstFormat format, gi
gboolean qt_gst_element_query_duration(GstElement *element, GstFormat format, gint64 *cur);
GstCaps *qt_gst_caps_normalize(GstCaps *caps);
const gchar *qt_gst_element_get_factory_name(GstElement *element);
+gboolean qt_gst_caps_can_intersect(const GstCaps * caps1, const GstCaps * caps2);
+GList *qt_gst_video_sinks();
QDebug operator <<(QDebug debug, GstCaps *caps);
diff --git a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h
index a1ef5616b..9c04b9804 100644
--- a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h
+++ b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h
@@ -157,7 +157,12 @@ private:
static gboolean unlock(GstBaseSink *sink);
+#if GST_CHECK_VERSION(0, 10, 25)
static GstFlowReturn show_frame(GstVideoSink *sink, GstBuffer *buffer);
+#else
+ static GstFlowReturn preroll(GstBaseSink *sink, GstBuffer *buffer);
+ static GstFlowReturn render(GstBaseSink *sink, GstBuffer *buffer);
+#endif
private:
QVideoSurfaceGstDelegate *delegate;
diff --git a/src/multimedia/multimedia.pro b/src/multimedia/multimedia.pro
index 3aff75949..e3f368cf4 100644
--- a/src/multimedia/multimedia.pro
+++ b/src/multimedia/multimedia.pro
@@ -55,6 +55,8 @@ SOURCES += \
qmediastoragelocation.cpp \
qmultimedia.cpp
+CONFIG += simd optimize_full
+
include(audio/audio.pri)
include(camera/camera.pri)
include(controls/controls.pri)
diff --git a/src/multimedia/video/qvideoframe.cpp b/src/multimedia/video/qvideoframe.cpp
index 4e9e28a4d..f0495577c 100644
--- a/src/multimedia/video/qvideoframe.cpp
+++ b/src/multimedia/video/qvideoframe.cpp
@@ -33,8 +33,10 @@
#include "qvideoframe.h"
+#include "qvideoframe_p.h"
#include "qimagevideobuffer_p.h"
#include "qmemoryvideobuffer_p.h"
+#include "qvideoframeconversionhelper_p.h"
#include <qimage.h>
#include <qpair.h>
@@ -654,6 +656,8 @@ bool QVideoFrame::map(QAbstractVideoBuffer::MapMode mode)
d->data[2] = d->data[1] + (d->bytesPerLine[1] * d->size.height() / 2);
break;
}
+ default:
+ break;
}
d->mappedCount++;
@@ -994,11 +998,133 @@ QImage::Format QVideoFrame::imageFormatFromPixelFormat(PixelFormat format)
case Format_AdobeDng:
return QImage::Format_Invalid;
case Format_User:
+ default:
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*);
+
+static VideoFrameConvertFunc qConvertFuncs[QVideoFrame::NPixelFormats] = {
+ /* Format_Invalid */ Q_NULLPTR, // Not needed
+ /* Format_ARGB32 */ Q_NULLPTR, // Not needed
+ /* Format_ARGB32_Premultiplied */ Q_NULLPTR, // Not needed
+ /* Format_RGB32 */ Q_NULLPTR, // Not needed
+ /* Format_RGB24 */ Q_NULLPTR, // Not needed
+ /* Format_RGB565 */ Q_NULLPTR, // Not needed
+ /* Format_RGB555 */ Q_NULLPTR, // Not needed
+ /* Format_ARGB8565_Premultiplied */ Q_NULLPTR, // Not needed
+ /* Format_BGRA32 */ qt_convert_BGRA32_to_ARGB32,
+ /* Format_BGRA32_Premultiplied */ qt_convert_BGRA32_to_ARGB32,
+ /* 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 */ Q_NULLPTR,
+ /* Format_AYUV444 */ qt_convert_AYUV444_to_ARGB32,
+ /* Format_AYUV444_Premultiplied */ Q_NULLPTR,
+ /* Format_YUV444 */ qt_convert_YUV444_to_ARGB32,
+ /* Format_YUV420P */ qt_convert_YUV420P_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 */ Q_NULLPTR,
+ /* Format_IMC2 */ Q_NULLPTR,
+ /* Format_IMC3 */ Q_NULLPTR,
+ /* Format_IMC4 */ Q_NULLPTR,
+ /* Format_Y8 */ Q_NULLPTR,
+ /* Format_Y16 */ Q_NULLPTR,
+ /* Format_Jpeg */ Q_NULLPTR, // Not needed
+ /* Format_CameraRaw */ Q_NULLPTR,
+ /* Format_AdobeDng */ Q_NULLPTR
+};
+
+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
+}
+
+/*!
+ \internal
+*/
+QImage qt_imageFromVideoFrame(const QVideoFrame &f)
+{
+ QVideoFrame &frame = const_cast<QVideoFrame&>(f);
+ QImage result;
+
+ if (!frame.isValid() || !frame.map(QAbstractVideoBuffer::ReadOnly))
+ return result;
+
+ // Formats supported by QImage don't need conversion
+ QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(frame.pixelFormat());
+ if (imageFormat != QImage::Format_Invalid) {
+ result = QImage(frame.bits(), frame.width(), frame.height(), imageFormat).copy();
+ }
+
+ // Load from JPG
+ else if (frame.pixelFormat() == QVideoFrame::Format_Jpeg) {
+ result.loadFromData(frame.bits(), frame.mappedBytes(), "JPG");
+ }
+
+ // Need conversion
+ else {
+ static bool initAsmFuncsDone = false;
+ if (!initAsmFuncsDone) {
+ qInitConvertFuncsAsm();
+ initAsmFuncsDone = true;
+ }
+ VideoFrameConvertFunc convert = qConvertFuncs[frame.pixelFormat()];
+ if (!convert) {
+ qWarning() << Q_FUNC_INFO << ": unsupported pixel format" << frame.pixelFormat();
+ } else {
+ result = QImage(frame.width(), frame.height(), QImage::Format_ARGB32);
+ convert(frame, result.bits());
+ }
+ }
+
+ frame.unmap();
+
+ return result;
+}
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, QVideoFrame::PixelFormat pf)
{
diff --git a/src/multimedia/video/qvideoframe.h b/src/multimedia/video/qvideoframe.h
index a273b7f73..633604ebb 100644
--- a/src/multimedia/video/qvideoframe.h
+++ b/src/multimedia/video/qvideoframe.h
@@ -96,6 +96,9 @@ public:
Format_CameraRaw,
Format_AdobeDng,
+#ifndef Q_QDOC
+ NPixelFormats,
+#endif
Format_User = 1000
};
diff --git a/src/multimedia/video/qvideoframe_p.h b/src/multimedia/video/qvideoframe_p.h
new file mode 100644
index 000000000..15260c26f
--- /dev/null
+++ b/src/multimedia/video/qvideoframe_p.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVIDEOFRAME_P_H
+#define QVIDEOFRAME_P_H
+
+#include <QtMultimedia/qvideoframe.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+Q_MULTIMEDIA_EXPORT QImage qt_imageFromVideoFrame(const QVideoFrame &frame);
+
+QT_END_NAMESPACE
+
+#endif // QVIDEOFRAME_P_H
+
diff --git a/src/multimedia/video/qvideoframeconversionhelper.cpp b/src/multimedia/video/qvideoframeconversionhelper.cpp
new file mode 100644
index 000000000..9599b1947
--- /dev/null
+++ b/src/multimedia/video/qvideoframeconversionhelper.cpp
@@ -0,0 +1,348 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvideoframeconversionhelper_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#define CLAMP(n) (n > 255 ? 255 : (n < 0 ? 0 : n))
+
+#define EXPAND_UV(u, v) \
+ int uu = u - 128; \
+ int vv = v - 128; \
+ int rv = 409 * vv + 128; \
+ int guv = 100 * uu + 208 * vv + 128; \
+ int bu = 516 * uu + 128; \
+
+static inline quint32 qYUVToARGB32(int y, int rv, int guv, int bu, int a = 0xff)
+{
+ int yy = (y - 16) * 298;
+ return (a << 24)
+ | CLAMP((yy + rv) >> 8) << 16
+ | CLAMP((yy - guv) >> 8) << 8
+ | CLAMP((yy + bu) >> 8);
+}
+
+static inline void planarYUV420_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 += 2) {
+ const uchar *lineY0 = y;
+ const uchar *lineY1 = y + yStride;
+ 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);
+ *rgb1++ = qYUVToARGB32(*lineY1++, rv, guv, bu);
+ *rgb1++ = qYUVToARGB32(*lineY1++, 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)
+{
+ FETCH_INFO_TRIPLANAR(frame)
+ planarYUV420_to_ARGB32(plane1, plane1Stride,
+ plane2, plane2Stride,
+ plane3, plane3Stride,
+ 1,
+ reinterpret_cast<quint32*>(output),
+ width, height);
+}
+
+void QT_FASTCALL qt_convert_YV12_to_ARGB32(const QVideoFrame &frame, uchar *output)
+{
+ FETCH_INFO_TRIPLANAR(frame)
+ planarYUV420_to_ARGB32(plane1, plane1Stride,
+ plane3, plane3Stride,
+ plane2, plane2Stride,
+ 1,
+ reinterpret_cast<quint32*>(output),
+ width, height);
+}
+
+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++ = qYUVToARGB32(y, rv, guv, bu, a);
+ }
+
+ src += stride;
+ }
+}
+
+void QT_FASTCALL qt_convert_YUV444_to_ARGB32(const QVideoFrame &frame, uchar *output)
+{
+ FETCH_INFO_PACKED(frame)
+ MERGE_LOOPS(width, height, stride, 3)
+
+ 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 y = *lineSrc++;
+ int u = *lineSrc++;
+ int v = *lineSrc++;
+
+ EXPAND_UV(u, v);
+
+ *rgb++ = qYUVToARGB32(y, rv, guv, bu);
+ }
+
+ src += stride;
+ }
+}
+
+void QT_FASTCALL qt_convert_UYVY_to_ARGB32(const QVideoFrame &frame, uchar *output)
+{
+ FETCH_INFO_PACKED(frame)
+ MERGE_LOOPS(width, height, stride, 2)
+
+ quint32 *rgb = reinterpret_cast<quint32*>(output);
+
+ for (int i = 0; i < height; ++i) {
+ const uchar *lineSrc = src;
+
+ for (int j = 0; j < width; j += 2) {
+ int u = *lineSrc++;
+ int y0 = *lineSrc++;
+ int v = *lineSrc++;
+ int y1 = *lineSrc++;
+
+ EXPAND_UV(u, v);
+
+ *rgb++ = qYUVToARGB32(y0, rv, guv, bu);
+ *rgb++ = qYUVToARGB32(y1, rv, guv, bu);
+ }
+
+ src += stride;
+ }
+}
+
+void QT_FASTCALL qt_convert_YUYV_to_ARGB32(const QVideoFrame &frame, uchar *output)
+{
+ FETCH_INFO_PACKED(frame)
+ MERGE_LOOPS(width, height, stride, 2)
+
+ quint32 *rgb = reinterpret_cast<quint32*>(output);
+
+ for (int i = 0; i < height; ++i) {
+ const uchar *lineSrc = src;
+
+ for (int j = 0; j < width; j += 2) {
+ int y0 = *lineSrc++;
+ int u = *lineSrc++;
+ int y1 = *lineSrc++;
+ int v = *lineSrc++;
+
+ EXPAND_UV(u, v);
+
+ *rgb++ = qYUVToARGB32(y0, rv, guv, bu);
+ *rgb++ = qYUVToARGB32(y1, rv, guv, bu);
+ }
+
+ src += stride;
+ }
+}
+
+void QT_FASTCALL qt_convert_NV12_to_ARGB32(const QVideoFrame &frame, uchar *output)
+{
+ FETCH_INFO_BIPLANAR(frame)
+ planarYUV420_to_ARGB32(plane1, plane1Stride,
+ plane2, plane2Stride,
+ plane2 + 1, plane2Stride,
+ 2,
+ reinterpret_cast<quint32*>(output),
+ width, height);
+}
+
+void QT_FASTCALL qt_convert_NV21_to_ARGB32(const QVideoFrame &frame, uchar *output)
+{
+ FETCH_INFO_BIPLANAR(frame)
+ planarYUV420_to_ARGB32(plane1, plane1Stride,
+ plane2 + 1, plane2Stride,
+ plane2, plane2Stride,
+ 2,
+ reinterpret_cast<quint32*>(output),
+ width, height);
+}
+
+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++ = qConvertBGRA32ToARGB32(*bgra++);
+ *argb++ = qConvertBGRA32ToARGB32(*bgra++);
+ *argb++ = qConvertBGRA32ToARGB32(*bgra++);
+ *argb++ = qConvertBGRA32ToARGB32(*bgra++);
+ }
+
+ // leftovers
+ for (; x < width; ++x)
+ *argb++ = qConvertBGRA32ToARGB32(*bgra++);
+
+ src += stride;
+ }
+}
+
+void QT_FASTCALL qt_convert_BGR24_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++ = qConvertBGR24ToARGB32(bgr);
+ bgr += 3;
+ *argb++ = qConvertBGR24ToARGB32(bgr);
+ bgr += 3;
+ *argb++ = qConvertBGR24ToARGB32(bgr);
+ bgr += 3;
+ *argb++ = qConvertBGR24ToARGB32(bgr);
+ bgr += 3;
+ }
+
+ // leftovers
+ for (; x < width; ++x) {
+ *argb++ = qConvertBGR24ToARGB32(bgr);
+ bgr += 3;
+ }
+
+ src += stride;
+ }
+}
+
+void QT_FASTCALL qt_convert_BGR565_to_ARGB32(const QVideoFrame &frame, uchar *output)
+{
+ FETCH_INFO_PACKED(frame)
+ MERGE_LOOPS(width, height, stride, 2)
+
+ quint32 *argb = reinterpret_cast<quint32*>(output);
+
+ for (int y = 0; y < height; ++y) {
+ const quint16 *bgr = reinterpret_cast<const quint16*>(src);
+
+ int x = 0;
+ for (; x < width - 3; x += 4) {
+ *argb++ = qConvertBGR565ToARGB32(*bgr++);
+ *argb++ = qConvertBGR565ToARGB32(*bgr++);
+ *argb++ = qConvertBGR565ToARGB32(*bgr++);
+ *argb++ = qConvertBGR565ToARGB32(*bgr++);
+ }
+
+ // leftovers
+ for (; x < width; ++x)
+ *argb++ = qConvertBGR565ToARGB32(*bgr++);
+
+ src += stride;
+ }
+}
+
+void QT_FASTCALL qt_convert_BGR555_to_ARGB32(const QVideoFrame &frame, uchar *output)
+{
+ FETCH_INFO_PACKED(frame)
+ MERGE_LOOPS(width, height, stride, 2)
+
+ quint32 *argb = reinterpret_cast<quint32*>(output);
+
+ for (int y = 0; y < height; ++y) {
+ const quint16 *bgr = reinterpret_cast<const quint16*>(src);
+
+ int x = 0;
+ for (; x < width - 3; x += 4) {
+ *argb++ = qConvertBGR555ToARGB32(*bgr++);
+ *argb++ = qConvertBGR555ToARGB32(*bgr++);
+ *argb++ = qConvertBGR555ToARGB32(*bgr++);
+ *argb++ = qConvertBGR555ToARGB32(*bgr++);
+ }
+
+ // leftovers
+ for (; x < width; ++x)
+ *argb++ = qConvertBGR555ToARGB32(*bgr++);
+
+ src += stride;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/multimedia/video/qvideoframeconversionhelper_avx2.cpp b/src/multimedia/video/qvideoframeconversionhelper_avx2.cpp
new file mode 100644
index 000000000..c769c8868
--- /dev/null
+++ b/src/multimedia/video/qvideoframeconversionhelper_avx2.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvideoframeconversionhelper_p.h"
+
+#ifdef QT_COMPILER_SUPPORTS_AVX2
+
+QT_BEGIN_NAMESPACE
+
+void QT_FASTCALL qt_convert_BGRA32_to_ARGB32_avx2(const QVideoFrame &frame, uchar *output)
+{
+ FETCH_INFO_PACKED(frame)
+ MERGE_LOOPS(width, height, stride, 4)
+ quint32 *argb = reinterpret_cast<quint32*>(output);
+
+ const __m256i shuffleMask = _mm256_set_epi8(12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3,
+ 12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3);
+
+ for (int y = 0; y < height; ++y) {
+ const quint32 *bgra = reinterpret_cast<const quint32*>(src);
+
+ int x = 0;
+ ALIGN(32, argb, x, width) {
+ *argb = qConvertBGRA32ToARGB32(*bgra);
+ ++bgra;
+ ++argb;
+ }
+
+ for (; x < width - 15; x += 16) {
+ __m256i pixelData = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(bgra));
+ __m256i pixelData2 = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(bgra + 8));
+ bgra += 16;
+ pixelData = _mm256_shuffle_epi8(pixelData, shuffleMask);
+ pixelData2 = _mm256_shuffle_epi8(pixelData2, shuffleMask);
+ _mm256_store_si256(reinterpret_cast<__m256i*>(argb), pixelData);
+ _mm256_store_si256(reinterpret_cast<__m256i*>(argb + 8), pixelData2);
+ argb += 16;
+ }
+
+ // leftovers
+ for (; x < width; ++x) {
+ *argb = qConvertBGRA32ToARGB32(*bgra);
+ ++bgra;
+ ++argb;
+ }
+
+ src += stride;
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimedia/video/qvideoframeconversionhelper_p.h b/src/multimedia/video/qvideoframeconversionhelper_p.h
new file mode 100644
index 000000000..eead17a91
--- /dev/null
+++ b/src/multimedia/video/qvideoframeconversionhelper_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVIDEOFRAMECONVERSIONHELPER_P_H
+#define QVIDEOFRAMECONVERSIONHELPER_P_H
+
+#include <qvideoframe.h>
+#include <private/qsimd_p.h>
+
+typedef void (QT_FASTCALL *VideoFrameConvertFunc)(const QVideoFrame &frame, uchar *output);
+
+inline quint32 qConvertBGRA32ToARGB32(quint32 bgra)
+{
+ return (((bgra & 0xFF000000) >> 24)
+ | ((bgra & 0x00FF0000) >> 8)
+ | ((bgra & 0x0000FF00) << 8)
+ | ((bgra & 0x000000FF) << 24));
+}
+
+inline quint32 qConvertBGR24ToARGB32(const uchar *bgr)
+{
+ return 0xFF000000 | bgr[0] | bgr[1] << 8 | bgr[2] << 16;
+}
+
+inline quint32 qConvertBGR565ToARGB32(quint16 bgr)
+{
+ return 0xff000000
+ | ((((bgr) >> 8) & 0xf8) | (((bgr) >> 13) & 0x7))
+ | ((((bgr) << 5) & 0xfc00) | (((bgr) >> 1) & 0x300))
+ | ((((bgr) << 19) & 0xf80000) | (((bgr) << 14) & 0x70000));
+}
+
+inline quint32 qConvertBGR555ToARGB32(quint16 bgr)
+{
+ return 0xff000000
+ | ((((bgr) >> 7) & 0xf8) | (((bgr) >> 12) & 0x7))
+ | ((((bgr) << 6) & 0xf800) | (((bgr) << 1) & 0x700))
+ | ((((bgr) << 19) & 0xf80000) | (((bgr) << 11) & 0x70000));
+}
+
+#define FETCH_INFO_PACKED(frame) \
+ const uchar *src = frame.bits(); \
+ int stride = frame.bytesPerLine(); \
+ int width = frame.width(); \
+ int height = frame.height();
+
+#define FETCH_INFO_BIPLANAR(frame) \
+ const uchar *plane1 = frame.bits(0); \
+ const uchar *plane2 = frame.bits(1); \
+ int plane1Stride = frame.bytesPerLine(0); \
+ int plane2Stride = frame.bytesPerLine(1); \
+ int width = frame.width(); \
+ int height = frame.height();
+
+#define FETCH_INFO_TRIPLANAR(frame) \
+ const uchar *plane1 = frame.bits(0); \
+ const uchar *plane2 = frame.bits(1); \
+ const uchar *plane3 = frame.bits(2); \
+ int plane1Stride = frame.bytesPerLine(0); \
+ int plane2Stride = frame.bytesPerLine(1); \
+ int plane3Stride = frame.bytesPerLine(2); \
+ int width = frame.width(); \
+ int height = frame.height(); \
+
+#define MERGE_LOOPS(width, height, stride, bpp) \
+ if (stride == width * bpp) { \
+ width *= height; \
+ height = 1; \
+ stride = 0; \
+ }
+
+#define ALIGN(boundary, ptr, x, length) \
+ for (; ((reinterpret_cast<qintptr>(ptr) & (boundary - 1)) != 0) && x < length; ++x)
+
+#endif // QVIDEOFRAMECONVERSIONHELPER_P_H
+
diff --git a/src/multimedia/video/qvideoframeconversionhelper_sse2.cpp b/src/multimedia/video/qvideoframeconversionhelper_sse2.cpp
new file mode 100644
index 000000000..27689e5bb
--- /dev/null
+++ b/src/multimedia/video/qvideoframeconversionhelper_sse2.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvideoframeconversionhelper_p.h"
+
+#ifdef QT_COMPILER_SUPPORTS_SSE2
+
+QT_BEGIN_NAMESPACE
+
+void QT_FASTCALL qt_convert_BGRA32_to_ARGB32_sse2(const QVideoFrame &frame, uchar *output)
+{
+ FETCH_INFO_PACKED(frame)
+ MERGE_LOOPS(width, height, stride, 4)
+ quint32 *argb = reinterpret_cast<quint32*>(output);
+
+ const __m128i zero = _mm_setzero_si128();
+
+ for (int y = 0; y < height; ++y) {
+ const quint32 *bgra = reinterpret_cast<const quint32*>(src);
+
+ int x = 0;
+ ALIGN(16, argb, x, width) {
+ *argb = qConvertBGRA32ToARGB32(*bgra);
+ ++bgra;
+ ++argb;
+ }
+
+ for (; x < width - 3; x += 4) {
+ __m128i pixelData = _mm_loadu_si128(reinterpret_cast<const __m128i*>(bgra));
+ bgra += 4;
+ __m128i gaComponents = _mm_unpacklo_epi8(pixelData, zero);
+ __m128i brComponents = _mm_unpackhi_epi8(pixelData, zero);
+ gaComponents = _mm_shufflelo_epi16(_mm_shufflehi_epi16(gaComponents, _MM_SHUFFLE(0, 1, 2, 3)), _MM_SHUFFLE(0, 1, 2, 3)); // swap GA
+ brComponents = _mm_shufflelo_epi16(_mm_shufflehi_epi16(brComponents, _MM_SHUFFLE(0, 1, 2, 3)), _MM_SHUFFLE(0, 1, 2, 3)); // swap BR
+ pixelData = _mm_packus_epi16(gaComponents, brComponents);
+ _mm_store_si128(reinterpret_cast<__m128i*>(argb), pixelData);
+ argb += 4;
+ }
+
+ // leftovers
+ for (; x < width; ++x) {
+ *argb = qConvertBGRA32ToARGB32(*bgra);
+ ++bgra;
+ ++argb;
+ }
+
+ src += stride;
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimedia/video/qvideoframeconversionhelper_ssse3.cpp b/src/multimedia/video/qvideoframeconversionhelper_ssse3.cpp
new file mode 100644
index 000000000..b15617cef
--- /dev/null
+++ b/src/multimedia/video/qvideoframeconversionhelper_ssse3.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvideoframeconversionhelper_p.h"
+
+#ifdef QT_COMPILER_SUPPORTS_SSSE3
+
+QT_BEGIN_NAMESPACE
+
+void QT_FASTCALL qt_convert_BGRA32_to_ARGB32_ssse3(const QVideoFrame &frame, uchar *output)
+{
+ FETCH_INFO_PACKED(frame)
+ MERGE_LOOPS(width, height, stride, 4)
+ quint32 *argb = reinterpret_cast<quint32*>(output);
+
+ __m128i shuffleMask = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3);
+
+ for (int y = 0; y < height; ++y) {
+ const quint32 *bgra = reinterpret_cast<const quint32*>(src);
+
+ int x = 0;
+ ALIGN(16, argb, x, width) {
+ *argb = qConvertBGRA32ToARGB32(*bgra);
+ ++bgra;
+ ++argb;
+ }
+
+ for (; x < width - 7; x += 8) {
+ __m128i pixelData = _mm_loadu_si128(reinterpret_cast<const __m128i*>(bgra));
+ __m128i pixelData2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(bgra + 4));
+ bgra += 8;
+ pixelData = _mm_shuffle_epi8(pixelData, shuffleMask);
+ pixelData2 = _mm_shuffle_epi8(pixelData2, shuffleMask);
+ _mm_store_si128(reinterpret_cast<__m128i*>(argb), pixelData);
+ _mm_store_si128(reinterpret_cast<__m128i*>(argb + 4), pixelData2);
+ argb += 8;
+ }
+
+ // leftovers
+ for (; x < width; ++x) {
+ *argb = qConvertBGRA32ToARGB32(*bgra);
+ ++bgra;
+ ++argb;
+ }
+
+ src += stride;
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimedia/video/qvideooutputorientationhandler_p.h b/src/multimedia/video/qvideooutputorientationhandler_p.h
index 252ee2920..c690cafae 100644
--- a/src/multimedia/video/qvideooutputorientationhandler_p.h
+++ b/src/multimedia/video/qvideooutputorientationhandler_p.h
@@ -59,10 +59,10 @@ public:
int currentOrientation() const;
-signals:
+Q_SIGNALS:
void orientationChanged(int angle);
-private slots:
+private Q_SLOTS:
void screenOrientationChanged(Qt::ScreenOrientation orientation);
private:
diff --git a/src/multimedia/video/video.pri b/src/multimedia/video/video.pri
index 3e39d9d18..e5fa697ce 100644
--- a/src/multimedia/video/video.pri
+++ b/src/multimedia/video/video.pri
@@ -14,7 +14,9 @@ PRIVATE_HEADERS += \
video/qimagevideobuffer_p.h \
video/qmemoryvideobuffer_p.h \
video/qvideooutputorientationhandler_p.h \
- video/qvideosurfaceoutput_p.h
+ video/qvideosurfaceoutput_p.h \
+ video/qvideoframe_p.h \
+ video/qvideoframeconversionhelper_p.h
SOURCES += \
video/qabstractvideobuffer.cpp \
@@ -26,4 +28,9 @@ SOURCES += \
video/qvideosurfaceformat.cpp \
video/qvideosurfaceoutput.cpp \
video/qvideoprobe.cpp \
- video/qabstractvideofilter.cpp
+ video/qabstractvideofilter.cpp \
+ video/qvideoframeconversionhelper.cpp
+
+SSE2_SOURCES += video/qvideoframeconversionhelper_sse2.cpp
+SSSE3_SOURCES += video/qvideoframeconversionhelper_ssse3.cpp
+AVX2_SOURCES += video/qvideoframeconversionhelper_avx2.cpp