昨天花了一天的時間來整理這塊的業務,因爲自己做QT的時間也不長.
上來我們就直接說重點了:
首先在pro文件中,我們必須指定使用opengl庫:
QT += opengl
LIBS += -L./libs -lopengl32
在QT中我是直接創建了一個控件,讓這個控件繼承QOpenGLWidget。
同時還必須繼承QOpenGLFunctions,這樣我們就可以使用: opengl 的相關 functions功能,比如glViewport等等.
#ifndef YUVGLWEIGHT_H
#define YUVGLWEIGHT_H
#include <QtWidgets/QOpenGLWidget>
#include <QOpenGLShaderProgram>
#include <QGLShader>
#include <QOpenGLFunctions>
#include <QOpenGLContext>
class YUVGLWeight : public QOpenGLWidget ,QOpenGLFunctions
{
Q_OBJECT
public:
explicit YUVGLWeight(QWidget *parent = nullptr);
protected:
virtual void initializeGL();
virtual void resizeGL(int w, int h);
virtual void paintGL();
private:
int screen_w;
int screen_h;
QOpenGLContext *context_;
QOpenGLShaderProgram program_;
GLuint attr_pos;
GLuint attr_uv;
GLuint sam_y;
GLuint sam_u;
GLuint sam_v;
GLuint samplerConvertMatrix;
//for test
GLuint sam_rgb;
GLuint textures_[3];
// 類是用來繼承的,不是用來進行初始化的
// QOpenGLFunctions glFunctions_;
//解碼成功後的寬高
int srcW_ = 352,srcH_ = 288;
signals:
public slots:
};
#endif // YUVGLWEIGHT_H
再看實現類,我們實現類的目的是把yuv渲染出來:
#include "yuvglweight.h"
#include <QDebug>
#include <QGLFormat>
#include <QtOpenGL>
const char *vertexShaderStr =
"attribute vec3 position; \n"
"attribute vec2 texcoord; \n"
"varying vec2 v_texcoord; \n"
"void main() \n"
"{ \n"
" v_texcoord = texcoord ; \n"
" gl_Position = vec4(position , 1.0) ; \n"
"} \n"
;
const char *fragShaderStr =
"varying vec2 v_texcoord; \n"
"uniform sampler2D y_sampler; \n"
"uniform sampler2D u_sampler; \n"
"uniform sampler2D v_sampler; \n"
"uniform mat3 colorConversionMatrix; \n"
"uniform sampler2D rgb_sampler; \n"
"void main() \n"
"{ \n"
// " vec3 yuv; \n"
// " vec3 rgb; \n"
// " yuv.x = texture2D(y_sampler,v_texcoord).r - (16.0/255.0); \n"
// " yuv.yz = texture2D(u_sampler,v_texcoord).rg - vec2(0.5,0.5); \n"
// " rgb = colorConversionMatrix * yuv; \n"
// " gl_FragColor = vec4(rgb,1.0); \n"
// // " gl_FragColor = vec4( texture2D(rgb_sampler,v_texcoord).rgb , 1.0 ); \n"
" float y,u,v,r,g,b; \n"
" y = texture2D(y_sampler,v_texcoord).r; \n"
" u = texture2D(u_sampler,v_texcoord).r; \n"
" v = texture2D(v_sampler,v_texcoord).r; \n"
" y = 1.16438355 * (y - 0.0625); \n"
" u = u - 0.5; \n"
" v = v - 0.5; \n"
" r = clamp(y + 1.596 * v, 0.0, 1.0); \n"
" g = clamp(y - 0.391 * u - 0.813 * v, 0.0, 1.0); \n"
" b = clamp(y + 2.018 * u, 0.0, 1.0); \n"
" gl_FragColor = vec4(r,g,b,1.0) ; \n"
"} \n"
;
YUVGLWeight::YUVGLWeight(QWidget *parent) : QOpenGLWidget(parent)
{
}
void YUVGLWeight::initializeGL()
{
//初始化opengl模塊
QGLFormat format;
format.setVersion(2,2);
format.setProfile(QGLFormat::CoreProfile);
initializeOpenGLFunctions();
// context_ = new QOpenGLContext();
// context_->create();
// context_->makeCurrent(this);
//1.編譯shader模塊
program_.addShaderFromSourceCode(QOpenGLShader::Vertex,vertexShaderStr);
program_.addShaderFromSourceCode(QOpenGLShader::Fragment,fragShaderStr);
program_.link();
program_.bind();
attr_pos = program_.attributeLocation("position");
attr_uv = program_.attributeLocation("texcoord");
sam_y = program_.uniformLocation("y_sampler");
sam_u = program_.uniformLocation("u_sampler");
sam_v = program_.uniformLocation("v_sampler");
samplerConvertMatrix = program_.uniformLocation("colorConversionMatrix");
sam_rgb = program_.uniformLocation("rgb_sampler");
qDebug() << "position :" << attr_pos ;
qDebug() << "texcoord_ :" << attr_uv ;
qDebug() << "sam y_:"<< sam_y ;
qDebug() << "sam_u:" << sam_u ;
qDebug() << "sam_v:" << sam_v ;
qDebug() << "convert matrix:" << samplerConvertMatrix ;
//讀取yuv的數據
uint8_t * pbuf = new uint8_t [srcW_ * srcH_ * 3 / 2] ;
FILE *fs = fopen("d://akiyo_cif.yuv" , "rb+");
fread(pbuf,srcW_ * srcH_ * 3 / 2 , 1,fs);
fclose(fs);
glGenTextures(3,textures_);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,textures_[0]);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,srcW_,srcH_,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,pbuf);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D,textures_[1]);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,srcW_>>1,srcH_>>1,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,pbuf + srcW_ * srcH_);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D,textures_[2]);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,srcW_>>1,srcH_>>1,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,pbuf + srcW_ * srcH_ + srcW_ * srcH_ / 4);
delete[] pbuf;
pbuf = NULL;
glActiveTexture(0);
glBindTexture(GL_TEXTURE_2D,0);
}
void YUVGLWeight::resizeGL(int w, int h)
{
screen_w = w;
screen_h = h;
qDebug()<< "resize gl:" << w ;
}
void YUVGLWeight::paintGL()
{
glClearColor(1.0f,0.0f,0.0f,1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0,0,screen_w,screen_h);
qDebug() << "program object:" << program_.programId() ;
glUseProgram(program_.programId());
GLfloat arrays[6 * 5] =
{
//第一個三角形 -- 逆時針
-1.0f,-1.0f,0.0f , 0.0f,1.0f , // bottom left
1.0f ,-1.0f,0.0f , 1.0f,1.0f , // bottom right
1.0f,1.0f,0.0f, 1.0f,0.0f , // top right
// 第二個三角形
1.0f,1.0f,0.0f, 1.0f,0.0f , // top right
-1.0f,1.0f,0.0f, 0.0f,0.0f ,// top left
-1.0f,-1.0f,0.0f , 0.0f,1.0f , // bottom left
};
glEnableVertexAttribArray(attr_pos);
glVertexAttribPointer(
attr_pos ,
3,
GL_FLOAT,
GL_FALSE,
5 * sizeof( GL_FLOAT ) ,
arrays);
glEnableVertexAttribArray(attr_uv);
glVertexAttribPointer(
attr_uv ,
2,
GL_FLOAT,
GL_FALSE,
5 * sizeof( GL_FLOAT ) ,
&arrays[3] ); //注意這裏千萬不要使用: arrays + 3 * sizeof(GLFloat),因爲arrays的是float類型,移位的時候,是按float進行移位的.
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,textures_[0]);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D,textures_[1]);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D,textures_[2]);
const GLfloat kColorConversion709[] = {
1.164f, 1.164f, 1.164f,
0.0f, -0.213f, 2.112f,
1.793f, -0.533f, 0.0f,
};
glUniform1i(sam_y,0);
glUniform1i(sam_u,1);
glUniform1i(sam_v,2);
glUniformMatrix3fv(samplerConvertMatrix, 1, GL_FALSE, kColorConversion709);
glUniform1i(sam_rgb , 2);
glDrawArrays(GL_TRIANGLES,0,6);
}
最終的渲染效果如下:
yuv圖片下載地址:
http://trace.eas.asu.edu/yuv/index.html