利用Qt + OpenGL 渲染 YUV数据,播放视频 mac版
来源:互联网 发布:淘宝的等级怎么提升 编辑:程序博客网 时间:2024/05/16 13:38
最近利用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_OBJECTpublic: 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
#include "renderview.h"#include <QPainter>#include <QSurfaceFormat>#include <QMutex>#include <QDebug>#include <QSurfaceFormat>#include "DecoderCtrl/MainConcept.h"#define BUFFER_MAX_SIZE 1920*1080+1024const 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);
0 0
- 利用Qt + OpenGL 渲染 YUV数据,播放视频 mac版
- OpenGL播放yuv视频
- OpenGL播放yuv视频
- OpenGL播放yuv视频
- OpenGL播放yuv视频
- qt采用opengl显示yuv视频数据
- OpenGL渲染YUV数据
- yuv视频用opengl播放
- iOS OpenGL渲染YUV数据
- iOS中OpenGL-ES渲染YUV视频
- ios opengl 播放 yuv数据
- android opengl 播放 yuv数据
- 基于 qt 的 Opengl 渲染 YUV
- 使用D3D渲染YUV视频数据
- 使用D3D渲染YUV视频数据
- 使用D3D渲染YUV视频数据
- OpenGL渲染(YUV数据格式)
- OpenGL显示YUV视频
- 关于boost vs2015 windows安装出现问题的解决
- 【2分钟搞定极光推送】极光推送Android端集成
- 图解 Python 深拷贝和浅拷贝
- 仿饿了么 +
- MongoDB错误和使用总结
- 利用Qt + OpenGL 渲染 YUV数据,播放视频 mac版
- 《Java虚拟机原理图解》 1.2.3、Class文件中的常量池详解(下)
- [mac]开机老是进入安全模式
- vue 路由
- 机器学习电话面/视频面 cheetsheet ——常用机器学习算法优缺点一览(可直接打印)
- muduo库整体架构简析
- 设计模式无限重读之最少知识原则(LKP)
- WSASend调用成功 GetQueuedCompletionStatus一直阻塞
- 文章标题