【开源项目】QT OPENGL 与 shader 绘制展示视频代码实例 OPenGL直接显示YUV数据
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                【开源项目】QT OPENGL 与 shader 绘制展示视频代码实例 OPenGL直接显示YUV数据
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                本文使用QT中的QOpenGLFunctions(此類封裝了OPenGL的方法,相當于QT版OPenGL)
其次重載?void paintGL();? ?void initializeGL();? void resizeGL(int width, int height);是基本操作
 ?* 三種GLSL變量說明
 ?* varying 頂點與片元共享
 ?* attribute 頂點使用,由bindAttributeLocation傳入
 ?* uniform 程序傳入,uniformLocation獲取地址
XvideoWidget.h
#pragma once#include <QOpenGLWidget> #include<QOpenGLFunctions> #include<QGLShaderProgram>class XvideoWidget : public QOpenGLWidget,protected QOpenGLFunctions {Q_OBJECTpublic:XvideoWidget(QWidget *parent);~XvideoWidget();protected://重載//刷新顯示void paintGL();//初始化GLvoid initializeGL();//窗口尺寸變化void resizeGL(int width, int height);private://shader程序QGLShaderProgram program;//shader中yuv變量地址GLuint unis[3] = { 0 };//openg的 texture地址GLuint texs[3] = { 0 };//材質內存空間unsigned char *datas[3] = { 0 };int width = 352;int height = 288;};XvideoWidget.cpp
#include "XvideoWidget.h" #include <QDebug> #include <QTimer> //自動加雙引號 #define GET_STR(x) #x #define A_VER 3 #define T_VER 4FILE *fp = NULL;//頂點shader const char *vString = GET_STR( attribute vec4 vertexIn; //頂點坐標 attribute vec2 textureIn; //材質坐標 varying vec2 textureOut; //頂點shader片元shader共享 void main(void) {gl_Position = vertexIn;textureOut = textureIn; } );//片元shader const char *tString = GET_STR( varying vec2 textureOut; uniform sampler2D tex_y; uniform sampler2D tex_u; uniform sampler2D tex_v; void main(void) {vec3 rgb;vec3 yuv;yuv.x = texture2D(tex_y, textureOut).r;yuv.y = texture2D(tex_u, textureOut).r - 0.5;yuv.z = texture2D(tex_v, textureOut).r - 0.5;//YUV轉RGB固定公式,利用矩陣轉換rgb = mat3(1.0, 1.0, 1.0,0.0, -0.39465, 2.03211,1.13983, -0.58060, 0.0) * yuv;gl_FragColor = vec4(rgb, 1.0); });//準備yuv數據 // ffmpeg -i v1080.mp4 -t 10 -s 240x128 -pix_fmt yuv420p out240x128.yuv XvideoWidget::XvideoWidget(QWidget *parent): QOpenGLWidget(parent) { }XvideoWidget::~XvideoWidget() { }//初始化opengl void XvideoWidget::initializeGL() {qDebug() << "initializeGL";//初始化opengl (QOpenGLFunctions繼承)函數 initializeOpenGLFunctions();//program加載shader(頂點和片元)腳本//片元(像素)qDebug() << program.addShaderFromSourceCode(QGLShader::Fragment, tString);//頂點shaderqDebug() << program.addShaderFromSourceCode(QGLShader::Vertex, vString);//設置頂點坐標的變量program.bindAttributeLocation("vertexIn", A_VER);//設置材質坐標program.bindAttributeLocation("textureIn", T_VER);//編譯shaderqDebug() << "program.link() = " << program.link();qDebug() << "program.bind() = " << program.bind();//傳遞頂點和材質坐標//頂點static const GLfloat ver[] = {-1.0f,-1.0f,1.0f,-1.0f,-1.0f, 1.0f,1.0f,1.0f};//材質static const GLfloat tex[] = {0.0f, 1.0f,1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f};//頂點glVertexAttribPointer(A_VER, 2, GL_FLOAT, 0, 0, ver);glEnableVertexAttribArray(A_VER);//材質glVertexAttribPointer(T_VER, 2, GL_FLOAT, 0, 0, tex);glEnableVertexAttribArray(T_VER);//從shader獲取材質unis[0] = program.uniformLocation("tex_y");unis[1] = program.uniformLocation("tex_u");unis[2] = program.uniformLocation("tex_v");//創建材質,創建三個對象glGenTextures(3, texs);//Y 綁定材質glBindTexture(GL_TEXTURE_2D, texs[0]);//放大過濾,線性插值 GL_NEAREST(效率高,但馬賽克嚴重)glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//創建材質顯卡空間glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, 0);//UglBindTexture(GL_TEXTURE_2D, texs[1]);//放大過濾,線性插值glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//創建材質顯卡空間glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width / 2, height / 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0);//VglBindTexture(GL_TEXTURE_2D, texs[2]);//放大過濾,線性插值glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//創建材質顯卡空間glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width / 2, height / 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0);///分配材質內存空間datas[0] = new unsigned char[width*height]; //Ydatas[1] = new unsigned char[width*height / 4]; //Udatas[2] = new unsigned char[width*height / 4]; //Vfp = fopen("VIDEO2.yuv", "rb");if (!fp){qDebug() << "VIDEO2.yuv file open failed!";}//啟動定時器QTimer *ti = new QTimer(this);connect(ti, SIGNAL(timeout()), this, SLOT(update()));ti->start(40); }//刷新顯示 void XvideoWidget::paintGL() {if (feof(fp)){fseek(fp, 0, SEEK_SET);}fread(datas[0], 1, width*height, fp);fread(datas[1], 1, width*height / 4, fp);fread(datas[2], 1, width*height / 4, fp);glActiveTexture(GL_TEXTURE0);//激活第0層glBindTexture(GL_TEXTURE_2D, texs[0]); //0層綁定到Y材質//修改材質內容(復制內存內容)glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, datas[0]);//與shader uni遍歷關聯glUniform1i(unis[0], 0);//0表示對應0層glActiveTexture(GL_TEXTURE0 + 1);glBindTexture(GL_TEXTURE_2D, texs[1]); //1層綁定到U材質//修改材質內容(復制內存內容)glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_RED, GL_UNSIGNED_BYTE, datas[1]);//與shader uni遍歷關聯glUniform1i(unis[1], 1);glActiveTexture(GL_TEXTURE0 + 2);glBindTexture(GL_TEXTURE_2D, texs[2]); //2層綁定到V材質//修改材質內容(復制內存內容)glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_RED, GL_UNSIGNED_BYTE, datas[2]);//與shader uni遍歷關聯glUniform1i(unis[2], 2);glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);qDebug() << "paintGL"; }// 窗口尺寸變化 void XvideoWidget::resizeGL(int width, int height) {qDebug() << "resizeGL " << width << ":" << height; }本文配套開源項目
總結
以上是生活随笔為你收集整理的【开源项目】QT OPENGL 与 shader 绘制展示视频代码实例 OPenGL直接显示YUV数据的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 【开源项目】QT播放PCM音频实例详细
 - 下一篇: Ubuntu下如何正确安装FFmpeg