diff options
author | Yoann Lopes <yoann.lopes@digia.com> | 2014-01-30 14:32:29 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-01-30 14:32:29 +0100 |
commit | 67b86a9fbd87fb50e896bf66313c2f949501df5b (patch) | |
tree | 999c6c5c3b9f5c8961d17fd18cca35ff7db83edb /src | |
parent | 5980bc41cf55073e63236467466a59577d406937 (diff) | |
parent | 9459acf48eaa9326e58bb1658408d045482a573b (diff) | |
download | qtmultimedia-67b86a9fbd87fb50e896bf66313c2f949501df5b.tar.gz |
Merge "Merge remote-tracking branch 'origin/stable' into dev" into refs/staging/dev
Diffstat (limited to 'src')
39 files changed, 1356 insertions, 280 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 5f66dc748..d77217906 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 |