diff --git a/src/QtScrcpy.pro b/src/QtScrcpy.pro
index 1a3ed8b..a7f34ff 100644
--- a/src/QtScrcpy.pro
+++ b/src/QtScrcpy.pro
@@ -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
diff --git a/src/dialog.cpp b/src/dialog.cpp
index 17ca4e1..e4e3187 100644
--- a/src/dialog.cpp
+++ b/src/dialog.cpp
@@ -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);
}
diff --git a/src/dialog.h b/src/dialog.h
index ef22fdf..2c3db67 100644
--- a/src/dialog.h
+++ b/src/dialog.h
@@ -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
diff --git a/src/dialog.ui b/src/dialog.ui
index 2b74cd0..bf3d1c0 100644
--- a/src/dialog.ui
+++ b/src/dialog.ui
@@ -6,8 +6,8 @@
0
0
- 716
- 757
+ 924
+ 365
@@ -57,8 +57,8 @@
230
20
- 451
- 701
+ 651
+ 301
diff --git a/src/glyuvwidget.h b/src/glyuvwidget.h
index 4e9657f..352141b 100644
--- a/src/glyuvwidget.h
+++ b/src/glyuvwidget.h
@@ -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;
diff --git a/src/yuvglwidget.cpp b/src/yuvglwidget.cpp
new file mode 100644
index 0000000..b0d9b6f
--- /dev/null
+++ b/src/yuvglwidget.cpp
@@ -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();
+}
diff --git a/src/yuvglwidget.h b/src/yuvglwidget.h
new file mode 100644
index 0000000..01dace2
--- /dev/null
+++ b/src/yuvglwidget.h
@@ -0,0 +1,55 @@
+#ifndef YUVGLWIDGET_H
+#define YUVGLWIDGET_H
+
+#include
+#include
+#include
+#include
+#include
+
+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