From c00954b6a90299c010bdaf12eeaf295882dee435 Mon Sep 17 00:00:00 2001 From: Barry <870709864@qq.com> Date: Sun, 4 Nov 2018 12:24:16 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BA=AFqt=20opengl=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/QtScrcpy.pro | 2 - src/dialog.cpp | 15 +-- src/dialog.h | 2 - src/main.cpp | 4 +- src/qyuvopenglwidget.cpp | 101 ++++++----------- src/qyuvopenglwidget.h | 6 +- src/yuvglwidget.cpp | 228 --------------------------------------- src/yuvglwidget.h | 56 ---------- 8 files changed, 40 insertions(+), 374 deletions(-) delete mode 100644 src/yuvglwidget.cpp delete mode 100644 src/yuvglwidget.h diff --git a/src/QtScrcpy.pro b/src/QtScrcpy.pro index 938adb1..f9cc0e9 100644 --- a/src/QtScrcpy.pro +++ b/src/QtScrcpy.pro @@ -33,7 +33,6 @@ SOURCES += \ server.cpp \ convert.cpp \ frames.cpp \ - yuvglwidget.cpp \ fpscounter.cpp \ qyuvopenglwidget.cpp @@ -44,7 +43,6 @@ HEADERS += \ server.h \ convert.h \ frames.h \ - yuvglwidget.h \ fpscounter.h \ qyuvopenglwidget.h diff --git a/src/dialog.cpp b/src/dialog.cpp index 5478521..43e30b1 100644 --- a/src/dialog.cpp +++ b/src/dialog.cpp @@ -4,7 +4,6 @@ #include "dialog.h" #include "ui_dialog.h" #include "adbprocess.h" -#include "yuvglwidget.h" #include "qyuvopenglwidget.h" void saveAVFrame_YUV_ToTempFile(const AVFrame *pFrame) @@ -39,7 +38,7 @@ void saveAVFrame_YUV_ToTempFile(const AVFrame *pFrame) t_file.flush(); } -#define OPENGL_EX + Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) @@ -48,14 +47,9 @@ Dialog::Dialog(QWidget *parent) : setWindowFlags(windowFlags() | Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint); -#ifdef OPENGL_EX + w = new QYUVOpenGLWidget(this); ui->verticalLayout->addWidget(w); -#else - w2 = new YUVGLWidget(this); - ui->verticalLayout->addWidget(w2); -#endif - Decoder::init(); @@ -81,13 +75,8 @@ Dialog::Dialog(QWidget *parent) : frames.lock(); const AVFrame *frame = frames.consumeRenderedFrame(); //saveAVFrame_YUV_ToTempFile(frame); -#ifdef OPENGL_EX 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]); -#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(); },Qt::QueuedConnection); } diff --git a/src/dialog.h b/src/dialog.h index 777bdc4..17fbf41 100644 --- a/src/dialog.h +++ b/src/dialog.h @@ -11,7 +11,6 @@ namespace Ui { class Dialog; } -class YUVGLWidget; class QYUVOpenGLWidget; class Dialog : public QDialog { @@ -34,7 +33,6 @@ private: Decoder decoder; Frames frames; QYUVOpenGLWidget* w; - YUVGLWidget* w2; }; #endif // DIALOG_H diff --git a/src/main.cpp b/src/main.cpp index 815dc61..ad9a0dd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,7 +7,7 @@ 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_UseSoftwareOpenGL); @@ -17,7 +17,7 @@ int main(int argc, char *argv[]) qputenv("QTSCRCPY_SERVER_PATH", "G:\\mygitcode\\QtScrcpy\\src\\scrcpy-server.jar"); Dialog w; - w.move(50, 930); + //w.move(50, 930); w.show(); return a.exec(); diff --git a/src/qyuvopenglwidget.cpp b/src/qyuvopenglwidget.cpp index e176403..342ea89 100644 --- a/src/qyuvopenglwidget.cpp +++ b/src/qyuvopenglwidget.cpp @@ -105,25 +105,29 @@ void QYUVOpenGLWidget::setFrameSize(const QSize &frameSize) { if (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) { - if (m_textureY->textureId()) { - QOpenGLPixelTransferOptions options; - options.setRowLength(linesizeY); - m_textureY->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt8,dataY, &options); - options.setRowLength(linesizeU); - m_textureU->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt8,dataU, &options); - options.setRowLength(linesizeV); - m_textureV->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt8,dataV, &options); + if (m_frameSize.isEmpty()) { + return; + } + QOpenGLPixelTransferOptions options; + if (m_textureY->isStorageAllocated()) { + options.setRowLength(linesizeY); + m_textureY->setData(QOpenGLTexture::Luminance, QOpenGLTexture::UInt8,dataY, &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(); } @@ -145,28 +149,23 @@ void QYUVOpenGLWidget::initializeGL() void QYUVOpenGLWidget::paintGL() { - if (m_needInit) { - //TODO 需要deInitTextures吗 + if (m_frameSize.isEmpty()) { + return; + } + if (m_needUpdate) { initTextures(); - m_needInit = false; + m_needUpdate = false; } - - if (m_textureY->textureId()) { - m_textureY->bind(0); + if (m_textureY->isStorageAllocated()) { + m_textureY->bind(0); + } + if (m_textureU->isStorageAllocated()) { m_textureU->bind(1); + } + if (m_textureV->isStorageAllocated()) { 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); @@ -222,8 +221,8 @@ void QYUVOpenGLWidget::initTextures() // 设置所有方向上纹理超出坐标时的显示策略(也可单个方向单独设置) m_textureY->setWrapMode(QOpenGLTexture::ClampToEdge); m_textureY->setMipLevels(1); - m_textureY->setFormat(QOpenGLTexture::R8_UNorm); - m_textureY->allocateStorage(); + m_textureY->setFormat(QOpenGLTexture::LuminanceFormat); + m_textureY->allocateStorage(QOpenGLTexture::Luminance, QOpenGLTexture::UInt8); } if (m_textureU) { @@ -233,8 +232,8 @@ void QYUVOpenGLWidget::initTextures() m_textureU->setMagnificationFilter(QOpenGLTexture::Linear); m_textureU->setWrapMode(QOpenGLTexture::ClampToEdge); m_textureU->setMipLevels(1); - m_textureU->setFormat(QOpenGLTexture::R8_UNorm); - m_textureU->allocateStorage(); + m_textureU->setFormat(QOpenGLTexture::LuminanceFormat); + m_textureU->allocateStorage(QOpenGLTexture::Luminance, QOpenGLTexture::UInt8); } if (m_textureV) { @@ -244,40 +243,9 @@ void QYUVOpenGLWidget::initTextures() m_textureV->setMagnificationFilter(QOpenGLTexture::Linear); m_textureV->setWrapMode(QOpenGLTexture::ClampToEdge); m_textureV->setMipLevels(1); - m_textureV->setFormat(QOpenGLTexture::R8_UNorm); - m_textureV->allocateStorage(); + m_textureV->setFormat(QOpenGLTexture::LuminanceFormat); + 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() @@ -291,7 +259,6 @@ void QYUVOpenGLWidget::deInitTextures() if (m_textureV) { m_textureV->destroy(); } - } void QYUVOpenGLWidget::updateTexture(GLuint texture, quint32 textureType, quint8 *pixels, quint32 stride) diff --git a/src/qyuvopenglwidget.h b/src/qyuvopenglwidget.h index 338aa0a..5202bb8 100644 --- a/src/qyuvopenglwidget.h +++ b/src/qyuvopenglwidget.h @@ -1,5 +1,6 @@ #ifndef QYUVOPENGLWIDGET_H #define QYUVOPENGLWIDGET_H + #include #include #include @@ -33,7 +34,7 @@ private: private: // 视频帧尺寸 QSize m_frameSize = {-1, -1}; - bool m_needInit = false; + bool m_needUpdate = false; // 顶点缓冲对象(Vertex Buffer Objects, VBO):默认即为VertexBuffer(GL_ARRAY_BUFFER)类型 QOpenGLBuffer m_vbo; @@ -45,9 +46,6 @@ private: QOpenGLTexture* m_textureY = Q_NULLPTR; QOpenGLTexture* m_textureU = Q_NULLPTR; QOpenGLTexture* m_textureV = Q_NULLPTR; - - // YUV纹理,用于生成纹理贴图 - GLuint m_texture[3] = {0}; }; #endif // QYUVOPENGLWIDGET_H diff --git a/src/yuvglwidget.cpp b/src/yuvglwidget.cpp deleted file mode 100644 index 3e8ab95..0000000 --- a/src/yuvglwidget.cpp +++ /dev/null @@ -1,228 +0,0 @@ -#include - -#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; - } -} diff --git a/src/yuvglwidget.h b/src/yuvglwidget.h deleted file mode 100644 index 7684e7f..0000000 --- a/src/yuvglwidget.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef YUVGLWIDGET_H -#define YUVGLWIDGET_H - -#include -#include -#include -//#include - -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