diff --git a/src/QtScrcpy.pro b/src/QtScrcpy.pro
index fe7b42c..c53bad3 100644
--- a/src/QtScrcpy.pro
+++ b/src/QtScrcpy.pro
@@ -29,46 +29,35 @@ DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
main.cpp \
dialog.cpp \
- adbprocess.cpp \
- decoder.cpp \
- server.cpp \
- convert.cpp \
- frames.cpp \
- fpscounter.cpp \
- qyuvopenglwidget.cpp \
- videoform.cpp \
- devicesocket.cpp \
- tcpserver.cpp \
- controlevent.cpp \
- controller.cpp
+ videoform.cpp
HEADERS += \
dialog.h \
- adbprocess.h \
- decoder.h \
- server.h \
- convert.h \
- frames.h \
- fpscounter.h \
- qyuvopenglwidget.h \
- videoform.h \
- devicesocket.h \
- tcpserver.h \
- qscrcpyevent.h \
- controlevent.h \
- controller.h
+ videoform.h
FORMS += \
dialog.ui \
videoform.ui
#子工程
+include ($$PWD/common/common.pri)
+include ($$PWD/server/server.pri)
+include ($$PWD/adb/adb.pri)
+include ($$PWD/decoder/decoder.pri)
+include ($$PWD/render/render.pri)
include ($$PWD/android/android.pri)
+include ($$PWD/inputcontrol/inputcontrol.pri)
# 附加包含路径
INCLUDEPATH += \
$$PWD/ffmpeg/include \
- $$PWD/android
+ $$PWD/common \
+ $$PWD/server \
+ $$PWD/adb \
+ $$PWD/decoder \
+ $$PWD/render \
+ $$PWD/android \
+ $$PWD/inputcontrol
# 依赖库
LIBS += \
diff --git a/src/QtScrcpy.pro.user.37b22fe b/src/QtScrcpy.pro.user.37b22fe
deleted file mode 100644
index 24ede2b..0000000
--- a/src/QtScrcpy.pro.user.37b22fe
+++ /dev/null
@@ -1,318 +0,0 @@
-
-
-
-
-
- EnvironmentId
- {37b22fe7-3e02-43d3-85e3-251a3ebe4093}
-
-
- ProjectExplorer.Project.ActiveTarget
- 0
-
-
- ProjectExplorer.Project.EditorSettings
-
- true
- false
- true
-
- Cpp
-
- CppGlobal
-
-
-
- QmlJS
-
- QmlJSGlobal
-
-
- 2
- UTF-8
- false
- 4
- false
- 80
- true
- true
- 1
- true
- false
- 0
- true
- true
- 0
- 8
- true
- 1
- true
- true
- true
- false
-
-
-
- ProjectExplorer.Project.PluginSettings
-
-
-
- ProjectExplorer.Project.Target.0
-
- Desktop Qt 5.9.6 MSVC2015 32bit
- Desktop Qt 5.9.6 MSVC2015 32bit
- qt.596.win32_msvc2015_kit
- 0
- 0
- 0
-
- G:/mygitcode/QtScrcpy/build-QtScrcpy-Desktop_Qt_5_9_6_MSVC2015_32bit-Debug
-
-
- true
- qmake
-
- QtProjectManager.QMakeBuildStep
- true
-
- false
- false
- false
-
-
- true
- Make
-
- Qt4ProjectManager.MakeStep
-
- false
-
-
-
- 2
- Build
-
- ProjectExplorer.BuildSteps.Build
-
-
-
- true
- Make
-
- Qt4ProjectManager.MakeStep
-
- true
- clean
-
-
- 1
- Clean
-
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- Debug
- Debug
- Qt4ProjectManager.Qt4BuildConfiguration
- 2
- true
-
-
- G:/mygitcode/QtScrcpy/build-QtScrcpy-Desktop_Qt_5_9_6_MSVC2015_32bit-Release
-
-
- true
- qmake
-
- QtProjectManager.QMakeBuildStep
- false
-
- false
- false
- false
-
-
- true
- Make
-
- Qt4ProjectManager.MakeStep
-
- false
-
-
-
- 2
- Build
-
- ProjectExplorer.BuildSteps.Build
-
-
-
- true
- Make
-
- Qt4ProjectManager.MakeStep
-
- true
- clean
-
-
- 1
- Clean
-
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- Release
- Release
- Qt4ProjectManager.Qt4BuildConfiguration
- 0
- true
-
-
- G:/mygitcode/QtScrcpy/build-QtScrcpy-Desktop_Qt_5_9_6_MSVC2015_32bit-Profile
-
-
- true
- qmake
-
- QtProjectManager.QMakeBuildStep
- true
-
- false
- true
- false
-
-
- true
- Make
-
- Qt4ProjectManager.MakeStep
-
- false
-
-
-
- 2
- Build
-
- ProjectExplorer.BuildSteps.Build
-
-
-
- true
- Make
-
- Qt4ProjectManager.MakeStep
-
- true
- clean
-
-
- 1
- Clean
-
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- Profile
- Profile
- Qt4ProjectManager.Qt4BuildConfiguration
- 0
- true
-
- 3
-
-
- 0
- 部署
-
- ProjectExplorer.BuildSteps.Deploy
-
- 1
- 部署设置
-
- ProjectExplorer.DefaultDeployConfiguration
-
- 1
-
-
- false
- false
- 1000
-
- true
-
- false
- false
- false
- false
- true
- 0.01
- 10
- true
- 1
- 25
-
- 1
- true
- false
- true
- valgrind
-
- 0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
-
- 2
-
- QtScrcpy
-
- Qt4ProjectManager.Qt4RunConfiguration:G:/mygitcode/QtScrcpy/src/QtScrcpy.pro
- true
-
- QtScrcpy.pro
- false
-
- G:/mygitcode/QtScrcpy/build-QtScrcpy-Desktop_Qt_5_9_6_MSVC2015_32bit-Debug
- 3768
- false
- true
- false
- false
- true
-
- 1
-
-
-
- ProjectExplorer.Project.TargetCount
- 1
-
-
- ProjectExplorer.Project.Updater.FileVersion
- 18
-
-
- Version
- 18
-
-
diff --git a/src/adb/adb.pri b/src/adb/adb.pri
new file mode 100644
index 0000000..762cbac
--- /dev/null
+++ b/src/adb/adb.pri
@@ -0,0 +1,5 @@
+HEADERS += \
+ $$PWD/adbprocess.h
+
+SOURCES += \
+ $$PWD/adbprocess.cpp
diff --git a/src/adbprocess.cpp b/src/adb/adbprocess.cpp
similarity index 100%
rename from src/adbprocess.cpp
rename to src/adb/adbprocess.cpp
diff --git a/src/adbprocess.h b/src/adb/adbprocess.h
similarity index 100%
rename from src/adbprocess.h
rename to src/adb/adbprocess.h
diff --git a/src/android/android.pri b/src/android/android.pri
new file mode 100644
index 0000000..0b6db18
--- /dev/null
+++ b/src/android/android.pri
@@ -0,0 +1,3 @@
+HEADERS += \
+ $$PWD/input.h \
+ $$PWD/keycodes.h
diff --git a/src/common/common.pri b/src/common/common.pri
new file mode 100644
index 0000000..6bdf623
--- /dev/null
+++ b/src/common/common.pri
@@ -0,0 +1,2 @@
+HEADERS += \
+ $$PWD/qscrcpyevent.h
diff --git a/src/qscrcpyevent.h b/src/common/qscrcpyevent.h
similarity index 100%
rename from src/qscrcpyevent.h
rename to src/common/qscrcpyevent.h
diff --git a/src/convert.cpp b/src/decoder/convert.cpp
similarity index 100%
rename from src/convert.cpp
rename to src/decoder/convert.cpp
diff --git a/src/convert.h b/src/decoder/convert.h
similarity index 100%
rename from src/convert.h
rename to src/decoder/convert.h
diff --git a/src/decoder.cpp b/src/decoder/decoder.cpp
similarity index 100%
rename from src/decoder.cpp
rename to src/decoder/decoder.cpp
diff --git a/src/decoder.h b/src/decoder/decoder.h
similarity index 100%
rename from src/decoder.h
rename to src/decoder/decoder.h
diff --git a/src/decoder/decoder.pri b/src/decoder/decoder.pri
new file mode 100644
index 0000000..f563b9e
--- /dev/null
+++ b/src/decoder/decoder.pri
@@ -0,0 +1,12 @@
+HEADERS += \
+ $$PWD/convert.h \
+ $$PWD/decoder.h \
+ $$PWD/frames.h \
+ $$PWD/fpscounter.h
+
+SOURCES += \
+ $$PWD/convert.cpp \
+ $$PWD/decoder.cpp \
+ $$PWD/frames.cpp \
+ $$PWD/fpscounter.cpp
+
diff --git a/src/fpscounter.cpp b/src/decoder/fpscounter.cpp
similarity index 93%
rename from src/fpscounter.cpp
rename to src/decoder/fpscounter.cpp
index 2cf0781..492e51e 100644
--- a/src/fpscounter.cpp
+++ b/src/decoder/fpscounter.cpp
@@ -1,71 +1,71 @@
-#include
-#include
-
-#include "fpscounter.h"
-
-FpsCounter::FpsCounter(QObject* parent) : QObject(parent)
-{
-
-}
-
-FpsCounter::~FpsCounter()
-{
-
-}
-
-void FpsCounter::start()
-{
- resetCounter();
- startCounterTimer();
-}
-
-void FpsCounter::stop()
-{
- stopCounterTimer();
- resetCounter();
-}
-
-bool FpsCounter::isStarted()
-{
- return m_counterTimer;
-}
-
-void FpsCounter::addRenderedFrame()
-{
- m_rendered++;
-}
-
-void FpsCounter::addSkippedFrame()
-{
- m_skipped++;
-}
-
-void FpsCounter::timerEvent(QTimerEvent *event)
-{
- if (event && m_counterTimer == event->timerId()) {
- m_curRendered = m_rendered;
- m_curSkipped = m_skipped;
- resetCounter();
- //qInfo("FPS:%d Discard:%d", m_curRendered, m_skipped);
- }
-}
-
-void FpsCounter::startCounterTimer()
-{
- stopCounterTimer();
- m_counterTimer = startTimer(1000);
-}
-
-void FpsCounter::stopCounterTimer()
-{
- if (m_counterTimer) {
- killTimer(m_counterTimer);
- m_counterTimer = 0;
- }
-}
-
-void FpsCounter::resetCounter()
-{
- m_rendered = 0;
- m_skipped = 0;
-}
+#include
+#include
+
+#include "fpscounter.h"
+
+FpsCounter::FpsCounter(QObject* parent) : QObject(parent)
+{
+
+}
+
+FpsCounter::~FpsCounter()
+{
+
+}
+
+void FpsCounter::start()
+{
+ resetCounter();
+ startCounterTimer();
+}
+
+void FpsCounter::stop()
+{
+ stopCounterTimer();
+ resetCounter();
+}
+
+bool FpsCounter::isStarted()
+{
+ return m_counterTimer;
+}
+
+void FpsCounter::addRenderedFrame()
+{
+ m_rendered++;
+}
+
+void FpsCounter::addSkippedFrame()
+{
+ m_skipped++;
+}
+
+void FpsCounter::timerEvent(QTimerEvent *event)
+{
+ if (event && m_counterTimer == event->timerId()) {
+ m_curRendered = m_rendered;
+ m_curSkipped = m_skipped;
+ resetCounter();
+ //qInfo("FPS:%d Discard:%d", m_curRendered, m_skipped);
+ }
+}
+
+void FpsCounter::startCounterTimer()
+{
+ stopCounterTimer();
+ m_counterTimer = startTimer(1000);
+}
+
+void FpsCounter::stopCounterTimer()
+{
+ if (m_counterTimer) {
+ killTimer(m_counterTimer);
+ m_counterTimer = 0;
+ }
+}
+
+void FpsCounter::resetCounter()
+{
+ m_rendered = 0;
+ m_skipped = 0;
+}
diff --git a/src/fpscounter.h b/src/decoder/fpscounter.h
similarity index 94%
rename from src/fpscounter.h
rename to src/decoder/fpscounter.h
index bfad3d2..82daa79 100644
--- a/src/fpscounter.h
+++ b/src/decoder/fpscounter.h
@@ -1,35 +1,35 @@
-#ifndef FPSCOUNTER_H
-#define FPSCOUNTER_H
-#include
-
-class FpsCounter : public QObject
-{
- Q_OBJECT
-public:
- FpsCounter(QObject* parent = Q_NULLPTR);
- virtual ~FpsCounter();
-
- void start();
- void stop();
- bool isStarted();
- void addRenderedFrame();
- void addSkippedFrame();
-
-protected:
- virtual void timerEvent(QTimerEvent *event);
-
-private:
- void startCounterTimer();
- void stopCounterTimer();
- void resetCounter();
-
-private:
- quint32 m_counterTimer = 0;
- quint32 m_curRendered = 0;
- quint32 m_curSkipped = 0;
-
- quint32 m_rendered = 0;
- quint32 m_skipped = 0;
-};
-
-#endif // FPSCOUNTER_H
+#ifndef FPSCOUNTER_H
+#define FPSCOUNTER_H
+#include
+
+class FpsCounter : public QObject
+{
+ Q_OBJECT
+public:
+ FpsCounter(QObject* parent = Q_NULLPTR);
+ virtual ~FpsCounter();
+
+ void start();
+ void stop();
+ bool isStarted();
+ void addRenderedFrame();
+ void addSkippedFrame();
+
+protected:
+ virtual void timerEvent(QTimerEvent *event);
+
+private:
+ void startCounterTimer();
+ void stopCounterTimer();
+ void resetCounter();
+
+private:
+ quint32 m_counterTimer = 0;
+ quint32 m_curRendered = 0;
+ quint32 m_curSkipped = 0;
+
+ quint32 m_rendered = 0;
+ quint32 m_skipped = 0;
+};
+
+#endif // FPSCOUNTER_H
diff --git a/src/frames.cpp b/src/decoder/frames.cpp
similarity index 100%
rename from src/frames.cpp
rename to src/decoder/frames.cpp
diff --git a/src/frames.h b/src/decoder/frames.h
similarity index 100%
rename from src/frames.h
rename to src/decoder/frames.h
diff --git a/src/controlevent.cpp b/src/inputcontrol/controlevent.cpp
similarity index 100%
rename from src/controlevent.cpp
rename to src/inputcontrol/controlevent.cpp
diff --git a/src/controlevent.h b/src/inputcontrol/controlevent.h
similarity index 100%
rename from src/controlevent.h
rename to src/inputcontrol/controlevent.h
diff --git a/src/controller.cpp b/src/inputcontrol/controller.cpp
similarity index 100%
rename from src/controller.cpp
rename to src/inputcontrol/controller.cpp
diff --git a/src/controller.h b/src/inputcontrol/controller.h
similarity index 100%
rename from src/controller.h
rename to src/inputcontrol/controller.h
diff --git a/src/inputcontrol/inputcontrol.pri b/src/inputcontrol/inputcontrol.pri
new file mode 100644
index 0000000..bcbbdaf
--- /dev/null
+++ b/src/inputcontrol/inputcontrol.pri
@@ -0,0 +1,8 @@
+HEADERS += \
+ $$PWD/controlevent.h \
+ $$PWD/controller.h
+
+SOURCES += \
+ $$PWD/controlevent.cpp \
+ $$PWD/controller.cpp
+
diff --git a/src/qyuvopenglwidget.cpp b/src/render/qyuvopenglwidget.cpp
similarity index 97%
rename from src/qyuvopenglwidget.cpp
rename to src/render/qyuvopenglwidget.cpp
index 9fd0aba..02c1c2e 100644
--- a/src/qyuvopenglwidget.cpp
+++ b/src/render/qyuvopenglwidget.cpp
@@ -1,241 +1,241 @@
-#include
-#include
-
-#include "qyuvopenglwidget.h"
-
-// 存储顶点坐标和纹理坐标
-// 存在一起缓存在vbo
-// 使用glVertexAttribPointer指定访问方式即可
-static const GLfloat coordinate[] = {
- // 顶点坐标,存储4个xyz坐标
- // 坐标范围为[-1,1],中心点为 0,0
- // 二维图像z始终为0
- // GL_TRIANGLE_STRIP的绘制方式:
- // 使用前3个坐标绘制一个三角形,使用后三个坐标绘制一个三角形,正好为一个矩形
- // x y z
- -1.0f, -1.0f, 0.0f,
- 1.0f, -1.0f, 0.0f,
- -1.0f, 1.0f, 0.0f,
- 1.0f, 1.0f, 0.0f,
-
- // 纹理坐标,存储4个xy坐标
- // 坐标范围为[0,1],左下角为 0,0
- // TODO 为什么这个顺序指定四个顶点?顶点坐标和纹理坐标如何映射的?
- 0.0f, 1.0f,
- 1.0f, 1.0f,
- 0.0f, 0.0f,
- 1.0f, 0.0f
-};
-
-// 顶点着色器
-static const QString s_vertShader = R"(
- attribute vec3 vertexIn; // xyz顶点坐标
- attribute vec2 textureIn; // xy纹理坐标
- varying vec2 textureOut; // 传递给片段着色器的纹理坐标
- void main(void)
- {
- gl_Position = vec4(vertexIn, 1.0); // 1.0表示vertexIn是一个顶点位置
- textureOut = textureIn; // 纹理坐标直接传递给片段着色器
- }
-)";
-
-// 片段着色器
-static QString s_fragShader = R"(
- varying vec2 textureOut; // 由顶点着色器传递过来的纹理坐标
- uniform sampler2D textureY; // uniform 纹理单元,利用纹理单元可以使用多个纹理
- uniform sampler2D textureU; // sampler2D是2D采样器
- uniform sampler2D textureV; // 声明yuv三个纹理单元
- void main(void)
- {
- vec3 yuv;
- vec3 rgb;
- // 根据指定的纹理textureY和坐标textureOut来采样
- yuv.x = texture2D(textureY, textureOut).r;
- yuv.y = texture2D(textureU, textureOut).r - 0.5;
- yuv.z = texture2D(textureV, textureOut).r - 0.5;
- // 采样完转为rgb
- rgb = mat3(1.0, 1.0, 1.0,
- 0.0, -0.39465, 2.03211,
- 1.13983, -0.58060, 0.0) * yuv;
- // 输出颜色值
- gl_FragColor = vec4(rgb, 1.0);
- }
-)";
-
-QYUVOpenGLWidget::QYUVOpenGLWidget(QWidget *parent) : QOpenGLWidget(parent)
-{
-
-}
-
-QYUVOpenGLWidget::~QYUVOpenGLWidget()
-{
- makeCurrent();
- m_vbo.destroy();
- deInitTextures();
- doneCurrent();
-}
-
-QSize QYUVOpenGLWidget::minimumSizeHint() const
-{
- return QSize(50, 50);
-}
-
-QSize QYUVOpenGLWidget::sizeHint() const
-{
- return size();
-}
-
-void QYUVOpenGLWidget::setFrameSize(const QSize &frameSize)
-{
- if (m_frameSize != frameSize) {
- m_frameSize = frameSize;
- m_needUpdate = true;
- // inittexture immediately
- repaint();
- }
-}
-
-const QSize& QYUVOpenGLWidget::frameSize()
-{
- return m_frameSize;
-}
-
-void QYUVOpenGLWidget::updateTextures(quint8 *dataY, quint8 *dataU, quint8 *dataV, quint32 linesizeY, quint32 linesizeU, quint32 linesizeV)
-{
- if (m_textureInited) {
- updateTexture(m_texture[0], 0, dataY, linesizeY);
- updateTexture(m_texture[1], 1, dataU, linesizeU);
- updateTexture(m_texture[2], 2, dataV, linesizeV);
- update();
- }
-}
-
-void QYUVOpenGLWidget::initializeGL()
-{
- initializeOpenGLFunctions();
- glDisable(GL_DEPTH_TEST);
-
- // 顶点缓冲对象初始化
- m_vbo.create();
- m_vbo.bind();
- m_vbo.allocate(coordinate, sizeof(coordinate));
- initShader();
- // 设置背景清理色为黑色
- glClearColor(0.0,0.0,0.0,0.0);
- // 清理颜色背景
- glClear(GL_COLOR_BUFFER_BIT);
-}
-
-void QYUVOpenGLWidget::paintGL()
-{
- if (m_needUpdate) {
- deInitTextures();
- initTextures();
- m_needUpdate = false;
- }
-
- if (m_textureInited) {
- 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);
- }
-}
-
-void QYUVOpenGLWidget::resizeGL(int width, int height)
-{
- glViewport(0, 0, width, height);
- repaint();
-}
-
-void QYUVOpenGLWidget::initShader()
-{
- // opengles的float、int等要手动指定精度
- if (QCoreApplication::testAttribute(Qt::AA_UseOpenGLES)) {
- s_fragShader.prepend(R"(
- precision mediump int;
- precision mediump float;
- )");
- }
- m_shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, s_vertShader);
- m_shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, s_fragShader);
- m_shaderProgram.link();
- m_shaderProgram.bind();
-
- // 指定顶点坐标在vbo中的访问方式
- // 参数解释:顶点坐标在shader中的参数名称,顶点坐标为float,起始偏移为0,顶点坐标类型为vec3,步幅为3个float
- m_shaderProgram.setAttributeBuffer("vertexIn", GL_FLOAT, 0, 3, 3 * sizeof(float));
- // 启用顶点属性
- m_shaderProgram.enableAttributeArray("vertexIn");
-
- // 指定纹理坐标在vbo中的访问方式
- // 参数解释:纹理坐标在shader中的参数名称,纹理坐标为float,起始偏移为12个float(跳过前面存储的12个顶点坐标),纹理坐标类型为vec2,步幅为2个float
- m_shaderProgram.setAttributeBuffer("textureIn", GL_FLOAT, 12 * sizeof(float), 2, 2 * sizeof(float));
- m_shaderProgram.enableAttributeArray("textureIn");
-
- // 关联片段着色器中的纹理单元和opengl中的纹理单元(opengl一般提供16个纹理单元)
- m_shaderProgram.setUniformValue("textureY", 0);
- m_shaderProgram.setUniformValue("textureU", 1);
- m_shaderProgram.setUniformValue("textureV", 2);
-}
-
-void QYUVOpenGLWidget::initTextures()
-{
- // 创建纹理
- 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);
-
- m_textureInited = true;
-}
-
-void QYUVOpenGLWidget::deInitTextures()
-{
- glDeleteTextures(3, m_texture);
- memset(m_texture, 0, 3);
- m_textureInited = false;
-}
-
-void QYUVOpenGLWidget::updateTexture(GLuint texture, quint32 textureType, quint8 *pixels, quint32 stride)
-{
- if (!pixels)
- return;
-
- QSize size = 0 == textureType ? m_frameSize : m_frameSize/2;
-
- makeCurrent();
- glBindTexture(GL_TEXTURE_2D, texture);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size.width(), size.height(), GL_RED, GL_UNSIGNED_BYTE, pixels);
- doneCurrent();
-}
+#include
+#include
+
+#include "qyuvopenglwidget.h"
+
+// 存储顶点坐标和纹理坐标
+// 存在一起缓存在vbo
+// 使用glVertexAttribPointer指定访问方式即可
+static const GLfloat coordinate[] = {
+ // 顶点坐标,存储4个xyz坐标
+ // 坐标范围为[-1,1],中心点为 0,0
+ // 二维图像z始终为0
+ // GL_TRIANGLE_STRIP的绘制方式:
+ // 使用前3个坐标绘制一个三角形,使用后三个坐标绘制一个三角形,正好为一个矩形
+ // x y z
+ -1.0f, -1.0f, 0.0f,
+ 1.0f, -1.0f, 0.0f,
+ -1.0f, 1.0f, 0.0f,
+ 1.0f, 1.0f, 0.0f,
+
+ // 纹理坐标,存储4个xy坐标
+ // 坐标范围为[0,1],左下角为 0,0
+ // TODO 为什么这个顺序指定四个顶点?顶点坐标和纹理坐标如何映射的?
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ 0.0f, 0.0f,
+ 1.0f, 0.0f
+};
+
+// 顶点着色器
+static const QString s_vertShader = R"(
+ attribute vec3 vertexIn; // xyz顶点坐标
+ attribute vec2 textureIn; // xy纹理坐标
+ varying vec2 textureOut; // 传递给片段着色器的纹理坐标
+ void main(void)
+ {
+ gl_Position = vec4(vertexIn, 1.0); // 1.0表示vertexIn是一个顶点位置
+ textureOut = textureIn; // 纹理坐标直接传递给片段着色器
+ }
+)";
+
+// 片段着色器
+static QString s_fragShader = R"(
+ varying vec2 textureOut; // 由顶点着色器传递过来的纹理坐标
+ uniform sampler2D textureY; // uniform 纹理单元,利用纹理单元可以使用多个纹理
+ uniform sampler2D textureU; // sampler2D是2D采样器
+ uniform sampler2D textureV; // 声明yuv三个纹理单元
+ void main(void)
+ {
+ vec3 yuv;
+ vec3 rgb;
+ // 根据指定的纹理textureY和坐标textureOut来采样
+ yuv.x = texture2D(textureY, textureOut).r;
+ yuv.y = texture2D(textureU, textureOut).r - 0.5;
+ yuv.z = texture2D(textureV, textureOut).r - 0.5;
+ // 采样完转为rgb
+ rgb = mat3(1.0, 1.0, 1.0,
+ 0.0, -0.39465, 2.03211,
+ 1.13983, -0.58060, 0.0) * yuv;
+ // 输出颜色值
+ gl_FragColor = vec4(rgb, 1.0);
+ }
+)";
+
+QYUVOpenGLWidget::QYUVOpenGLWidget(QWidget *parent) : QOpenGLWidget(parent)
+{
+
+}
+
+QYUVOpenGLWidget::~QYUVOpenGLWidget()
+{
+ makeCurrent();
+ m_vbo.destroy();
+ deInitTextures();
+ doneCurrent();
+}
+
+QSize QYUVOpenGLWidget::minimumSizeHint() const
+{
+ return QSize(50, 50);
+}
+
+QSize QYUVOpenGLWidget::sizeHint() const
+{
+ return size();
+}
+
+void QYUVOpenGLWidget::setFrameSize(const QSize &frameSize)
+{
+ if (m_frameSize != frameSize) {
+ m_frameSize = frameSize;
+ m_needUpdate = true;
+ // inittexture immediately
+ repaint();
+ }
+}
+
+const QSize& QYUVOpenGLWidget::frameSize()
+{
+ return m_frameSize;
+}
+
+void QYUVOpenGLWidget::updateTextures(quint8 *dataY, quint8 *dataU, quint8 *dataV, quint32 linesizeY, quint32 linesizeU, quint32 linesizeV)
+{
+ if (m_textureInited) {
+ updateTexture(m_texture[0], 0, dataY, linesizeY);
+ updateTexture(m_texture[1], 1, dataU, linesizeU);
+ updateTexture(m_texture[2], 2, dataV, linesizeV);
+ update();
+ }
+}
+
+void QYUVOpenGLWidget::initializeGL()
+{
+ initializeOpenGLFunctions();
+ glDisable(GL_DEPTH_TEST);
+
+ // 顶点缓冲对象初始化
+ m_vbo.create();
+ m_vbo.bind();
+ m_vbo.allocate(coordinate, sizeof(coordinate));
+ initShader();
+ // 设置背景清理色为黑色
+ glClearColor(0.0,0.0,0.0,0.0);
+ // 清理颜色背景
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+void QYUVOpenGLWidget::paintGL()
+{
+ if (m_needUpdate) {
+ deInitTextures();
+ initTextures();
+ m_needUpdate = false;
+ }
+
+ if (m_textureInited) {
+ 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);
+ }
+}
+
+void QYUVOpenGLWidget::resizeGL(int width, int height)
+{
+ glViewport(0, 0, width, height);
+ repaint();
+}
+
+void QYUVOpenGLWidget::initShader()
+{
+ // opengles的float、int等要手动指定精度
+ if (QCoreApplication::testAttribute(Qt::AA_UseOpenGLES)) {
+ s_fragShader.prepend(R"(
+ precision mediump int;
+ precision mediump float;
+ )");
+ }
+ m_shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, s_vertShader);
+ m_shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, s_fragShader);
+ m_shaderProgram.link();
+ m_shaderProgram.bind();
+
+ // 指定顶点坐标在vbo中的访问方式
+ // 参数解释:顶点坐标在shader中的参数名称,顶点坐标为float,起始偏移为0,顶点坐标类型为vec3,步幅为3个float
+ m_shaderProgram.setAttributeBuffer("vertexIn", GL_FLOAT, 0, 3, 3 * sizeof(float));
+ // 启用顶点属性
+ m_shaderProgram.enableAttributeArray("vertexIn");
+
+ // 指定纹理坐标在vbo中的访问方式
+ // 参数解释:纹理坐标在shader中的参数名称,纹理坐标为float,起始偏移为12个float(跳过前面存储的12个顶点坐标),纹理坐标类型为vec2,步幅为2个float
+ m_shaderProgram.setAttributeBuffer("textureIn", GL_FLOAT, 12 * sizeof(float), 2, 2 * sizeof(float));
+ m_shaderProgram.enableAttributeArray("textureIn");
+
+ // 关联片段着色器中的纹理单元和opengl中的纹理单元(opengl一般提供16个纹理单元)
+ m_shaderProgram.setUniformValue("textureY", 0);
+ m_shaderProgram.setUniformValue("textureU", 1);
+ m_shaderProgram.setUniformValue("textureV", 2);
+}
+
+void QYUVOpenGLWidget::initTextures()
+{
+ // 创建纹理
+ 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);
+
+ m_textureInited = true;
+}
+
+void QYUVOpenGLWidget::deInitTextures()
+{
+ glDeleteTextures(3, m_texture);
+ memset(m_texture, 0, 3);
+ m_textureInited = false;
+}
+
+void QYUVOpenGLWidget::updateTexture(GLuint texture, quint32 textureType, quint8 *pixels, quint32 stride)
+{
+ if (!pixels)
+ return;
+
+ QSize size = 0 == textureType ? m_frameSize : m_frameSize/2;
+
+ makeCurrent();
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size.width(), size.height(), GL_RED, GL_UNSIGNED_BYTE, pixels);
+ doneCurrent();
+}
diff --git a/src/qyuvopenglwidget.h b/src/render/qyuvopenglwidget.h
similarity index 96%
rename from src/qyuvopenglwidget.h
rename to src/render/qyuvopenglwidget.h
index ed7fff0..d9d4f1b 100644
--- a/src/qyuvopenglwidget.h
+++ b/src/render/qyuvopenglwidget.h
@@ -1,49 +1,49 @@
-#ifndef QYUVOPENGLWIDGET_H
-#define QYUVOPENGLWIDGET_H
-#include
-#include
-#include
-#include
-
-class QYUVOpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
-{
- Q_OBJECT
-public:
- explicit QYUVOpenGLWidget(QWidget *parent = nullptr);
- virtual ~QYUVOpenGLWidget();
-
- QSize minimumSizeHint() const override;
- QSize sizeHint() const override;
-
- void setFrameSize(const QSize& frameSize);
- const QSize& frameSize();
- void updateTextures(quint8* dataY, quint8* dataU, quint8* dataV, quint32 linesizeY, quint32 linesizeU, quint32 linesizeV);
-
-protected:
- void initializeGL();
- void paintGL();
- void resizeGL(int width, int height);
-
-private:
- void initShader();
- void initTextures();
- void deInitTextures();
- void updateTexture(GLuint texture, quint32 textureType, quint8* pixels, quint32 stride);
-
-private:
- // 视频帧尺寸
- QSize m_frameSize = {-1, -1};
- bool m_needUpdate = false;
- bool m_textureInited = false;
-
- // 顶点缓冲对象(Vertex Buffer Objects, VBO):默认即为VertexBuffer(GL_ARRAY_BUFFER)类型
- QOpenGLBuffer m_vbo;
-
- // 着色器程序:编译链接着色器
- QOpenGLShaderProgram m_shaderProgram;
-
- // YUV纹理,用于生成纹理贴图
- GLuint m_texture[3] = {0};
-};
-
-#endif // QYUVOPENGLWIDGET_H
+#ifndef QYUVOPENGLWIDGET_H
+#define QYUVOPENGLWIDGET_H
+#include
+#include
+#include
+#include
+
+class QYUVOpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
+{
+ Q_OBJECT
+public:
+ explicit QYUVOpenGLWidget(QWidget *parent = nullptr);
+ virtual ~QYUVOpenGLWidget();
+
+ QSize minimumSizeHint() const override;
+ QSize sizeHint() const override;
+
+ void setFrameSize(const QSize& frameSize);
+ const QSize& frameSize();
+ void updateTextures(quint8* dataY, quint8* dataU, quint8* dataV, quint32 linesizeY, quint32 linesizeU, quint32 linesizeV);
+
+protected:
+ void initializeGL();
+ void paintGL();
+ void resizeGL(int width, int height);
+
+private:
+ void initShader();
+ void initTextures();
+ void deInitTextures();
+ void updateTexture(GLuint texture, quint32 textureType, quint8* pixels, quint32 stride);
+
+private:
+ // 视频帧尺寸
+ QSize m_frameSize = {-1, -1};
+ bool m_needUpdate = false;
+ bool m_textureInited = false;
+
+ // 顶点缓冲对象(Vertex Buffer Objects, VBO):默认即为VertexBuffer(GL_ARRAY_BUFFER)类型
+ QOpenGLBuffer m_vbo;
+
+ // 着色器程序:编译链接着色器
+ QOpenGLShaderProgram m_shaderProgram;
+
+ // YUV纹理,用于生成纹理贴图
+ GLuint m_texture[3] = {0};
+};
+
+#endif // QYUVOPENGLWIDGET_H
diff --git a/src/render/render.pri b/src/render/render.pri
new file mode 100644
index 0000000..357d548
--- /dev/null
+++ b/src/render/render.pri
@@ -0,0 +1,5 @@
+HEADERS += \
+ $$PWD/qyuvopenglwidget.h
+
+SOURCES += \
+ $$PWD/qyuvopenglwidget.cpp
diff --git a/src/devicesocket.cpp b/src/server/devicesocket.cpp
similarity index 100%
rename from src/devicesocket.cpp
rename to src/server/devicesocket.cpp
diff --git a/src/devicesocket.h b/src/server/devicesocket.h
similarity index 100%
rename from src/devicesocket.h
rename to src/server/devicesocket.h
diff --git a/src/server.cpp b/src/server/server.cpp
similarity index 100%
rename from src/server.cpp
rename to src/server/server.cpp
diff --git a/src/server.h b/src/server/server.h
similarity index 100%
rename from src/server.h
rename to src/server/server.h
diff --git a/src/server/server.pri b/src/server/server.pri
new file mode 100644
index 0000000..428d8e4
--- /dev/null
+++ b/src/server/server.pri
@@ -0,0 +1,9 @@
+HEADERS += \
+ $$PWD/devicesocket.h \
+ $$PWD/server.h \
+ $$PWD/tcpserver.h
+
+SOURCES += \
+ $$PWD/devicesocket.cpp \
+ $$PWD/server.cpp \
+ $$PWD/tcpserver.cpp
diff --git a/src/tcpserver.cpp b/src/server/tcpserver.cpp
similarity index 94%
rename from src/tcpserver.cpp
rename to src/server/tcpserver.cpp
index fdc9a64..bddb56d 100644
--- a/src/tcpserver.cpp
+++ b/src/server/tcpserver.cpp
@@ -1,19 +1,19 @@
-#include "tcpserver.h"
-#include "devicesocket.h"
-
-TcpServer::TcpServer(QObject *parent) : QTcpServer(parent)
-{
-
-}
-
-TcpServer::~TcpServer()
-{
-
-}
-
-void TcpServer::incomingConnection(qintptr handle)
-{
- DeviceSocket *socket = new DeviceSocket();
- socket->setSocketDescriptor(handle);
- addPendingConnection(socket);
-}
+#include "tcpserver.h"
+#include "devicesocket.h"
+
+TcpServer::TcpServer(QObject *parent) : QTcpServer(parent)
+{
+
+}
+
+TcpServer::~TcpServer()
+{
+
+}
+
+void TcpServer::incomingConnection(qintptr handle)
+{
+ DeviceSocket *socket = new DeviceSocket();
+ socket->setSocketDescriptor(handle);
+ addPendingConnection(socket);
+}
diff --git a/src/tcpserver.h b/src/server/tcpserver.h
similarity index 94%
rename from src/tcpserver.h
rename to src/server/tcpserver.h
index 7156814..d8e52be 100644
--- a/src/tcpserver.h
+++ b/src/server/tcpserver.h
@@ -1,17 +1,17 @@
-#ifndef TCPSERVER_H
-#define TCPSERVER_H
-
-#include
-
-class TcpServer : public QTcpServer
-{
- Q_OBJECT
-public:
- explicit TcpServer(QObject *parent = nullptr);
- virtual ~TcpServer();
-
-protected:
- virtual void incomingConnection(qintptr handle);
-};
-
-#endif // TCPSERVER_H
+#ifndef TCPSERVER_H
+#define TCPSERVER_H
+
+#include
+
+class TcpServer : public QTcpServer
+{
+ Q_OBJECT
+public:
+ explicit TcpServer(QObject *parent = nullptr);
+ virtual ~TcpServer();
+
+protected:
+ virtual void incomingConnection(qintptr handle);
+};
+
+#endif // TCPSERVER_H