mirror of
https://github.com/barry-ran/QtScrcpy.git
synced 2025-07-31 21:08:38 +00:00
纯qt opengl实现
This commit is contained in:
parent
d059c47fda
commit
c1f6c13fd8
8 changed files with 40 additions and 374 deletions
|
@ -33,7 +33,6 @@ SOURCES += \
|
||||||
server.cpp \
|
server.cpp \
|
||||||
convert.cpp \
|
convert.cpp \
|
||||||
frames.cpp \
|
frames.cpp \
|
||||||
yuvglwidget.cpp \
|
|
||||||
fpscounter.cpp \
|
fpscounter.cpp \
|
||||||
qyuvopenglwidget.cpp
|
qyuvopenglwidget.cpp
|
||||||
|
|
||||||
|
@ -44,7 +43,6 @@ HEADERS += \
|
||||||
server.h \
|
server.h \
|
||||||
convert.h \
|
convert.h \
|
||||||
frames.h \
|
frames.h \
|
||||||
yuvglwidget.h \
|
|
||||||
fpscounter.h \
|
fpscounter.h \
|
||||||
qyuvopenglwidget.h
|
qyuvopenglwidget.h
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include "dialog.h"
|
#include "dialog.h"
|
||||||
#include "ui_dialog.h"
|
#include "ui_dialog.h"
|
||||||
#include "adbprocess.h"
|
#include "adbprocess.h"
|
||||||
#include "yuvglwidget.h"
|
|
||||||
#include "qyuvopenglwidget.h"
|
#include "qyuvopenglwidget.h"
|
||||||
|
|
||||||
void saveAVFrame_YUV_ToTempFile(const AVFrame *pFrame)
|
void saveAVFrame_YUV_ToTempFile(const AVFrame *pFrame)
|
||||||
|
@ -39,7 +38,7 @@ void saveAVFrame_YUV_ToTempFile(const AVFrame *pFrame)
|
||||||
t_file.flush();
|
t_file.flush();
|
||||||
|
|
||||||
}
|
}
|
||||||
#define OPENGL_EX
|
|
||||||
Dialog::Dialog(QWidget *parent) :
|
Dialog::Dialog(QWidget *parent) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
ui(new Ui::Dialog)
|
ui(new Ui::Dialog)
|
||||||
|
@ -48,14 +47,9 @@ Dialog::Dialog(QWidget *parent) :
|
||||||
setWindowFlags(windowFlags()
|
setWindowFlags(windowFlags()
|
||||||
| Qt::WindowMaximizeButtonHint
|
| Qt::WindowMaximizeButtonHint
|
||||||
| Qt::WindowMinimizeButtonHint);
|
| Qt::WindowMinimizeButtonHint);
|
||||||
#ifdef OPENGL_EX
|
|
||||||
w = new QYUVOpenGLWidget(this);
|
w = new QYUVOpenGLWidget(this);
|
||||||
ui->verticalLayout->addWidget(w);
|
ui->verticalLayout->addWidget(w);
|
||||||
#else
|
|
||||||
w2 = new YUVGLWidget(this);
|
|
||||||
ui->verticalLayout->addWidget(w2);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
Decoder::init();
|
Decoder::init();
|
||||||
|
|
||||||
|
@ -81,13 +75,8 @@ Dialog::Dialog(QWidget *parent) :
|
||||||
frames.lock();
|
frames.lock();
|
||||||
const AVFrame *frame = frames.consumeRenderedFrame();
|
const AVFrame *frame = frames.consumeRenderedFrame();
|
||||||
//saveAVFrame_YUV_ToTempFile(frame);
|
//saveAVFrame_YUV_ToTempFile(frame);
|
||||||
#ifdef OPENGL_EX
|
|
||||||
w->setFrameSize(QSize(frame->width, frame->height));
|
w->setFrameSize(QSize(frame->width, frame->height));
|
||||||
w->updateTextures(frame->data[0], frame->data[1], frame->data[2], frame->linesize[0], frame->linesize[1], frame->linesize[2]);
|
w->updateTextures(frame->data[0], frame->data[1], frame->data[2], frame->linesize[0], frame->linesize[1], frame->linesize[2]);
|
||||||
#else
|
|
||||||
w2->setFrameSize(QSize(frame->width, frame->height));
|
|
||||||
w2->updateTextures(frame->data[0], frame->data[1], frame->data[2], frame->linesize[0], frame->linesize[1], frame->linesize[2]);
|
|
||||||
#endif
|
|
||||||
frames.unLock();
|
frames.unLock();
|
||||||
},Qt::QueuedConnection);
|
},Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ namespace Ui {
|
||||||
class Dialog;
|
class Dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
class YUVGLWidget;
|
|
||||||
class QYUVOpenGLWidget;
|
class QYUVOpenGLWidget;
|
||||||
class Dialog : public QDialog
|
class Dialog : public QDialog
|
||||||
{
|
{
|
||||||
|
@ -34,7 +33,6 @@ private:
|
||||||
Decoder decoder;
|
Decoder decoder;
|
||||||
Frames frames;
|
Frames frames;
|
||||||
QYUVOpenGLWidget* w;
|
QYUVOpenGLWidget* w;
|
||||||
YUVGLWidget* w2;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DIALOG_H
|
#endif // DIALOG_H
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
|
//QApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
|
||||||
//QApplication::setAttribute(Qt::AA_UseOpenGLES);
|
//QApplication::setAttribute(Qt::AA_UseOpenGLES);
|
||||||
//QApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
|
//QApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ int main(int argc, char *argv[])
|
||||||
qputenv("QTSCRCPY_SERVER_PATH", "G:\\mygitcode\\QtScrcpy\\src\\scrcpy-server.jar");
|
qputenv("QTSCRCPY_SERVER_PATH", "G:\\mygitcode\\QtScrcpy\\src\\scrcpy-server.jar");
|
||||||
|
|
||||||
Dialog w;
|
Dialog w;
|
||||||
w.move(50, 930);
|
//w.move(50, 930);
|
||||||
w.show();
|
w.show();
|
||||||
|
|
||||||
return a.exec();
|
return a.exec();
|
||||||
|
|
|
@ -105,25 +105,29 @@ void QYUVOpenGLWidget::setFrameSize(const QSize &frameSize)
|
||||||
{
|
{
|
||||||
if (m_frameSize != frameSize) {
|
if (m_frameSize != frameSize) {
|
||||||
m_frameSize = frameSize;
|
m_frameSize = frameSize;
|
||||||
m_needInit = true;
|
m_needUpdate = true;
|
||||||
|
repaint();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QYUVOpenGLWidget::updateTextures(quint8 *dataY, quint8 *dataU, quint8 *dataV, quint32 linesizeY, quint32 linesizeU, quint32 linesizeV)
|
void QYUVOpenGLWidget::updateTextures(quint8 *dataY, quint8 *dataU, quint8 *dataV, quint32 linesizeY, quint32 linesizeU, quint32 linesizeV)
|
||||||
{
|
{
|
||||||
if (m_textureY->textureId()) {
|
if (m_frameSize.isEmpty()) {
|
||||||
QOpenGLPixelTransferOptions options;
|
return;
|
||||||
options.setRowLength(linesizeY);
|
}
|
||||||
m_textureY->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt8,dataY, &options);
|
QOpenGLPixelTransferOptions options;
|
||||||
options.setRowLength(linesizeU);
|
if (m_textureY->isStorageAllocated()) {
|
||||||
m_textureU->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt8,dataU, &options);
|
options.setRowLength(linesizeY);
|
||||||
options.setRowLength(linesizeV);
|
m_textureY->setData(QOpenGLTexture::Luminance, QOpenGLTexture::UInt8,dataY, &options);
|
||||||
m_textureV->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt8,dataV, &options);
|
}
|
||||||
|
if (m_textureU->isStorageAllocated()) {
|
||||||
|
options.setRowLength(linesizeU);
|
||||||
|
m_textureU->setData(QOpenGLTexture::Luminance, QOpenGLTexture::UInt8,dataU, &options);
|
||||||
|
}
|
||||||
|
if (m_textureV->isStorageAllocated()) {
|
||||||
|
options.setRowLength(linesizeV);
|
||||||
|
m_textureV->setData(QOpenGLTexture::Luminance, QOpenGLTexture::UInt8,dataV, &options);
|
||||||
}
|
}
|
||||||
|
|
||||||
//updateTexture(m_texture[0], 0, dataY, linesizeY);
|
|
||||||
//updateTexture(m_texture[1], 1, dataU, linesizeU);
|
|
||||||
//updateTexture(m_texture[2], 2, dataV, linesizeV);
|
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,28 +149,23 @@ void QYUVOpenGLWidget::initializeGL()
|
||||||
|
|
||||||
void QYUVOpenGLWidget::paintGL()
|
void QYUVOpenGLWidget::paintGL()
|
||||||
{
|
{
|
||||||
if (m_needInit) {
|
if (m_frameSize.isEmpty()) {
|
||||||
//TODO 需要deInitTextures吗
|
return;
|
||||||
|
}
|
||||||
|
if (m_needUpdate) {
|
||||||
initTextures();
|
initTextures();
|
||||||
m_needInit = false;
|
m_needUpdate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_textureY->isStorageAllocated()) {
|
||||||
if (m_textureY->textureId()) {
|
|
||||||
m_textureY->bind(0);
|
m_textureY->bind(0);
|
||||||
|
}
|
||||||
|
if (m_textureU->isStorageAllocated()) {
|
||||||
m_textureU->bind(1);
|
m_textureU->bind(1);
|
||||||
|
}
|
||||||
|
if (m_textureV->isStorageAllocated()) {
|
||||||
m_textureV->bind(2);
|
m_textureV->bind(2);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, m_texture[0]);
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE1);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, m_texture[1]);
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE2);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, m_texture[2]);
|
|
||||||
*/
|
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
|
@ -222,8 +221,8 @@ void QYUVOpenGLWidget::initTextures()
|
||||||
// 设置所有方向上纹理超出坐标时的显示策略(也可单个方向单独设置)
|
// 设置所有方向上纹理超出坐标时的显示策略(也可单个方向单独设置)
|
||||||
m_textureY->setWrapMode(QOpenGLTexture::ClampToEdge);
|
m_textureY->setWrapMode(QOpenGLTexture::ClampToEdge);
|
||||||
m_textureY->setMipLevels(1);
|
m_textureY->setMipLevels(1);
|
||||||
m_textureY->setFormat(QOpenGLTexture::R8_UNorm);
|
m_textureY->setFormat(QOpenGLTexture::LuminanceFormat);
|
||||||
m_textureY->allocateStorage();
|
m_textureY->allocateStorage(QOpenGLTexture::Luminance, QOpenGLTexture::UInt8);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_textureU) {
|
if (m_textureU) {
|
||||||
|
@ -233,8 +232,8 @@ void QYUVOpenGLWidget::initTextures()
|
||||||
m_textureU->setMagnificationFilter(QOpenGLTexture::Linear);
|
m_textureU->setMagnificationFilter(QOpenGLTexture::Linear);
|
||||||
m_textureU->setWrapMode(QOpenGLTexture::ClampToEdge);
|
m_textureU->setWrapMode(QOpenGLTexture::ClampToEdge);
|
||||||
m_textureU->setMipLevels(1);
|
m_textureU->setMipLevels(1);
|
||||||
m_textureU->setFormat(QOpenGLTexture::R8_UNorm);
|
m_textureU->setFormat(QOpenGLTexture::LuminanceFormat);
|
||||||
m_textureU->allocateStorage();
|
m_textureU->allocateStorage(QOpenGLTexture::Luminance, QOpenGLTexture::UInt8);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_textureV) {
|
if (m_textureV) {
|
||||||
|
@ -244,40 +243,9 @@ void QYUVOpenGLWidget::initTextures()
|
||||||
m_textureV->setMagnificationFilter(QOpenGLTexture::Linear);
|
m_textureV->setMagnificationFilter(QOpenGLTexture::Linear);
|
||||||
m_textureV->setWrapMode(QOpenGLTexture::ClampToEdge);
|
m_textureV->setWrapMode(QOpenGLTexture::ClampToEdge);
|
||||||
m_textureV->setMipLevels(1);
|
m_textureV->setMipLevels(1);
|
||||||
m_textureV->setFormat(QOpenGLTexture::R8_UNorm);
|
m_textureV->setFormat(QOpenGLTexture::LuminanceFormat);
|
||||||
m_textureV->allocateStorage();
|
m_textureV->allocateStorage(QOpenGLTexture::Luminance, QOpenGLTexture::UInt8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// 创建纹理
|
|
||||||
glGenTextures(1, &m_texture[0]);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, m_texture[0]);
|
|
||||||
// 设置纹理缩放时的策略
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
// 设置st方向上纹理超出坐标时的显示策略
|
|
||||||
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_RED, m_frameSize.width(), m_frameSize.height(), 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
|
|
||||||
glGenTextures(1, &m_texture[1]);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, m_texture[1]);
|
|
||||||
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_RED, m_frameSize.width()/2, m_frameSize.height()/2, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
|
|
||||||
glGenTextures(1, &m_texture[2]);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, m_texture[2]);
|
|
||||||
// 设置纹理缩放时的策略
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
// 设置st方向上纹理超出坐标时的显示策略
|
|
||||||
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_RED, m_frameSize.width()/2, m_frameSize.height()/2, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QYUVOpenGLWidget::deInitTextures()
|
void QYUVOpenGLWidget::deInitTextures()
|
||||||
|
@ -291,7 +259,6 @@ void QYUVOpenGLWidget::deInitTextures()
|
||||||
if (m_textureV) {
|
if (m_textureV) {
|
||||||
m_textureV->destroy();
|
m_textureV->destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QYUVOpenGLWidget::updateTexture(GLuint texture, quint32 textureType, quint8 *pixels, quint32 stride)
|
void QYUVOpenGLWidget::updateTexture(GLuint texture, quint32 textureType, quint8 *pixels, quint32 stride)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#ifndef QYUVOPENGLWIDGET_H
|
#ifndef QYUVOPENGLWIDGET_H
|
||||||
#define QYUVOPENGLWIDGET_H
|
#define QYUVOPENGLWIDGET_H
|
||||||
|
|
||||||
#include <QOpenGLWidget>
|
#include <QOpenGLWidget>
|
||||||
#include <QOpenGLFunctions>
|
#include <QOpenGLFunctions>
|
||||||
#include <QOpenGLShaderProgram>
|
#include <QOpenGLShaderProgram>
|
||||||
|
@ -33,7 +34,7 @@ private:
|
||||||
private:
|
private:
|
||||||
// 视频帧尺寸
|
// 视频帧尺寸
|
||||||
QSize m_frameSize = {-1, -1};
|
QSize m_frameSize = {-1, -1};
|
||||||
bool m_needInit = false;
|
bool m_needUpdate = false;
|
||||||
|
|
||||||
// 顶点缓冲对象(Vertex Buffer Objects, VBO):默认即为VertexBuffer(GL_ARRAY_BUFFER)类型
|
// 顶点缓冲对象(Vertex Buffer Objects, VBO):默认即为VertexBuffer(GL_ARRAY_BUFFER)类型
|
||||||
QOpenGLBuffer m_vbo;
|
QOpenGLBuffer m_vbo;
|
||||||
|
@ -45,9 +46,6 @@ private:
|
||||||
QOpenGLTexture* m_textureY = Q_NULLPTR;
|
QOpenGLTexture* m_textureY = Q_NULLPTR;
|
||||||
QOpenGLTexture* m_textureU = Q_NULLPTR;
|
QOpenGLTexture* m_textureU = Q_NULLPTR;
|
||||||
QOpenGLTexture* m_textureV = Q_NULLPTR;
|
QOpenGLTexture* m_textureV = Q_NULLPTR;
|
||||||
|
|
||||||
// YUV纹理,用于生成纹理贴图
|
|
||||||
GLuint m_texture[3] = {0};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QYUVOPENGLWIDGET_H
|
#endif // QYUVOPENGLWIDGET_H
|
||||||
|
|
|
@ -1,228 +0,0 @@
|
||||||
#include <QOpenGLShaderProgram>
|
|
||||||
|
|
||||||
#include "yuvglwidget.h"
|
|
||||||
|
|
||||||
static QString vertShader = 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];
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
static QString fragShader = 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);
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
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();
|
|
||||||
deInitTextures();
|
|
||||||
doneCurrent();
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize YUVGLWidget::minimumSizeHint() const
|
|
||||||
{
|
|
||||||
return QSize(50, 50);
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize YUVGLWidget::sizeHint() const
|
|
||||||
{
|
|
||||||
return size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void YUVGLWidget::setFrameSize(const QSize& frameSize)
|
|
||||||
{
|
|
||||||
if (m_frameSize != frameSize) {
|
|
||||||
m_frameSize = frameSize;
|
|
||||||
m_needInit = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void YUVGLWidget::initializeGL()
|
|
||||||
{
|
|
||||||
initializeOpenGLFunctions();
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
|
||||||
m_vao.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
void YUVGLWidget::paintGL()
|
|
||||||
{
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
|
|
||||||
// init
|
|
||||||
if (m_needInit) {
|
|
||||||
initShader();
|
|
||||||
initTextures();
|
|
||||||
m_needInit = false;
|
|
||||||
}
|
|
||||||
m_vao.bind();
|
|
||||||
if (m_program) {
|
|
||||||
QMatrix4x4 matrix;
|
|
||||||
matrix.ortho(0, width(), height(), 0, 0.0, 100.0f);
|
|
||||||
m_program->setUniformValue("u_pm", matrix);
|
|
||||||
glUniform4f(m_drawPos, 0, 0, width(), height());
|
|
||||||
}
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, m_texture[Texture_Y]);
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE1);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, m_texture[Texture_U]);
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE2);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, m_texture[Texture_V]);
|
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void YUVGLWidget::resizeGL(int width, int height)
|
|
||||||
{
|
|
||||||
glViewport(0, 0, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void YUVGLWidget::initShader()
|
|
||||||
{
|
|
||||||
if (m_program) {
|
|
||||||
m_program->release();
|
|
||||||
delete m_program;
|
|
||||||
m_program = Q_NULLPTR;
|
|
||||||
}
|
|
||||||
m_program = new QOpenGLShaderProgram(this);
|
|
||||||
// Setup shaders
|
|
||||||
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertShader);
|
|
||||||
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragShader);
|
|
||||||
m_program->link();
|
|
||||||
m_program->bind();
|
|
||||||
m_program->setUniformValue("y_tex", Texture_Y);
|
|
||||||
m_program->setUniformValue("u_tex", Texture_U);
|
|
||||||
m_program->setUniformValue("v_tex", Texture_V);
|
|
||||||
m_drawPos = m_program->uniformLocation("draw_pos");
|
|
||||||
}
|
|
||||||
|
|
||||||
void YUVGLWidget::updateTextures(quint8 *dataY, quint8 *dataU, quint8 *dataV, quint32 linesizeY, quint32 linesizeU, quint32 linesizeV)
|
|
||||||
{
|
|
||||||
bindPixelTexture(m_texture[Texture_Y], Texture_Y, dataY, linesizeY);
|
|
||||||
bindPixelTexture(m_texture[Texture_U], Texture_U, dataU, linesizeU);
|
|
||||||
bindPixelTexture(m_texture[Texture_V], Texture_V, dataV, linesizeV);
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void YUVGLWidget::bindPixelTexture(GLuint texture, YUVTextureType textureType, quint8* pixels, quint32 stride)
|
|
||||||
{
|
|
||||||
if (!pixels)
|
|
||||||
return;
|
|
||||||
|
|
||||||
QSize size(0, 0);
|
|
||||||
calcTextureSize(textureType, size);
|
|
||||||
|
|
||||||
makeCurrent();
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture);
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
|
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size.width(), size.height(), GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels);
|
|
||||||
doneCurrent();
|
|
||||||
}
|
|
||||||
|
|
||||||
void YUVGLWidget::initTexture(qint32 textureType)
|
|
||||||
{
|
|
||||||
if (Texture_NULL >= textureType || Texture_Size <= textureType) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
glGenTextures(1, &m_texture[textureType]);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, m_texture[textureType]);
|
|
||||||
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);
|
|
||||||
|
|
||||||
QSize size(0, 0);
|
|
||||||
calcTextureSize(textureType, size);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, size.width(), size.height(), 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void YUVGLWidget::initTextures()
|
|
||||||
{
|
|
||||||
//TODO: use FBO?
|
|
||||||
|
|
||||||
deInitTextures();
|
|
||||||
for (int i = Texture_Y; i < Texture_Size; i++) {
|
|
||||||
initTexture(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void YUVGLWidget::deInitTextures()
|
|
||||||
{
|
|
||||||
glDeleteTextures(3, m_texture);
|
|
||||||
memset(m_texture, 0, Texture_Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void YUVGLWidget::calcTextureSize(qint32 textureType, QSize &size)
|
|
||||||
{
|
|
||||||
if (Texture_NULL >= textureType || Texture_Size <= textureType) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (Texture_Y == textureType) {
|
|
||||||
size = m_frameSize;
|
|
||||||
} else {
|
|
||||||
size = m_frameSize / 2;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
#ifndef YUVGLWIDGET_H
|
|
||||||
#define YUVGLWIDGET_H
|
|
||||||
|
|
||||||
#include <QOpenGLFunctions>
|
|
||||||
#include <QOpenGLVertexArrayObject>
|
|
||||||
#include <QOpenGLWidget>
|
|
||||||
//#include <QSurfaceFormat>
|
|
||||||
|
|
||||||
class QOpenGLShaderProgram;
|
|
||||||
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(const QSize& frameSize);
|
|
||||||
void updateTextures(quint8* dataY, quint8* dataU, quint8* dataV, quint32 linesizeY, quint32 linesizeU, quint32 linesizeV);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void initializeGL() override;
|
|
||||||
void paintGL() override;
|
|
||||||
void resizeGL(int width, int height) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum YUVTextureType {
|
|
||||||
Texture_NULL = -1,
|
|
||||||
Texture_Y,
|
|
||||||
Texture_U,
|
|
||||||
Texture_V,
|
|
||||||
Texture_Size
|
|
||||||
};
|
|
||||||
|
|
||||||
void initShader();
|
|
||||||
void initTexture(qint32 textureType);
|
|
||||||
void initTextures();
|
|
||||||
void deInitTextures();
|
|
||||||
void calcTextureSize(qint32 textureType, QSize& size);
|
|
||||||
|
|
||||||
void bindPixelTexture(GLuint texture, YUVTextureType textureType, quint8* pixels, quint32 stride);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QSize m_frameSize = {0, 0};
|
|
||||||
bool m_needInit = false;
|
|
||||||
|
|
||||||
QOpenGLShaderProgram* m_program = Q_NULLPTR;
|
|
||||||
QOpenGLVertexArrayObject m_vao;
|
|
||||||
// yuv texture
|
|
||||||
GLuint m_texture[Texture_Size] = {0};
|
|
||||||
GLint m_drawPos = -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // YUVGLWIDGET_H
|
|
Loading…
Add table
Add a link
Reference in a new issue