summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gsttools/qgstappsrc.cpp41
-rw-r--r--src/imports/multimedia/multimedia.cpp3
-rw-r--r--src/imports/multimedia/multimedia.pro13
-rw-r--r--src/multimedia/qtmultimediaquicktools_headers/qdeclarativevideooutput_backend_p.h (renamed from src/imports/multimedia/qdeclarativevideooutput_backend_p.h)12
-rw-r--r--src/multimedia/qtmultimediaquicktools_headers/qdeclarativevideooutput_p.h (renamed from src/imports/multimedia/qdeclarativevideooutput_p.h)4
-rw-r--r--src/multimedia/qtmultimediaquicktools_headers/qsgvideonode_p.h2
-rw-r--r--src/plugins/android/src/common/qandroidmultimediautils.cpp565
-rw-r--r--src/plugins/android/src/common/qandroidvideorendercontrol.cpp167
-rw-r--r--src/plugins/android/src/common/qandroidvideorendercontrol.h36
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp43
-rw-r--r--src/plugins/android/src/wrappers/jcamera.cpp18
-rw-r--r--src/plugins/android/src/wrappers/jcamera.h1
-rw-r--r--src/plugins/android/videonode/qandroidsgvideonode.cpp162
-rw-r--r--src/plugins/android/videonode/qandroidsgvideonode.h9
-rw-r--r--src/plugins/android/videonode/qandroidsgvideonodeplugin.cpp4
-rw-r--r--src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm34
-rw-r--r--src/plugins/gstreamer/camerabin/camerabin.pro4
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinaudioencoder.cpp9
-rw-r--r--src/plugins/gstreamer/camerabin/camerabincontrol.cpp3
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinmetadata.cpp48
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinrecorder.cpp6
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinservice.cpp4
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinsession.cpp190
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinsession.h5
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinvideoencoder.cpp15
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinviewfindersettings.cpp106
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinviewfindersettings.h70
-rw-r--r--src/qtmultimediaquicktools/qdeclarativevideooutput.cpp (renamed from src/imports/multimedia/qdeclarativevideooutput.cpp)23
-rw-r--r--src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp (renamed from src/imports/multimedia/qdeclarativevideooutput_render.cpp)0
-rw-r--r--src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h (renamed from src/imports/multimedia/qdeclarativevideooutput_render_p.h)0
-rw-r--r--src/qtmultimediaquicktools/qdeclarativevideooutput_window.cpp (renamed from src/imports/multimedia/qdeclarativevideooutput_window.cpp)0
-rw-r--r--src/qtmultimediaquicktools/qdeclarativevideooutput_window_p.h (renamed from src/imports/multimedia/qdeclarativevideooutput_window_p.h)0
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_i420.cpp (renamed from src/imports/multimedia/qsgvideonode_i420.cpp)4
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_i420.h (renamed from src/imports/multimedia/qsgvideonode_i420.h)3
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_rgb.cpp (renamed from src/imports/multimedia/qsgvideonode_rgb.cpp)4
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_rgb.h (renamed from src/imports/multimedia/qsgvideonode_rgb.h)3
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_texture.cpp (renamed from src/imports/multimedia/qsgvideonode_texture.cpp)4
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_texture.h (renamed from src/imports/multimedia/qsgvideonode_texture.h)3
-rw-r--r--src/qtmultimediaquicktools/qtmultimediaquicktools.pro18
-rw-r--r--tests/auto/integration/qdeclarativevideooutput/qdeclarativevideooutput.pro3
-rw-r--r--tests/auto/integration/qdeclarativevideooutput/tst_qdeclarativevideooutput.cpp2
-rw-r--r--tests/auto/integration/qdeclarativevideooutput_window/qdeclarativevideooutput_window.pro3
-rw-r--r--tests/auto/integration/qdeclarativevideooutput_window/tst_qdeclarativevideooutput_window.cpp2
43 files changed, 1358 insertions, 288 deletions
diff --git a/src/gsttools/qgstappsrc.cpp b/src/gsttools/qgstappsrc.cpp
index c74639ef2..8917bda85 100644
--- a/src/gsttools/qgstappsrc.cpp
+++ b/src/gsttools/qgstappsrc.cpp
@@ -149,28 +149,29 @@ void QGstAppSrc::pushDataToAppSrc()
size = qMin(m_stream->bytesAvailable(), queueSize());
else
size = qMin(m_stream->bytesAvailable(), (qint64)m_dataRequestSize);
- void *data = g_malloc(size);
- GstBuffer* buffer = gst_app_buffer_new(data, size, g_free, data);
- buffer->offset = m_stream->pos();
- qint64 bytesRead = m_stream->read((char*)GST_BUFFER_DATA(buffer), size);
- buffer->offset_end = buffer->offset + bytesRead - 1;
-
- if (bytesRead > 0) {
- m_dataRequested = false;
- m_enoughData = false;
- GstFlowReturn ret = gst_app_src_push_buffer (GST_APP_SRC (element()), buffer);
- if (ret == GST_FLOW_ERROR) {
- qWarning()<<"appsrc: push buffer error";
- } else if (ret == GST_FLOW_WRONG_STATE) {
- qWarning()<<"appsrc: push buffer wrong state";
- } else if (ret == GST_FLOW_RESEND) {
- qWarning()<<"appsrc: push buffer resend";
- }
- }
- // After reading we might be all done
- if (m_stream->atEnd())
+ if (size) {
+ void *data = g_malloc(size);
+ GstBuffer* buffer = gst_app_buffer_new(data, size, g_free, data);
+ buffer->offset = m_stream->pos();
+ qint64 bytesRead = m_stream->read((char*)GST_BUFFER_DATA(buffer), size);
+ buffer->offset_end = buffer->offset + bytesRead - 1;
+
+ if (bytesRead > 0) {
+ m_dataRequested = false;
+ m_enoughData = false;
+ GstFlowReturn ret = gst_app_src_push_buffer (GST_APP_SRC (element()), buffer);
+ if (ret == GST_FLOW_ERROR) {
+ qWarning()<<"appsrc: push buffer error";
+ } else if (ret == GST_FLOW_WRONG_STATE) {
+ qWarning()<<"appsrc: push buffer wrong state";
+ } else if (ret == GST_FLOW_RESEND) {
+ qWarning()<<"appsrc: push buffer resend";
+ }
+ }
+ } else {
sendEOS();
+ }
} else if (m_stream->atEnd()) {
sendEOS();
}
diff --git a/src/imports/multimedia/multimedia.cpp b/src/imports/multimedia/multimedia.cpp
index f05252f5c..94b697e85 100644
--- a/src/imports/multimedia/multimedia.cpp
+++ b/src/imports/multimedia/multimedia.cpp
@@ -45,9 +45,10 @@
#include <QtQml/qqmlcomponent.h>
#include "qsoundeffect.h"
+#include <private/qdeclarativevideooutput_p.h>
+
#include "qdeclarativemediametadata_p.h"
#include "qdeclarativeaudio_p.h"
-#include "qdeclarativevideooutput_p.h"
#include "qdeclarativeradio_p.h"
#include "qdeclarativeradiodata_p.h"
#include "qdeclarativecamera_p.h"
diff --git a/src/imports/multimedia/multimedia.pro b/src/imports/multimedia/multimedia.pro
index d738dd4f2..f6fdfe9cc 100644
--- a/src/imports/multimedia/multimedia.pro
+++ b/src/imports/multimedia/multimedia.pro
@@ -3,13 +3,6 @@ QT += qml quick network multimedia-private qtmultimediaquicktools-private
HEADERS += \
qdeclarativeaudio_p.h \
qdeclarativemediametadata_p.h \
- qdeclarativevideooutput_p.h \
- qdeclarativevideooutput_backend_p.h \
- qdeclarativevideooutput_render_p.h \
- qdeclarativevideooutput_window_p.h \
- qsgvideonode_i420.h \
- qsgvideonode_rgb.h \
- qsgvideonode_texture.h \
qdeclarativeradio_p.h \
qdeclarativeradiodata_p.h \
qdeclarativecamera_p.h \
@@ -25,12 +18,6 @@ HEADERS += \
SOURCES += \
multimedia.cpp \
qdeclarativeaudio.cpp \
- qdeclarativevideooutput.cpp \
- qdeclarativevideooutput_render.cpp \
- qdeclarativevideooutput_window.cpp \
- qsgvideonode_i420.cpp \
- qsgvideonode_rgb.cpp \
- qsgvideonode_texture.cpp \
qdeclarativeradio.cpp \
qdeclarativeradiodata.cpp \
qdeclarativecamera.cpp \
diff --git a/src/imports/multimedia/qdeclarativevideooutput_backend_p.h b/src/multimedia/qtmultimediaquicktools_headers/qdeclarativevideooutput_backend_p.h
index f731b77f1..f7235b518 100644
--- a/src/imports/multimedia/qdeclarativevideooutput_backend_p.h
+++ b/src/multimedia/qtmultimediaquicktools_headers/qdeclarativevideooutput_backend_p.h
@@ -47,6 +47,7 @@
#include <QtCore/qsize.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qsgnode.h>
+#include <private/qtmultimediaquickdefs_p.h>
QT_BEGIN_NAMESPACE
@@ -54,7 +55,7 @@ class QAbstractVideoSurface;
class QDeclarativeVideoOutput;
class QMediaService;
-class QDeclarativeVideoBackend
+class Q_MULTIMEDIAQUICK_EXPORT QDeclarativeVideoBackend
{
public:
explicit QDeclarativeVideoBackend(QDeclarativeVideoOutput *parent)
@@ -82,6 +83,15 @@ protected:
QPointer<QMediaService> m_service;
};
+class QDeclarativeVideoBackendFactoryInterface
+{
+public:
+ virtual QDeclarativeVideoBackend *create(QDeclarativeVideoOutput *parent) = 0;
+};
+
+#define QDeclarativeVideoBackendFactoryInterface_iid "org.qt-project.qt.declarativevideobackendfactory/5.2"
+Q_DECLARE_INTERFACE(QDeclarativeVideoBackendFactoryInterface, QDeclarativeVideoBackendFactoryInterface_iid)
+
/*
* Helper - returns true if the given orientation has the same aspect as the default (e.g. 180*n)
*/
diff --git a/src/imports/multimedia/qdeclarativevideooutput_p.h b/src/multimedia/qtmultimediaquicktools_headers/qdeclarativevideooutput_p.h
index 07fdb41e3..2ca7c2933 100644
--- a/src/imports/multimedia/qdeclarativevideooutput_p.h
+++ b/src/multimedia/qtmultimediaquicktools_headers/qdeclarativevideooutput_p.h
@@ -48,6 +48,8 @@
#include <QtQuick/qquickitem.h>
#include <QtCore/qpointer.h>
+#include <private/qtmultimediaquickdefs_p.h>
+
QT_BEGIN_NAMESPACE
class QMediaObject;
@@ -55,7 +57,7 @@ class QMediaService;
class QDeclarativeVideoBackend;
class QVideoOutputOrientationHandler;
-class QDeclarativeVideoOutput : public QQuickItem
+class Q_MULTIMEDIAQUICK_EXPORT QDeclarativeVideoOutput : public QQuickItem
{
Q_OBJECT
Q_DISABLE_COPY(QDeclarativeVideoOutput)
diff --git a/src/multimedia/qtmultimediaquicktools_headers/qsgvideonode_p.h b/src/multimedia/qtmultimediaquicktools_headers/qsgvideonode_p.h
index 71230ca35..f8cca4fcc 100644
--- a/src/multimedia/qtmultimediaquicktools_headers/qsgvideonode_p.h
+++ b/src/multimedia/qtmultimediaquicktools_headers/qsgvideonode_p.h
@@ -76,7 +76,7 @@ public:
virtual QSGVideoNode *createNode(const QVideoSurfaceFormat &format) = 0;
};
-#define QSGVideoNodeFactoryInterface_iid "org.qt-project.qt.sgvideonodefactory/5.0"
+#define QSGVideoNodeFactoryInterface_iid "org.qt-project.qt.sgvideonodefactory/5.2"
Q_DECLARE_INTERFACE(QSGVideoNodeFactoryInterface, QSGVideoNodeFactoryInterface_iid)
class Q_MULTIMEDIAQUICK_EXPORT QSGVideoNodeFactoryPlugin : public QObject, public QSGVideoNodeFactoryInterface
diff --git a/src/plugins/android/src/common/qandroidmultimediautils.cpp b/src/plugins/android/src/common/qandroidmultimediautils.cpp
index 9bf38a869..230dfe65f 100644
--- a/src/plugins/android/src/common/qandroidmultimediautils.cpp
+++ b/src/plugins/android/src/common/qandroidmultimediautils.cpp
@@ -76,28 +76,563 @@ 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 int frameSize = width * height;
+ const uchar *y0 = yuv;
+ const uchar *y1 = yuv + width;
+ const uchar *vu = yuv + width * height;
+
+ quint32 *rgb0 = rgb;
+ quint32 *rgb1 = rgb + width;
- int a = 0;
- for (int i = 0, ci = 0; i < height; ++i, ci += 1) {
- for (int j = 0, cj = 0; j < width; ++j, cj += 1) {
- int y = (0xff & ((int) yuv[ci * width + cj]));
- int v = (0xff & ((int) yuv[frameSize + (ci >> 1) * width + (cj & ~1) + 0]));
- int u = (0xff & ((int) yuv[frameSize + (ci >> 1) * width + (cj & ~1) + 1]));
- y = y < 16 ? 16 : y;
+ for (int i = 0; i < height; i += 2) {
+ for (int j = 0; j < width; j += 2) {
+ int v = *vu++;
+ int u = *vu++;
- int r = (int) (1.164f * (y - 16) + 1.596f * (v - 128));
- int g = (int) (1.164f * (y - 16) - 0.813f * (v - 128) - 0.391f * (u - 128));
- int b = (int) (1.164f * (y - 16) + 2.018f * (u - 128));
+ int ruv = coefficientsRV[v] >> 15;
+ int guv = (coefficientsGU[u] + coefficientsGV[v]) >> 15;
+ int buv = coefficientsBU[u] >> 15;
- r = qBound(0, r, 255);
- g = qBound(0, g, 255);
- b = qBound(0, b, 255);
+ int y = coefficientsY[*y0++] >> 15;
+ int r = y + ruv;
+ int g = y + guv;
+ int b = y + buv;
+ *rgb0++ = MAKE_RGB(r, g, b);
- rgb[a++] = 0xff000000 | (r << 16) | (g << 8) | 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;
}
}
diff --git a/src/plugins/android/src/common/qandroidvideorendercontrol.cpp b/src/plugins/android/src/common/qandroidvideorendercontrol.cpp
index 5306fe918..55f71d735 100644
--- a/src/plugins/android/src/common/qandroidvideorendercontrol.cpp
+++ b/src/plugins/android/src/common/qandroidvideorendercontrol.cpp
@@ -49,22 +49,39 @@
#include <qcoreapplication.h>
#include <qopenglcontext.h>
#include <qopenglfunctions.h>
+#include <qopenglshaderprogram.h>
+#include <qopenglframebufferobject.h>
QT_BEGIN_NAMESPACE
-#define ExternalGLTextureHandle QAbstractVideoBuffer::HandleType(QAbstractVideoBuffer::UserHandle + 1)
+static const GLfloat g_vertex_data[] = {
+ -1.f, 1.f,
+ 1.f, 1.f,
+ 1.f, -1.f,
+ -1.f, -1.f
+};
+
+static const GLfloat g_texture_data[] = {
+ 0.f, 0.f,
+ 1.f, 0.f,
+ 1.f, 1.f,
+ 0.f, 1.f
+};
-TextureDeleter::~TextureDeleter()
+OpenGLResourcesDeleter::~OpenGLResourcesDeleter()
{
- glDeleteTextures(1, &m_id);
+ glDeleteTextures(1, &m_textureID);
+ delete m_fbo;
+ delete m_program;
}
class AndroidTextureVideoBuffer : public QAbstractVideoBuffer
{
public:
- AndroidTextureVideoBuffer(JSurfaceTexture *surface)
- : QAbstractVideoBuffer(ExternalGLTextureHandle)
- , m_surfaceTexture(surface)
+ AndroidTextureVideoBuffer(QAndroidVideoRendererControl *control)
+ : QAbstractVideoBuffer(GLTextureHandle)
+ , m_control(control)
+ , m_textureUpdated(false)
{
}
@@ -76,18 +93,18 @@ public:
QVariant handle() const
{
- if (m_data.isEmpty()) {
+ if (!m_textureUpdated) {
// update the video texture (called from the render thread)
- m_surfaceTexture->updateTexImage();
- m_data << (uint)m_surfaceTexture->textureID() << m_surfaceTexture->getTransformMatrix();
+ m_control->renderFrameToFbo();
+ m_textureUpdated = true;
}
- return m_data;
+ return m_control->m_fbo->texture();
}
private:
- mutable JSurfaceTexture *m_surfaceTexture;
- mutable QVariantList m_data;
+ mutable QAndroidVideoRendererControl *m_control;
+ mutable bool m_textureUpdated;
};
QAndroidVideoRendererControl::QAndroidVideoRendererControl(QObject *parent)
@@ -97,7 +114,9 @@ QAndroidVideoRendererControl::QAndroidVideoRendererControl(QObject *parent)
, m_surfaceTexture(0)
, m_surfaceHolder(0)
, m_externalTex(0)
- , m_textureDeleter(0)
+ , m_fbo(0)
+ , m_program(0)
+ , m_glDeleter(0)
{
}
@@ -117,8 +136,8 @@ QAndroidVideoRendererControl::~QAndroidVideoRendererControl()
delete m_surfaceHolder;
m_surfaceHolder = 0;
}
- if (m_textureDeleter)
- m_textureDeleter->deleteLater();
+ if (m_glDeleter)
+ m_glDeleter->deleteLater();
}
QAbstractVideoSurface *QAndroidVideoRendererControl::surface() const
@@ -162,7 +181,8 @@ bool QAndroidVideoRendererControl::initSurfaceTexture()
// for the GL render thread to call us back to do it.
if (QOpenGLContext::currentContext()) {
glGenTextures(1, &m_externalTex);
- m_textureDeleter = new TextureDeleter(m_externalTex);
+ m_glDeleter = new OpenGLResourcesDeleter;
+ m_glDeleter->setTexture(m_externalTex);
} else if (!m_externalTex) {
return false;
}
@@ -174,9 +194,9 @@ bool QAndroidVideoRendererControl::initSurfaceTexture()
} else {
delete m_surfaceTexture;
m_surfaceTexture = 0;
- m_textureDeleter->deleteLater();
+ m_glDeleter->deleteLater();
m_externalTex = 0;
- m_textureDeleter = 0;
+ m_glDeleter = 0;
}
return m_surfaceTexture != 0;
@@ -208,6 +228,8 @@ jobject QAndroidVideoRendererControl::surfaceTexture()
void QAndroidVideoRendererControl::setVideoSize(const QSize &size)
{
+ QMutexLocker locker(&m_mutex);
+
if (m_nativeSize == size)
return;
@@ -228,7 +250,7 @@ void QAndroidVideoRendererControl::onFrameAvailable()
if (!m_nativeSize.isValid() || !m_surface)
return;
- QAbstractVideoBuffer *buffer = new AndroidTextureVideoBuffer(m_surfaceTexture);
+ QAbstractVideoBuffer *buffer = new AndroidTextureVideoBuffer(this);
QVideoFrame frame(buffer, m_nativeSize, QVideoFrame::Format_BGR32);
if (m_surface->isActive() && (m_surface->surfaceFormat().pixelFormat() != frame.pixelFormat()
@@ -237,8 +259,8 @@ void QAndroidVideoRendererControl::onFrameAvailable()
}
if (!m_surface->isActive()) {
- QVideoSurfaceFormat format(frame.size(), frame.pixelFormat(), ExternalGLTextureHandle);
- format.setScanLineDirection(QVideoSurfaceFormat::BottomToTop);
+ QVideoSurfaceFormat format(frame.size(), frame.pixelFormat(),
+ QAbstractVideoBuffer::GLTextureHandle);
m_surface->start(format);
}
@@ -247,13 +269,114 @@ void QAndroidVideoRendererControl::onFrameAvailable()
m_surface->present(frame);
}
+void QAndroidVideoRendererControl::renderFrameToFbo()
+{
+ QMutexLocker locker(&m_mutex);
+
+ createGLResources();
+
+ m_surfaceTexture->updateTexImage();
+
+ // save current render states
+ GLboolean stencilTestEnabled;
+ GLboolean depthTestEnabled;
+ GLboolean scissorTestEnabled;
+ GLboolean blendEnabled;
+ glGetBooleanv(GL_STENCIL_TEST, &stencilTestEnabled);
+ glGetBooleanv(GL_DEPTH_TEST, &depthTestEnabled);
+ glGetBooleanv(GL_SCISSOR_TEST, &scissorTestEnabled);
+ glGetBooleanv(GL_BLEND, &blendEnabled);
+
+ if (stencilTestEnabled)
+ glDisable(GL_STENCIL_TEST);
+ if (depthTestEnabled)
+ glDisable(GL_DEPTH_TEST);
+ if (scissorTestEnabled)
+ glDisable(GL_SCISSOR_TEST);
+ if (blendEnabled)
+ glDisable(GL_BLEND);
+
+ m_fbo->bind();
+
+ glViewport(0, 0, m_nativeSize.width(), m_nativeSize.height());
+
+ m_program->bind();
+ m_program->enableAttributeArray(0);
+ m_program->enableAttributeArray(1);
+ m_program->setUniformValue("frameTexture", GLuint(0));
+ m_program->setUniformValue("texMatrix", m_surfaceTexture->getTransformMatrix());
+
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, g_vertex_data);
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, g_texture_data);
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ m_program->disableAttributeArray(0);
+ m_program->disableAttributeArray(1);
+
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
+ m_fbo->release();
+
+ // restore render states
+ if (stencilTestEnabled)
+ glEnable(GL_STENCIL_TEST);
+ if (depthTestEnabled)
+ glEnable(GL_DEPTH_TEST);
+ if (scissorTestEnabled)
+ glEnable(GL_SCISSOR_TEST);
+ if (blendEnabled)
+ glEnable(GL_BLEND);
+}
+
+void QAndroidVideoRendererControl::createGLResources()
+{
+ if (!m_fbo || m_fbo->size() != m_nativeSize) {
+ delete m_fbo;
+ m_fbo = new QOpenGLFramebufferObject(m_nativeSize);
+ m_glDeleter->setFbo(m_fbo);
+ }
+
+ if (!m_program) {
+ m_program = new QOpenGLShaderProgram;
+
+ QOpenGLShader *vertexShader = new QOpenGLShader(QOpenGLShader::Vertex, m_program);
+ vertexShader->compileSourceCode("attribute highp vec4 vertexCoordsArray; \n" \
+ "attribute highp vec2 textureCoordArray; \n" \
+ "uniform highp mat4 texMatrix; \n" \
+ "varying highp vec2 textureCoords; \n" \
+ "void main(void) \n" \
+ "{ \n" \
+ " gl_Position = vertexCoordsArray; \n" \
+ " textureCoords = (texMatrix * vec4(textureCoordArray, 0.0, 1.0)).xy; \n" \
+ "}\n");
+ m_program->addShader(vertexShader);
+
+ QOpenGLShader *fragmentShader = new QOpenGLShader(QOpenGLShader::Fragment, m_program);
+ fragmentShader->compileSourceCode("#extension GL_OES_EGL_image_external : require \n" \
+ "varying highp vec2 textureCoords; \n" \
+ "uniform samplerExternalOES frameTexture; \n" \
+ "void main() \n" \
+ "{ \n" \
+ " gl_FragColor = texture2D(frameTexture, textureCoords); \n" \
+ "}\n");
+ m_program->addShader(fragmentShader);
+
+ m_program->bindAttributeLocation("vertexCoordsArray", 0);
+ m_program->bindAttributeLocation("textureCoordArray", 1);
+ m_program->link();
+
+ m_glDeleter->setShaderProgram(m_program);
+ }
+}
+
void QAndroidVideoRendererControl::customEvent(QEvent *e)
{
if (e->type() == QEvent::User) {
// This is running in the render thread (OpenGL enabled)
if (!m_externalTex) {
glGenTextures(1, &m_externalTex);
- m_textureDeleter = new TextureDeleter(m_externalTex); // will be deleted in the correct thread
+ m_glDeleter = new OpenGLResourcesDeleter; // will cleanup GL resources in the correct thread
+ m_glDeleter->setTexture(m_externalTex);
emit readyChanged(true);
}
}
diff --git a/src/plugins/android/src/common/qandroidvideorendercontrol.h b/src/plugins/android/src/common/qandroidvideorendercontrol.h
index 5d9130c07..6ce1e2dd4 100644
--- a/src/plugins/android/src/common/qandroidvideorendercontrol.h
+++ b/src/plugins/android/src/common/qandroidvideorendercontrol.h
@@ -43,22 +43,37 @@
#define QANDROIDVIDEORENDERCONTROL_H
#include <qvideorenderercontrol.h>
+#include <qmutex.h>
#include "qandroidvideooutput.h"
#include "jsurfacetexture.h"
QT_BEGIN_NAMESPACE
class JSurfaceTextureHolder;
+class QOpenGLTexture;
+class QOpenGLFramebufferObject;
+class QOpenGLShaderProgram;
-class TextureDeleter : public QObject
+class OpenGLResourcesDeleter : public QObject
{
Q_OBJECT
public:
- TextureDeleter(uint id) : m_id(id) { }
- ~TextureDeleter();
+ OpenGLResourcesDeleter()
+ : m_textureID(0)
+ , m_fbo(0)
+ , m_program(0)
+ { }
+
+ ~OpenGLResourcesDeleter();
+
+ void setTexture(quint32 id) { m_textureID = id; }
+ void setFbo(QOpenGLFramebufferObject *fbo) { m_fbo = fbo; }
+ void setShaderProgram(QOpenGLShaderProgram *prog) { m_program = prog; }
private:
- uint m_id;
+ quint32 m_textureID;
+ QOpenGLFramebufferObject *m_fbo;
+ QOpenGLShaderProgram *m_program;
};
class QAndroidVideoRendererControl : public QVideoRendererControl, public QAndroidVideoOutput
@@ -88,6 +103,10 @@ private Q_SLOTS:
private:
bool initSurfaceTexture();
+ void renderFrameToFbo();
+ void createGLResources();
+
+ QMutex m_mutex;
QAbstractVideoSurface *m_surface;
QSize m_nativeSize;
@@ -95,8 +114,13 @@ private:
QJNIObjectPrivate *m_androidSurface;
JSurfaceTexture *m_surfaceTexture;
JSurfaceTextureHolder *m_surfaceHolder;
- uint m_externalTex;
- TextureDeleter *m_textureDeleter;
+
+ quint32 m_externalTex;
+ QOpenGLFramebufferObject *m_fbo;
+ QOpenGLShaderProgram *m_program;
+ OpenGLResourcesDeleter *m_glDeleter;
+
+ friend class AndroidTextureVideoBuffer;
};
QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp b/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp
index 345a29174..ccf028529 100644
--- a/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp
+++ b/src/plugins/android/src/mediacapture/qandroidcamerafocuscontrol.cpp
@@ -46,15 +46,36 @@
QT_BEGIN_NAMESPACE
-static QRect adjustedArea(const QRectF &area)
+static QPointF rotateNormalizedPoint(const QPointF &point, int rotation)
+{
+ const qreal one(1.0f);
+
+ switch (rotation) {
+ case 0:
+ default:
+ return point;
+ case 90:
+ return QPointF(point.y(), one - point.x());
+ case 180:
+ return QPointF(one - point.x(), one - point.y());
+ case 270:
+ return QPointF(one - point.y(), point.x());
+ }
+}
+
+static QRect adjustedArea(const QRectF &area, int rotation)
{
// Qt maps focus points in the range (0.0, 0.0) -> (1.0, 1.0)
// Android maps focus points in the range (-1000, -1000) -> (1000, 1000)
// Converts an area in Qt coordinates to Android coordinates
- return QRect(-1000 + qRound(area.x() * 2000),
- -1000 + qRound(area.y() * 2000),
- qRound(area.width() * 2000),
- qRound(area.height() * 2000))
+ // Applies 'rotation' in the counter-clockwise direction
+ QRectF rotated(rotateNormalizedPoint(area.topLeft(), rotation),
+ rotateNormalizedPoint(area.bottomRight(), rotation));
+
+ return QRect(-1000 + qRound(rotated.x() * 2000),
+ -1000 + qRound(rotated.y() * 2000),
+ qRound(rotated.width() * 2000),
+ qRound(rotated.height() * 2000))
.intersected(QRect(-1000, -1000, 2000, 2000));
}
@@ -242,6 +263,9 @@ void QAndroidCameraFocusControl::updateFocusZones(QCameraFocusZone::FocusZoneSta
if (!viewportSize.isValid())
return;
+ if (m_session->camera()->getDisplayOrientation() % 180)
+ viewportSize.transpose();
+
QSizeF focusSize(50.f / viewportSize.width(), 50.f / viewportSize.height());
float x = qBound(qreal(0),
m_actualFocusPoint.x() - (focusSize.width() / 2),
@@ -264,8 +288,13 @@ void QAndroidCameraFocusControl::setCameraFocusArea()
// in FocusPointAuto mode, leave the area list empty
// to let the driver choose the focus point.
- for (int i = 0; i < m_focusZones.size(); ++i)
- areas.append(adjustedArea(m_focusZones.at(i).area()));
+ for (int i = 0; i < m_focusZones.size(); ++i) {
+ // The area passed to Android should be in sensor orientation.
+ // What we have in m_focusZones is in viewport orientation, so revert the rotation set
+ // on the viewport to get sensor coordinates.
+ areas.append(adjustedArea(m_focusZones.at(i).area(),
+ m_session->camera()->getDisplayOrientation()));
+ }
}
m_session->camera()->setFocusAreas(areas);
diff --git a/src/plugins/android/src/wrappers/jcamera.cpp b/src/plugins/android/src/wrappers/jcamera.cpp
index d24a59a38..c880141af 100644
--- a/src/plugins/android/src/wrappers/jcamera.cpp
+++ b/src/plugins/android/src/wrappers/jcamera.cpp
@@ -151,6 +151,7 @@ class JCameraWorker : public QObject, public QJNIObjectPrivate
friend class JCamera;
JCameraWorker(JCamera *camera, int cameraId, jobject cam, QThread *workerThread);
+ ~JCameraWorker();
Q_INVOKABLE void release();
@@ -230,6 +231,7 @@ class JCameraWorker : public QObject, public QJNIObjectPrivate
QSize m_previewSize;
int m_rotation;
+ int m_displayOrientation;
bool m_hasAPI14;
@@ -275,9 +277,7 @@ JCamera::~JCamera()
g_objectMap.remove(d->m_cameraId);
g_objectMapMutex.unlock();
}
- QThread *workerThread = d->m_workerThread;
d->deleteLater();
- workerThread->quit();
}
JCamera *JCamera::open(int cameraId)
@@ -337,8 +337,14 @@ int JCamera::getNativeOrientation()
return d->getNativeOrientation();
}
+int JCamera::getDisplayOrientation() const
+{
+ return d->m_displayOrientation;
+}
+
void JCamera::setDisplayOrientation(int degrees)
{
+ d->m_displayOrientation = degrees;
QMetaObject::invokeMethod(d, "setDisplayOrientation", Q_ARG(int, degrees));
}
@@ -372,7 +378,7 @@ void JCamera::setPreviewSize(const QSize &size)
d->m_parametersMutex.lock();
bool areParametersValid = d->m_parameters.isValid();
d->m_parametersMutex.unlock();
- if (!areParametersValid || !size.isValid())
+ if (!areParametersValid)
return;
d->m_previewSize = size;
@@ -620,6 +626,7 @@ JCameraWorker::JCameraWorker(JCamera *camera, int cameraId, jobject cam, QThread
, QJNIObjectPrivate(cam)
, m_cameraId(cameraId)
, m_rotation(0)
+ , m_displayOrientation(0)
, m_hasAPI14(false)
, m_parametersMutex(QMutex::Recursive)
{
@@ -661,6 +668,11 @@ JCameraWorker::JCameraWorker(JCamera *camera, int cameraId, jobject cam, QThread
}
}
+JCameraWorker::~JCameraWorker()
+{
+ m_workerThread->quit();
+}
+
void JCameraWorker::release()
{
m_previewSize = QSize();
diff --git a/src/plugins/android/src/wrappers/jcamera.h b/src/plugins/android/src/wrappers/jcamera.h
index 535efe214..e9063f120 100644
--- a/src/plugins/android/src/wrappers/jcamera.h
+++ b/src/plugins/android/src/wrappers/jcamera.h
@@ -88,6 +88,7 @@ public:
CameraFacing getFacing();
int getNativeOrientation();
+ int getDisplayOrientation() const;
void setDisplayOrientation(int degrees);
QSize getPreferredPreviewSizeForVideo();
diff --git a/src/plugins/android/videonode/qandroidsgvideonode.cpp b/src/plugins/android/videonode/qandroidsgvideonode.cpp
index 7f13dc981..8c441a748 100644
--- a/src/plugins/android/videonode/qandroidsgvideonode.cpp
+++ b/src/plugins/android/videonode/qandroidsgvideonode.cpp
@@ -61,41 +61,42 @@ public:
}
protected:
+
const char *vertexShader() const {
- return
- "uniform highp mat4 qt_Matrix; \n"
- "uniform highp mat4 texMatrix; \n"
- "attribute highp vec4 qt_VertexPosition; \n"
- "attribute highp vec2 qt_VertexTexCoord; \n"
- "varying highp vec2 qt_TexCoord; \n"
- "void main() { \n"
- " qt_TexCoord = (texMatrix * vec4(qt_VertexTexCoord, 0.0, 1.0)).xy; \n"
- " gl_Position = qt_Matrix * qt_VertexPosition; \n"
- "}";
+ const char *shader =
+ "uniform highp mat4 qt_Matrix; \n"
+ "attribute highp vec4 qt_VertexPosition; \n"
+ "attribute highp vec2 qt_VertexTexCoord; \n"
+ "varying highp vec2 qt_TexCoord; \n"
+ "void main() { \n"
+ " qt_TexCoord = qt_VertexTexCoord; \n"
+ " gl_Position = qt_Matrix * qt_VertexPosition; \n"
+ "}";
+ return shader;
}
const char *fragmentShader() const {
- return
- "#extension GL_OES_EGL_image_external : require \n"
- "uniform samplerExternalOES videoTexture; \n"
- "uniform lowp float opacity; \n"
- "varying highp vec2 qt_TexCoord; \n"
- "void main() \n"
- "{ \n"
- " gl_FragColor = texture2D(videoTexture, qt_TexCoord) * opacity; \n"
- "}";
+ static const char *shader =
+ "uniform sampler2D rgbTexture;"
+ "uniform lowp float opacity;"
+ ""
+ "varying highp vec2 qt_TexCoord;"
+ ""
+ "void main()"
+ "{"
+ " gl_FragColor = texture2D(rgbTexture, qt_TexCoord) * opacity;"
+ "}";
+ return shader;
}
void initialize() {
m_id_matrix = program()->uniformLocation("qt_Matrix");
- m_id_texMatrix = program()->uniformLocation("texMatrix");
- m_id_texture = program()->uniformLocation("videoTexture");
+ m_id_Texture = program()->uniformLocation("rgbTexture");
m_id_opacity = program()->uniformLocation("opacity");
}
int m_id_matrix;
- int m_id_texMatrix;
- int m_id_texture;
+ int m_id_Texture;
int m_id_opacity;
};
@@ -104,15 +105,12 @@ class QAndroidSGVideoNodeMaterial : public QSGMaterial
public:
QAndroidSGVideoNodeMaterial()
: m_textureId(0)
+ , m_textureUpdated(false)
+ , m_opacity(1.0)
{
setFlag(Blending, false);
}
- ~QAndroidSGVideoNodeMaterial()
- {
- m_frame = QVideoFrame();
- }
-
QSGMaterialType *type() const {
static QSGMaterialType theType;
return &theType;
@@ -124,81 +122,93 @@ public:
int compare(const QSGMaterial *other) const {
const QAndroidSGVideoNodeMaterial *m = static_cast<const QAndroidSGVideoNodeMaterial *>(other);
- return m_textureId - m->m_textureId;
- }
+ int diff = m_textureId - m->m_textureId;
+ if (diff)
+ return diff;
- void setVideoFrame(const QVideoFrame &frame) {
- QMutexLocker lock(&m_frameMutex);
- m_frame = frame;
+ return (m_opacity > m->m_opacity) ? 1 : -1;
}
- bool updateTexture()
- {
- QMutexLocker lock(&m_frameMutex);
- bool texMatrixDirty = false;
-
- if (m_frame.isValid()) {
- QVariantList list = m_frame.handle().toList();
-
- GLuint texId = list.at(0).toUInt();
- QMatrix4x4 mat = qvariant_cast<QMatrix4x4>(list.at(1));
-
- texMatrixDirty = texId != m_textureId || mat != m_texMatrix;
-
- m_textureId = texId;
- m_texMatrix = mat;
-
- // the texture is already bound and initialized at this point,
- // no need to call glTexParams
+ void updateBlending() {
+ setFlag(Blending, qFuzzyCompare(m_opacity, qreal(1.0)) ? false : true);
+ }
- } else {
- m_textureId = 0;
+ void updateTexture(GLuint id, const QSize &size) {
+ if (m_textureId != id || m_textureSize != size) {
+ m_textureId = id;
+ m_textureSize = size;
+ m_textureUpdated = true;
}
+ }
- return texMatrixDirty;
+ void bind()
+ {
+ glBindTexture(GL_TEXTURE_2D, m_textureId);
+ if (m_textureUpdated) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ m_textureUpdated = false;
+ }
}
- QVideoFrame m_frame;
- QMutex m_frameMutex;
+ QSize m_textureSize;
GLuint m_textureId;
- QMatrix4x4 m_texMatrix;
+ bool m_textureUpdated;
+ qreal m_opacity;
};
+
+QAndroidSGVideoNode::QAndroidSGVideoNode(const QVideoSurfaceFormat &format)
+ : m_format(format)
+{
+ setFlags(OwnsMaterial | UsePreprocess);
+ m_material = new QAndroidSGVideoNodeMaterial;
+ setMaterial(m_material);
+}
+
+QAndroidSGVideoNode::~QAndroidSGVideoNode()
+{
+ m_frame = QVideoFrame();
+}
+
+void QAndroidSGVideoNode::setCurrentFrame(const QVideoFrame &frame)
+{
+ QMutexLocker lock(&m_frameMutex);
+ m_frame = frame;
+ markDirty(DirtyMaterial);
+}
+
void QAndroidSGVideoNodeMaterialShader::updateState(const RenderState &state,
QSGMaterial *newMaterial,
QSGMaterial *oldMaterial)
{
Q_UNUSED(oldMaterial);
QAndroidSGVideoNodeMaterial *mat = static_cast<QAndroidSGVideoNodeMaterial *>(newMaterial);
- program()->setUniformValue(m_id_texture, 0);
+ program()->setUniformValue(m_id_Texture, 0);
- if (mat->updateTexture())
- program()->setUniformValue(m_id_texMatrix, mat->m_texMatrix);
+ mat->bind();
- if (state.isOpacityDirty())
- program()->setUniformValue(m_id_opacity, state.opacity());
+ if (state.isOpacityDirty()) {
+ mat->m_opacity = state.opacity();
+ mat->updateBlending();
+ program()->setUniformValue(m_id_opacity, GLfloat(mat->m_opacity));
+ }
if (state.isMatrixDirty())
program()->setUniformValue(m_id_matrix, state.combinedMatrix());
}
-QAndroidSGVideoNode::QAndroidSGVideoNode(const QVideoSurfaceFormat &format)
- : m_format(format)
+void QAndroidSGVideoNode::preprocess()
{
- setFlag(QSGNode::OwnsMaterial);
- m_material = new QAndroidSGVideoNodeMaterial;
- setMaterial(m_material);
-}
+ QMutexLocker lock(&m_frameMutex);
-void QAndroidSGVideoNode::setCurrentFrame(const QVideoFrame &frame)
-{
- m_material->setVideoFrame(frame);
- markDirty(DirtyMaterial);
-}
+ GLuint texId = 0;
+ if (m_frame.isValid())
+ texId = m_frame.handle().toUInt();
-QVideoFrame::PixelFormat QAndroidSGVideoNode::pixelFormat() const
-{
- return m_format.pixelFormat();
+ m_material->updateTexture(texId, m_frame.size());
}
QT_END_NAMESPACE
diff --git a/src/plugins/android/videonode/qandroidsgvideonode.h b/src/plugins/android/videonode/qandroidsgvideonode.h
index b5b383fb6..5da72dd2d 100644
--- a/src/plugins/android/videonode/qandroidsgvideonode.h
+++ b/src/plugins/android/videonode/qandroidsgvideonode.h
@@ -43,6 +43,7 @@
#define QANDROIDSGVIDEONODE_H
#include <private/qsgvideonode_p.h>
+#include <qmutex.h>
QT_BEGIN_NAMESPACE
@@ -52,14 +53,18 @@ class QAndroidSGVideoNode : public QSGVideoNode
{
public:
QAndroidSGVideoNode(const QVideoSurfaceFormat &format);
+ ~QAndroidSGVideoNode();
void setCurrentFrame(const QVideoFrame &frame);
- QVideoFrame::PixelFormat pixelFormat() const;
+ QVideoFrame::PixelFormat pixelFormat() const { return m_format.pixelFormat(); }
+
+ void preprocess();
private:
- QVideoSurfaceFormat m_format;
QAndroidSGVideoNodeMaterial *m_material;
+ QMutex m_frameMutex;
QVideoFrame m_frame;
+ QVideoSurfaceFormat m_format;
};
QT_END_NAMESPACE
diff --git a/src/plugins/android/videonode/qandroidsgvideonodeplugin.cpp b/src/plugins/android/videonode/qandroidsgvideonodeplugin.cpp
index 155c66ada..e1fb286a2 100644
--- a/src/plugins/android/videonode/qandroidsgvideonodeplugin.cpp
+++ b/src/plugins/android/videonode/qandroidsgvideonodeplugin.cpp
@@ -44,14 +44,12 @@
QT_BEGIN_NAMESPACE
-#define ExternalGLTextureHandle (QAbstractVideoBuffer::UserHandle + 1)
-
QList<QVideoFrame::PixelFormat> QAndroidSGVideoNodeFactoryPlugin::supportedPixelFormats(
QAbstractVideoBuffer::HandleType handleType) const
{
QList<QVideoFrame::PixelFormat> pixelFormats;
- if (handleType == ExternalGLTextureHandle)
+ if (handleType == QAbstractVideoBuffer::GLTextureHandle)
pixelFormats.append(QVideoFrame::Format_BGR32);
return pixelFormats;
diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm
index bb2bc75cb..cf2ad307e 100644
--- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm
+++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm
@@ -134,15 +134,17 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe
- (void) unloadMedia
{
[m_player setRate:0.0];
- [m_playerItem removeObserver:self forKeyPath:AVF_STATUS_KEY];
+ if (m_playerItem) {
+ [m_playerItem removeObserver:self forKeyPath:AVF_STATUS_KEY];
- [[NSNotificationCenter defaultCenter] removeObserver:self
+ [[NSNotificationCenter defaultCenter] removeObserver:self
name:AVPlayerItemDidPlayToEndTimeNotification
object:m_playerItem];
- [[NSNotificationCenter defaultCenter] removeObserver:self
+ [[NSNotificationCenter defaultCenter] removeObserver:self
name:AVPlayerItemTimeJumpedNotification
object:m_playerItem];
- m_playerItem = 0;
+ m_playerItem = 0;
+ }
}
- (void) prepareToPlayAsset:(AVURLAsset *)asset
@@ -232,8 +234,11 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe
[m_player removeObserver:self forKeyPath:AVF_RATE_KEY];
[m_player release];
m_player = 0;
- [m_playerLayer release];
- m_playerLayer = 0; //Will have been released
+
+ if (m_playerLayer) {
+ [m_playerLayer release];
+ m_playerLayer = 0; //Will have been released
+ }
}
//Get a new AVPlayer initialized to play the specified player item.
@@ -398,14 +403,21 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe
#ifdef QT_DEBUG_AVF
qDebug() << Q_FUNC_INFO;
#endif
- [m_player removeObserver:self forKeyPath:AVF_CURRENT_ITEM_KEY];
- [m_player removeObserver:self forKeyPath:AVF_RATE_KEY];
- [m_player release];
+ if (m_player) {
+ [m_player removeObserver:self forKeyPath:AVF_CURRENT_ITEM_KEY];
+ [m_player removeObserver:self forKeyPath:AVF_RATE_KEY];
+ [m_player release];
+ }
- [m_playerLayer release];
+ if (m_playerLayer) {
+ [m_playerLayer release];
+ }
[self unloadMedia];
- [m_URL release];
+
+ if (m_URL) {
+ [m_URL release];
+ }
[super dealloc];
}
diff --git a/src/plugins/gstreamer/camerabin/camerabin.pro b/src/plugins/gstreamer/camerabin/camerabin.pro
index e18da8e6e..9efa0812a 100644
--- a/src/plugins/gstreamer/camerabin/camerabin.pro
+++ b/src/plugins/gstreamer/camerabin/camerabin.pro
@@ -29,7 +29,8 @@ HEADERS += \
$$PWD/camerabinvideoencoder.h \
$$PWD/camerabinresourcepolicy.h \
$$PWD/camerabincapturedestination.h \
- $$PWD/camerabincapturebufferformat.h
+ $$PWD/camerabincapturebufferformat.h \
+ $$PWD/camerabinviewfindersettings.h
SOURCES += \
$$PWD/camerabinserviceplugin.cpp \
@@ -46,6 +47,7 @@ SOURCES += \
$$PWD/camerabinvideoencoder.cpp \
$$PWD/camerabinresourcepolicy.cpp \
$$PWD/camerabincapturedestination.cpp \
+ $$PWD/camerabinviewfindersettings.cpp \
$$PWD/camerabincapturebufferformat.cpp
maemo6 {
diff --git a/src/plugins/gstreamer/camerabin/camerabinaudioencoder.cpp b/src/plugins/gstreamer/camerabin/camerabinaudioencoder.cpp
index 78750f03d..0fa854cc5 100644
--- a/src/plugins/gstreamer/camerabin/camerabinaudioencoder.cpp
+++ b/src/plugins/gstreamer/camerabin/camerabinaudioencoder.cpp
@@ -106,18 +106,19 @@ void CameraBinAudioEncoder::resetActualSettings()
GstEncodingProfile *CameraBinAudioEncoder::createProfile()
{
QString codec = m_actualAudioSettings.codec();
+ QString preset = m_actualAudioSettings.encodingOption(QStringLiteral("preset")).toString();
GstCaps *caps;
if (codec.isEmpty())
- caps = gst_caps_new_any();
+ return 0;
else
caps = gst_caps_from_string(codec.toLatin1());
return (GstEncodingProfile *)gst_encoding_audio_profile_new(
caps,
- NULL, //preset
- NULL, //restriction
- 0); //presence
+ !preset.isEmpty() ? preset.toLatin1().constData() : NULL, //preset
+ NULL, //restriction
+ 0); //presence
}
QT_END_NAMESPACE
diff --git a/src/plugins/gstreamer/camerabin/camerabincontrol.cpp b/src/plugins/gstreamer/camerabin/camerabincontrol.cpp
index 8c63959cf..c84ebc41a 100644
--- a/src/plugins/gstreamer/camerabin/camerabincontrol.cpp
+++ b/src/plugins/gstreamer/camerabin/camerabincontrol.cpp
@@ -115,10 +115,11 @@ void CameraBinControl::setCaptureMode(QCamera::CaptureModes mode)
captureMode() == QCamera::CaptureStillImage ?
CamerabinResourcePolicy::ImageCaptureResources :
CamerabinResourcePolicy::VideoCaptureResources);
-
+#if (GST_VERSION_MAJOR == 0) && ((GST_VERSION_MINOR < 10) || (GST_VERSION_MICRO < 23))
//due to bug in v4l2src, it's necessary to reload camera on video caps changes
//https://bugzilla.gnome.org/show_bug.cgi?id=649832
reloadLater();
+#endif
}
emit captureModeChanged(mode);
}
diff --git a/src/plugins/gstreamer/camerabin/camerabinmetadata.cpp b/src/plugins/gstreamer/camerabin/camerabinmetadata.cpp
index 353fd8be6..1e55e9e84 100644
--- a/src/plugins/gstreamer/camerabin/camerabinmetadata.cpp
+++ b/src/plugins/gstreamer/camerabin/camerabinmetadata.cpp
@@ -54,12 +54,43 @@ struct QGstreamerMetaDataKeyLookup
const char *token;
};
+static QVariant fromGStreamerOrientation(const QVariant &value)
+{
+ // Note gstreamer tokens either describe the counter clockwise rotation of the
+ // image or the clockwise transform to apply to correct the image. The orientation
+ // value returned is the clockwise rotation of the image.
+ const QString token = value.toString();
+ if (token == QStringLiteral("rotate-90"))
+ return 270;
+ else if (token == QStringLiteral("rotate-180"))
+ return 180;
+ else if (token == QStringLiteral("rotate-270"))
+ return 90;
+ else
+ return 0;
+}
+
+static QVariant toGStreamerOrientation(const QVariant &value)
+{
+ switch (value.toInt()) {
+ case 90:
+ return QStringLiteral("rotate-270");
+ case 180:
+ return QStringLiteral("rotate-180");
+ case 270:
+ return QStringLiteral("rotate-90");
+ default:
+ return QStringLiteral("rotate-0");
+ }
+}
+
static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] =
{
{ QMediaMetaData::Title, GST_TAG_TITLE },
//{ QMediaMetaData::SubTitle, 0 },
//{ QMediaMetaData::Author, 0 },
{ QMediaMetaData::Comment, GST_TAG_COMMENT },
+ { QMediaMetaData::Date, GST_TAG_DATE_TIME },
{ QMediaMetaData::Description, GST_TAG_DESCRIPTION },
//{ QMediaMetaData::Category, 0 },
{ QMediaMetaData::Genre, GST_TAG_GENRE },
@@ -120,7 +151,9 @@ static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] =
//{ QMediaMetaData::CameraManufacturer, 0 },
//{ QMediaMetaData::CameraModel, 0 },
//{ QMediaMetaData::Event, 0 },
- //{ QMediaMetaData::Subject, 0 }
+ //{ QMediaMetaData::Subject, 0 },
+
+ { QMediaMetaData::Orientation, GST_TAG_IMAGE_ORIENTATION }
};
CameraBinMetaData::CameraBinMetaData(QObject *parent)
@@ -130,6 +163,10 @@ CameraBinMetaData::CameraBinMetaData(QObject *parent)
QVariant CameraBinMetaData::metaData(const QString &key) const
{
+ if (key == QMediaMetaData::Orientation) {
+ return fromGStreamerOrientation(m_values.value(QByteArray(GST_TAG_IMAGE_ORIENTATION)));
+ }
+
static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
for (int i = 0; i < count; ++i) {
@@ -144,6 +181,15 @@ QVariant CameraBinMetaData::metaData(const QString &key) const
void CameraBinMetaData::setMetaData(const QString &key, const QVariant &value)
{
+ if (key == QMediaMetaData::Orientation) {
+ m_values.insert(QByteArray(GST_TAG_IMAGE_ORIENTATION), toGStreamerOrientation(value));
+
+ emit QMetaDataWriterControl::metaDataChanged();
+ emit metaDataChanged(m_values);
+
+ return;
+ }
+
static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
for (int i = 0; i < count; ++i) {
diff --git a/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp b/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp
index c8967dfb7..4ac0d942e 100644
--- a/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp
+++ b/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp
@@ -191,8 +191,10 @@ GstEncodingContainerProfile *CameraBinRecorder::videoProfile()
GstEncodingProfile *audioProfile = m_session->audioEncodeControl()->createProfile();
GstEncodingProfile *videoProfile = m_session->videoEncodeControl()->createProfile();
- gst_encoding_container_profile_add_profile(containerProfile, audioProfile);
- gst_encoding_container_profile_add_profile(containerProfile, videoProfile);
+ if (audioProfile)
+ gst_encoding_container_profile_add_profile(containerProfile, audioProfile);
+ if (videoProfile)
+ gst_encoding_container_profile_add_profile(containerProfile, videoProfile);
}
return containerProfile;
diff --git a/src/plugins/gstreamer/camerabin/camerabinservice.cpp b/src/plugins/gstreamer/camerabin/camerabinservice.cpp
index a916ee88e..df02a9ecc 100644
--- a/src/plugins/gstreamer/camerabin/camerabinservice.cpp
+++ b/src/plugins/gstreamer/camerabin/camerabinservice.cpp
@@ -61,6 +61,7 @@
#include "camerabinimageprocessing.h"
#include "camerabincapturebufferformat.h"
#include "camerabincapturedestination.h"
+#include "camerabinviewfindersettings.h"
#include <private/qgstreamerbushelper_p.h>
#include <private/qgstreameraudioinputselector_p.h>
@@ -240,6 +241,9 @@ QMediaControl *CameraBinService::requestControl(const char *name)
if (qstrcmp(name, QCameraCaptureBufferFormatControl_iid) == 0)
return m_captureSession->captureBufferFormatControl();
+ if (qstrcmp(name, QCameraViewfinderSettingsControl_iid) == 0)
+ return m_captureSession->viewfinderSettingsControl();
+
return 0;
}
diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.cpp b/src/plugins/gstreamer/camerabin/camerabinsession.cpp
index e61615bc1..28e237776 100644
--- a/src/plugins/gstreamer/camerabin/camerabinsession.cpp
+++ b/src/plugins/gstreamer/camerabin/camerabinsession.cpp
@@ -55,6 +55,7 @@
#endif
#include "camerabinimageprocessing.h"
+#include "camerabinviewfindersettings.h"
#include "camerabincapturedestination.h"
#include "camerabincapturebufferformat.h"
@@ -75,6 +76,7 @@
#include <QtGui/qdesktopservices.h>
#include <QtGui/qimage.h>
+#include <QtCore/qdatetime.h>
//#define CAMERABIN_DEBUG 1
//#define CAMERABIN_DEBUG_DUMP_BIN 1
@@ -91,6 +93,8 @@
#define AUDIO_SOURCE_PROPERTY "audio-source"
#define SUPPORTED_IMAGE_CAPTURE_CAPS_PROPERTY "image-capture-supported-caps"
#define SUPPORTED_VIDEO_CAPTURE_CAPS_PROPERTY "video-capture-supported-caps"
+#define SUPPORTED_VIEWFINDER_CAPS_PROPERTY "viewfinder-supported-caps"
+#define AUDIO_CAPTURE_CAPS_PROPERTY "audio-capture-caps"
#define IMAGE_CAPTURE_CAPS_PROPERTY "image-capture-caps"
#define VIDEO_CAPTURE_CAPS_PROPERTY "video-capture-caps"
#define VIEWFINDER_CAPS_PROPERTY "viewfinder-caps"
@@ -110,10 +114,6 @@
#define PREVIEW_CAPS_4_3 \
"video/x-raw-rgb, width = (int) 640, height = (int) 480"
-#define VIEWFINDER_RESOLUTION_4x3 QSize(640, 480)
-#define VIEWFINDER_RESOLUTION_3x2 QSize(720, 480)
-#define VIEWFINDER_RESOLUTION_16x9 QSize(800, 450)
-
//using GST_STATE_READY for QCamera::LoadedState
//may not work reliably at least with some webcams.
@@ -170,6 +170,7 @@ CameraBinSession::CameraBinSession(QObject *parent)
m_imageProcessingControl = new CameraBinImageProcessing(this);
m_captureDestinationControl = new CameraBinCaptureDestination(this);
m_captureBufferFormatControl = new CameraBinCaptureBufferFormat(this);
+ m_viewfinderSettingsControl = new CameraBinViewfinderSettings(this);
QByteArray envFlags = qgetenv("QT_GSTREAMER_CAMERABIN_FLAGS");
if (!envFlags.isEmpty())
@@ -246,8 +247,7 @@ bool CameraBinSession::setupCameraBin()
return true;
}
-static GstCaps *resolutionToCaps(const QSize &resolution,
- const QPair<int, int> &rate = qMakePair<int,int>(0,0))
+static GstCaps *resolutionToCaps(const QSize &resolution, const QPair<int, int> &rate = qMakePair<int,int>(0,0))
{
if (resolution.isEmpty())
return gst_caps_new_any();
@@ -263,7 +263,23 @@ static GstCaps *resolutionToCaps(const QSize &resolution,
"width", G_TYPE_INT, resolution.width(),
"height", G_TYPE_INT, resolution.height(),
"framerate", GST_TYPE_FRACTION, rate.first, rate.second,
- NULL), NULL);
+ NULL),
+ gst_structure_new("video/x-raw-data",
+ "width", G_TYPE_INT, resolution.width(),
+ "height", G_TYPE_INT, resolution.height(),
+ "framerate", GST_TYPE_FRACTION, rate.first, rate.second,
+ NULL),
+ gst_structure_new("video/x-android-buffer",
+ "width", G_TYPE_INT, resolution.width(),
+ "height", G_TYPE_INT, resolution.height(),
+ "framerate", GST_TYPE_FRACTION, rate.first, rate.second,
+ NULL),
+ gst_structure_new("image/jpeg",
+ "width", G_TYPE_INT, resolution.width(),
+ "height", G_TYPE_INT, resolution.height(),
+ "framerate", GST_TYPE_FRACTION, rate.first, rate.second,
+ NULL),
+ NULL);
} else {
caps = gst_caps_new_full (gst_structure_new ("video/x-raw-yuv",
"width", G_TYPE_INT, resolution.width(),
@@ -271,88 +287,92 @@ static GstCaps *resolutionToCaps(const QSize &resolution,
NULL),
gst_structure_new ("video/x-raw-rgb",
"width", G_TYPE_INT, resolution.width(),
- "height", G_TYPE_INT, resolution.height(), NULL), NULL);
+ "height", G_TYPE_INT, resolution.height(),
+ NULL),
+ gst_structure_new("video/x-raw-data",
+ "width", G_TYPE_INT, resolution.width(),
+ "height", G_TYPE_INT, resolution.height(),
+ NULL),
+ gst_structure_new ("video/x-android-buffer",
+ "width", G_TYPE_INT, resolution.width(),
+ "height", G_TYPE_INT, resolution.height(),
+ NULL),
+ gst_structure_new ("image/jpeg",
+ "width", G_TYPE_INT, resolution.width(),
+ "height", G_TYPE_INT, resolution.height(),
+ NULL),
+ NULL);
}
+
return caps;
}
void CameraBinSession::setupCaptureResolution()
{
- if (m_captureMode == QCamera::CaptureStillImage) {
- QSize resolution = m_imageEncodeControl->imageSettings().resolution();
-
- //by default select the maximum supported resolution
- if (resolution.isEmpty()) {
- bool continuous = false;
- QList<QSize> resolutions = supportedResolutions(qMakePair<int,int>(0,0),
- &continuous,
- QCamera::CaptureStillImage);
- if (!resolutions.isEmpty())
- resolution = resolutions.last();
- }
-
- QSize viewfinderResolution = VIEWFINDER_RESOLUTION_4x3;
-
- if (!resolution.isEmpty()) {
- GstCaps *caps = resolutionToCaps(resolution);
-#if CAMERABIN_DEBUG
- qDebug() << Q_FUNC_INFO << "set image resolution" << resolution << gst_caps_to_string(caps);
-#endif
- g_object_set(m_camerabin, IMAGE_CAPTURE_CAPS_PROPERTY, caps, NULL);
- gst_caps_unref(caps);
-
- if (!resolution.isEmpty()) {
- qreal aspectRatio = qreal(resolution.width()) / resolution.height();
- if (aspectRatio < 1.4)
- viewfinderResolution = VIEWFINDER_RESOLUTION_4x3;
- else if (aspectRatio > 1.7)
- viewfinderResolution = VIEWFINDER_RESOLUTION_16x9;
- else
- viewfinderResolution = VIEWFINDER_RESOLUTION_3x2;
- }
- } else {
- g_object_set(m_camerabin, IMAGE_CAPTURE_CAPS_PROPERTY, GST_CAPS_ANY, NULL);
- }
-
- //on low res cameras the viewfinder resolution should not be bigger
- //then capture resolution
- if (viewfinderResolution.width() > resolution.width() && !resolution.isEmpty())
- viewfinderResolution = resolution;
-
- GstCaps *viewfinderCaps = resolutionToCaps(viewfinderResolution);
+ QSize resolution = m_imageEncodeControl->imageSettings().resolution();
+ if (!resolution.isEmpty()) {
+ GstCaps *caps = resolutionToCaps(resolution);
#if CAMERABIN_DEBUG
- qDebug() << "Set viewfinder resolution" << viewfinderResolution <<gst_caps_to_string(viewfinderCaps);
+ qDebug() << Q_FUNC_INFO << "set image resolution" << resolution << gst_caps_to_string(caps);
#endif
- g_object_set(m_camerabin, VIEWFINDER_CAPS_PROPERTY, viewfinderCaps, NULL);
- gst_caps_unref(viewfinderCaps);
+ g_object_set(m_camerabin, IMAGE_CAPTURE_CAPS_PROPERTY, caps, NULL);
+ gst_caps_unref(caps);
+ } else {
+ g_object_set(m_camerabin, IMAGE_CAPTURE_CAPS_PROPERTY, NULL, NULL);
}
- if (m_captureMode == QCamera::CaptureVideo) {
- QSize resolution = m_videoEncodeControl->actualVideoSettings().resolution();
- //qreal framerate = m_videoEncodeControl->videoSettings().frameRate();
-
- if (resolution.isEmpty()) {
- //select the hightest supported resolution
- bool continuous = false;
- QList<QSize> resolutions = supportedResolutions(qMakePair<int,int>(0,0),
- &continuous,
- QCamera::CaptureVideo);
- if (!resolutions.isEmpty())
- resolution = resolutions.last();
- }
-
+ resolution = m_videoEncodeControl->actualVideoSettings().resolution();
+ //qreal framerate = m_videoEncodeControl->videoSettings().frameRate();
+ if (!resolution.isEmpty()) {
GstCaps *caps = resolutionToCaps(resolution /*, framerate*/); //convert to rational
#if CAMERABIN_DEBUG
qDebug() << Q_FUNC_INFO << "set video resolution" << resolution << gst_caps_to_string(caps);
#endif
-
- //Use the same resolution for viewfinder and video capture
g_object_set(m_camerabin, VIDEO_CAPTURE_CAPS_PROPERTY, caps, NULL);
+ gst_caps_unref(caps);
+ } else {
+ g_object_set(m_camerabin, VIDEO_CAPTURE_CAPS_PROPERTY, NULL, NULL);
+ }
+
+ resolution = m_viewfinderSettingsControl->resolution();
+ if (!resolution.isEmpty()) {
+ GstCaps *caps = resolutionToCaps(resolution);
+#if CAMERABIN_DEBUG
+ qDebug() << Q_FUNC_INFO << "set viewfinder resolution" << resolution << gst_caps_to_string(caps);
+#endif
g_object_set(m_camerabin, VIEWFINDER_CAPS_PROPERTY, caps, NULL);
gst_caps_unref(caps);
+ } else {
+ g_object_set(m_camerabin, VIEWFINDER_CAPS_PROPERTY, NULL, NULL);
}
}
+void CameraBinSession::setAudioCaptureCaps()
+{
+ QAudioEncoderSettings settings = m_audioEncodeControl->audioSettings();
+ const int sampleRate = settings.sampleRate();
+ const int channelCount = settings.channelCount();
+
+ if (sampleRate == -1 && channelCount == -1)
+ return;
+
+ GstStructure *structure = gst_structure_new(
+ "audio/x-raw-int",
+ "endianness", G_TYPE_INT, 1234,
+ "signed", G_TYPE_BOOLEAN, TRUE,
+ "width", G_TYPE_INT, 16,
+ "depth", G_TYPE_INT, 16,
+ NULL);
+ if (sampleRate != -1)
+ gst_structure_set(structure, "rate", G_TYPE_INT, sampleRate, NULL);
+ if (channelCount != -1)
+ gst_structure_set(structure, "channels", G_TYPE_INT, channelCount, NULL);
+
+ GstCaps *caps = gst_caps_new_full(structure, NULL);
+ g_object_set(G_OBJECT(m_camerabin), AUDIO_CAPTURE_CAPS_PROPERTY, caps, NULL);
+ gst_caps_unref(caps);
+}
+
GstElement *CameraBinSession::buildCameraSource()
{
#if CAMERABIN_DEBUG
@@ -658,14 +678,14 @@ void CameraBinSession::setState(QCamera::State newState)
GstState pending = GST_STATE_NULL;
gst_element_get_state(m_camerabin, &binState, &pending, 0);
- if (captureMode() == QCamera::CaptureVideo) {
- m_recorderControl->applySettings();
+ m_recorderControl->applySettings();
- g_object_set (G_OBJECT(m_camerabin),
- "video-profile",
- m_recorderControl->videoProfile(),
- NULL);
- }
+ g_object_set (G_OBJECT(m_camerabin),
+ "video-profile",
+ m_recorderControl->videoProfile(),
+ NULL);
+
+ setAudioCaptureCaps();
setupCaptureResolution();
@@ -745,7 +765,7 @@ void CameraBinSession::setMetaData(const QMap<QByteArray, QVariant> &data)
switch(tagValue.type()) {
case QVariant::String:
gst_tag_setter_add_tags(GST_TAG_SETTER(element),
- GST_TAG_MERGE_REPLACE_ALL,
+ GST_TAG_MERGE_REPLACE,
tagName.toUtf8().constData(),
tagValue.toString().toUtf8().constData(),
NULL);
@@ -753,18 +773,29 @@ void CameraBinSession::setMetaData(const QMap<QByteArray, QVariant> &data)
case QVariant::Int:
case QVariant::LongLong:
gst_tag_setter_add_tags(GST_TAG_SETTER(element),
- GST_TAG_MERGE_REPLACE_ALL,
+ GST_TAG_MERGE_REPLACE,
tagName.toUtf8().constData(),
tagValue.toInt(),
NULL);
break;
case QVariant::Double:
gst_tag_setter_add_tags(GST_TAG_SETTER(element),
- GST_TAG_MERGE_REPLACE_ALL,
+ GST_TAG_MERGE_REPLACE,
tagName.toUtf8().constData(),
tagValue.toDouble(),
NULL);
break;
+ case QVariant::DateTime: {
+ QDateTime date = tagValue.toDateTime().toLocalTime();
+ gst_tag_setter_add_tags(GST_TAG_SETTER(element),
+ GST_TAG_MERGE_REPLACE,
+ tagName.toUtf8().constData(),
+ gst_date_time_new_local_time(
+ date.date().year(), date.date().month(), date.date().day(),
+ date.time().hour(), date.time().minute(), date.time().second()),
+ NULL);
+ break;
+ }
default:
break;
}
@@ -940,6 +971,7 @@ bool CameraBinSession::processBusMessage(const QGstreamerMessage &message)
emit stateChanged(m_state = QCamera::UnloadedState);
break;
case GST_STATE_READY:
+ setMetaData(m_metaData);
if (m_state != QCamera::LoadedState)
emit stateChanged(m_state = QCamera::LoadedState);
break;
diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.h b/src/plugins/gstreamer/camerabin/camerabinsession.h
index dab8d84cc..3332f4c78 100644
--- a/src/plugins/gstreamer/camerabin/camerabinsession.h
+++ b/src/plugins/gstreamer/camerabin/camerabinsession.h
@@ -74,6 +74,7 @@ class CameraBinZoom;
class CameraBinCaptureDestination;
class CameraBinCaptureBufferFormat;
class QGstreamerVideoRendererInterface;
+class CameraBinViewfinderSettings;
class QGstreamerElementFactory
{
@@ -136,7 +137,7 @@ public:
CameraBinImageProcessing *imageProcessingControl() const { return m_imageProcessingControl; }
CameraBinCaptureDestination *captureDestinationControl() const { return m_captureDestinationControl; }
CameraBinCaptureBufferFormat *captureBufferFormatControl() const { return m_captureBufferFormatControl; }
-
+ CameraBinViewfinderSettings *viewfinderSettingsControl() const { return m_viewfinderSettingsControl; }
CameraBinRecorder *recorderControl() const { return m_recorderControl; }
CameraBinContainer *mediaContainerControl() const { return m_mediaContainerControl; }
@@ -192,6 +193,7 @@ private slots:
private:
bool setupCameraBin();
void setupCaptureResolution();
+ void setAudioCaptureCaps();
static void updateBusyStatus(GObject *o, GParamSpec *p, gpointer d);
QUrl m_sink;
@@ -229,6 +231,7 @@ private:
CameraBinImageProcessing *m_imageProcessingControl;
CameraBinCaptureDestination *m_captureDestinationControl;
CameraBinCaptureBufferFormat *m_captureBufferFormatControl;
+ CameraBinViewfinderSettings *m_viewfinderSettingsControl;
QGstreamerBusHelper *m_busHelper;
GstBus* m_bus;
diff --git a/src/plugins/gstreamer/camerabin/camerabinvideoencoder.cpp b/src/plugins/gstreamer/camerabin/camerabinvideoencoder.cpp
index 47a61c9a3..cb479d8df 100644
--- a/src/plugins/gstreamer/camerabin/camerabinvideoencoder.cpp
+++ b/src/plugins/gstreamer/camerabin/camerabinvideoencoder.cpp
@@ -160,18 +160,25 @@ QPair<int,int> CameraBinVideoEncoder::rateAsRational(qreal frameRate) const
GstEncodingProfile *CameraBinVideoEncoder::createProfile()
{
QString codec = m_actualVideoSettings.codec();
+ QString preset = m_actualVideoSettings.encodingOption(QStringLiteral("preset")).toString();
+
GstCaps *caps;
if (codec.isEmpty())
- caps = gst_caps_new_any();
+ caps = 0;
else
caps = gst_caps_from_string(codec.toLatin1());
- return (GstEncodingProfile *)gst_encoding_video_profile_new(
+ GstEncodingVideoProfile *profile = gst_encoding_video_profile_new(
caps,
- NULL, //preset
+ !preset.isEmpty() ? preset.toLatin1().constData() : NULL, //preset
NULL, //restriction
- 0); //presence
+ 1); //presence
+
+ gst_encoding_video_profile_set_pass(profile, 0);
+ gst_encoding_video_profile_set_variableframerate(profile, TRUE);
+
+ return (GstEncodingProfile *)profile;
}
QT_END_NAMESPACE
diff --git a/src/plugins/gstreamer/camerabin/camerabinviewfindersettings.cpp b/src/plugins/gstreamer/camerabin/camerabinviewfindersettings.cpp
new file mode 100644
index 000000000..373dbee77
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinviewfindersettings.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Jolla Ltd.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "camerabinviewfindersettings.h"
+
+
+QT_BEGIN_NAMESPACE
+
+CameraBinViewfinderSettings::CameraBinViewfinderSettings(QObject *parent)
+ : QCameraViewfinderSettingsControl(parent)
+{
+}
+
+CameraBinViewfinderSettings::~CameraBinViewfinderSettings()
+{
+}
+
+bool CameraBinViewfinderSettings::isViewfinderParameterSupported(ViewfinderParameter parameter) const
+{
+ switch (parameter) {
+ case Resolution:
+ return true;
+ case PixelAspectRatio:
+ case MinimumFrameRate:
+ case MaximumFrameRate:
+ case PixelFormat:
+ case UserParameter:
+ return false;
+ }
+ return false;
+}
+
+QVariant CameraBinViewfinderSettings::viewfinderParameter(ViewfinderParameter parameter) const
+{
+ switch (parameter) {
+ case Resolution:
+ return m_resolution;
+ case PixelAspectRatio:
+ case MinimumFrameRate:
+ case MaximumFrameRate:
+ case PixelFormat:
+ case UserParameter:
+ return QVariant();
+ }
+ return false;
+}
+
+void CameraBinViewfinderSettings::setViewfinderParameter(ViewfinderParameter parameter, const QVariant &value)
+{
+ switch (parameter) {
+ case Resolution:
+ m_resolution = value.toSize();
+ case PixelAspectRatio:
+ case MinimumFrameRate:
+ case MaximumFrameRate:
+ case PixelFormat:
+ case UserParameter:
+ break;
+ }
+}
+
+QSize CameraBinViewfinderSettings::resolution() const
+{
+ return m_resolution;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/gstreamer/camerabin/camerabinviewfindersettings.h b/src/plugins/gstreamer/camerabin/camerabinviewfindersettings.h
new file mode 100644
index 000000000..835f532dc
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinviewfindersettings.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Jolla Ltd.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CAMERABINVIEWFINDERSETTINGS_H
+#define CAMERABINVIEWFINDERSETTINGS_H
+
+#include <qcameraviewfindersettingscontrol.h>
+
+#include <QtCore/qsize.h>
+
+QT_BEGIN_NAMESPACE
+
+class CameraBinViewfinderSettings : public QCameraViewfinderSettingsControl
+{
+ Q_OBJECT
+public:
+ CameraBinViewfinderSettings(QObject *parent);
+ ~CameraBinViewfinderSettings();
+
+ bool isViewfinderParameterSupported(ViewfinderParameter parameter) const;
+ QVariant viewfinderParameter(ViewfinderParameter parameter) const;
+ void setViewfinderParameter(ViewfinderParameter parameter, const QVariant &value);
+
+ QSize resolution() const;
+
+private:
+ QSize m_resolution;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/imports/multimedia/qdeclarativevideooutput.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp
index 6d6107e51..321fd5e81 100644
--- a/src/imports/multimedia/qdeclarativevideooutput.cpp
+++ b/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp
@@ -46,6 +46,7 @@
#include <private/qvideooutputorientationhandler_p.h>
#include <QtMultimedia/qmediaobject.h>
#include <QtMultimedia/qmediaservice.h>
+#include <private/qmediapluginloader_p.h>
//#define DEBUG_VIDEOITEM
@@ -211,12 +212,28 @@ void QDeclarativeVideoOutput::setSource(QObject *source)
emit sourceChanged();
}
+Q_GLOBAL_STATIC_WITH_ARGS(QMediaPluginLoader, videoBackendFactoryLoader,
+ (QDeclarativeVideoBackendFactoryInterface_iid, QLatin1String("video/declarativevideobackend"), Qt::CaseInsensitive))
+
bool QDeclarativeVideoOutput::createBackend(QMediaService *service)
{
bool backendAvailable = false;
- m_backend.reset(new QDeclarativeVideoRendererBackend(this));
- if (m_backend->init(service))
- backendAvailable = true;
+
+ foreach (QObject *instance, videoBackendFactoryLoader()->instances(QLatin1String("declarativevideobackend"))) {
+ if (QDeclarativeVideoBackendFactoryInterface *plugin = qobject_cast<QDeclarativeVideoBackendFactoryInterface*>(instance)) {
+ m_backend.reset(plugin->create(this));
+ if (m_backend && m_backend->init(service)) {
+ backendAvailable = true;
+ break;
+ }
+ }
+ }
+
+ if (!backendAvailable) {
+ m_backend.reset(new QDeclarativeVideoRendererBackend(this));
+ if (m_backend->init(service))
+ backendAvailable = true;
+ }
// QDeclarativeVideoWindowBackend only works when there is a service with a QVideoWindowControl.
// Without service, the QDeclarativeVideoRendererBackend should always work.
diff --git a/src/imports/multimedia/qdeclarativevideooutput_render.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp
index cd03cd6b8..cd03cd6b8 100644
--- a/src/imports/multimedia/qdeclarativevideooutput_render.cpp
+++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp
diff --git a/src/imports/multimedia/qdeclarativevideooutput_render_p.h b/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h
index 3682c15a6..3682c15a6 100644
--- a/src/imports/multimedia/qdeclarativevideooutput_render_p.h
+++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h
diff --git a/src/imports/multimedia/qdeclarativevideooutput_window.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput_window.cpp
index 2da63c107..2da63c107 100644
--- a/src/imports/multimedia/qdeclarativevideooutput_window.cpp
+++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_window.cpp
diff --git a/src/imports/multimedia/qdeclarativevideooutput_window_p.h b/src/qtmultimediaquicktools/qdeclarativevideooutput_window_p.h
index eb7b35b85..eb7b35b85 100644
--- a/src/imports/multimedia/qdeclarativevideooutput_window_p.h
+++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_window_p.h
diff --git a/src/imports/multimedia/qsgvideonode_i420.cpp b/src/qtmultimediaquicktools/qsgvideonode_i420.cpp
index f91fb5a07..d7eb04863 100644
--- a/src/imports/multimedia/qsgvideonode_i420.cpp
+++ b/src/qtmultimediaquicktools/qsgvideonode_i420.cpp
@@ -46,6 +46,8 @@
#include <QtGui/QOpenGLFunctions>
#include <QtGui/QOpenGLShaderProgram>
+QT_BEGIN_NAMESPACE
+
QList<QVideoFrame::PixelFormat> QSGVideoNodeFactory_I420::supportedPixelFormats(
QAbstractVideoBuffer::HandleType handleType) const
{
@@ -324,3 +326,5 @@ void QSGVideoMaterialShader_YUV420::updateState(const RenderState &state,
if (state.isMatrixDirty())
program()->setUniformValue(m_id_matrix, state.combinedMatrix());
}
+
+QT_END_NAMESPACE
diff --git a/src/imports/multimedia/qsgvideonode_i420.h b/src/qtmultimediaquicktools/qsgvideonode_i420.h
index 96050abb8..a9def5514 100644
--- a/src/imports/multimedia/qsgvideonode_i420.h
+++ b/src/qtmultimediaquicktools/qsgvideonode_i420.h
@@ -45,6 +45,8 @@
#include <private/qsgvideonode_p.h>
#include <QtMultimedia/qvideosurfaceformat.h>
+QT_BEGIN_NAMESPACE
+
class QSGVideoMaterial_YUV420;
class QSGVideoNode_I420 : public QSGVideoNode
{
@@ -70,5 +72,6 @@ public:
QSGVideoNode *createNode(const QVideoSurfaceFormat &format);
};
+QT_END_NAMESPACE
#endif // QSGVIDEONODE_I420_H
diff --git a/src/imports/multimedia/qsgvideonode_rgb.cpp b/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp
index b0fb7dcf8..fbe60c9a7 100644
--- a/src/imports/multimedia/qsgvideonode_rgb.cpp
+++ b/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp
@@ -46,6 +46,8 @@
#include <QtGui/QOpenGLFunctions>
#include <QtGui/QOpenGLShaderProgram>
+QT_BEGIN_NAMESPACE
+
QList<QVideoFrame::PixelFormat> QSGVideoNodeFactory_RGB::supportedPixelFormats(
QAbstractVideoBuffer::HandleType handleType) const
{
@@ -283,3 +285,5 @@ void QSGVideoMaterialShader_RGB::updateState(const RenderState &state,
if (state.isMatrixDirty())
program()->setUniformValue(m_id_matrix, state.combinedMatrix());
}
+
+QT_END_NAMESPACE
diff --git a/src/imports/multimedia/qsgvideonode_rgb.h b/src/qtmultimediaquicktools/qsgvideonode_rgb.h
index ffec41955..141a00e9f 100644
--- a/src/imports/multimedia/qsgvideonode_rgb.h
+++ b/src/qtmultimediaquicktools/qsgvideonode_rgb.h
@@ -45,6 +45,8 @@
#include <private/qsgvideonode_p.h>
#include <QtMultimedia/qvideosurfaceformat.h>
+QT_BEGIN_NAMESPACE
+
class QSGVideoMaterial_RGB;
class QSGVideoNode_RGB : public QSGVideoNode
@@ -70,5 +72,6 @@ public:
QSGVideoNode *createNode(const QVideoSurfaceFormat &format);
};
+QT_END_NAMESPACE
#endif // QSGVIDEONODE_RGB_H
diff --git a/src/imports/multimedia/qsgvideonode_texture.cpp b/src/qtmultimediaquicktools/qsgvideonode_texture.cpp
index e0d9737b0..2320387b1 100644
--- a/src/imports/multimedia/qsgvideonode_texture.cpp
+++ b/src/qtmultimediaquicktools/qsgvideonode_texture.cpp
@@ -46,6 +46,8 @@
#include <QtGui/QOpenGLFunctions>
#include <QtGui/QOpenGLShaderProgram>
+QT_BEGIN_NAMESPACE
+
QList<QVideoFrame::PixelFormat> QSGVideoNodeFactory_Texture::supportedPixelFormats(
QAbstractVideoBuffer::HandleType handleType) const
{
@@ -265,3 +267,5 @@ void QSGVideoMaterialShader_Texture::updateState(const RenderState &state,
if (state.isMatrixDirty())
program()->setUniformValue(m_id_matrix, state.combinedMatrix());
}
+
+QT_END_NAMESPACE
diff --git a/src/imports/multimedia/qsgvideonode_texture.h b/src/qtmultimediaquicktools/qsgvideonode_texture.h
index 8d369ebc1..42dadbcbb 100644
--- a/src/imports/multimedia/qsgvideonode_texture.h
+++ b/src/qtmultimediaquicktools/qsgvideonode_texture.h
@@ -45,6 +45,8 @@
#include <private/qsgvideonode_p.h>
#include <QtMultimedia/qvideosurfaceformat.h>
+QT_BEGIN_NAMESPACE
+
class QSGVideoMaterial_Texture;
class QSGVideoNode_Texture : public QSGVideoNode
@@ -70,5 +72,6 @@ public:
QSGVideoNode *createNode(const QVideoSurfaceFormat &format);
};
+QT_END_NAMESPACE
#endif
diff --git a/src/qtmultimediaquicktools/qtmultimediaquicktools.pro b/src/qtmultimediaquicktools/qtmultimediaquicktools.pro
index da4d0dc1a..6fd38be86 100644
--- a/src/qtmultimediaquicktools/qtmultimediaquicktools.pro
+++ b/src/qtmultimediaquicktools/qtmultimediaquicktools.pro
@@ -11,10 +11,24 @@ DEFINES += QT_BUILD_QTMM_QUICK_LIB
INCLUDEPATH += ../multimedia/qtmultimediaquicktools_headers/
PRIVATE_HEADERS += \
+ ../multimedia/qtmultimediaquicktools_headers/qdeclarativevideooutput_p.h \
+ ../multimedia/qtmultimediaquicktools_headers/qdeclarativevideooutput_backend_p.h \
../multimedia/qtmultimediaquicktools_headers/qsgvideonode_p.h \
../multimedia/qtmultimediaquicktools_headers/qtmultimediaquickdefs_p.h
SOURCES += \
- qsgvideonode_p.cpp
+ qsgvideonode_p.cpp \
+ qdeclarativevideooutput.cpp \
+ qdeclarativevideooutput_render.cpp \
+ qdeclarativevideooutput_window.cpp \
+ qsgvideonode_i420.cpp \
+ qsgvideonode_rgb.cpp \
+ qsgvideonode_texture.cpp
-HEADERS += $$PRIVATE_HEADERS
+HEADERS += \
+ $$PRIVATE_HEADERS \
+ qdeclarativevideooutput_render_p.h \
+ qdeclarativevideooutput_window_p.h \
+ qsgvideonode_i420.h \
+ qsgvideonode_rgb.h \
+ qsgvideonode_texture.h
diff --git a/tests/auto/integration/qdeclarativevideooutput/qdeclarativevideooutput.pro b/tests/auto/integration/qdeclarativevideooutput/qdeclarativevideooutput.pro
index b9be929ea..573e5559e 100644
--- a/tests/auto/integration/qdeclarativevideooutput/qdeclarativevideooutput.pro
+++ b/tests/auto/integration/qdeclarativevideooutput/qdeclarativevideooutput.pro
@@ -3,9 +3,6 @@ TARGET = tst_qdeclarativevideooutput
QT += multimedia-private qml testlib quick
CONFIG += testcase
-OTHER_FILES += \
- ../../../../src/imports/multimedia/qdeclarativevideooutput_p.h
-
SOURCES += \
tst_qdeclarativevideooutput.cpp
diff --git a/tests/auto/integration/qdeclarativevideooutput/tst_qdeclarativevideooutput.cpp b/tests/auto/integration/qdeclarativevideooutput/tst_qdeclarativevideooutput.cpp
index 05c507f25..5ee2481f4 100644
--- a/tests/auto/integration/qdeclarativevideooutput/tst_qdeclarativevideooutput.cpp
+++ b/tests/auto/integration/qdeclarativevideooutput/tst_qdeclarativevideooutput.cpp
@@ -46,7 +46,7 @@
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
-#include "qdeclarativevideooutput_p.h"
+#include "private/qdeclarativevideooutput_p.h"
#include <qabstractvideosurface.h>
#include <qvideorenderercontrol.h>
diff --git a/tests/auto/integration/qdeclarativevideooutput_window/qdeclarativevideooutput_window.pro b/tests/auto/integration/qdeclarativevideooutput_window/qdeclarativevideooutput_window.pro
index 3cc5e0980..655fbc7b9 100644
--- a/tests/auto/integration/qdeclarativevideooutput_window/qdeclarativevideooutput_window.pro
+++ b/tests/auto/integration/qdeclarativevideooutput_window/qdeclarativevideooutput_window.pro
@@ -3,9 +3,6 @@ TARGET = tst_qdeclarativevideooutput_window
QT += multimedia-private qml testlib quick
CONFIG += testcase
-OTHER_FILES += \
- ../../../../src/imports/multimedia/qdeclarativevideooutput_p.h
-
SOURCES += \
tst_qdeclarativevideooutput_window.cpp
diff --git a/tests/auto/integration/qdeclarativevideooutput_window/tst_qdeclarativevideooutput_window.cpp b/tests/auto/integration/qdeclarativevideooutput_window/tst_qdeclarativevideooutput_window.cpp
index b4bcd5045..97a441ae5 100644
--- a/tests/auto/integration/qdeclarativevideooutput_window/tst_qdeclarativevideooutput_window.cpp
+++ b/tests/auto/integration/qdeclarativevideooutput_window/tst_qdeclarativevideooutput_window.cpp
@@ -42,7 +42,7 @@
//TESTED_COMPONENT=plugins/declarative/multimedia
-#include "qdeclarativevideooutput_p.h"
+#include "private/qdeclarativevideooutput_p.h"
#include <QtCore/qobject.h>
#include <QtTest/qtest.h>
#include <QtQml/qqmlengine.h>