|
|
|
@ -1,50 +1,8 @@
|
|
|
|
#include "yuvglwidget.h"
|
|
|
|
#include <QOpenGLShaderProgram>
|
|
|
|
|
|
|
|
|
|
|
|
YUVGLWidget::YUVGLWidget(QWidget *parent) :
|
|
|
|
|
|
|
|
QOpenGLWidget(parent)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// 设置opengl兼容性格式为CoreProfile
|
|
|
|
|
|
|
|
QSurfaceFormat defaultFormat = QSurfaceFormat::defaultFormat();
|
|
|
|
|
|
|
|
defaultFormat.setProfile(QSurfaceFormat::CoreProfile);
|
|
|
|
|
|
|
|
defaultFormat.setVersion(3, 3); // Adapt to your system
|
|
|
|
|
|
|
|
QSurfaceFormat::setDefaultFormat(defaultFormat);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setFormat(defaultFormat);
|
|
|
|
#include "yuvglwidget.h"
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
YUVGLWidget::~YUVGLWidget()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
makeCurrent();
|
|
|
|
|
|
|
|
if (y_tex) glDeleteTextures(1, &y_tex);
|
|
|
|
|
|
|
|
if (u_tex) glDeleteTextures(1, &u_tex);
|
|
|
|
|
|
|
|
if (v_tex) glDeleteTextures(1, &v_tex);
|
|
|
|
|
|
|
|
doneCurrent();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QSize YUVGLWidget::minimumSizeHint() const
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return QSize(50, 50);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QSize YUVGLWidget::sizeHint() const
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return QSize(3840, 2160); // 4k video
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void YUVGLWidget::setFrameSize(unsigned int width, unsigned int height)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_frameWidth = width;
|
|
|
|
|
|
|
|
m_frameHeight = height;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void YUVGLWidget::initializeGL()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
initializeOpenGLFunctions();
|
|
|
|
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
initializeTextures();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QString vert = R"(
|
|
|
|
static QString vertShader = R"(
|
|
|
|
#version 150 core
|
|
|
|
#version 150 core
|
|
|
|
uniform mat4 u_pm;
|
|
|
|
uniform mat4 u_pm;
|
|
|
|
uniform vec4 draw_pos;
|
|
|
|
uniform vec4 draw_pos;
|
|
|
|
@ -75,7 +33,7 @@ void YUVGLWidget::initializeGL()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)";
|
|
|
|
)";
|
|
|
|
|
|
|
|
|
|
|
|
QString frag = R"(
|
|
|
|
static QString fragShader = R"(
|
|
|
|
#version 150 core
|
|
|
|
#version 150 core
|
|
|
|
uniform sampler2D y_tex;
|
|
|
|
uniform sampler2D y_tex;
|
|
|
|
uniform sampler2D u_tex;
|
|
|
|
uniform sampler2D u_tex;
|
|
|
|
@ -101,23 +59,49 @@ void YUVGLWidget::initializeGL()
|
|
|
|
fragcolor.b = dot(yuv, B_cf);
|
|
|
|
fragcolor.b = dot(yuv, B_cf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)";
|
|
|
|
)";
|
|
|
|
// Setup shaders
|
|
|
|
|
|
|
|
m_program.addShaderFromSourceCode(QOpenGLShader::Vertex, vert);
|
|
|
|
|
|
|
|
m_program.addShaderFromSourceCode(QOpenGLShader::Fragment, frag);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// m_program.bindAttributeLocation("y_tex", 0);
|
|
|
|
YUVGLWidget::YUVGLWidget(QWidget *parent) :
|
|
|
|
// m_program.bindAttributeLocation("u_tex", 1);
|
|
|
|
QOpenGLWidget(parent)
|
|
|
|
// m_program.bindAttributeLocation("v_tex", 2);
|
|
|
|
{
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
// 设置opengl兼容性格式为CoreProfile
|
|
|
|
|
|
|
|
QSurfaceFormat defaultFormat = QSurfaceFormat::defaultFormat();
|
|
|
|
|
|
|
|
defaultFormat.setProfile(QSurfaceFormat::CoreProfile);
|
|
|
|
|
|
|
|
defaultFormat.setVersion(3, 3); // Adapt to your system
|
|
|
|
|
|
|
|
QSurfaceFormat::setDefaultFormat(defaultFormat);
|
|
|
|
|
|
|
|
setFormat(defaultFormat);
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_program.link();
|
|
|
|
YUVGLWidget::~YUVGLWidget()
|
|
|
|
m_program.bind();
|
|
|
|
{
|
|
|
|
|
|
|
|
makeCurrent();
|
|
|
|
|
|
|
|
deInitTextures();
|
|
|
|
|
|
|
|
doneCurrent();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_program.setUniformValue("y_tex", 0);
|
|
|
|
QSize YUVGLWidget::minimumSizeHint() const
|
|
|
|
m_program.setUniformValue("u_tex", 1);
|
|
|
|
{
|
|
|
|
m_program.setUniformValue("v_tex", 2);
|
|
|
|
return QSize(50, 50);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
u_pos = m_program.uniformLocation("draw_pos");
|
|
|
|
QSize YUVGLWidget::sizeHint() const
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return size();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void YUVGLWidget::setFrameSize(const QSize& frameSize)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (m_frameSize != frameSize) {
|
|
|
|
|
|
|
|
m_frameSize = frameSize;
|
|
|
|
|
|
|
|
m_needInit = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void YUVGLWidget::initializeGL()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
initializeOpenGLFunctions();
|
|
|
|
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
m_vao.create();
|
|
|
|
m_vao.create();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -125,86 +109,120 @@ void YUVGLWidget::paintGL()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// init
|
|
|
|
|
|
|
|
if (m_needInit) {
|
|
|
|
|
|
|
|
initShader();
|
|
|
|
|
|
|
|
initTextures();
|
|
|
|
|
|
|
|
m_needInit = false;
|
|
|
|
|
|
|
|
}
|
|
|
|
m_vao.bind();
|
|
|
|
m_vao.bind();
|
|
|
|
|
|
|
|
if (m_program) {
|
|
|
|
QMatrix4x4 m;
|
|
|
|
QMatrix4x4 matrix;
|
|
|
|
m.ortho(0, width(), height(), 0, 0.0, 100.0f);
|
|
|
|
matrix.ortho(0, width(), height(), 0, 0.0, 100.0f);
|
|
|
|
|
|
|
|
m_program->setUniformValue("u_pm", matrix);
|
|
|
|
m_program.setUniformValue("u_pm", m);
|
|
|
|
glUniform4f(m_drawPos, 0, 0, width(), height());
|
|
|
|
|
|
|
|
}
|
|
|
|
glUniform4f(u_pos, 0, 0, width(), height());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, y_tex);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, m_texture[Texture_Y]);
|
|
|
|
|
|
|
|
|
|
|
|
glActiveTexture(GL_TEXTURE1);
|
|
|
|
glActiveTexture(GL_TEXTURE1);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, u_tex);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, m_texture[Texture_U]);
|
|
|
|
|
|
|
|
|
|
|
|
glActiveTexture(GL_TEXTURE2);
|
|
|
|
glActiveTexture(GL_TEXTURE2);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, v_tex);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, m_texture[Texture_V]);
|
|
|
|
|
|
|
|
|
|
|
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
|
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void YUVGLWidget::resizeGL(int width, int height)
|
|
|
|
void YUVGLWidget::setYPixels(uint8_t* pixels, int stride)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
bindPixelTexture(y_tex, YTexture, pixels, stride);
|
|
|
|
glViewport(0, 0, width, height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void YUVGLWidget::setUPixels(uint8_t* pixels, int stride)
|
|
|
|
void YUVGLWidget::initShader()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
bindPixelTexture(u_tex, UTexture, pixels, stride);
|
|
|
|
if (m_program) {
|
|
|
|
|
|
|
|
m_program->release();
|
|
|
|
|
|
|
|
delete m_program;
|
|
|
|
|
|
|
|
m_program = Q_NULLPTR;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
m_program = new QOpenGLShaderProgram(this);
|
|
|
|
|
|
|
|
// Setup shaders
|
|
|
|
|
|
|
|
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertShader);
|
|
|
|
|
|
|
|
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragShader);
|
|
|
|
|
|
|
|
m_program->link();
|
|
|
|
|
|
|
|
m_program->bind();
|
|
|
|
|
|
|
|
m_program->setUniformValue("y_tex", Texture_Y);
|
|
|
|
|
|
|
|
m_program->setUniformValue("u_tex", Texture_U);
|
|
|
|
|
|
|
|
m_program->setUniformValue("v_tex", Texture_V);
|
|
|
|
|
|
|
|
m_drawPos = m_program->uniformLocation("draw_pos");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void YUVGLWidget::setVPixels(uint8_t* pixels, int stride)
|
|
|
|
void YUVGLWidget::updateTextures(quint8 *dataY, quint8 *dataU, quint8 *dataV, quint32 linesizeY, quint32 linesizeU, quint32 linesizeV)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
bindPixelTexture(v_tex, VTexture, pixels, stride);
|
|
|
|
bindPixelTexture(m_texture[Texture_Y], Texture_Y, dataY, linesizeY);
|
|
|
|
|
|
|
|
bindPixelTexture(m_texture[Texture_U], Texture_U, dataU, linesizeU);
|
|
|
|
|
|
|
|
bindPixelTexture(m_texture[Texture_V], Texture_V, dataV, linesizeV);
|
|
|
|
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void YUVGLWidget::bindPixelTexture(GLuint texture, YUVTextureType textureType, quint8* pixels, quint32 stride)
|
|
|
|
void YUVGLWidget::initializeTextures()
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
//TODO: use FBO?
|
|
|
|
if (!pixels)
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
// Setup textures
|
|
|
|
QSize size(0, 0);
|
|
|
|
glGenTextures(1, &y_tex);
|
|
|
|
calcTextureSize(textureType, size);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, y_tex);
|
|
|
|
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
|
|
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
|
|
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, m_frameWidth, m_frameHeight, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
glGenTextures(1, &u_tex);
|
|
|
|
makeCurrent();
|
|
|
|
glBindTexture(GL_TEXTURE_2D, u_tex);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size.width(), size.height(), GL_RED, GL_UNSIGNED_BYTE, pixels);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
|
|
doneCurrent();
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
|
|
}
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, m_frameWidth/2, m_frameHeight/2, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
glGenTextures(1, &v_tex);
|
|
|
|
void YUVGLWidget::initTexture(qint32 textureType)
|
|
|
|
glBindTexture(GL_TEXTURE_2D, v_tex);
|
|
|
|
{
|
|
|
|
|
|
|
|
if (Texture_NULL >= textureType || Texture_Size <= textureType) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
glGenTextures(1, &m_texture[textureType]);
|
|
|
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, m_texture[textureType]);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, m_frameWidth/2, m_frameHeight/2, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
|
|
|
|
|
|
|
|
|
|
|
|
QSize size(0, 0);
|
|
|
|
|
|
|
|
calcTextureSize(textureType, size);
|
|
|
|
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, size.width(), size.height(), 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void YUVGLWidget::bindPixelTexture(GLuint texture, YUVGLWidget::YUVTextureType textureType, uint8_t* pixels, int stride)
|
|
|
|
void YUVGLWidget::initTextures()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (!pixels)
|
|
|
|
//TODO: use FBO?
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int const width = textureType == YTexture ? m_frameWidth : m_frameWidth/2;
|
|
|
|
deInitTextures();
|
|
|
|
unsigned int const height = textureType == YTexture ? m_frameHeight : m_frameHeight/2;
|
|
|
|
for (int i = Texture_Y; i < Texture_Size; i++) {
|
|
|
|
|
|
|
|
initTexture(i);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
makeCurrent();
|
|
|
|
void YUVGLWidget::deInitTextures()
|
|
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
|
|
{
|
|
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
|
|
|
|
glDeleteTextures(3, m_texture);
|
|
|
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, pixels);
|
|
|
|
memset(m_texture, 0, Texture_Size);
|
|
|
|
//glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, m_frameWidth/2, m_frameHeight/2, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
|
|
|
|
}
|
|
|
|
doneCurrent();
|
|
|
|
|
|
|
|
|
|
|
|
void YUVGLWidget::calcTextureSize(qint32 textureType, QSize &size)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (Texture_NULL >= textureType || Texture_Size <= textureType) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Texture_Y == textureType) {
|
|
|
|
|
|
|
|
size = m_frameSize;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
size = m_frameSize / 2;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|