diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..0642203 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,13 @@ + +# These are supported funding model platforms + +github: barry-ran +patreon: # Replace with a single Patreon username +open_collective: QtScrcpy +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: ["https://paypal.me/QtScrcpy", "https://gitee.com/Barryda/MyPictureBed/blob/master/QtScrcpy/payme.md"] \ No newline at end of file diff --git a/QtScrcpy/device/decoder/fpscounter.cpp b/QtScrcpy/device/decoder/fpscounter.cpp index 0bb099f..e59bb40 100644 --- a/QtScrcpy/device/decoder/fpscounter.cpp +++ b/QtScrcpy/device/decoder/fpscounter.cpp @@ -40,6 +40,7 @@ void FpsCounter::timerEvent(QTimerEvent *event) m_curRendered = m_rendered; m_curSkipped = m_skipped; resetCounter(); + emit updateFPS(m_curRendered); //qInfo("FPS:%d Discard:%d", m_curRendered, m_skipped); } } diff --git a/QtScrcpy/device/decoder/fpscounter.h b/QtScrcpy/device/decoder/fpscounter.h index badb958..50a8d7a 100644 --- a/QtScrcpy/device/decoder/fpscounter.h +++ b/QtScrcpy/device/decoder/fpscounter.h @@ -15,6 +15,9 @@ public: void addRenderedFrame(); void addSkippedFrame(); +signals: + void updateFPS(quint32 fps); + protected: virtual void timerEvent(QTimerEvent *event); diff --git a/QtScrcpy/device/decoder/videobuffer.cpp b/QtScrcpy/device/decoder/videobuffer.cpp index 6ddecbd..f41e922 100644 --- a/QtScrcpy/device/decoder/videobuffer.cpp +++ b/QtScrcpy/device/decoder/videobuffer.cpp @@ -115,6 +115,11 @@ void VideoBuffer::interrupt() } } +FpsCounter *VideoBuffer::getFPSCounter() +{ + return &m_fpsCounter; +} + void VideoBuffer::swap() { AVFrame *tmp = m_decodingFrame; diff --git a/QtScrcpy/device/decoder/videobuffer.h b/QtScrcpy/device/decoder/videobuffer.h index fad772a..908cbc6 100644 --- a/QtScrcpy/device/decoder/videobuffer.h +++ b/QtScrcpy/device/decoder/videobuffer.h @@ -37,6 +37,8 @@ public: // wake up and avoid any blocking call void interrupt(); + FpsCounter *getFPSCounter(); + private: void swap(); diff --git a/QtScrcpy/device/device.cpp b/QtScrcpy/device/device.cpp index fe87af9..6f4609b 100644 --- a/QtScrcpy/device/device.cpp +++ b/QtScrcpy/device/device.cpp @@ -277,6 +277,7 @@ void Device::initSignals() m_vb->unLock(); }, Qt::QueuedConnection); + connect(m_vb->getFPSCounter(), &::FpsCounter::updateFPS, m_videoForm, &VideoForm::updateFPS); } } diff --git a/QtScrcpy/device/ui/videoform.cpp b/QtScrcpy/device/ui/videoform.cpp index c6b9428..5f41be0 100644 --- a/QtScrcpy/device/ui/videoform.cpp +++ b/QtScrcpy/device/ui/videoform.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -68,6 +69,16 @@ void VideoForm::initUI() ui->keepRadioWidget->setWidget(m_videoWidget); ui->keepRadioWidget->setWidthHeightRadio(m_widthHeightRatio); + m_fpsLabel = new QLabel(m_videoWidget); + QFont ft; + ft.setPointSize(15); + ft.setWeight(QFont::Light); + ft.setBold(true); + m_fpsLabel->setFont(ft); + m_fpsLabel->move(5, 15); + m_fpsLabel->setMinimumWidth(100); + m_fpsLabel->setStyleSheet(R"(QLabel {color: #00FF00;})"); + setMouseTracking(true); m_videoWidget->setMouseTracking(true); ui->keepRadioWidget->setMouseTracking(true); @@ -115,6 +126,14 @@ void VideoForm::removeBlackRect() resize(ui->keepRadioWidget->goodSize()); } +void VideoForm::showFPS(bool show) +{ + if (!m_fpsLabel) { + return; + } + m_fpsLabel->setVisible(show); +} + void VideoForm::updateRender(const AVFrame *frame) { if (m_videoWidget->isHidden()) { @@ -429,6 +448,15 @@ void VideoForm::onSwitchFullScreen() } } +void VideoForm::updateFPS(quint32 fps) +{ + qDebug() << "FPS:" << fps; + if (!m_fpsLabel) { + return; + } + m_fpsLabel->setText(QString("FPS:%1").arg(fps)); +} + void VideoForm::staysOnTop(bool top) { bool needShow = false; diff --git a/QtScrcpy/device/ui/videoform.h b/QtScrcpy/device/ui/videoform.h index e000f5a..bda37a4 100644 --- a/QtScrcpy/device/ui/videoform.h +++ b/QtScrcpy/device/ui/videoform.h @@ -14,6 +14,7 @@ class ToolForm; class Device; class FileHandler; class QYUVOpenGLWidget; +class QLabel; class VideoForm : public QWidget { Q_OBJECT @@ -29,9 +30,11 @@ public: const QSize &frameSize(); void resizeSquare(); void removeBlackRect(); + void showFPS(bool show); public slots: void onSwitchFullScreen(); + void updateFPS(quint32 fps); private: void updateStyleSheet(bool vertical); @@ -68,6 +71,7 @@ private: QPointer m_toolForm; QPointer m_loadingWidget; QPointer m_videoWidget; + QPointer m_fpsLabel; //inside member QSize m_frameSize; diff --git a/QtScrcpy/devicemanage/devicemanage.cpp b/QtScrcpy/devicemanage/devicemanage.cpp index 9d6e113..6bcfcaa 100644 --- a/QtScrcpy/devicemanage/devicemanage.cpp +++ b/QtScrcpy/devicemanage/devicemanage.cpp @@ -76,6 +76,21 @@ bool DeviceManage::staysOnTop(const QString &serial) return true; } +void DeviceManage::showFPS(const QString &serial, bool show) +{ + if (!serial.isEmpty() && m_devices.contains(serial)) { + auto it = m_devices.find(serial); + if (!it->data()) { + return; + } + if (!it->data()->getVideoForm()) { + return; + } + it->data()->getVideoForm()->showFPS(show); + } + return; +} + bool DeviceManage::disconnectDevice(const QString &serial) { bool ret = false; diff --git a/QtScrcpy/devicemanage/devicemanage.h b/QtScrcpy/devicemanage/devicemanage.h index 1d0250a..968a6e0 100644 --- a/QtScrcpy/devicemanage/devicemanage.h +++ b/QtScrcpy/devicemanage/devicemanage.h @@ -16,6 +16,7 @@ public: bool connectDevice(Device::DeviceParams params); void updateScript(QString script); bool staysOnTop(const QString &serial); + void showFPS(const QString &serial, bool show); bool disconnectDevice(const QString &serial); void disconnectAllDevice(); diff --git a/QtScrcpy/dialog.cpp b/QtScrcpy/dialog.cpp index 722da32..38fa4d8 100644 --- a/QtScrcpy/dialog.cpp +++ b/QtScrcpy/dialog.cpp @@ -188,6 +188,7 @@ void Dialog::on_startServerBtn_clicked() if (ui->alwaysTopCheck->isChecked()) { m_deviceManage.staysOnTop(params.serial); } + m_deviceManage.showFPS(params.serial, ui->fpsCheck->isChecked()); } void Dialog::on_stopServerBtn_clicked() diff --git a/QtScrcpy/dialog.ui b/QtScrcpy/dialog.ui index 9060e15..05c7eef 100644 --- a/QtScrcpy/dialog.ui +++ b/QtScrcpy/dialog.ui @@ -208,10 +208,23 @@ 0 - - + + + + + 0 + 0 + + - record screen + screen-off + + + + + + + frameless @@ -231,8 +244,8 @@ - - + + 0 @@ -240,7 +253,10 @@ - screen-off + background record + + + false @@ -260,26 +276,17 @@ - - - - - 0 - 0 - - + + - background record - - - false + record screen - - + + - frameless + show fps diff --git a/QtScrcpy/res/i18n/QtScrcpy_en.qm b/QtScrcpy/res/i18n/QtScrcpy_en.qm index 2db842e..62f5dce 100644 Binary files a/QtScrcpy/res/i18n/QtScrcpy_en.qm and b/QtScrcpy/res/i18n/QtScrcpy_en.qm differ diff --git a/QtScrcpy/res/i18n/QtScrcpy_en.ts b/QtScrcpy/res/i18n/QtScrcpy_en.ts index 8321b51..4b9df55 100644 --- a/QtScrcpy/res/i18n/QtScrcpy_en.ts +++ b/QtScrcpy/res/i18n/QtScrcpy_en.ts @@ -16,22 +16,22 @@ file transfer failed - + install apk install apk - + file transfer file transfer - + wait current %1 to complete wait current %1 to complete - + %1 complete, save in %2 %1 complete, save in %2 @@ -41,7 +41,7 @@ %1 complete\n save in %2 - + %1 failed %1 failed @@ -49,17 +49,17 @@ Dialog - + Wireless Wireless - + wireless connect wireless connect - + wireless disconnect wireless disconnect @@ -75,7 +75,7 @@ - + select path select path @@ -85,42 +85,47 @@ record format: - + record screen record screen - + frameless frameless - + + show fps + show fps + + + stop all server stop all server - + adb command: adb command: - + terminate terminate - + execute execute - + clear clear - + reverse connection reverse connection @@ -129,12 +134,12 @@ auto enable - + background record background record - + screen-off screen-off @@ -149,7 +154,7 @@ max size: - + always on top always on top @@ -159,27 +164,27 @@ refresh script - + get device IP get device IP - + USB line USB line - + stop server stop server - + start server start server - + device serial: device serial: @@ -193,17 +198,17 @@ bit rate: - + start adbd start adbd - + refresh devices refresh devices - + original original @@ -221,7 +226,7 @@ You can download it at the following address: This software is completely open source and free.\nStrictly used for illegal purposes, or at your own risk.\nYou can download it at the following address: - + This software is completely open source and free. Strictly used for illegal purposes, or at your own risk. You can download it at the following address: This software is completely open source and free. Strictly used for illegal purposes, or at your own risk. You can download it at the following address: @@ -317,7 +322,7 @@ You can download it at the following address: file transfer failed - + file does not exist file does not exist diff --git a/QtScrcpy/res/i18n/QtScrcpy_zh.qm b/QtScrcpy/res/i18n/QtScrcpy_zh.qm index e5ce84d..2a6e5c8 100644 Binary files a/QtScrcpy/res/i18n/QtScrcpy_zh.qm and b/QtScrcpy/res/i18n/QtScrcpy_zh.qm differ diff --git a/QtScrcpy/res/i18n/QtScrcpy_zh.ts b/QtScrcpy/res/i18n/QtScrcpy_zh.ts index 40d4e3a..bb0223f 100644 --- a/QtScrcpy/res/i18n/QtScrcpy_zh.ts +++ b/QtScrcpy/res/i18n/QtScrcpy_zh.ts @@ -16,22 +16,22 @@ 文件传输失败 - + install apk 安装apk - + file transfer 文件传输 - + wait current %1 to complete 等待当前%1完成 - + %1 complete, save in %2 %1完成,保存在%2 @@ -41,7 +41,7 @@ %1完成\n 保存在 %2 - + %1 failed %1 失败 @@ -49,17 +49,17 @@ Dialog - + Wireless 无线 - + wireless connect 无线连接 - + wireless disconnect 无线断开 @@ -75,7 +75,7 @@ - + select path 选择路径 @@ -85,42 +85,47 @@ 录制格式: - + record screen 录制屏幕 - + frameless 无边框 - + + show fps + 显示fps + + + stop all server 停止所有服务 - + adb command: adb命令: - + terminate 终止 - + execute 执行 - + clear 清理 - + reverse connection 反向连接 @@ -129,12 +134,12 @@ 自动启用脚本 - + background record 后台录制 - + screen-off 自动息屏 @@ -149,7 +154,7 @@ 最大尺寸: - + always on top 窗口置顶 @@ -159,27 +164,27 @@ 刷新脚本 - + get device IP 获取设备IP - + USB line USB线 - + stop server 停止服务 - + start server 启动服务 - + device serial: 设备序列号: @@ -193,17 +198,17 @@ 比特率: - + start adbd 启动adbd - + refresh devices 刷新设备列表 - + original 原始 @@ -221,7 +226,7 @@ You can download it at the following address: 本软件完全开源免费.\n严禁用于非法用途,否则后果自负.\n你可以在下面地址下载: - + This software is completely open source and free. Strictly used for illegal purposes, or at your own risk. You can download it at the following address: 本软件完全开源免费,严禁用于非法用途,否则后果自负,你可以在下面地址下载: @@ -317,7 +322,7 @@ You can download it at the following address: 文件传输失败 - + file does not exist 文件不存在 diff --git a/README.md b/README.md index c381a4b..11fc4e8 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # QtScrcpy +[![Financial Contributors on Open Collective](https://opencollective.com/QtScrcpy/all/badge.svg?label=financial+contributors)](https://opencollective.com/QtScrcpy) ![Windows](https://github.com/barry-ran/QtScrcpy/workflows/Windows/badge.svg) ![MacOS](https://github.com/barry-ran/QtScrcpy/workflows/MacOS/badge.svg) ![Ubuntu](https://github.com/barry-ran/QtScrcpy/workflows/Ubuntu/badge.svg) @@ -51,6 +52,11 @@ Here is the instruction of adding new customized mapping files. - Press the ~ key again to switch back to normal mode - (For PUBG and similar games) If you want to drive cars with WASD, you need to check the `single rocker mode` in the game setting. +## Group control +You can control all your phones at the same time. + +![](docs/image/group-control.gif) + ## Thanks QtScrcpy is based on [Genymobile's](https://github.com/Genymobile) [scrcpy](https://github.com/Genymobile/scrcpy) project. Thanks @@ -65,7 +71,7 @@ video render|sdl|opengl cross-platform|self implemented|provided by Qt language|C|C++ style|sync|async -control|single touch|single/multi touch +keymap|no custom keymap|support custom keymap build|meson+gradle|Qt Creator - It's very easy to customize your GUI with Qt @@ -264,3 +270,33 @@ Since it is based on scrcpy, respect its Licence [Barry CSDN](https://blog.csdn.net/rankun1) An ordinary programmer, working mainly in C++ for desktop client development, graduated from Shandong for more than a year of steel simulation education software, and later moved to Shanghai to work in security, online education related fields, familiar with audio and video. I have an understanding of audio and video fields such as voice calls, live education, video conferencing and other related solutions. At the same time have android, linux server and other development experience. + +## Contributors + +### Code Contributors + +This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. + + +### Financial Contributors + +Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/QtScrcpy/contribute)] + +#### Individuals + + + +#### Organizations + +Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/QtScrcpy/contribute)] + + + + + + + + + + + \ No newline at end of file diff --git a/README_zh.md b/README_zh.md index acbb6ce..109c6a4 100644 --- a/README_zh.md +++ b/README_zh.md @@ -51,6 +51,11 @@ QtScrcpy可以通过USB(或通过TCP/IP)连接Android设备,并进行显示和 - 再次按~键切换为正常控制模式 - 要想wasd控制开车记得在载具设置中设置为单摇杆模式 +## 群控 +你可以同时控制所有的手机 + +![gc](docs/image/group-control.gif) + ## 感谢 基于[Genymobile](https://github.com/Genymobile)的[scrcpy](https://github.com/Genymobile/scrcpy)项目进行复刻,重构,非常感谢。QtScrcpy和原版scrcpy区别如下: @@ -63,7 +68,7 @@ QtScrcpy可以通过USB(或通过TCP/IP)连接Android设备,并进行显示和 跨平台基础设施|自己封装|Qt提供 编程语言|C|C++ 编程方式|同步|异步 -控制方式|单点触控|单点/多点触控 +按键映射|不支持自定义|支持自定义按键映射 编译方式|meson+gradle|Qt Creator - 使用Qt可以非常容易的定制自己的界面 diff --git a/docs/FAQ.md b/docs/FAQ.md index 91c9864..7ea6efa 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -26,6 +26,11 @@ QtScrcpy.exe>属性>兼容性>更改高DPI设置>覆盖高DPI缩放行为>由以 ![image](image/USB调试(安全设置).jpg) +## 可以控制,但无法看到画面 +控制台错误信息可能会包含 QOpenGLShaderProgram::attributeLocation(vertexIn): shader program is not linked + +一般是由于显卡不支持当前的视频渲染方式,config.ini里修改下解码方式,改成1或者2试试 + ## 手机通过数据线连接电脑,刷新设备列表以后,没有任何设备出现 随便下载一个手机助手,尝试连接成功以后,再用QtScrcpy刷新设备列表连接 @@ -35,6 +40,3 @@ QtScrcpy.exe>属性>兼容性>更改高DPI设置>覆盖高DPI缩放行为>由以 ## 错误信息:Could not open video stream 导致这个错误的原因有很多,最简单的解决方法是在分辨率设置中,选择一个较低的分辨率 -## 错误信息:QOpenGLShaderProgram::attributeLocation(vertexIn): shader program is not linked -config.ini里修改下解码方式,改成1或者2试试 - diff --git a/docs/image/group-control.gif b/docs/image/group-control.gif new file mode 100644 index 0000000..1d7f3dc Binary files /dev/null and b/docs/image/group-control.gif differ