利用Qt + OpenGL 渲染 YUV数据,播放视频 mac版
2017-03-03 13:32
816 查看
最近利用Qt渲染YUV数据,折腾了很久,最开始使用FFmpeg将YUV数据转换成RGB数据后在用qt绘制,很快得到了成功,但是cpu占用率太大,最后放弃了。
在这先感谢来自文章http://blog.csdn.net/su_vast/article/details/52214642的作者,使用他的代码我实现了Windows上的YUV数据渲染。但是移植到mac上渲染不出来,经过折腾及对OpenGL的了解,发现问题出在OpenGL版本问题上,不同版本OpenGL的shader编写使用有些不同,资料来源于http://blog.csdn.net/ym19860303/article/details/44115135。
下面是我写的代码,有什么不完善的地方请读者反馈,相互学习。
renderview.h
#ifndef RENDERVIEW_H
#define RENDERVIEW_H
#include <QWidget>
#include <QOpenGLWidget>
#include <QGLContext>
#include <QGLWidget>
#include <QOpenGLTexture>
#include "global.h"
class RenderView : public QOpenGLWidget
{
Q_OBJECT
public:
RenderView(QWidget* parent = 0);
~RenderView();
void Render(unsigned char* buffer,int w, int h);
protected:
//virtual void paintEvent(QPaintEvent *event);
virtual void initializeGL();
virtual void resizeGL( int w, int h );
virtual void paintGL();
private:
GLuint prepareShaderProgram();
private:
GLuint m_shader;
GLuint m_vertexBuffer;
GLuint textureUniformY;
GLuint textureUniformU;
GLuint textureUniformV;
GLuint vertexBuffer;
GLuint vertextAttribute;
GLuint textureAttribute;
GLuint id_y;
GLuint id_u;
GLuint id_v;
int m_nVideoW;
int m_nVideoH;
int m_nViewW;
int m_nViewH;
unsigned char* m_pBufYuv420p;
unsigned char* m_pBuffer;
bool m_bStartPlay;
};
#endif // RENDERVIEW_H
renderview.cpp
#include "renderview.h"
#include <QPainter>
#include <QSurfaceFormat>
#include <QMutex>
#include <QDebug>
#include <QSurfaceFormat>
#include "DecoderCtrl/MainConcept.h"
#define BUFFER_MAX_SIZE 1920*1080+1024
const char *vsrc =
"#version 410\n"
"in vec4 vertexIn;\n"
"in vec2 textureIn;\n"
"out vec2 textureOut;\n"
"void main(void)\n"
"{\n"
" gl_Position = vertexIn;\n"
" textureOut = textureIn;\n"
"}";
const char *fsrc =
"#version 410\n"
"in vec2 textureOut;\n"
"out vec4 fragColor;\n"
"uniform sampler2D tex_y;\n"
"uniform sampler2D tex_u;\n"
"uniform sampler2D tex_v;\n"
"void main(void)\n"
"{\n"
" vec3 yuv;\n"
" vec3 rgb;\n"
" yuv.x = texture(tex_y, textureOut).r;\n"
" yuv.y = texture(tex_u, textureOut).r - 0.5;\n"
" yuv.z = texture(tex_v, textureOut).r - 0.5;\n"
" rgb = mat3( 1, 1, 1,\n"
" 0, -0.21482, 2.12798,\n"
" 1.28033, -0.38059, 0) * yuv;\n"
" fragColor = vec4(rgb, 1);\n"
"}";
void RenderYuv(unsigned char* yuvBuffer,int width, int height,void *pdate)
{
RenderView *render = (RenderView*)pdate;
if(render)
{
render->Render(yuvBuffer, width, height);
}
}
RenderView::RenderView(QWidget* parent) :
QOpenGLWidget(parent)
,m_pBufYuv420p(NULL)
,m_nVideoW(0)
,m_nVideoH(0)
,m_nViewW(0)
,m_nViewH(0)
,m_bStartPlay(false)
{
setAutoFillBackground(false);
MC_Codec_SetRenderNotify(RenderYuv, this);
m_pBufYuv420p = new unsigned char[BUFFER_MAX_SIZE];
memset(m_pBufYuv420p, 0, BUFFER_MAX_SIZE);
}
RenderView::~RenderView()
{
}
void RenderView::Render(unsigned char* buffer,int w, int h)
{
m_nVideoW = w;
m_nVideoH = h;
m_bStartPlay = true;
unsigned long bufLen = w*h*3/2;
m_pBufYuv420p = buffer;
memcpy(m_pBufYuv420p, buffer, bufLen);
update();
}
GLuint RenderView::prepareShaderProgram()
{
GLuint program = glCreateProgram();
//vertex shader
GLuint vertexShader = glCreateShader( GL_VERTEX_SHADER);
glShaderSource( vertexShader, 1, (const GLchar**)&vsrc, NULL );
glCompileShader( vertexShader );
GLint compiled;
glGetShaderiv( vertexShader, GL_COMPILE_STATUS, &compiled );
if ( !compiled ) {
GLint logSize;
glGetShaderiv( vertexShader, GL_INFO_LOG_LENGTH, &logSize );
char* logMsg = new char[logSize];
glGetShaderInfoLog( vertexShader, logSize, NULL, logMsg );
qWarning() << logMsg;
delete [] logMsg;
exit( EXIT_FAILURE );
}
glAttachShader( program, vertexShader );
//fragment shader
GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER);
glShaderSource( fragmentShader, 1, (const GLchar**)&fsrc, NULL );
glCompileShader( fragmentShader );
glGetShaderiv( fragmentShader, GL_COMPILE_STATUS, &compiled );
if ( !compiled ) {
GLint logSize;
glGetShaderiv( vertexShader, GL_INFO_LOG_LENGTH, &logSize );
char* logMsg = new char[logSize];
glGetShaderInfoLog( fragmentShader, logSize, NULL, logMsg );
qWarning() << logMsg;
delete [] logMsg;
exit( EXIT_FAILURE );
}
glAttachShader( program, fragmentShader );
/* Link output */
glBindFragDataLocation(program, 0, "fragColor");
/* link and error check */
glLinkProgram(program);
GLint linked;
glGetProgramiv( program, GL_LINK_STATUS, &linked );
if ( !linked ) {
qWarning() << "Shader program failed to link";
GLint logSize;
glGetProgramiv( program, GL_INFO_LOG_LENGTH, &logSize);
char* logMsg = new char[logSize];
glGetProgramInfoLog( program, logSize, NULL, logMsg );
qWarning() << logMsg ;
delete [] logMsg;
exit( EXIT_FAILURE );
}
/* use program object */
glUseProgram(program);
return program;
}
void RenderView::initializeGL()
{
//glSetup();
// Prepare a complete shader program...
m_shader = prepareShaderProgram();
textureUniformY = glGetUniformLocation(m_shader, "tex_y");
textureUniformU = glGetUniformLocation(m_shader, "tex_u");
textureUniformV = glGetUniformLocation(m_shader, "tex_v");
// Create a interleaved triangle (vec3 position, vec3 color)
float vertexPoints[] ={
-1.0f, -1.0f,0.0f, 1.0f,
1.0f, -1.0f,1.0f, 1.0f,
-1.0f, 1.0f,0.0f, 0.0f,
1.0f, 1.0f,1.0f, 0.0f,
};
glGenVertexArrays(1, &m_vertexBuffer);
glBindVertexArray(m_vertexBuffer);
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, 4 * 4 * sizeof(float), vertexPoints, GL_STATIC_DRAW);
vertextAttribute = glGetAttribLocation(m_shader, "vertexIn");
textureAttribute = glGetAttribLocation(m_shader, "textureIn");
glEnableVertexAttribArray(vertextAttribute);
glVertexAttribPointer(vertextAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(float)*4, (const GLvoid *)0);
glEnableVertexAttribArray(textureAttribute);
glVertexAttribPointer(textureAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(float)*4, (const GLvoid *)(sizeof(float)*2));
//Init Texture
glGenTextures(1, &id_y);
glBindTexture(GL_TEXTURE_2D, id_y);
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);
glGenTextures(1, &id_u);
glBindTexture(GL_TEXTURE_2D, id_u);
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);
glGenTextures(1, &id_v);
glBindTexture(GL_TEXTURE_2D, id_v);
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);
//glCheckError();
}
void RenderView::resizeGL( int w, int h )
{
// Set the viewport to window dimensions
m_nViewW = w;
m_nViewH = h;
glViewport( 0, 0, w, qMax( h, 1 ) );
//glCheckError();
}
void RenderView::paintGL()
{
// Clear the buffer with the current clearing color
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
if(m_bStartPlay)
{
float x,y;
float wRatio = (float)m_nViewW/m_nVideoW;
float hRatio = (float)m_nViewH/m_nVideoH;
float minRatio = qMin(wRatio, hRatio);
y = m_nVideoH * minRatio/m_nViewH;
x = m_nVideoW * minRatio/m_nViewW;
float vertexPoints[] ={
-x, -y,0.0f, 1.0f,
x, -y,1.0f, 1.0f,
-x, y,0.0f, 0.0f,
x, y,1.0f, 0.0f,
};
glBufferData(GL_ARRAY_BUFFER, 4 * 4 * sizeof(float), vertexPoints, GL_STATIC_DRAW);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, id_y);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_nVideoW, m_nVideoH, 0, GL_RED, GL_UNSIGNED_BYTE, m_pBufYuv420p);
glUniform1i(textureUniformY, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, id_u);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_nVideoW / 2, m_nVideoH / 2, 0, GL_RED, GL_UNSIGNED_BYTE, (char*)m_pBufYuv420p + m_nVideoW*m_nVideoH);
glUniform1i(textureUniformU, 1);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, id_v);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_nVideoW / 2, m_nVideoH / 2, 0, GL_RED, GL_UNSIGNED_BYTE, (char*)m_pBufYuv420p + m_nVideoW*m_nVideoH * 5 / 4);
glUniform1i(textureUniformV, 2);
// Draw stuff
glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
}
//∫glCheckError();
}
在界面显示前记得添加下面代码
QSurfaceFormat format;
format.setVersion(4,1);
format.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(format);
在这先感谢来自文章http://blog.csdn.net/su_vast/article/details/52214642的作者,使用他的代码我实现了Windows上的YUV数据渲染。但是移植到mac上渲染不出来,经过折腾及对OpenGL的了解,发现问题出在OpenGL版本问题上,不同版本OpenGL的shader编写使用有些不同,资料来源于http://blog.csdn.net/ym19860303/article/details/44115135。
下面是我写的代码,有什么不完善的地方请读者反馈,相互学习。
renderview.h
#ifndef RENDERVIEW_H
#define RENDERVIEW_H
#include <QWidget>
#include <QOpenGLWidget>
#include <QGLContext>
#include <QGLWidget>
#include <QOpenGLTexture>
#include "global.h"
class RenderView : public QOpenGLWidget
{
Q_OBJECT
public:
RenderView(QWidget* parent = 0);
~RenderView();
void Render(unsigned char* buffer,int w, int h);
protected:
//virtual void paintEvent(QPaintEvent *event);
virtual void initializeGL();
virtual void resizeGL( int w, int h );
virtual void paintGL();
private:
GLuint prepareShaderProgram();
private:
GLuint m_shader;
GLuint m_vertexBuffer;
GLuint textureUniformY;
GLuint textureUniformU;
GLuint textureUniformV;
GLuint vertexBuffer;
GLuint vertextAttribute;
GLuint textureAttribute;
GLuint id_y;
GLuint id_u;
GLuint id_v;
int m_nVideoW;
int m_nVideoH;
int m_nViewW;
int m_nViewH;
unsigned char* m_pBufYuv420p;
unsigned char* m_pBuffer;
bool m_bStartPlay;
};
#endif // RENDERVIEW_H
renderview.cpp
#include "renderview.h"
#include <QPainter>
#include <QSurfaceFormat>
#include <QMutex>
#include <QDebug>
#include <QSurfaceFormat>
#include "DecoderCtrl/MainConcept.h"
#define BUFFER_MAX_SIZE 1920*1080+1024
const char *vsrc =
"#version 410\n"
"in vec4 vertexIn;\n"
"in vec2 textureIn;\n"
"out vec2 textureOut;\n"
"void main(void)\n"
"{\n"
" gl_Position = vertexIn;\n"
" textureOut = textureIn;\n"
"}";
const char *fsrc =
"#version 410\n"
"in vec2 textureOut;\n"
"out vec4 fragColor;\n"
"uniform sampler2D tex_y;\n"
"uniform sampler2D tex_u;\n"
"uniform sampler2D tex_v;\n"
"void main(void)\n"
"{\n"
" vec3 yuv;\n"
" vec3 rgb;\n"
" yuv.x = texture(tex_y, textureOut).r;\n"
" yuv.y = texture(tex_u, textureOut).r - 0.5;\n"
" yuv.z = texture(tex_v, textureOut).r - 0.5;\n"
" rgb = mat3( 1, 1, 1,\n"
" 0, -0.21482, 2.12798,\n"
" 1.28033, -0.38059, 0) * yuv;\n"
" fragColor = vec4(rgb, 1);\n"
"}";
void RenderYuv(unsigned char* yuvBuffer,int width, int height,void *pdate)
{
RenderView *render = (RenderView*)pdate;
if(render)
{
render->Render(yuvBuffer, width, height);
}
}
RenderView::RenderView(QWidget* parent) :
QOpenGLWidget(parent)
,m_pBufYuv420p(NULL)
,m_nVideoW(0)
,m_nVideoH(0)
,m_nViewW(0)
,m_nViewH(0)
,m_bStartPlay(false)
{
setAutoFillBackground(false);
MC_Codec_SetRenderNotify(RenderYuv, this);
m_pBufYuv420p = new unsigned char[BUFFER_MAX_SIZE];
memset(m_pBufYuv420p, 0, BUFFER_MAX_SIZE);
}
RenderView::~RenderView()
{
}
void RenderView::Render(unsigned char* buffer,int w, int h)
{
m_nVideoW = w;
m_nVideoH = h;
m_bStartPlay = true;
unsigned long bufLen = w*h*3/2;
m_pBufYuv420p = buffer;
memcpy(m_pBufYuv420p, buffer, bufLen);
update();
}
GLuint RenderView::prepareShaderProgram()
{
GLuint program = glCreateProgram();
//vertex shader
GLuint vertexShader = glCreateShader( GL_VERTEX_SHADER);
glShaderSource( vertexShader, 1, (const GLchar**)&vsrc, NULL );
glCompileShader( vertexShader );
GLint compiled;
glGetShaderiv( vertexShader, GL_COMPILE_STATUS, &compiled );
if ( !compiled ) {
GLint logSize;
glGetShaderiv( vertexShader, GL_INFO_LOG_LENGTH, &logSize );
char* logMsg = new char[logSize];
glGetShaderInfoLog( vertexShader, logSize, NULL, logMsg );
qWarning() << logMsg;
delete [] logMsg;
exit( EXIT_FAILURE );
}
glAttachShader( program, vertexShader );
//fragment shader
GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER);
glShaderSource( fragmentShader, 1, (const GLchar**)&fsrc, NULL );
glCompileShader( fragmentShader );
glGetShaderiv( fragmentShader, GL_COMPILE_STATUS, &compiled );
if ( !compiled ) {
GLint logSize;
glGetShaderiv( vertexShader, GL_INFO_LOG_LENGTH, &logSize );
char* logMsg = new char[logSize];
glGetShaderInfoLog( fragmentShader, logSize, NULL, logMsg );
qWarning() << logMsg;
delete [] logMsg;
exit( EXIT_FAILURE );
}
glAttachShader( program, fragmentShader );
/* Link output */
glBindFragDataLocation(program, 0, "fragColor");
/* link and error check */
glLinkProgram(program);
GLint linked;
glGetProgramiv( program, GL_LINK_STATUS, &linked );
if ( !linked ) {
qWarning() << "Shader program failed to link";
GLint logSize;
glGetProgramiv( program, GL_INFO_LOG_LENGTH, &logSize);
char* logMsg = new char[logSize];
glGetProgramInfoLog( program, logSize, NULL, logMsg );
qWarning() << logMsg ;
delete [] logMsg;
exit( EXIT_FAILURE );
}
/* use program object */
glUseProgram(program);
return program;
}
void RenderView::initializeGL()
{
//glSetup();
// Prepare a complete shader program...
m_shader = prepareShaderProgram();
textureUniformY = glGetUniformLocation(m_shader, "tex_y");
textureUniformU = glGetUniformLocation(m_shader, "tex_u");
textureUniformV = glGetUniformLocation(m_shader, "tex_v");
// Create a interleaved triangle (vec3 position, vec3 color)
float vertexPoints[] ={
-1.0f, -1.0f,0.0f, 1.0f,
1.0f, -1.0f,1.0f, 1.0f,
-1.0f, 1.0f,0.0f, 0.0f,
1.0f, 1.0f,1.0f, 0.0f,
};
glGenVertexArrays(1, &m_vertexBuffer);
glBindVertexArray(m_vertexBuffer);
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, 4 * 4 * sizeof(float), vertexPoints, GL_STATIC_DRAW);
vertextAttribute = glGetAttribLocation(m_shader, "vertexIn");
textureAttribute = glGetAttribLocation(m_shader, "textureIn");
glEnableVertexAttribArray(vertextAttribute);
glVertexAttribPointer(vertextAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(float)*4, (const GLvoid *)0);
glEnableVertexAttribArray(textureAttribute);
glVertexAttribPointer(textureAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(float)*4, (const GLvoid *)(sizeof(float)*2));
//Init Texture
glGenTextures(1, &id_y);
glBindTexture(GL_TEXTURE_2D, id_y);
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);
glGenTextures(1, &id_u);
glBindTexture(GL_TEXTURE_2D, id_u);
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);
glGenTextures(1, &id_v);
glBindTexture(GL_TEXTURE_2D, id_v);
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);
//glCheckError();
}
void RenderView::resizeGL( int w, int h )
{
// Set the viewport to window dimensions
m_nViewW = w;
m_nViewH = h;
glViewport( 0, 0, w, qMax( h, 1 ) );
//glCheckError();
}
void RenderView::paintGL()
{
// Clear the buffer with the current clearing color
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
if(m_bStartPlay)
{
float x,y;
float wRatio = (float)m_nViewW/m_nVideoW;
float hRatio = (float)m_nViewH/m_nVideoH;
float minRatio = qMin(wRatio, hRatio);
y = m_nVideoH * minRatio/m_nViewH;
x = m_nVideoW * minRatio/m_nViewW;
float vertexPoints[] ={
-x, -y,0.0f, 1.0f,
x, -y,1.0f, 1.0f,
-x, y,0.0f, 0.0f,
x, y,1.0f, 0.0f,
};
glBufferData(GL_ARRAY_BUFFER, 4 * 4 * sizeof(float), vertexPoints, GL_STATIC_DRAW);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, id_y);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_nVideoW, m_nVideoH, 0, GL_RED, GL_UNSIGNED_BYTE, m_pBufYuv420p);
glUniform1i(textureUniformY, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, id_u);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_nVideoW / 2, m_nVideoH / 2, 0, GL_RED, GL_UNSIGNED_BYTE, (char*)m_pBufYuv420p + m_nVideoW*m_nVideoH);
glUniform1i(textureUniformU, 1);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, id_v);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_nVideoW / 2, m_nVideoH / 2, 0, GL_RED, GL_UNSIGNED_BYTE, (char*)m_pBufYuv420p + m_nVideoW*m_nVideoH * 5 / 4);
glUniform1i(textureUniformV, 2);
// Draw stuff
glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
}
//∫glCheckError();
}
在界面显示前记得添加下面代码
QSurfaceFormat format;
format.setVersion(4,1);
format.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(format);
相关文章推荐
- qt5_qml_Opengl_shader 第四弹----------------------纹理贴图(YUV视频循环播放)
- qt采用opengl显示yuv视频数据
- 如何使用DirectDraw直接显示RGB、YUV视频数据(播放yuv)
- 如何使用DirectDraw直接显示RGB、YUV视频数据(播放yuv) 分类: VC++ DirectX 2013-11-09 09:39 758人阅读 评论(0) 收藏
- yuv视频用opengl播放
- 视频学习笔记:Android OpenGL渲染YUV420P图像
- 视频和音频播放的演示最简单的例子6:OpenGL广播YUV420P(T经exture,采用Shader)
- OpenGL渲染(YUV数据格式)
- FFmpeg-利用ffplay.c保存视频解码后的数据yuv420
- 利用MAC中的QuickTime视频播放器来播放各种媒体视频
- 使用D3D渲染YUV视频数据
- OpenGL播放yuv视频
- 使用D3D渲染YUV视频数据
- 如何使用DirectDraw直接显示RGB、YUV视频数据(播放yuv)
- 使用D3D渲染YUV视频数据
- OpenGL播放yuv视频
- 使用D3D渲染YUV视频数据
- OpenGL播放yuv视频
- [工具]利用EasyRTSPClient工具检查摄像机RTSP流不能播放原因以及排查音视频数据无法播放问题
- OpenGL播放yuv视频