opengl渲染方案2测试

This commit is contained in:
rankun 2018-10-25 17:01:51 +08:00
parent 9b92e79cfe
commit 7f456da9e5
7 changed files with 305 additions and 17 deletions

View file

@ -32,7 +32,8 @@ SOURCES += \
server.cpp \
convert.cpp \
glyuvwidget.cpp \
frames.cpp
frames.cpp \
yuvglwidget.cpp
HEADERS += \
dialog.h \
@ -41,7 +42,8 @@ HEADERS += \
server.h \
convert.h \
glyuvwidget.h \
frames.h
frames.h \
yuvglwidget.h
FORMS += \
dialog.ui

View file

@ -1,8 +1,11 @@
#include "dialog.h"
#include "ui_dialog.h"
#include "adbprocess.h"
#include "glyuvwidget.h"
#include "glyuvwidget.h"
#include "yuvglwidget.h"
//#define OPENGL_PLAN2
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
@ -10,9 +13,16 @@ Dialog::Dialog(QWidget *parent) :
{
ui->setupUi(this);
#ifdef OPENGL_PLAN2
w2 = new YUVGLWidget(this);
w2->resize(ui->imgLabel->size());
w2->move(230, 20);
#else
w = new GLYuvWidget(this);
w->resize(ui->imgLabel->size());
w->move(230, 20);
#endif
Decoder::init();
@ -37,14 +47,23 @@ Dialog::Dialog(QWidget *parent) :
QObject::connect(&decoder, &Decoder::newFrame, this, [this](){
frames.lock();
const AVFrame *frame = frames.consumeRenderedFrame();
w->setVideoSize(frame->width, frame->height);
/*
if (!prepare_for_frame(screen, new_frame_size)) {
mutex_unlock(frames->mutex);
return SDL_FALSE;
}
*/
w->updateTexture(frame->data[0], frame->data[1], frame->data[2], frame->linesize[0], frame->linesize[1], frame->linesize[2]);
#ifdef OPENGL_PLAN2
w2->setFrameSize(frame->width, frame->height);
w2->setYPixels(frame->data[0], frame->linesize[0]);
w2->setUPixels(frame->data[1], frame->linesize[1]);
w2->setVPixels(frame->data[2], frame->linesize[2]);
w2->update();
#else
w->setVideoSize(frame->width, frame->height);
/*
if (!prepare_for_frame(screen, new_frame_size)) {
mutex_unlock(frames->mutex);
return SDL_FALSE;
}
*/
w->updateTexture(frame->data[0], frame->data[1], frame->data[2], frame->linesize[0], frame->linesize[1], frame->linesize[2]);
#endif
frames.unLock();
},Qt::QueuedConnection);
}

View file

@ -12,6 +12,7 @@ class Dialog;
}
class GLYuvWidget;
class YUVGLWidget;
class Dialog : public QDialog
{
Q_OBJECT
@ -33,6 +34,7 @@ private:
Decoder decoder;
Frames frames;
GLYuvWidget* w;
YUVGLWidget* w2;
};
#endif // DIALOG_H

View file

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>716</width>
<height>757</height>
<width>924</width>
<height>365</height>
</rect>
</property>
<property name="windowTitle">
@ -57,8 +57,8 @@
<rect>
<x>230</x>
<y>20</y>
<width>451</width>
<height>701</height>
<width>651</width>
<height>301</height>
</rect>
</property>
<property name="styleSheet">

View file

@ -46,8 +46,8 @@ private:
GLuint m_idV = 0;
// 视频宽高
quint32 m_videoWidth = 1080;
quint32 m_videoHeight = 2160;
quint32 m_videoWidth = 2160;
quint32 m_videoHeight = 1080;
quint8* m_bufferY = Q_NULLPTR;
quint8* m_bufferU = Q_NULLPTR;

210
src/yuvglwidget.cpp Normal file
View file

@ -0,0 +1,210 @@
#include "yuvglwidget.h"
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);
}
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"(
#version 150 core
uniform mat4 u_pm;
uniform vec4 draw_pos;
const vec2 verts[4] = vec2[] (
vec2(-0.5, 0.5),
vec2(-0.5, -0.5),
vec2( 0.5, 0.5),
vec2( 0.5, -0.5)
);
const vec2 texcoords[4] = vec2[] (
vec2(0.0, 1.0),
vec2(0.0, 0.0),
vec2(1.0, 1.0),
vec2(1.0, 0.0)
);
out vec2 v_coord;
void main() {
vec2 vert = verts[gl_VertexID];
vec4 p = vec4((0.5 * draw_pos.z) + draw_pos.x + (vert.x * draw_pos.z),
(0.5 * draw_pos.w) + draw_pos.y + (vert.y * draw_pos.w),
0, 1);
gl_Position = u_pm * p;
v_coord = texcoords[gl_VertexID];
}
)";
QString frag = R"(
#version 150 core
uniform sampler2D y_tex;
uniform sampler2D u_tex;
uniform sampler2D v_tex;
in vec2 v_coord;
//layout( location = 0 ) out vec4 fragcolor;
out vec4 fragcolor;
const vec3 R_cf = vec3(1.164383, 0.000000, 1.596027);
const vec3 G_cf = vec3(1.164383, -0.391762, -0.812968);
const vec3 B_cf = vec3(1.164383, 2.017232, 0.000000);
const vec3 offset = vec3(-0.0625, -0.5, -0.5);
void main() {
float y = texture(y_tex, v_coord).r;
float u = texture(u_tex, v_coord).r;
float v = texture(v_tex, v_coord).r;
vec3 yuv = vec3(y,u,v);
yuv += offset;
fragcolor = vec4(0.0, 0.0, 0.0, 1.0);
fragcolor.r = dot(yuv, R_cf);
fragcolor.g = dot(yuv, G_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);
// m_program.bindAttributeLocation("u_tex", 1);
// m_program.bindAttributeLocation("v_tex", 2);
m_program.link();
m_program.bind();
m_program.setUniformValue("y_tex", 0);
m_program.setUniformValue("u_tex", 1);
m_program.setUniformValue("v_tex", 2);
u_pos = m_program.uniformLocation("draw_pos");
m_vao.create();
}
void YUVGLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
m_vao.bind();
QMatrix4x4 m;
m.ortho(0, width(), height(), 0, 0.0, 100.0f);
m_program.setUniformValue("u_pm", m);
glUniform4f(u_pos, 0, 0, width(), height());
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, y_tex);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, u_tex);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, v_tex);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void YUVGLWidget::setYPixels(uint8_t* pixels, int stride)
{
bindPixelTexture(y_tex, YTexture, pixels, stride);
}
void YUVGLWidget::setUPixels(uint8_t* pixels, int stride)
{
bindPixelTexture(u_tex, UTexture, pixels, stride);
}
void YUVGLWidget::setVPixels(uint8_t* pixels, int stride)
{
bindPixelTexture(v_tex, VTexture, pixels, stride);
}
void YUVGLWidget::initializeTextures()
{
//TODO: use FBO?
// Setup textures
glGenTextures(1, &y_tex);
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);
glBindTexture(GL_TEXTURE_2D, u_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/2, m_frameHeight/2, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
glGenTextures(1, &v_tex);
glBindTexture(GL_TEXTURE_2D, v_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/2, m_frameHeight/2, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
}
void YUVGLWidget::bindPixelTexture(GLuint texture, YUVGLWidget::YUVTextureType textureType, uint8_t* pixels, int stride)
{
if (!pixels)
return;
unsigned int const width = textureType == YTexture ? m_frameWidth : m_frameWidth/2;
unsigned int const height = textureType == YTexture ? m_frameHeight : m_frameHeight/2;
makeCurrent();
glBindTexture(GL_TEXTURE_2D, texture);
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, pixels);
//glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, m_frameWidth/2, m_frameHeight/2, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
doneCurrent();
}

55
src/yuvglwidget.h Normal file
View file

@ -0,0 +1,55 @@
#ifndef YUVGLWIDGET_H
#define YUVGLWIDGET_H
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLWidget>
#include <QSurfaceFormat>
class YUVGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
public:
explicit YUVGLWidget(QWidget* parent = 0);
~YUVGLWidget();
QSize minimumSizeHint() const override;
QSize sizeHint() const override;
void setFrameSize(unsigned int width, unsigned int height);
void setYPixels(uint8_t* pixels, int stride);
void setUPixels(uint8_t* pixels, int stride);
void setVPixels(uint8_t* pixels, int stride);
protected:
void initializeGL() override;
void paintGL() override;
//void resizeGL(int width, int height) override;
private:
enum YUVTextureType {
YTexture,
UTexture,
VTexture
};
void initializeTextures();
void bindPixelTexture(GLuint texture, YUVTextureType textureType, uint8_t* pixels, int stride);
QOpenGLShaderProgram m_program;
QOpenGLVertexArrayObject m_vao;
//unsigned int m_frameWidth {3840}; // 4k
//unsigned int m_frameHeight {2160};
unsigned int m_frameWidth {2160};
unsigned int m_frameHeight {1080};
GLuint y_tex {0};
GLuint u_tex {0};
GLuint v_tex {0};
GLint u_pos {0};
};
#endif // YUVGLWIDGET_H