summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2015-11-05 10:10:26 +0100
committerLiang Qi <liang.qi@theqtcompany.com>2015-11-05 10:10:26 +0100
commit11df4e75e4eca82d28dc147fcefb29d62b38a5dc (patch)
tree36f7593c1f5d48123127a918ec23c6fe47b8169a
parent318159c8492883d7ef29804a68c398cceaa5f89a (diff)
parent3ef5831041fe1206043f3b36f063eef4842ce243 (diff)
Merge remote-tracking branch 'origin/5.6' into dev
-rw-r--r--dist/changes-5.5.168
-rw-r--r--src/gsttools/qgstreamervideooverlay.cpp15
-rw-r--r--src/gsttools/qgstutils.cpp69
-rw-r--r--src/gsttools/qvideosurfacegstsink.cpp31
-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
-rw-r--r--src/multimediawidgets/doc/qtmultimediawidgets.qdocconf2
-rw-r--r--src/plugins/android/src/common/qandroidmultimediautils.cpp559
-rw-r--r--src/plugins/android/src/common/qandroidmultimediautils.h1
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcamerasession.cpp11
-rw-r--r--src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm16
-rw-r--r--src/plugins/avfoundation/camera/avfcamerasession.h4
-rw-r--r--src/plugins/avfoundation/camera/avfcamerasession.mm4
-rw-r--r--src/plugins/avfoundation/camera/avfimagecapturecontrol.h20
-rw-r--r--src/plugins/avfoundation/camera/avfimagecapturecontrol.mm84
-rw-r--r--src/plugins/directshow/player/directshowplayercontrol.cpp100
-rw-r--r--src/plugins/directshow/player/directshowplayercontrol.h6
-rw-r--r--src/plugins/directshow/player/directshowplayerservice.cpp29
-rw-r--r--src/plugins/directshow/player/directshowplayerservice.h1
-rw-r--r--src/plugins/directshow/player/videosurfacefilter.cpp30
-rw-r--r--src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp10
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp2
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp7
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp16
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp5
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp7
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp8
-rw-r--r--src/plugins/winrt/qwinrtcameracontrol.cpp54
-rw-r--r--src/plugins/winrt/qwinrtcameracontrol.h3
-rw-r--r--src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp21
-rw-r--r--src/plugins/winrt/qwinrtmediaplayercontrol.cpp1
-rw-r--r--tests/auto/integration/qmediaplayerbackend/BLACKLIST1
44 files changed, 1375 insertions, 724 deletions
diff --git a/dist/changes-5.5.1 b/dist/changes-5.5.1
new file mode 100644
index 000000000..d81d815b1
--- /dev/null
+++ b/dist/changes-5.5.1
@@ -0,0 +1,68 @@
+Qt 5.5.1 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.5.0.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+ http://doc.qt.io/qt-5.5/
+
+The Qt version 5.5 series is binary compatible with the 5.4.x series.
+Applications compiled for 5.4 will continue to run with 5.5.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+ http://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Library *
+****************************************************************************
+
+QtMultimedia
+------------
+
+ - The environment variable QT_QUICK_NO_TEXTURE_VIDEOFRAMES can now be used
+ to disable OpenGL texture based video frames when using the VideoOutput
+ QML type. This can be useful in applications that wish to filter and
+ process the video frames using QAbstractVideoFilter and are not GPU
+ based.
+ - QCamera's viewfinder capabilities functions now report correct values
+ when filtering by pixel aspect ratio.
+ - [QTBUG-46359] fixed crash after using moveToThread() on a QSoundEffect.
+ - [QTBUG-47205] fixed VideoOutput (QML) rendering frames from the wrong
+ source when having multiple VideoOutputs using different sources.
+ - [QTBUG-47630] fixed Camera.supportedViewfinderFrameRateRanges() (QML)
+ returning incorrect values when the argument is not of type 'size'.
+ - [QTBUG-47859] fixed crash when using Radio.radioData (QML) without
+ a radio backend available.
+
+****************************************************************************
+* Platform Specific Changes *
+****************************************************************************
+
+Android
+-------
+
+ - Fixed QVideoProbe stopping to work when using QMediaRecorder to record
+ the camera.
+ - Video frames passed to a QAbstractVideoFilter can now be mapped to
+ system memory.
+
+Linux
+-----
+
+ - QCameraImageProcessing::isWhiteBalanceModeSupported() now correctly
+ reports if a given white balance mode is supported.
+ - [QTBUG-45707] fixed QAudioRecorder::stop() sometimes failing to
+ actually stop the recording.
+
+ WinRT
+-----
+
+ - [QTBUG-46456] QCameraImageCapture: getting the list of supported
+ image capture resolutions and setting the image capture resolution is
+ now supported.
+ - [QTBUG-47373] fixed crash occurring with some camera operations.
diff --git a/src/gsttools/qgstreamervideooverlay.cpp b/src/gsttools/qgstreamervideooverlay.cpp
index 1dcedbcd6..06f93ef6a 100644
--- a/src/gsttools/qgstreamervideooverlay.cpp
+++ b/src/gsttools/qgstreamervideooverlay.cpp
@@ -148,9 +148,7 @@ GstElement *QGstreamerVideoOverlay::findBestVideoSink() const
// If none of the known video sinks are available, try to find one that implements the
// GstVideoOverlay interface and has autoplugging rank.
- GList *list = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO,
- GST_RANK_MARGINAL);
-
+ GList *list = qt_gst_video_sinks();
for (GList *item = list; item != NULL; item = item->next) {
GstElementFactory *f = GST_ELEMENT_FACTORY(item->data);
@@ -242,12 +240,17 @@ void QGstreamerVideoOverlay::setRenderRectangle(const QRect &rect)
h = rect.height();
}
-#if !GST_CHECK_VERSION(1,0,0)
+#if GST_CHECK_VERSION(1,0,0)
+ if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink))
+ gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(m_videoSink), x, y, w, h);
+#elif GST_CHECK_VERSION(0, 10, 29)
if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink))
gst_x_overlay_set_render_rectangle(GST_X_OVERLAY(m_videoSink), x, y , w , h);
#else
- if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink))
- gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(m_videoSink), x, y, w, h);
+ Q_UNUSED(x)
+ Q_UNUSED(y)
+ Q_UNUSED(w)
+ Q_UNUSED(h)
#endif
}
diff --git a/src/gsttools/qgstutils.cpp b/src/gsttools/qgstutils.cpp
index b13038c21..50a56232a 100644
--- a/src/gsttools/qgstutils.cpp
+++ b/src/gsttools/qgstutils.cpp
@@ -774,6 +774,7 @@ QSet<QString> QGstUtils::supportedMimeTypes(bool (*isValidFactory)(GstElementFac
return supportedMimeTypes;
}
+#if GST_CHECK_VERSION(1, 0, 0)
namespace {
struct ColorFormat { QImage::Format imageFormat; GstVideoFormat gstFormat; };
@@ -786,6 +787,7 @@ static const ColorFormat qt_colorLookup[] =
};
}
+#endif
#if GST_CHECK_VERSION(1,0,0)
QImage QGstUtils::bufferToImage(GstBuffer *buffer, const GstVideoInfo &videoInfo)
@@ -1212,6 +1214,7 @@ void QGstUtils::setMetaData(GstElement *element, const QMap<QByteArray, QVariant
tagValue.toDouble(),
NULL);
break;
+#if GST_CHECK_VERSION(0, 10, 31)
case QVariant::DateTime: {
QDateTime date = tagValue.toDateTime().toLocalTime();
gst_tag_setter_add_tags(GST_TAG_SETTER(element),
@@ -1223,6 +1226,7 @@ void QGstUtils::setMetaData(GstElement *element, const QMap<QByteArray, QVariant
NULL);
break;
}
+#endif
default:
break;
}
@@ -1408,8 +1412,10 @@ GstCaps *qt_gst_pad_get_caps(GstPad *pad)
{
#if GST_CHECK_VERSION(1,0,0)
return gst_pad_query_caps(pad, NULL);
-#else
+#elif GST_CHECK_VERSION(0, 10, 26)
return gst_pad_get_caps_reffed(pad);
+#else
+ return gst_pad_get_caps(pad);
#endif
}
@@ -1464,6 +1470,67 @@ const gchar *qt_gst_element_get_factory_name(GstElement *element)
return name;
}
+gboolean qt_gst_caps_can_intersect(const GstCaps * caps1, const GstCaps * caps2)
+{
+#if GST_CHECK_VERSION(0, 10, 25)
+ return gst_caps_can_intersect(caps1, caps2);
+#else
+ GstCaps *intersection = gst_caps_intersect(caps1, caps2);
+ gboolean res = !gst_caps_is_empty(intersection);
+ gst_caps_unref(intersection);
+ return res;
+#endif
+}
+
+#if !GST_CHECK_VERSION(0, 10, 31)
+static gboolean qt_gst_videosink_factory_filter(GstPluginFeature *feature, gpointer)
+{
+ guint rank;
+ const gchar *klass;
+
+ if (!GST_IS_ELEMENT_FACTORY(feature))
+ return FALSE;
+
+ klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(feature));
+ if (!(strstr(klass, "Sink") && strstr(klass, "Video")))
+ return FALSE;
+
+ rank = gst_plugin_feature_get_rank(feature);
+ if (rank < GST_RANK_MARGINAL)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gint qt_gst_compare_ranks(GstPluginFeature *f1, GstPluginFeature *f2)
+{
+ gint diff;
+
+ diff = gst_plugin_feature_get_rank(f2) - gst_plugin_feature_get_rank(f1);
+ if (diff != 0)
+ return diff;
+
+ return strcmp(gst_plugin_feature_get_name(f2), gst_plugin_feature_get_name (f1));
+}
+#endif
+
+GList *qt_gst_video_sinks()
+{
+ GList *list = NULL;
+
+#if GST_CHECK_VERSION(0, 10, 31)
+ list = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO,
+ GST_RANK_MARGINAL);
+#else
+ list = gst_registry_feature_filter(gst_registry_get_default(),
+ (GstPluginFeatureFilter)qt_gst_videosink_factory_filter,
+ FALSE, NULL);
+ list = g_list_sort(list, (GCompareFunc)qt_gst_compare_ranks);
+#endif
+
+ return list;
+}
+
QDebug operator <<(QDebug debug, GstCaps *caps)
{
if (caps) {
diff --git a/src/gsttools/qvideosurfacegstsink.cpp b/src/gsttools/qvideosurfacegstsink.cpp
index 737bc648d..d59709723 100644
--- a/src/gsttools/qvideosurfacegstsink.cpp
+++ b/src/gsttools/qvideosurfacegstsink.cpp
@@ -376,9 +376,6 @@ void QVideoSurfaceGstSink::class_init(gpointer g_class, gpointer class_data)
sink_parent_class = reinterpret_cast<GstVideoSinkClass *>(g_type_class_peek_parent(g_class));
- GstVideoSinkClass *video_sink_class = reinterpret_cast<GstVideoSinkClass *>(g_class);
- video_sink_class->show_frame = QVideoSurfaceGstSink::show_frame;
-
GstBaseSinkClass *base_sink_class = reinterpret_cast<GstBaseSinkClass *>(g_class);
base_sink_class->get_caps = QVideoSurfaceGstSink::get_caps;
base_sink_class->set_caps = QVideoSurfaceGstSink::set_caps;
@@ -387,6 +384,14 @@ void QVideoSurfaceGstSink::class_init(gpointer g_class, gpointer class_data)
base_sink_class->stop = QVideoSurfaceGstSink::stop;
base_sink_class->unlock = QVideoSurfaceGstSink::unlock;
+#if GST_CHECK_VERSION(0, 10, 25)
+ GstVideoSinkClass *video_sink_class = reinterpret_cast<GstVideoSinkClass *>(g_class);
+ video_sink_class->show_frame = QVideoSurfaceGstSink::show_frame;
+#else
+ base_sink_class->preroll = QVideoSurfaceGstSink::preroll;
+ base_sink_class->render = QVideoSurfaceGstSink::render;
+#endif
+
GstElementClass *element_class = reinterpret_cast<GstElementClass *>(g_class);
element_class->change_state = QVideoSurfaceGstSink::change_state;
@@ -674,10 +679,30 @@ gboolean QVideoSurfaceGstSink::unlock(GstBaseSink *base)
return TRUE;
}
+#if GST_CHECK_VERSION(0, 10, 25)
GstFlowReturn QVideoSurfaceGstSink::show_frame(GstVideoSink *base, GstBuffer *buffer)
{
VO_SINK(base);
return sink->delegate->render(buffer);
}
+#else
+GstFlowReturn QVideoSurfaceGstSink::preroll(GstBaseSink *base, GstBuffer *buffer)
+{
+ VO_SINK(base);
+ gboolean showPrerollFrame = true;
+ g_object_get(G_OBJECT(sink), "show-preroll-frame", &showPrerollFrame, NULL);
+
+ if (showPrerollFrame)
+ return sink->delegate->render(buffer);
+
+ return GST_FLOW_OK;
+}
+
+GstFlowReturn QVideoSurfaceGstSink::render(GstBaseSink *base, GstBuffer *buffer)
+{
+ VO_SINK(base);
+ return sink->delegate->render(buffer);
+}
+#endif
QT_END_NAMESPACE
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
diff --git a/src/multimediawidgets/doc/qtmultimediawidgets.qdocconf b/src/multimediawidgets/doc/qtmultimediawidgets.qdocconf
index 19e956a0e..4d36dae89 100644
--- a/src/multimediawidgets/doc/qtmultimediawidgets.qdocconf
+++ b/src/multimediawidgets/doc/qtmultimediawidgets.qdocconf
@@ -28,7 +28,7 @@ exampledirs += ../../../examples/multimediawidgets \
snippets
# Specify example install dir under QT_INSTALL_EXAMPLES
-examplesinstallpath = multimediawidgets
+examplesinstallpath = qtmultimedia/multimediawidgets
headerdirs += ../
diff --git a/src/plugins/android/src/common/qandroidmultimediautils.cpp b/src/plugins/android/src/common/qandroidmultimediautils.cpp
index a41cc0e1b..9255db549 100644
--- a/src/plugins/android/src/common/qandroidmultimediautils.cpp
+++ b/src/plugins/android/src/common/qandroidmultimediautils.cpp
@@ -68,564 +68,5 @@ bool qt_sizeLessThan(const QSize &s1, const QSize &s2)
return s1.width() * s1.height() < s2.width() * s2.height();
}
-// Pre-computed Y coefficients for all possible y values (0-255). Stored as fixed-point (16:16)
-// Y = 1.164 * (y - 16)
-static const int coefficientsY[256] = {
- -593888, -555746, -517604, -479462, -441320, -403178, -365036, -326894, -288752, -250610,
- -212468, -174326, -136184, -98042, -59900, -21758, 16384, 54526, 92668, 130810,
- 168952, 207094, 245236, 283378, 321520, 359662, 397804, 435946, 474088, 512230,
- 550372, 588514, 626656, 664798, 702940, 741082, 779224, 817366, 855508, 893650,
- 931792, 969934, 1008076, 1046218, 1084360, 1122502, 1160644, 1198786, 1236928, 1275070,
- 1313212, 1351354, 1389496, 1427638, 1465780, 1503922, 1542064, 1580206, 1618348, 1656490,
- 1694632, 1732774, 1770916, 1809058, 1847200, 1885342, 1923484, 1961626, 1999768, 2037910,
- 2076052, 2114194, 2152336, 2190478, 2228620, 2266762, 2304904, 2343046, 2381188, 2419330,
- 2457472, 2495614, 2533756, 2571898, 2610040, 2648182, 2686324, 2724466, 2762608, 2800750,
- 2838892, 2877034, 2915176, 2953318, 2991460, 3029602, 3067744, 3105886, 3144028, 3182170,
- 3220312, 3258454, 3296596, 3334738, 3372880, 3411022, 3449164, 3487306, 3525448, 3563590,
- 3601732, 3639874, 3678016, 3716158, 3754300, 3792442, 3830584, 3868726, 3906868, 3945010,
- 3983152, 4021294, 4059436, 4097578, 4135720, 4173862, 4212004, 4250146, 4288288, 4326430,
- 4364572, 4402714, 4440856, 4478998, 4517140, 4555282, 4593424, 4631566, 4669708, 4707850,
- 4745992, 4784134, 4822276, 4860418, 4898560, 4936702, 4974844, 5012986, 5051128, 5089270,
- 5127412, 5165554, 5203696, 5241838, 5279980, 5318122, 5356264, 5394406, 5432548, 5470690,
- 5508832, 5546974, 5585116, 5623258, 5661400, 5699542, 5737684, 5775826, 5813968, 5852110,
- 5890252, 5928394, 5966536, 6004678, 6042820, 6080962, 6119104, 6157246, 6195388, 6233530,
- 6271672, 6309814, 6347956, 6386098, 6424240, 6462382, 6500524, 6538666, 6576808, 6614950,
- 6653092, 6691234, 6729376, 6767518, 6805660, 6843802, 6881944, 6920086, 6958228, 6996370,
- 7034512, 7072654, 7110796, 7148938, 7187080, 7225222, 7263364, 7301506, 7339648, 7377790,
- 7415932, 7454074, 7492216, 7530358, 7568500, 7606642, 7644784, 7682926, 7721068, 7759210,
- 7797352, 7835494, 7873636, 7911778, 7949920, 7988062, 8026204, 8064346, 8102488, 8140630,
- 8178772, 8216914, 8255056, 8293198, 8331340, 8369482, 8407624, 8445766, 8483908, 8522050,
- 8560192, 8598334, 8636476, 8674618, 8712760, 8750902, 8789044, 8827186, 8865328, 8903470,
- 8941612, 8979754, 9017896, 9056038, 9094180, 9132322
-};
-
-// V lookup table for the Red component. Stored as fixed-point (16:16).
-// V = 1.596 * (v - 128)
-static const int coefficientsRV[256] = {
- -6694144, -6641846, -6589548, -6537250, -6484952, -6432654, -6380356, -6328058, -6275760,
- -6223462, -6171164, -6118866, -6066568, -6014270, -5961972, -5909674, -5857376, -5805078,
- -5752780, -5700482, -5648184, -5595886, -5543588, -5491290, -5438992, -5386694, -5334396,
- -5282098, -5229800, -5177502, -5125204, -5072906, -5020608, -4968310, -4916012, -4863714,
- -4811416, -4759118, -4706820, -4654522, -4602224, -4549926, -4497628, -4445330, -4393032,
- -4340734, -4288436, -4236138, -4183840, -4131542, -4079244, -4026946, -3974648, -3922350,
- -3870052, -3817754, -3765456, -3713158, -3660860, -3608562, -3556264, -3503966, -3451668,
- -3399370, -3347072, -3294774, -3242476, -3190178, -3137880, -3085582, -3033284, -2980986,
- -2928688, -2876390, -2824092, -2771794, -2719496, -2667198, -2614900, -2562602, -2510304,
- -2458006, -2405708, -2353410, -2301112, -2248814, -2196516, -2144218, -2091920, -2039622,
- -1987324, -1935026, -1882728, -1830430, -1778132, -1725834, -1673536, -1621238, -1568940,
- -1516642, -1464344, -1412046, -1359748, -1307450, -1255152, -1202854, -1150556, -1098258,
- -1045960, -993662, -941364, -889066, -836768, -784470, -732172, -679874, -627576,
- -575278, -522980, -470682, -418384, -366086, -313788, -261490, -209192, -156894,
- -104596, -52298, 0, 52298, 104596, 156894, 209192, 261490, 313788,
- 366086, 418384, 470682, 522980, 575278, 627576, 679874, 732172, 784470,
- 836768, 889066, 941364, 993662, 1045960, 1098258, 1150556, 1202854, 1255152,
- 1307450, 1359748, 1412046, 1464344, 1516642, 1568940, 1621238, 1673536, 1725834,
- 1778132, 1830430, 1882728, 1935026, 1987324, 2039622, 2091920, 2144218, 2196516,
- 2248814, 2301112, 2353410, 2405708, 2458006, 2510304, 2562602, 2614900, 2667198,
- 2719496, 2771794, 2824092, 2876390, 2928688, 2980986, 3033284, 3085582, 3137880,
- 3190178, 3242476, 3294774, 3347072, 3399370, 3451668, 3503966, 3556264, 3608562,
- 3660860, 3713158, 3765456, 3817754, 3870052, 3922350, 3974648, 4026946, 4079244,
- 4131542, 4183840, 4236138, 4288436, 4340734, 4393032, 4445330, 4497628, 4549926,
- 4602224, 4654522, 4706820, 4759118, 4811416, 4863714, 4916012, 4968310, 5020608,
- 5072906, 5125204, 5177502, 5229800, 5282098, 5334396, 5386694, 5438992, 5491290,
- 5543588, 5595886, 5648184, 5700482, 5752780, 5805078, 5857376, 5909674, 5961972,
- 6014270, 6066568, 6118866, 6171164, 6223462, 6275760, 6328058, 6380356, 6432654,
- 6484952, 6537250, 6589548, 6641846
-};
-
-// U lookup table for the Green component. Stored as fixed-point (16:16).
-// U = 0.391 * (u - 128)
-static const int coefficientsGU[256] = {
- 1639936, 1627124, 1614312, 1601500, 1588688, 1575876, 1563064, 1550252, 1537440,
- 1524628, 1511816, 1499004, 1486192, 1473380, 1460568, 1447756, 1434944, 1422132,
- 1409320, 1396508, 1383696, 1370884, 1358072, 1345260, 1332448, 1319636, 1306824,
- 1294012, 1281200, 1268388, 1255576, 1242764, 1229952, 1217140, 1204328, 1191516,
- 1178704, 1165892, 1153080, 1140268, 1127456, 1114644, 1101832, 1089020, 1076208,
- 1063396, 1050584, 1037772, 1024960, 1012148, 999336, 986524, 973712, 960900,
- 948088, 935276, 922464, 909652, 896840, 884028, 871216, 858404, 845592,
- 832780, 819968, 807156, 794344, 781532, 768720, 755908, 743096, 730284,
- 717472, 704660, 691848, 679036, 666224, 653412, 640600, 627788, 614976,
- 602164, 589352, 576540, 563728, 550916, 538104, 525292, 512480, 499668,
- 486856, 474044, 461232, 448420, 435608, 422796, 409984, 397172, 384360,
- 371548, 358736, 345924, 333112, 320300, 307488, 294676, 281864, 269052,
- 256240, 243428, 230616, 217804, 204992, 192180, 179368, 166556, 153744,
- 140932, 128120, 115308, 102496, 89684, 76872, 64060, 51248, 38436,
- 25624, 12812, 0, -12812, -25624, -38436, -51248, -64060, -76872,
- -89684, -102496, -115308, -128120, -140932, -153744, -166556, -179368, -192180,
- -204992, -217804, -230616, -243428, -256240, -269052, -281864, -294676, -307488,
- -320300, -333112, -345924, -358736, -371548, -384360, -397172, -409984, -422796,
- -435608, -448420, -461232, -474044, -486856, -499668, -512480, -525292, -538104,
- -550916, -563728, -576540, -589352, -602164, -614976, -627788, -640600, -653412,
- -666224, -679036, -691848, -704660, -717472, -730284, -743096, -755908, -768720,
- -781532, -794344, -807156, -819968, -832780, -845592, -858404, -871216, -884028,
- -896840, -909652, -922464, -935276, -948088, -960900, -973712, -986524, -999336,
- -1012148, -1024960, -1037772, -1050584, -1063396, -1076208, -1089020, -1101832, -1114644,
- -1127456, -1140268, -1153080, -1165892, -1178704, -1191516, -1204328, -1217140, -1229952,
- -1242764, -1255576, -1268388, -1281200, -1294012, -1306824, -1319636, -1332448, -1345260,
- -1358072, -1370884, -1383696, -1396508, -1409320, -1422132, -1434944, -1447756, -1460568,
- -1473380, -1486192, -1499004, -1511816, -1524628, -1537440, -1550252, -1563064, -1575876,
- -1588688, -1601500, -1614312, -1627124
-};
-
-// V lookup table for the Green component. Stored as fixed-point (16:16).
-// V = 0.813 * (v - 128)
-static const int coefficientsGV[256] = {
- 3409920, 3383280, 3356640, 3330000, 3303360, 3276720, 3250080, 3223440, 3196800,
- 3170160, 3143520, 3116880, 3090240, 3063600, 3036960, 3010320, 2983680, 2957040,
- 2930400, 2903760, 2877120, 2850480, 2823840, 2797200, 2770560, 2743920, 2717280,
- 2690640, 2664000, 2637360, 2610720, 2584080, 2557440, 2530800, 2504160, 2477520,
- 2450880, 2424240, 2397600, 2370960, 2344320, 2317680, 2291040, 2264400, 2237760,
- 2211120, 2184480, 2157840, 2131200, 2104560, 2077920, 2051280, 2024640, 1998000,
- 1971360, 1944720, 1918080, 1891440, 1864800, 1838160, 1811520, 1784880, 1758240,
- 1731600, 1704960, 1678320, 1651680, 1625040, 1598400, 1571760, 1545120, 1518480,
- 1491840, 1465200, 1438560, 1411920, 1385280, 1358640, 1332000, 1305360, 1278720,
- 1252080, 1225440, 1198800, 1172160, 1145520, 1118880, 1092240, 1065600, 1038960,
- 1012320, 985680, 959040, 932400, 905760, 879120, 852480, 825840, 799200,
- 772560, 745920, 719280, 692640, 666000, 639360, 612720, 586080, 559440,
- 532800, 506160, 479520, 452880, 426240, 399600, 372960, 346320, 319680,
- 293040, 266400, 239760, 213120, 186480, 159840, 133200, 106560, 79920,
- 53280, 26640, 0, -26640, -53280, -79920, -106560, -133200, -159840,
- -186480, -213120, -239760, -266400, -293040, -319680, -346320, -372960, -399600,
- -426240, -452880, -479520, -506160, -532800, -559440, -586080, -612720, -639360,
- -666000, -692640, -719280, -745920, -772560, -799200, -825840, -852480, -879120,
- -905760, -932400, -959040, -985680, -1012320, -1038960, -1065600, -1092240, -1118880,
- -1145520, -1172160, -1198800, -1225440, -1252080, -1278720, -1305360, -1332000, -1358640,
- -1385280, -1411920, -1438560, -1465200, -1491840, -1518480, -1545120, -1571760, -1598400,
- -1625040, -1651680, -1678320, -1704960, -1731600, -1758240, -1784880, -1811520, -1838160,
- -1864800, -1891440, -1918080, -1944720, -1971360, -1998000, -2024640, -2051280, -2077920,
- -2104560, -2131200, -2157840, -2184480, -2211120, -2237760, -2264400, -2291040, -2317680,
- -2344320, -2370960, -2397600, -2424240, -2450880, -2477520, -2504160, -2530800, -2557440,
- -2584080, -2610720, -2637360, -2664000, -2690640, -2717280, -2743920, -2770560, -2797200,
- -2823840, -2850480, -2877120, -2903760, -2930400, -2957040, -2983680, -3010320, -3036960,
- -3063600, -3090240, -3116880, -3143520, -3170160, -3196800, -3223440, -3250080, -3276720,
- -3303360, -3330000, -3356640, -3383280
-};
-
-// U lookup table for the Blue component. Stored as fixed-point (16:16).
-// U = 2.018 * (u - 128)
-static const int coefficientsBU[256] = {
- -8464128, -8398002, -8331876, -8265750, -8199624, -8133498, -8067372, -8001246, -7935120,
- -7868994, -7802868, -7736742, -7670616, -7604490, -7538364, -7472238, -7406112, -7339986,
- -7273860, -7207734, -7141608, -7075482, -7009356, -6943230, -6877104, -6810978, -6744852,
- -6678726, -6612600, -6546474, -6480348, -6414222, -6348096, -6281970, -6215844, -6149718,
- -6083592, -6017466, -5951340, -5885214, -5819088, -5752962, -5686836, -5620710, -5554584,
- -5488458, -5422332, -5356206, -5290080, -5223954, -5157828, -5091702, -5025576, -4959450,
- -4893324, -4827198, -4761072, -4694946, -4628820, -4562694, -4496568, -4430442, -4364316,
- -4298190, -4232064, -4165938, -4099812, -4033686, -3967560, -3901434, -3835308, -3769182,
- -3703056, -3636930, -3570804, -3504678, -3438552, -3372426, -3306300, -3240174, -3174048,
- -3107922, -3041796, -2975670, -2909544, -2843418, -2777292, -2711166, -2645040, -2578914,
- -2512788, -2446662, -2380536, -2314410, -2248284, -2182158, -2116032, -2049906, -1983780,
- -1917654, -1851528, -1785402, -1719276, -1653150, -1587024, -1520898, -1454772, -1388646,
- -1322520, -1256394, -1190268, -1124142, -1058016, -991890, -925764, -859638, -793512,
- -727386, -661260, -595134, -529008, -462882, -396756, -330630, -264504, -198378,
- -132252, -66126, 0, 66126, 132252, 198378, 264504, 330630, 396756,
- 462882, 529008, 595134, 661260, 727386, 793512, 859638, 925764, 991890,
- 1058016, 1124142, 1190268, 1256394, 1322520, 1388646, 1454772, 1520898, 1587024,
- 1653150, 1719276, 1785402, 1851528, 1917654, 1983780, 2049906, 2116032, 2182158,
- 2248284, 2314410, 2380536, 2446662, 2512788, 2578914, 2645040, 2711166, 2777292,
- 2843418, 2909544, 2975670, 3041796, 3107922, 3174048, 3240174, 3306300, 3372426,
- 3438552, 3504678, 3570804, 3636930, 3703056, 3769182, 3835308, 3901434, 3967560,
- 4033686, 4099812, 4165938, 4232064, 4298190, 4364316, 4430442, 4496568, 4562694,
- 4628820, 4694946, 4761072, 4827198, 4893324, 4959450, 5025576, 5091702, 5157828,
- 5223954, 5290080, 5356206, 5422332, 5488458, 5554584, 5620710, 5686836, 5752962,
- 5819088, 5885214, 5951340, 6017466, 6083592, 6149718, 6215844, 6281970, 6348096,
- 6414222, 6480348, 6546474, 6612600, 6678726, 6744852, 6810978, 6877104, 6943230,
- 7009356, 7075482, 7141608, 7207734, 7273860, 7339986, 7406112, 7472238, 7538364,
- 7604490, 7670616, 7736742, 7802868, 7868994, 7935120, 8001246, 8067372, 8133498,
- 8199624, 8265750, 8331876, 8398002
-};
-
-// R = min(max(r, 0), 255) << 16
-// where 'r' is the converted red component from YUV, which is always in the range -320 <= r < 704
-// and needs to be clamped to 0-255. It also precomputes the bitshift needed to create an RGB value.
-static const quint32 _clampedR[1024] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 65536, 131072, 196608, 262144, 327680, 393216, 458752,
- 524288, 589824, 655360, 720896, 786432, 851968, 917504, 983040,
- 1048576, 1114112, 1179648, 1245184, 1310720, 1376256, 1441792, 1507328,
- 1572864, 1638400, 1703936, 1769472, 1835008, 1900544, 1966080, 2031616,
- 2097152, 2162688, 2228224, 2293760, 2359296, 2424832, 2490368, 2555904,
- 2621440, 2686976, 2752512, 2818048, 2883584, 2949120, 3014656, 3080192,
- 3145728, 3211264, 3276800, 3342336, 3407872, 3473408, 3538944, 3604480,
- 3670016, 3735552, 3801088, 3866624, 3932160, 3997696, 4063232, 4128768,
- 4194304, 4259840, 4325376, 4390912, 4456448, 4521984, 4587520, 4653056,
- 4718592, 4784128, 4849664, 4915200, 4980736, 5046272, 5111808, 5177344,
- 5242880, 5308416, 5373952, 5439488, 5505024, 5570560, 5636096, 5701632,
- 5767168, 5832704, 5898240, 5963776, 6029312, 6094848, 6160384, 6225920,
- 6291456, 6356992, 6422528, 6488064, 6553600, 6619136, 6684672, 6750208,
- 6815744, 6881280, 6946816, 7012352, 7077888, 7143424, 7208960, 7274496,
- 7340032, 7405568, 7471104, 7536640, 7602176, 7667712, 7733248, 7798784,
- 7864320, 7929856, 7995392, 8060928, 8126464, 8192000, 8257536, 8323072,
- 8388608, 8454144, 8519680, 8585216, 8650752, 8716288, 8781824, 8847360,
- 8912896, 8978432, 9043968, 9109504, 9175040, 9240576, 9306112, 9371648,
- 9437184, 9502720, 9568256, 9633792, 9699328, 9764864, 9830400, 9895936,
- 9961472, 10027008, 10092544, 10158080, 10223616, 10289152, 10354688, 10420224,
- 10485760, 10551296, 10616832, 10682368, 10747904, 10813440, 10878976, 10944512,
- 11010048, 11075584, 11141120, 11206656, 11272192, 11337728, 11403264, 11468800,
- 11534336, 11599872, 11665408, 11730944, 11796480, 11862016, 11927552, 11993088,
- 12058624, 12124160, 12189696, 12255232, 12320768, 12386304, 12451840, 12517376,
- 12582912, 12648448, 12713984, 12779520, 12845056, 12910592, 12976128, 13041664,
- 13107200, 13172736, 13238272, 13303808, 13369344, 13434880, 13500416, 13565952,
- 13631488, 13697024, 13762560, 13828096, 13893632, 13959168, 14024704, 14090240,
- 14155776, 14221312, 14286848, 14352384, 14417920, 14483456, 14548992, 14614528,
- 14680064, 14745600, 14811136, 14876672, 14942208, 15007744, 15073280, 15138816,
- 15204352, 15269888, 15335424, 15400960, 15466496, 15532032, 15597568, 15663104,
- 15728640, 15794176, 15859712, 15925248, 15990784, 16056320, 16121856, 16187392,
- 16252928, 16318464, 16384000, 16449536, 16515072, 16580608, 16646144, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
- 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680
-};
-
-// G = min(max(g, 0), 255) << 8
-// where 'g' is the converted green component from YUV, which is always in the range -320 <= r < 704
-// and needs to be clamped to 0-255. It also precomputes the bitshift needed to create an RGB value.
-static const quint32 _clampedG[1024] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 256, 512, 768, 1024, 1280, 1536, 1792,
- 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840,
- 4096, 4352, 4608, 4864, 5120, 5376, 5632, 5888,
- 6144, 6400, 6656, 6912, 7168, 7424, 7680, 7936,
- 8192, 8448, 8704, 8960, 9216, 9472, 9728, 9984,
- 10240, 10496, 10752, 11008, 11264, 11520, 11776, 12032,
- 12288, 12544, 12800, 13056, 13312, 13568, 13824, 14080,
- 14336, 14592, 14848, 15104, 15360, 15616, 15872, 16128,
- 16384, 16640, 16896, 17152, 17408, 17664, 17920, 18176,
- 18432, 18688, 18944, 19200, 19456, 19712, 19968, 20224,
- 20480, 20736, 20992, 21248, 21504, 21760, 22016, 22272,
- 22528, 22784, 23040, 23296, 23552, 23808, 24064, 24320,
- 24576, 24832, 25088, 25344, 25600, 25856, 26112, 26368,
- 26624, 26880, 27136, 27392, 27648, 27904, 28160, 28416,
- 28672, 28928, 29184, 29440, 29696, 29952, 30208, 30464,
- 30720, 30976, 31232, 31488, 31744, 32000, 32256, 32512,
- 32768, 33024, 33280, 33536, 33792, 34048, 34304, 34560,
- 34816, 35072, 35328, 35584, 35840, 36096, 36352, 36608,
- 36864, 37120, 37376, 37632, 37888, 38144, 38400, 38656,
- 38912, 39168, 39424, 39680, 39936, 40192, 40448, 40704,
- 40960, 41216, 41472, 41728, 41984, 42240, 42496, 42752,
- 43008, 43264, 43520, 43776, 44032, 44288, 44544, 44800,
- 45056, 45312, 45568, 45824, 46080, 46336, 46592, 46848,
- 47104, 47360, 47616, 47872, 48128, 48384, 48640, 48896,
- 49152, 49408, 49664, 49920, 50176, 50432, 50688, 50944,
- 51200, 51456, 51712, 51968, 52224, 52480, 52736, 52992,
- 53248, 53504, 53760, 54016, 54272, 54528, 54784, 55040,
- 55296, 55552, 55808, 56064, 56320, 56576, 56832, 57088,
- 57344, 57600, 57856, 58112, 58368, 58624, 58880, 59136,
- 59392, 59648, 59904, 60160, 60416, 60672, 60928, 61184,
- 61440, 61696, 61952, 62208, 62464, 62720, 62976, 63232,
- 63488, 63744, 64000, 64256, 64512, 64768, 65024, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
- 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280
-};
-
-// B = min(max(b, 0), 255)
-// where 'b' is the converted blue component from YUV, which is always in the range -320 <= r < 704
-static const quint32 _clampedB[1024] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
- 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
- 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
- 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
- 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
- 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
- 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
- 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
- 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
-};
-
-static const quint32 *clampedR = _clampedR + 320;
-static const quint32 *clampedG = _clampedG + 320;
-static const quint32 *clampedB = _clampedB + 320;
-
-#define MAKE_RGB(r, g, b) 0xff000000 | clampedR[r] | clampedG[g] | clampedB[b]
-
-void qt_convert_NV21_to_ARGB32(const uchar *yuv, quint32 *rgb, int width, int height)
-{
- const uchar *y0 = yuv;
- const uchar *y1 = yuv + width;
- const uchar *vu = yuv + width * height;
-
- quint32 *rgb0 = rgb;
- quint32 *rgb1 = rgb + width;
-
- for (int i = 0; i < height; i += 2) {
- for (int j = 0; j < width; j += 2) {
- int v = *vu++;
- int u = *vu++;
-
- int ruv = coefficientsRV[v] >> 15;
- int guv = (coefficientsGU[u] + coefficientsGV[v]) >> 15;
- int buv = coefficientsBU[u] >> 15;
-
- int y = coefficientsY[*y0++] >> 15;
- int r = y + ruv;
- int g = y + guv;
- int b = y + buv;
- *rgb0++ = MAKE_RGB(r, g, b);
-
- y = coefficientsY[*y0++] >> 15;
- r = y + ruv;
- g = y + guv;
- b = y + buv;
- *rgb0++ = MAKE_RGB(r, g, b);
-
- y = coefficientsY[*y1++] >> 15;
- r = y + ruv;
- g = y + guv;
- b = y + buv;
- *rgb1++ = MAKE_RGB(r, g, b);
-
- y = coefficientsY[*y1++] >> 15;
- r = y + ruv;
- g = y + guv;
- b = y + buv;
- *rgb1++ = MAKE_RGB(r, g, b);
- }
-
- rgb0 += width;
- rgb1 += width;
- y0 += width;
- y1 += width;
- }
-}
QT_END_NAMESPACE
diff --git a/src/plugins/android/src/common/qandroidmultimediautils.h b/src/plugins/android/src/common/qandroidmultimediautils.h
index ea6a322e7..6955c49e9 100644
--- a/src/plugins/android/src/common/qandroidmultimediautils.h
+++ b/src/plugins/android/src/common/qandroidmultimediautils.h
@@ -45,7 +45,6 @@ int qt_findClosestValue(const QList<int> &list, int value);
bool qt_sizeLessThan(const QSize &s1, const QSize &s2);
-void qt_convert_NV21_to_ARGB32(const uchar *yuv, quint32 *rgb, int width, int height);
QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp
index 179bcdf96..cf1879eb1 100644
--- a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp
+++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp
@@ -43,6 +43,8 @@
#include <qguiapplication.h>
#include <qdebug.h>
#include <qvideoframe.h>
+#include <private/qmemoryvideobuffer_p.h>
+#include <private/qvideoframe_p.h>
QT_BEGIN_NAMESPACE
@@ -582,11 +584,10 @@ void QAndroidCameraSession::processPreviewImage(int id, const QByteArray &data,
QImage QAndroidCameraSession::prepareImageFromPreviewData(const QByteArray &data, int width, int height, int rotation)
{
- QImage result(width, height, QImage::Format_ARGB32);
- qt_convert_NV21_to_ARGB32((const uchar *)data.constData(),
- (quint32 *)result.bits(),
- width,
- height);
+ QVideoFrame frame(new QMemoryVideoBuffer(data, width),
+ QSize(width, height), QVideoFrame::Format_NV21);
+
+ QImage result = qt_imageFromVideoFrame(frame);
QTransform transform;
diff --git a/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm b/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm
index 924c62d97..705ec633f 100644
--- a/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm
+++ b/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm
@@ -174,7 +174,7 @@ public:
GL_RGBA,
CVPixelBufferGetWidth(m_buffer),
CVPixelBufferGetHeight(m_buffer),
- GL_BGRA,
+ GL_RGBA,
GL_UNSIGNED_BYTE,
0,
&m_texture);
@@ -240,18 +240,8 @@ private:
int width = CVPixelBufferGetWidth(imageBuffer);
int height = CVPixelBufferGetHeight(imageBuffer);
- QVideoFrame::PixelFormat format;
-
-#ifdef Q_OS_IOS
- bool useTexture = m_renderer->supportsTextures()
- && CVPixelBufferGetPixelFormatType(imageBuffer) == kCVPixelFormatType_32BGRA;
-
- if (useTexture)
- format = QVideoFrame::Format_BGRA32;
- else
-#endif
- format = AVFCameraViewfinderSettingsControl2::QtPixelFormatFromCVFormat(CVPixelBufferGetPixelFormatType(imageBuffer));
-
+ QVideoFrame::PixelFormat format =
+ AVFCameraViewfinderSettingsControl2::QtPixelFormatFromCVFormat(CVPixelBufferGetPixelFormatType(imageBuffer));
if (format == QVideoFrame::Format_Invalid)
return;
diff --git a/src/plugins/avfoundation/camera/avfcamerasession.h b/src/plugins/avfoundation/camera/avfcamerasession.h
index 2b322cfaf..838234522 100644
--- a/src/plugins/avfoundation/camera/avfcamerasession.h
+++ b/src/plugins/avfoundation/camera/avfcamerasession.h
@@ -70,6 +70,7 @@ public:
static int defaultCameraIndex();
static const QList<AVFCameraInfo> &availableCameraDevices();
static AVFCameraInfo cameraDeviceInfo(const QByteArray &device);
+ AVFCameraInfo activeCameraInfo() const { return m_activeCameraInfo; }
void setVideoOutput(AVFCameraRendererControl *output);
AVCaptureSession *captureSession() const { return m_captureSession; }
@@ -93,10 +94,12 @@ public Q_SLOTS:
void processSessionStopped();
void onCameraFrameFetched(const QVideoFrame &frame);
+
Q_SIGNALS:
void readyToConfigureConnections();
void stateChanged(QCamera::State newState);
void activeChanged(bool);
+ void newViewfinderFrame(const QVideoFrame &frame);
void error(int error, const QString &errorString);
private:
@@ -107,6 +110,7 @@ private:
static int m_defaultCameraIndex;
static QList<AVFCameraInfo> m_cameraDevices;
+ AVFCameraInfo m_activeCameraInfo;
AVFCameraService *m_service;
AVFCameraRendererControl *m_videoOutput;
diff --git a/src/plugins/avfoundation/camera/avfcamerasession.mm b/src/plugins/avfoundation/camera/avfcamerasession.mm
index 83f8c0ed3..66dc43d81 100644
--- a/src/plugins/avfoundation/camera/avfcamerasession.mm
+++ b/src/plugins/avfoundation/camera/avfcamerasession.mm
@@ -333,6 +333,7 @@ void AVFCameraSession::attachVideoInputDevice()
[m_captureSession removeInput:m_videoInput];
[m_videoInput release];
m_videoInput = 0;
+ m_activeCameraInfo = AVFCameraInfo();
}
AVCaptureDevice *videoDevice = m_service->videoDeviceControl()->createCaptureDevice();
@@ -346,6 +347,7 @@ void AVFCameraSession::attachVideoInputDevice()
qWarning() << "Failed to create video device input";
} else {
if ([m_captureSession canAddInput:m_videoInput]) {
+ m_activeCameraInfo = m_cameraDevices.at(m_service->videoDeviceControl()->selectedDevice());
[m_videoInput retain];
[m_captureSession addInput:m_videoInput];
} else {
@@ -414,6 +416,8 @@ FourCharCode AVFCameraSession::defaultCodec()
void AVFCameraSession::onCameraFrameFetched(const QVideoFrame &frame)
{
+ Q_EMIT newViewfinderFrame(frame);
+
m_videoProbesMutex.lock();
QSet<AVFMediaVideoProbeControl *>::const_iterator i = m_videoProbes.constBegin();
while (i != m_videoProbes.constEnd()) {
diff --git a/src/plugins/avfoundation/camera/avfimagecapturecontrol.h b/src/plugins/avfoundation/camera/avfimagecapturecontrol.h
index 993725653..dd5e8e8bb 100644
--- a/src/plugins/avfoundation/camera/avfimagecapturecontrol.h
+++ b/src/plugins/avfoundation/camera/avfimagecapturecontrol.h
@@ -36,19 +36,23 @@
#import <AVFoundation/AVFoundation.h>
+#include <QtCore/qqueue.h>
+#include <QtCore/qsemaphore.h>
#include <QtMultimedia/qcameraimagecapturecontrol.h>
+#include "avfcamerasession.h"
#include "avfstoragelocation.h"
QT_BEGIN_NAMESPACE
-class AVFCameraSession;
-class AVFCameraService;
-class AVFCameraControl;
-
class AVFImageCaptureControl : public QCameraImageCaptureControl
{
Q_OBJECT
public:
+ struct CaptureRequest {
+ int captureId;
+ QSemaphore *previewReady;
+ };
+
AVFImageCaptureControl(AVFCameraService *service, QObject *parent = 0);
~AVFImageCaptureControl();
@@ -64,8 +68,11 @@ public:
private Q_SLOTS:
void updateCaptureConnection();
void updateReadyStatus();
+ void onNewViewfinderFrame(const QVideoFrame &frame);
private:
+ void makeCapturePreview(CaptureRequest request, const QVideoFrame &frame, int rotation);
+
AVFCameraSession *m_session;
AVFCameraControl *m_cameraControl;
bool m_ready;
@@ -73,8 +80,13 @@ private:
AVCaptureStillImageOutput *m_stillImageOutput;
AVCaptureConnection *m_videoConnection;
AVFStorageLocation m_storageLocation;
+
+ QMutex m_requestsMutex;
+ QQueue<CaptureRequest> m_captureRequests;
};
+Q_DECLARE_TYPEINFO(AVFImageCaptureControl::CaptureRequest, Q_PRIMITIVE_TYPE);
+
QT_END_NAMESPACE
#endif
diff --git a/src/plugins/avfoundation/camera/avfimagecapturecontrol.mm b/src/plugins/avfoundation/camera/avfimagecapturecontrol.mm
index c28ccef8e..edaaf8ce3 100644
--- a/src/plugins/avfoundation/camera/avfimagecapturecontrol.mm
+++ b/src/plugins/avfoundation/camera/avfimagecapturecontrol.mm
@@ -33,14 +33,15 @@
#include "avfcameradebug.h"
#include "avfimagecapturecontrol.h"
-#include "avfcamerasession.h"
#include "avfcameraservice.h"
#include "avfcameracontrol.h"
#include <QtCore/qurl.h>
#include <QtCore/qfile.h>
#include <QtCore/qbuffer.h>
+#include <QtConcurrent/qtconcurrentrun.h>
#include <QtGui/qimagereader.h>
+#include <private/qvideoframe_p.h>
QT_USE_NAMESPACE
@@ -65,6 +66,10 @@ AVFImageCaptureControl::AVFImageCaptureControl(AVFCameraService *service, QObjec
connect(m_cameraControl, SIGNAL(statusChanged(QCamera::Status)), SLOT(updateReadyStatus()));
connect(m_session, SIGNAL(readyToConfigureConnections()), SLOT(updateCaptureConnection()));
+
+ connect(m_session, &AVFCameraSession::newViewfinderFrame,
+ this, &AVFImageCaptureControl::onNewViewfinderFrame,
+ Qt::DirectConnection);
}
AVFImageCaptureControl::~AVFImageCaptureControl()
@@ -106,9 +111,18 @@ int AVFImageCaptureControl::capture(const QString &fileName)
qDebugCamera() << "Capture image to" << actualFileName;
- int captureId = m_lastCaptureId;
+ CaptureRequest request = { m_lastCaptureId, new QSemaphore };
+ m_requestsMutex.lock();
+ m_captureRequests.enqueue(request);
+ m_requestsMutex.unlock();
+
[m_stillImageOutput captureStillImageAsynchronouslyFromConnection:m_videoConnection
completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) {
+
+ // Wait for the preview to be generated before saving the JPEG
+ request.previewReady->acquire();
+ delete request.previewReady;
+
if (error) {
QStringList messageParts;
messageParts << QString::fromUtf8([[error localizedDescription] UTF8String]);
@@ -119,64 +133,66 @@ int AVFImageCaptureControl::capture(const QString &fileName)
qDebugCamera() << "Image capture failed:" << errorMessage;
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(int, captureId),
+ Q_ARG(int, request.captureId),
Q_ARG(int, QCameraImageCapture::ResourceError),
Q_ARG(QString, errorMessage));
} else {
- qDebugCamera() << "Image captured:" << actualFileName;
- //we can't find the exact time the image is exposed,
- //but image capture is very fast on desktop, so emit it here
- QMetaObject::invokeMethod(this, "imageExposed", Qt::QueuedConnection,
- Q_ARG(int, captureId));
+ qDebugCamera() << "Image capture completed:" << actualFileName;
NSData *nsJpgData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
QByteArray jpgData = QByteArray::fromRawData((const char *)[nsJpgData bytes], [nsJpgData length]);
- //Generate snap preview as downscalled image
- {
- QBuffer buffer(&jpgData);
- QImageReader imageReader(&buffer);
- QSize imgSize = imageReader.size();
- int downScaleSteps = 0;
- while (imgSize.width() > 800 && downScaleSteps < 8) {
- imgSize.rwidth() /= 2;
- imgSize.rheight() /= 2;
- downScaleSteps++;
- }
-
- imageReader.setScaledSize(imgSize);
- QImage snapPreview = imageReader.read();
-
- QMetaObject::invokeMethod(this, "imageCaptured", Qt::QueuedConnection,
- Q_ARG(int, captureId),
- Q_ARG(QImage, snapPreview));
- }
-
- qDebugCamera() << "Image captured" << actualFileName;
-
QFile f(actualFileName);
if (f.open(QFile::WriteOnly)) {
if (f.write(jpgData) != -1) {
QMetaObject::invokeMethod(this, "imageSaved", Qt::QueuedConnection,
- Q_ARG(int, captureId),
+ Q_ARG(int, request.captureId),
Q_ARG(QString, actualFileName));
} else {
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(int, captureId),
+ Q_ARG(int, request.captureId),
Q_ARG(int, QCameraImageCapture::OutOfSpaceError),
Q_ARG(QString, f.errorString()));
}
} else {
QString errorMessage = tr("Could not open destination file:\n%1").arg(actualFileName);
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(int, captureId),
+ Q_ARG(int, request.captureId),
Q_ARG(int, QCameraImageCapture::ResourceError),
Q_ARG(QString, errorMessage));
}
}
}];
- return captureId;
+ return request.captureId;
+}
+
+void AVFImageCaptureControl::onNewViewfinderFrame(const QVideoFrame &frame)
+{
+ QMutexLocker locker(&m_requestsMutex);
+
+ if (m_captureRequests.isEmpty())
+ return;
+
+ CaptureRequest request = m_captureRequests.dequeue();
+ Q_EMIT imageExposed(request.captureId);
+
+ QtConcurrent::run(this, &AVFImageCaptureControl::makeCapturePreview,
+ request,
+ frame,
+ 0 /* rotation */);
+}
+
+void AVFImageCaptureControl::makeCapturePreview(CaptureRequest request,
+ const QVideoFrame &frame,
+ int rotation)
+{
+ QTransform transform;
+ transform.rotate(rotation);
+
+ Q_EMIT imageCaptured(request.captureId, qt_imageFromVideoFrame(frame).transformed(transform));
+
+ request.previewReady->release();
}
void AVFImageCaptureControl::cancelCapture()
diff --git a/src/plugins/directshow/player/directshowplayercontrol.cpp b/src/plugins/directshow/player/directshowplayercontrol.cpp
index a5fed4b95..e988cbdd3 100644
--- a/src/plugins/directshow/player/directshowplayercontrol.cpp
+++ b/src/plugins/directshow/player/directshowplayercontrol.cpp
@@ -73,7 +73,8 @@ DirectShowPlayerControl::DirectShowPlayerControl(DirectShowPlayerService *servic
, m_status(QMediaPlayer::NoMedia)
, m_error(QMediaPlayer::NoError)
, m_streamTypes(0)
- , m_muteVolume(-1)
+ , m_volume(100)
+ , m_muted(false)
, m_position(0)
, m_pendingPosition(-1)
, m_duration(0)
@@ -113,6 +114,11 @@ qint64 DirectShowPlayerControl::position() const
void DirectShowPlayerControl::setPosition(qint64 position)
{
+ if (m_status == QMediaPlayer::EndOfMedia) {
+ m_status = QMediaPlayer::LoadedMedia;
+ emit mediaStatusChanged(m_status);
+ }
+
if (m_state == QMediaPlayer::StoppedState && m_pendingPosition != position) {
m_pendingPosition = position;
emit positionChanged(m_pendingPosition);
@@ -125,63 +131,47 @@ void DirectShowPlayerControl::setPosition(qint64 position)
int DirectShowPlayerControl::volume() const
{
- if (m_muteVolume >= 0) {
- return m_muteVolume;
- } else if (m_audio) {
- long dB = 0;
-
- m_audio->get_Volume(&dB);
-
- return decibelsToVolume(dB);
- } else {
- return 0;
- }
+ return m_volume;
}
void DirectShowPlayerControl::setVolume(int volume)
{
int boundedVolume = qBound(0, volume, 100);
- if (m_muteVolume >= 0) {
- m_muteVolume = boundedVolume;
+ if (m_volume == boundedVolume)
+ return;
+
+ m_volume = boundedVolume;
- emit volumeChanged(m_muteVolume);
- } else if (m_audio) {
- m_audio->put_Volume(volumeToDecibels(volume));
+ if (!m_muted)
+ setVolumeHelper(m_volume);
- emit volumeChanged(boundedVolume);
- }
+ emit volumeChanged(m_volume);
}
bool DirectShowPlayerControl::isMuted() const
{
- return m_muteVolume >= 0;
+ return m_muted;
}
void DirectShowPlayerControl::setMuted(bool muted)
{
- if (muted && m_muteVolume < 0) {
- if (m_audio) {
- long dB = 0;
+ if (m_muted == muted)
+ return;
- m_audio->get_Volume(&dB);
+ m_muted = muted;
- m_muteVolume = decibelsToVolume(dB);
+ setVolumeHelper(m_muted ? 0 : m_volume);
- m_audio->put_Volume(-10000);
- } else {
- m_muteVolume = 0;
- }
+ emit mutedChanged(m_muted);
+}
- emit mutedChanged(muted);
- } else if (!muted && m_muteVolume >= 0) {
- if (m_audio) {
- m_audio->put_Volume(volumeToDecibels(m_muteVolume));
- }
- m_muteVolume = -1;
+void DirectShowPlayerControl::setVolumeHelper(int volume)
+{
+ if (!m_audio)
+ return;
- emit mutedChanged(muted);
- }
+ m_audio->put_Volume(volumeToDecibels(volume));
}
int DirectShowPlayerControl::bufferStatus() const
@@ -235,6 +225,8 @@ const QIODevice *DirectShowPlayerControl::mediaStream() const
void DirectShowPlayerControl::setMedia(const QMediaContent &media, QIODevice *stream)
{
+ m_pendingPosition = -1;
+
m_media = media;
m_stream = stream;
@@ -248,30 +240,35 @@ void DirectShowPlayerControl::setMedia(const QMediaContent &media, QIODevice *st
void DirectShowPlayerControl::play()
{
- if (m_status == QMediaPlayer::NoMedia)
- return;
- if (m_status == QMediaPlayer::InvalidMedia) {
- setMedia(m_media, m_stream);
- if (m_error != QMediaPlayer::NoError)
- return;
- }
- m_service->play();
- if (m_pendingPosition != -1)
- setPosition(m_pendingPosition);
- emit stateChanged(m_state = QMediaPlayer::PlayingState);
+ playOrPause(QMediaPlayer::PlayingState);
}
void DirectShowPlayerControl::pause()
{
- if (m_status == QMediaPlayer::NoMedia)
+ playOrPause(QMediaPlayer::PausedState);
+}
+
+void DirectShowPlayerControl::playOrPause(QMediaPlayer::State state)
+{
+ if (m_status == QMediaPlayer::NoMedia || state == QMediaPlayer::StoppedState)
return;
if (m_status == QMediaPlayer::InvalidMedia) {
setMedia(m_media, m_stream);
if (m_error != QMediaPlayer::NoError)
return;
}
- m_service->pause();
- emit stateChanged(m_state = QMediaPlayer::PausedState);
+
+ m_state = state;
+
+ if (m_pendingPosition != -1)
+ setPosition(m_pendingPosition);
+
+ if (state == QMediaPlayer::PausedState)
+ m_service->pause();
+ else
+ m_service->play();
+
+ emit stateChanged(m_state);
}
void DirectShowPlayerControl::stop()
@@ -389,6 +386,7 @@ void DirectShowPlayerControl::updateAudioOutput(IBaseFilter *filter)
m_audio->Release();
m_audio = com_cast<IBasicAudio>(filter, IID_IBasicAudio);
+ setVolumeHelper(m_muted ? 0 : m_volume);
}
void DirectShowPlayerControl::updateError(QMediaPlayer::Error error, const QString &errorString)
diff --git a/src/plugins/directshow/player/directshowplayercontrol.h b/src/plugins/directshow/player/directshowplayercontrol.h
index a42d3c7b1..ab842f511 100644
--- a/src/plugins/directshow/player/directshowplayercontrol.h
+++ b/src/plugins/directshow/player/directshowplayercontrol.h
@@ -114,8 +114,11 @@ private:
PropertiesChanged = QEvent::User
};
+ void playOrPause(QMediaPlayer::State state);
+
void scheduleUpdate(int properties);
void emitPropertyChanges();
+ void setVolumeHelper(int volume);
DirectShowPlayerService *m_service;
IBasicAudio *m_audio;
@@ -125,7 +128,8 @@ private:
QMediaPlayer::MediaStatus m_status;
QMediaPlayer::Error m_error;
int m_streamTypes;
- int m_muteVolume;
+ int m_volume;
+ bool m_muted;
qint64 m_position;
qint64 m_pendingPosition;
qint64 m_duration;
diff --git a/src/plugins/directshow/player/directshowplayerservice.cpp b/src/plugins/directshow/player/directshowplayerservice.cpp
index 67aea6e9a..b73fa5c4c 100644
--- a/src/plugins/directshow/player/directshowplayerservice.cpp
+++ b/src/plugins/directshow/player/directshowplayerservice.cpp
@@ -98,6 +98,7 @@ DirectShowPlayerService::DirectShowPlayerService(QObject *parent)
, m_videoOutput(0)
, m_rate(1.0)
, m_position(0)
+ , m_seekPosition(-1)
, m_duration(0)
, m_buffering(false)
, m_seekable(false)
@@ -217,6 +218,7 @@ void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream
m_error = QMediaPlayer::NoError;
m_errorString = QString();
m_position = 0;
+ m_seekPosition = -1;
m_duration = 0;
m_streamTypes = 0;
m_executedTasks = 0;
@@ -665,8 +667,10 @@ void DirectShowPlayerService::play()
if (m_executedTasks & Render) {
if (m_executedTasks & Stop) {
m_atEnd = false;
- m_position = 0;
- m_pendingTasks |= Seek;
+ if (m_seekPosition == -1) {
+ m_seekPosition = 0;
+ m_pendingTasks |= Seek;
+ }
m_executedTasks ^= Stop;
}
@@ -709,8 +713,10 @@ void DirectShowPlayerService::pause()
if (m_executedTasks & Render) {
if (m_executedTasks & Stop) {
m_atEnd = false;
- m_position = 0;
- m_pendingTasks |= Seek;
+ if (m_seekPosition == -1) {
+ m_seekPosition = 0;
+ m_pendingTasks |= Seek;
+ }
m_executedTasks ^= Stop;
}
@@ -780,7 +786,7 @@ void DirectShowPlayerService::doStop(QMutexLocker *locker)
control->Release();
}
- m_position = 0;
+ m_seekPosition = 0;
m_pendingTasks |= Seek;
m_executedTasks &= ~(Play | Pause);
@@ -884,7 +890,7 @@ void DirectShowPlayerService::seek(qint64 position)
{
QMutexLocker locker(&m_mutex);
- m_position = position;
+ m_seekPosition = position;
m_pendingTasks |= Seek;
@@ -894,8 +900,11 @@ void DirectShowPlayerService::seek(qint64 position)
void DirectShowPlayerService::doSeek(QMutexLocker *locker)
{
+ if (m_seekPosition == -1)
+ return;
+
if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
- LONGLONG seekPosition = LONGLONG(m_position) * qt_directShowTimeScale;
+ LONGLONG seekPosition = LONGLONG(m_seekPosition) * qt_directShowTimeScale;
// Cache current values as we can't query IMediaSeeking during a seek due to the
// possibility of a deadlock when flushing the VideoSurfaceFilter.
@@ -919,11 +928,11 @@ void DirectShowPlayerService::doSeek(QMutexLocker *locker)
m_position = currentPosition / qt_directShowTimeScale;
seeking->Release();
- } else {
- m_position = 0;
+
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(PositionChange)));
}
- QCoreApplication::postEvent(this, new QEvent(QEvent::Type(PositionChange)));
+ m_seekPosition = -1;
}
int DirectShowPlayerService::bufferStatus() const
diff --git a/src/plugins/directshow/player/directshowplayerservice.h b/src/plugins/directshow/player/directshowplayerservice.h
index c9d10351e..f4da103dc 100644
--- a/src/plugins/directshow/player/directshowplayerservice.h
+++ b/src/plugins/directshow/player/directshowplayerservice.h
@@ -194,6 +194,7 @@ private:
int m_streamTypes;
qreal m_rate;
qint64 m_position;
+ qint64 m_seekPosition;
qint64 m_duration;
bool m_buffering;
bool m_seekable;
diff --git a/src/plugins/directshow/player/videosurfacefilter.cpp b/src/plugins/directshow/player/videosurfacefilter.cpp
index 2f52e33de..901d2e908 100644
--- a/src/plugins/directshow/player/videosurfacefilter.cpp
+++ b/src/plugins/directshow/player/videosurfacefilter.cpp
@@ -147,6 +147,14 @@ HRESULT VideoSurfaceFilter::Stop()
m_sampleScheduler.stop();
+ if (thread() == QThread::currentThread()) {
+ flush();
+ } else {
+ QMutexLocker locker(&m_mutex);
+ m_loop->postEvent(this, new QEvent(QEvent::Type(FlushSurface)));
+ m_wait.wait(&m_mutex);
+ }
+
return S_OK;
}
@@ -606,10 +614,24 @@ void VideoSurfaceFilter::sampleReady()
IMediaSample *sample = m_sampleScheduler.takeSample(&eos);
if (sample) {
- m_surface->present(QVideoFrame(
- new MediaSampleVideoBuffer(sample, m_bytesPerLine),
- m_surfaceFormat.frameSize(),
- m_surfaceFormat.pixelFormat()));
+ QVideoFrame frame(new MediaSampleVideoBuffer(sample, m_bytesPerLine),
+ m_surfaceFormat.frameSize(),
+ m_surfaceFormat.pixelFormat());
+
+ if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
+ LONGLONG position = 0;
+ seeking->GetCurrentPosition(&position);
+ seeking->Release();
+
+ frame.setStartTime(position * 0.1);
+
+ REFERENCE_TIME startTime = -1;
+ REFERENCE_TIME endTime = -1;
+ if (sample->GetTime(&startTime, &endTime) == S_OK)
+ frame.setEndTime(frame.startTime() + (endTime - startTime) * 0.1);
+ }
+
+ m_surface->present(frame);
sample->Release();
diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp
index 6afee9433..f919bb1f7 100644
--- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp
+++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp
@@ -70,9 +70,15 @@ QMultimedia::SupportEstimate QGstreamerAudioDecoderServicePlugin::hasSupport(con
static bool isDecoderOrDemuxer(GstElementFactory *factory)
{
+#if GST_CHECK_VERSION(0, 10, 31)
return gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_DEMUXER)
- || gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_DECODER
- | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO);
+ || gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_DECODER
+ | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO);
+#else
+ return (factory
+ && (qstrcmp(factory->details.klass, "Codec/Decoder/Audio") == 0
+ || qstrcmp(factory->details.klass, "Codec/Demux") == 0));
+#endif
}
void QGstreamerAudioDecoderServicePlugin::updateSupportedMimeTypes() const
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp
index 0018209c2..fca38ecf8 100644
--- a/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp
+++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp
@@ -77,9 +77,7 @@ static const QGstreamerMetaDataKeyLookup *qt_gstreamerMetaDataKeys()
metadataKeys->insert(QMediaMetaData::AlbumTitle, GST_TAG_ALBUM);
metadataKeys->insert(QMediaMetaData::AlbumArtist, GST_TAG_ARTIST);
metadataKeys->insert(QMediaMetaData::ContributingArtist, GST_TAG_PERFORMER);
-#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19)
metadataKeys->insert(QMediaMetaData::Composer, GST_TAG_COMPOSER);
-#endif
//metadataKeys->insert(QMediaMetaData::Conductor, 0);
//metadataKeys->insert(QMediaMetaData::Lyrics, 0);
//metadataKeys->insert(QMediaMetaData::Mood, 0);
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp
index a9c66f836..8cbdb6717 100644
--- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp
+++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp
@@ -113,8 +113,15 @@ QMultimedia::SupportEstimate QGstreamerCaptureServicePlugin::hasSupport(const QS
static bool isEncoderOrMuxer(GstElementFactory *factory)
{
+#if GST_CHECK_VERSION(0, 10, 31)
return gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_MUXER)
|| gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_ENCODER);
+#else
+ return (factory
+ && (qstrcmp(factory->details.klass, "Codec/Encoder/Audio") == 0
+ || qstrcmp(factory->details.klass, "Codec/Encoder/Video") == 0
+ || qstrcmp(factory->details.klass, "Codec/Muxer") == 0 ));
+#endif
}
void QGstreamerCaptureServicePlugin::updateSupportedMimeTypes() const
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
index 77d8987f9..31ffa5065 100644
--- a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
+++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
@@ -628,12 +628,12 @@ bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMo
}
dumpGraph( QString("rebuild_graph_%1_%2").arg(m_pipelineMode).arg(newMode) );
+#ifdef QT_GST_CAPTURE_DEBUG
if (m_encodeBin) {
QString fileName = QString("rebuild_graph_encode_%1_%2").arg(m_pipelineMode).arg(newMode);
-#if !(GST_DISABLE_GST_DEBUG) && (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19)
- _gst_debug_bin_to_dot_file(GST_BIN(m_encodeBin), GST_DEBUG_GRAPH_SHOW_ALL, fileName.toLatin1());
-#endif
+ GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(m_encodeBin), GST_DEBUG_GRAPH_SHOW_ALL, fileName.toLatin1());
}
+#endif
if (ok) {
addAudioBufferProbe();
@@ -657,12 +657,12 @@ bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMo
void QGstreamerCaptureSession::dumpGraph(const QString &fileName)
{
-#if !(GST_DISABLE_GST_DEBUG) && (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19)
- _gst_debug_bin_to_dot_file(GST_BIN(m_pipeline),
- GstDebugGraphDetails(/*GST_DEBUG_GRAPH_SHOW_ALL |*/ GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES),
- fileName.toLatin1());
+#ifdef QT_GST_CAPTURE_DEBUG
+ GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(m_pipeline),
+ GstDebugGraphDetails(/*GST_DEBUG_GRAPH_SHOW_ALL |*/ GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES),
+ fileName.toLatin1());
#else
- Q_UNUSED(fileName);
+ Q_UNUSED(fileName)
#endif
}
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp
index ac0fe2a77..fdf43062f 100644
--- a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp
+++ b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp
@@ -76,13 +76,10 @@ static const QGstreamerMetaDataKeyLookup *qt_gstreamerMetaDataKeys()
// Music
metadataKeys->insert(GST_TAG_ALBUM, QMediaMetaData::AlbumTitle);
-#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 25)
+#if GST_CHECK_VERSION(0, 10, 25)
metadataKeys->insert(GST_TAG_ALBUM_ARTIST, QMediaMetaData::AlbumArtist);
#endif
metadataKeys->insert(GST_TAG_ARTIST, QMediaMetaData::ContributingArtist);
-#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19)
- metadataKeys->insert(GST_TAG_COMPOSER, QMediaMetaData::Composer);
-#endif
//metadataKeys->insert(0, QMediaMetaData::Conductor);
//metadataKeys->insert(0, QMediaMetaData::Lyrics);
//metadataKeys->insert(0, QMediaMetaData::Mood);
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp
index 004d561ae..b895c4d86 100644
--- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp
+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp
@@ -83,8 +83,15 @@ QMultimedia::SupportEstimate QGstreamerPlayerServicePlugin::hasSupport(const QSt
static bool isDecoderOrDemuxer(GstElementFactory *factory)
{
+#if GST_CHECK_VERSION(0, 10 ,31)
return gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_DEMUXER)
|| gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_DECODER);
+#else
+ return (factory
+ && (qstrcmp(factory->details.klass, "Codec/Decoder/Audio") == 0
+ || qstrcmp(factory->details.klass, "Codec/Decoder/Video") == 0
+ || qstrcmp(factory->details.klass, "Codec/Demux") == 0 ));
+#endif
}
void QGstreamerPlayerServicePlugin::updateSupportedMimeTypes() const
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp
index 4dce34113..c3d20e790 100644
--- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp
+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp
@@ -388,7 +388,7 @@ QMediaTimeRange QGstreamerPlayerSession::availablePlaybackRanges() const
if (duration() <= 0)
return ranges;
-#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 31)
+#if GST_CHECK_VERSION(0, 10, 31)
//GST_FORMAT_TIME would be more appropriate, but unfortunately it's not supported.
//with GST_FORMAT_PERCENT media is treated as encoded with constant bitrate.
GstQuery* query = gst_query_new_buffering(GST_FORMAT_PERCENT);
@@ -1637,7 +1637,7 @@ void QGstreamerPlayerSession::updateMuted()
}
}
-#if (GST_VERSION_MAJOR == 0) && ((GST_VERSION_MINOR < 10) || (GST_VERSION_MICRO < 33))
+#if !GST_CHECK_VERSION(0, 10, 33)
static gboolean factory_can_src_any_caps (GstElementFactory *factory, const GstCaps *caps)
{
GList *templates;
@@ -1653,7 +1653,7 @@ static gboolean factory_can_src_any_caps (GstElementFactory *factory, const GstC
if (templ->direction == GST_PAD_SRC) {
GstCaps *templcaps = gst_static_caps_get(&templ->static_caps);
- if (gst_caps_can_intersect(caps, templcaps)) {
+ if (qt_gst_caps_can_intersect(caps, templcaps)) {
gst_caps_unref(templcaps);
return TRUE;
}
@@ -1685,7 +1685,7 @@ GstAutoplugSelectResult QGstreamerPlayerSession::handleAutoplugSelect(GstBin *bi
GstCaps *sinkCaps = gst_pad_get_caps(sinkPad);
#endif
-#if (GST_VERSION_MAJOR == 0) && ((GST_VERSION_MINOR < 10) || (GST_VERSION_MICRO < 33))
+#if !GST_CHECK_VERSION(0, 10, 33)
if (!factory_can_src_any_caps(factory, sinkCaps))
#else
if (!gst_element_factory_can_src_any_caps(factory, sinkCaps))
diff --git a/src/plugins/winrt/qwinrtcameracontrol.cpp b/src/plugins/winrt/qwinrtcameracontrol.cpp
index 3489048d8..7a926ad60 100644
--- a/src/plugins/winrt/qwinrtcameracontrol.cpp
+++ b/src/plugins/winrt/qwinrtcameracontrol.cpp
@@ -43,8 +43,8 @@
#include "qwinrtcameralockscontrol.h"
#include <QtCore/qfunctions_winrt.h>
-#include <QtCore/QCoreApplication>
#include <QtCore/QPointer>
+#include <QtGui/QGuiApplication>
#include <mfapi.h>
#include <mferror.h>
@@ -524,6 +524,8 @@ public:
QPointer<QWinRTImageEncoderControl> imageEncoderControl;
QPointer<QWinRTCameraFocusControl> cameraFocusControl;
QPointer<QWinRTCameraLocksControl> cameraLocksControl;
+ QAtomicInt framesMapped;
+ QEventLoop *delayClose;
};
QWinRTCameraControl::QWinRTCameraControl(QObject *parent)
@@ -531,6 +533,7 @@ QWinRTCameraControl::QWinRTCameraControl(QObject *parent)
{
Q_D(QWinRTCameraControl);
+ d->delayClose = nullptr;
d->state = QCamera::UnloadedState;
d->status = QCamera::UnloadedStatus;
d->captureMode = QCamera::CaptureStillImage;
@@ -544,6 +547,11 @@ QWinRTCameraControl::QWinRTCameraControl(QObject *parent)
d->imageEncoderControl = new QWinRTImageEncoderControl(this);
d->cameraFocusControl = new QWinRTCameraFocusControl(this);
d->cameraLocksControl = new QWinRTCameraLocksControl(this);
+
+ if (qGuiApp) {
+ connect(qGuiApp, &QGuiApplication::applicationStateChanged,
+ this, &QWinRTCameraControl::onApplicationStateChanged);
+ }
}
QWinRTCameraControl::~QWinRTCameraControl()
@@ -612,6 +620,14 @@ void QWinRTCameraControl::setState(QCamera::State state)
case QCamera::UnloadedState: {
// Stop the camera if it is running (transition to LoadedState)
if (d->status == QCamera::ActiveStatus) {
+ if (d->framesMapped > 0) {
+ qWarning("%d QVideoFrame(s) mapped when closing down camera. Camera will wait for unmap before closing down.",
+ d->framesMapped);
+ if (!d->delayClose)
+ d->delayClose = new QEventLoop(this);
+ d->delayClose->exec();
+ }
+
ComPtr<IAsyncAction> op;
hr = d->capturePreview->StopPreviewAsync(&op);
RETURN_VOID_AND_EMIT_ERROR("Failed to stop camera preview");
@@ -767,6 +783,25 @@ void QWinRTCameraControl::onBufferRequested()
d->mediaSink->RequestSample();
}
+void QWinRTCameraControl::onApplicationStateChanged(Qt::ApplicationState state)
+{
+ Q_D(QWinRTCameraControl);
+ static QCamera::State savedState = d->state;
+ switch (state) {
+ case Qt::ApplicationInactive:
+ if (d->state != QCamera::UnloadedState) {
+ savedState = d->state;
+ setState(QCamera::UnloadedState);
+ }
+ break;
+ case Qt::ApplicationActive:
+ setState(QCamera::State(savedState));
+ break;
+ default:
+ break;
+ }
+}
+
HRESULT QWinRTCameraControl::initialize()
{
Q_D(QWinRTCameraControl);
@@ -1119,6 +1154,8 @@ bool QWinRTCameraControl::focus()
return false;
ComPtr<IAsyncAction> op;
HRESULT hr = d->focusControl->FocusAsync(&op);
+ if (HRESULT_CODE(hr) == ERROR_OPERATION_IN_PROGRESS)
+ return true;
Q_ASSERT_SUCCEEDED(hr);
hr = QWinRTFunctions::await(op, QWinRTFunctions::ProcessThreadEvents);
Q_ASSERT_SUCCEEDED(hr);
@@ -1208,6 +1245,21 @@ bool QWinRTCameraControl::unlockFocus()
#endif // !Q_OS_WINPHONE
+void QWinRTCameraControl::frameMapped()
+{
+ Q_D(QWinRTCameraControl);
+ ++d->framesMapped;
+}
+
+void QWinRTCameraControl::frameUnmapped()
+{
+ Q_D(QWinRTCameraControl);
+ --d->framesMapped;
+ Q_ASSERT(d->framesMapped >= 0);
+ if (!d->framesMapped && d->delayClose && d->delayClose->isRunning())
+ d->delayClose->exit();
+}
+
HRESULT QWinRTCameraControl::onCaptureFailed(IMediaCapture *, IMediaCaptureFailedEventArgs *args)
{
HRESULT hr;
diff --git a/src/plugins/winrt/qwinrtcameracontrol.h b/src/plugins/winrt/qwinrtcameracontrol.h
index ac1c922a4..b3c86adf9 100644
--- a/src/plugins/winrt/qwinrtcameracontrol.h
+++ b/src/plugins/winrt/qwinrtcameracontrol.h
@@ -99,9 +99,12 @@ public:
void emitError(int errorCode, const QString &errorString);
bool lockFocus();
bool unlockFocus();
+ void frameMapped();
+ void frameUnmapped();
private slots:
void onBufferRequested();
+ void onApplicationStateChanged(Qt::ApplicationState state);
private:
HRESULT enumerateDevices();
diff --git a/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp b/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp
index 7afef7669..7313ae7a2 100644
--- a/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp
+++ b/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp
@@ -38,6 +38,7 @@
#include <QtCore/qfunctions_winrt.h>
#include <QtCore/QSize>
+#include <QtCore/QPointer>
#include <QtCore/QVector>
#include <QVideoFrame>
@@ -45,6 +46,8 @@
#include <mfapi.h>
#include <wrl.h>
+#include "qwinrtcameracontrol.h"
+
#ifdef Q_OS_WINPHONE
#include <Windows.Security.ExchangeActiveSyncProvisioning.h>
using namespace ABI::Windows::Security::ExchangeActiveSyncProvisioning;
@@ -68,12 +71,14 @@ static bool blacklisted(const wchar_t (&blackListName)[n], const HString &device
class QWinRTCameraVideoBuffer : public QAbstractVideoBuffer
{
public:
- QWinRTCameraVideoBuffer(IMF2DBuffer *buffer, int size)
+ QWinRTCameraVideoBuffer(IMF2DBuffer *buffer, int size, QWinRTCameraControl *control)
: QAbstractVideoBuffer(NoHandle)
, currentMode(NotMapped)
, buffer(buffer)
, size(size)
+ , control(control)
{
+ Q_ASSERT(control);
}
~QWinRTCameraVideoBuffer()
@@ -88,13 +93,14 @@ public:
uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) Q_DECL_OVERRIDE
{
- if (currentMode != NotMapped || mode == NotMapped)
+ if (currentMode != NotMapped || mode == NotMapped || control && control->state() != QCamera::ActiveState)
return nullptr;
BYTE *bytes;
LONG stride;
HRESULT hr = buffer->Lock2D(&bytes, &stride);
RETURN_IF_FAILED("Failed to lock camera frame buffer", nullptr);
+ control->frameMapped();
if (bytesPerLine)
*bytesPerLine = stride;
@@ -111,12 +117,15 @@ public:
HRESULT hr = buffer->Unlock2D();
RETURN_VOID_IF_FAILED("Failed to unlock camera frame buffer");
currentMode = NotMapped;
+ if (control)
+ control->frameUnmapped();
}
private:
ComPtr<IMF2DBuffer> buffer;
MapMode currentMode;
int size;
+ QPointer<QWinRTCameraControl> control;
};
class D3DVideoBlitter
@@ -331,7 +340,9 @@ bool QWinRTCameraVideoRendererControl::dequeueFrame(QVideoFrame *frame)
return false;
}
- QWinRTCameraVideoBuffer *videoBuffer = new QWinRTCameraVideoBuffer(buffer.Get(), d->cameraSampleSize);
+ QWinRTCameraVideoBuffer *videoBuffer = new QWinRTCameraVideoBuffer(buffer.Get(),
+ d->cameraSampleSize,
+ static_cast<QWinRTCameraControl *>(parent()));
*frame = QVideoFrame(videoBuffer, size(), d->cameraSampleformat);
emit bufferRequested();
@@ -350,7 +361,9 @@ void QWinRTCameraVideoRendererControl::queueBuffer(IMF2DBuffer *buffer)
}
if (d->videoProbesCounter > 0 && d->cameraSampleformat != QVideoFrame::Format_Invalid) {
- QWinRTCameraVideoBuffer *videoBuffer = new QWinRTCameraVideoBuffer(buffer, d->cameraSampleSize);
+ QWinRTCameraVideoBuffer *videoBuffer = new QWinRTCameraVideoBuffer(buffer,
+ d->cameraSampleSize,
+ static_cast<QWinRTCameraControl *>(parent()));
QVideoFrame frame(videoBuffer, size(), d->cameraSampleformat);
emit videoFrameProbed(frame);
}
diff --git a/src/plugins/winrt/qwinrtmediaplayercontrol.cpp b/src/plugins/winrt/qwinrtmediaplayercontrol.cpp
index 8954d4445..ed2dbb943 100644
--- a/src/plugins/winrt/qwinrtmediaplayercontrol.cpp
+++ b/src/plugins/winrt/qwinrtmediaplayercontrol.cpp
@@ -51,7 +51,6 @@
#include <mfapi.h>
#include <mfmediaengine.h>
-#include <comdef.h>
#include <wrl.h>
using namespace Microsoft::WRL;
diff --git a/tests/auto/integration/qmediaplayerbackend/BLACKLIST b/tests/auto/integration/qmediaplayerbackend/BLACKLIST
index 0d2fe2872..dd6dd14b8 100644
--- a/tests/auto/integration/qmediaplayerbackend/BLACKLIST
+++ b/tests/auto/integration/qmediaplayerbackend/BLACKLIST
@@ -4,6 +4,7 @@ osx-10.8
osx-10.9
osx-10.10
windows 32bit developer-build
+windows 64bit developer-build
[construction]
opensuse-13.1 64bit