summaryrefslogtreecommitdiffstats
path: root/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp
diff options
context:
space:
mode:
authorTomasz Olszak <olszak.tomasz@gmail.com>2017-06-13 11:24:47 +0200
committerVaL Doroshchuk <valentyn.doroshchuk@qt.io>2018-01-15 08:39:28 +0000
commitd58b6b908ea130e9422b08b5b3b460b48da7d337 (patch)
tree3c0edf6f46ea880a451dd975125649527ee8d288 /src/qtmultimediaquicktools/qsgvideonode_yuv.cpp
parentb9440a3047cfca9ae253e850db31b8e9b08538e7 (diff)
Improve quality of YUVY and UYVY rendering
Idea is to upload YUYV/UYVY data as 2 textures and use GL_LINEAR like in biplanar formats. Having proper interpolation of only one texture (using e.g. mix function) resulted in vertical and horizontal 1 pixel stripes depending on scale. The reason was float precision and unexpected value of fract function. Additionally branching in shader is expensive so this solution should be more performant. Task-number: QTBUG-62155 Change-Id: I7ceeb09b4a54eecd16640a626b499d638b52c127 Reviewed-by: Christian Stromme <christian.stromme@qt.io>
Diffstat (limited to 'src/qtmultimediaquicktools/qsgvideonode_yuv.cpp')
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_yuv.cpp32
1 files changed, 19 insertions, 13 deletions
diff --git a/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp b/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp
index 38b5af943..b04c6b38b 100644
--- a/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp
+++ b/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp
@@ -134,16 +134,16 @@ public:
protected:
void initialize() Q_DECL_OVERRIDE {
m_id_matrix = program()->uniformLocation("qt_Matrix");
- m_id_yuvtexture = program()->uniformLocation("yuvTexture");
- m_id_imageWidth = program()->uniformLocation("imageWidth");
+ m_id_yTexture = program()->uniformLocation("yTexture");
+ m_id_uvTexture = program()->uniformLocation("uvTexture");
m_id_colorMatrix = program()->uniformLocation("colorMatrix");
m_id_opacity = program()->uniformLocation("opacity");
QSGMaterialShader::initialize();
}
int m_id_matrix;
- int m_id_yuvtexture;
- int m_id_imageWidth;
+ int m_id_yTexture;
+ int m_id_uvTexture;
int m_id_colorMatrix;
int m_id_opacity;
};
@@ -291,7 +291,7 @@ QSGVideoMaterial_YUV::QSGVideoMaterial_YUV(const QVideoSurfaceFormat &format) :
case QVideoFrame::Format_UYVY:
case QVideoFrame::Format_YUYV:
default:
- m_planeCount = 1;
+ m_planeCount = 2;
break;
}
@@ -355,12 +355,19 @@ void QSGVideoMaterial_YUV::bind()
if (m_format.pixelFormat() == QVideoFrame::Format_UYVY
|| m_format.pixelFormat() == QVideoFrame::Format_YUYV) {
- int fw = m_frame.width() / 2;
+ int fw = m_frame.width();
m_planeWidth[0] = fw;
-
- functions->glActiveTexture(GL_TEXTURE0);
- bindTexture(m_textureIds[0], fw, m_frame.height(), m_frame.bits(), GL_RGBA);
-
+ // In YUYV texture the UV plane appears with the 1/2 of image and Y width.
+ m_planeWidth[1] = fw / 2;
+ functions->glActiveTexture(GL_TEXTURE1);
+ // Either r,b (YUYV) or g,a (UYVY) values are used as source of YV.
+ // Additionally Y and V are set per 2 pixels hence only 1/2 of image with is used.
+ // Interpreting this properly in shaders allows to not copy or not make conditionals inside shaders,
+ // only interpretation of data changes.
+ bindTexture(m_textureIds[1], m_planeWidth[1], m_frame.height(), m_frame.bits(), GL_RGBA);
+ functions->glActiveTexture(GL_TEXTURE0); // Finish with 0 as default texture unit
+ // Either red (YUYV) or alpha (UYVY) values are used as source of Y
+ bindTexture(m_textureIds[0], m_planeWidth[0], m_frame.height(), m_frame.bits(), GL_LUMINANCE_ALPHA);
} else if (m_format.pixelFormat() == QVideoFrame::Format_NV12
|| m_format.pixelFormat() == QVideoFrame::Format_NV21) {
const int y = 0;
@@ -473,13 +480,12 @@ void QSGVideoMaterialShader_UYVY::updateState(const RenderState &state,
Q_UNUSED(oldMaterial);
QSGVideoMaterial_YUV *mat = static_cast<QSGVideoMaterial_YUV *>(newMaterial);
-
- program()->setUniformValue(m_id_yuvtexture, 0);
+ program()->setUniformValue(m_id_yTexture, 0);
+ program()->setUniformValue(m_id_uvTexture, 1);
mat->bind();
program()->setUniformValue(m_id_colorMatrix, mat->m_colorMatrix);
- program()->setUniformValue(m_id_imageWidth, mat->m_frame.width());
if (state.isOpacityDirty()) {
mat->m_opacity = state.opacity();