mirror of
https://github.com/barry-ran/QtScrcpy.git
synced 2025-08-01 13:28:38 +00:00
update:抽象出device,为多台连接做准备
This commit is contained in:
parent
0bd076d4ae
commit
d7fbd2671b
15 changed files with 364 additions and 215 deletions
|
@ -33,19 +33,13 @@ contains(DEFINES, USE_QTQUICK) {
|
||||||
# 源码
|
# 源码
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
main.cpp \
|
main.cpp \
|
||||||
dialog.cpp \
|
dialog.cpp
|
||||||
videoform.cpp \
|
|
||||||
toolform.cpp
|
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
dialog.h \
|
dialog.h
|
||||||
videoform.h \
|
|
||||||
toolform.h
|
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
dialog.ui \
|
dialog.ui
|
||||||
videoform.ui \
|
|
||||||
toolform.ui
|
|
||||||
|
|
||||||
# 子工程
|
# 子工程
|
||||||
include ($$PWD/common/common.pri)
|
include ($$PWD/common/common.pri)
|
||||||
|
@ -61,6 +55,8 @@ include ($$PWD/fontawesome/fontawesome.pri)
|
||||||
include ($$PWD/filehandler/filehandler.pri)
|
include ($$PWD/filehandler/filehandler.pri)
|
||||||
include ($$PWD/recorder/recorder.pri)
|
include ($$PWD/recorder/recorder.pri)
|
||||||
include ($$PWD/util/util.pri)
|
include ($$PWD/util/util.pri)
|
||||||
|
include ($$PWD/device/device.pri)
|
||||||
|
include ($$PWD/ui/ui.pri)
|
||||||
|
|
||||||
# 附加包含路径
|
# 附加包含路径
|
||||||
INCLUDEPATH += \
|
INCLUDEPATH += \
|
||||||
|
@ -77,6 +73,8 @@ INCLUDEPATH += \
|
||||||
$$PWD/filehandler \
|
$$PWD/filehandler \
|
||||||
$$PWD/recorder \
|
$$PWD/recorder \
|
||||||
$$PWD/util \
|
$$PWD/util \
|
||||||
|
$$PWD/device \
|
||||||
|
$$PWD/ui \
|
||||||
$$PWD/fontawesome
|
$$PWD/fontawesome
|
||||||
|
|
||||||
|
|
||||||
|
|
169
QtScrcpy/device/device.cpp
Normal file
169
QtScrcpy/device/device.cpp
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
#include "recorder.h"
|
||||||
|
#include "server.h"
|
||||||
|
#include "videobuffer.h"
|
||||||
|
#include "decoder.h"
|
||||||
|
#include "filehandler.h"
|
||||||
|
#include "stream.h"
|
||||||
|
#include "videoform.h"
|
||||||
|
|
||||||
|
Device::Device(DeviceParams params, QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_params(params)
|
||||||
|
{
|
||||||
|
m_vb = new VideoBuffer();
|
||||||
|
m_vb->init();
|
||||||
|
m_decoder = new Decoder(m_vb, this);
|
||||||
|
m_stream = new Stream(this);
|
||||||
|
m_stream->setDecoder(m_decoder);
|
||||||
|
|
||||||
|
m_server = new Server(this);
|
||||||
|
m_controller = new Controller(this);
|
||||||
|
m_fileHandler = new FileHandler(this);
|
||||||
|
|
||||||
|
if (!m_params.recordFileName.trimmed().isEmpty()) {
|
||||||
|
m_recorder = new Recorder(m_params.recordFileName);
|
||||||
|
m_stream->setRecoder(m_recorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_videoForm = new VideoForm();
|
||||||
|
m_videoForm->setController(m_controller);
|
||||||
|
m_videoForm->show();
|
||||||
|
|
||||||
|
initSignals();
|
||||||
|
startServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
Device::~Device()
|
||||||
|
{
|
||||||
|
if (m_server) {
|
||||||
|
m_server->stop();
|
||||||
|
}
|
||||||
|
// server must stop before decoder, because decoder block main thread
|
||||||
|
if (m_stream) {
|
||||||
|
m_stream->stopDecode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_recorder) {
|
||||||
|
delete m_recorder;
|
||||||
|
}
|
||||||
|
if (m_vb) {
|
||||||
|
m_vb->deInit();
|
||||||
|
delete m_vb;
|
||||||
|
}
|
||||||
|
if (m_videoForm) {
|
||||||
|
delete m_videoForm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoForm *Device::getVideoForm()
|
||||||
|
{
|
||||||
|
return m_videoForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::initSignals()
|
||||||
|
{
|
||||||
|
if (m_videoForm) {
|
||||||
|
connect(m_controller, &Controller::grabCursor, m_videoForm, &VideoForm::onGrabCursor);
|
||||||
|
}
|
||||||
|
if (m_fileHandler) {
|
||||||
|
connect(m_fileHandler, &FileHandler::fileHandlerResult, this, [this](FileHandler::FILE_HANDLER_RESULT processResult){
|
||||||
|
if (FileHandler::FAR_IS_RUNNING == processResult && m_videoForm) {
|
||||||
|
QMessageBox::warning(m_videoForm, "QtScrcpy", tr("wait current file transfer to complete"), QMessageBox::Ok);
|
||||||
|
}
|
||||||
|
if (FileHandler::FAR_SUCCESS_EXEC == processResult && m_videoForm) {
|
||||||
|
QMessageBox::information(m_videoForm, "QtScrcpy", tr("file transfer complete"), QMessageBox::Ok);
|
||||||
|
}
|
||||||
|
if (FileHandler::FAR_ERROR_EXEC == processResult && m_videoForm) {
|
||||||
|
QMessageBox::information(m_videoForm, "QtScrcpy", tr("file transfer failed"), QMessageBox::Ok);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_server) {
|
||||||
|
connect(m_server, &Server::serverStartResult, this, [this](bool success){
|
||||||
|
if (success) {
|
||||||
|
m_server->connectTo();
|
||||||
|
} else {
|
||||||
|
deleteLater();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
connect(m_server, &Server::connectToResult, this, [this](bool success, const QString &deviceName, const QSize &size){
|
||||||
|
if (success) {
|
||||||
|
float diff = m_startTimeCount.elapsed() / 1000.0f;
|
||||||
|
qInfo(QString("server start finish in %1s").arg(diff).toStdString().c_str());
|
||||||
|
|
||||||
|
// update ui
|
||||||
|
if (m_videoForm) {
|
||||||
|
m_videoForm->setWindowTitle(deviceName);
|
||||||
|
m_videoForm->updateShowSize(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// init recorder
|
||||||
|
if (m_recorder) {
|
||||||
|
m_recorder->setFrameSize(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// init decoder
|
||||||
|
m_stream->setVideoSocket(m_server->getVideoSocket());
|
||||||
|
m_stream->startDecode();
|
||||||
|
|
||||||
|
// init controller
|
||||||
|
m_controller->setControlSocket(m_server->getControlSocket());
|
||||||
|
|
||||||
|
if (m_params.closeScreen && m_controller) {
|
||||||
|
m_controller->setScreenPowerMode(ControlMsg::SPM_OFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
connect(m_server, &Server::onServerStop, this, [this](){
|
||||||
|
deleteLater();
|
||||||
|
qDebug() << "server process stop";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_stream) {
|
||||||
|
connect(m_stream, &Stream::onStreamStop, this, [this](){
|
||||||
|
deleteLater();
|
||||||
|
qDebug() << "stream thread stop";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_decoder) {
|
||||||
|
// must be Qt::QueuedConnection, ui update must be main thread
|
||||||
|
connect(m_decoder, &Decoder::onNewFrame, this, [this](){
|
||||||
|
m_vb->lock();
|
||||||
|
const AVFrame *frame = m_vb->consumeRenderedFrame();
|
||||||
|
if (m_videoForm) {
|
||||||
|
m_videoForm->updateRender(frame);
|
||||||
|
}
|
||||||
|
m_vb->unLock();
|
||||||
|
},Qt::QueuedConnection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::startServer()
|
||||||
|
{
|
||||||
|
// fix: macos cant recv finished signel, timer is ok
|
||||||
|
QTimer::singleShot(0, this, [this](){
|
||||||
|
m_startTimeCount.start();
|
||||||
|
// max size support 480p 720p 1080p 设备原生分辨率
|
||||||
|
// support wireless connect, example:
|
||||||
|
//m_server->start("192.168.0.174:5555", 27183, m_maxSize, m_bitRate, "");
|
||||||
|
// only one devices, serial can be null
|
||||||
|
// mark: crop input format: "width:height:x:y" or - for no crop, for example: "100:200:0:0"
|
||||||
|
// sendFrameMeta for recorder mp4
|
||||||
|
Server::ServerParams params;
|
||||||
|
params.serial = m_params.serial;
|
||||||
|
params.localPort = m_params.localPort;
|
||||||
|
params.maxSize = m_params.maxSize;
|
||||||
|
params.bitRate = m_params.bitRate;
|
||||||
|
params.crop = "-";
|
||||||
|
params.sendFrameMeta = m_recorder ? true : false;
|
||||||
|
params.control = true;
|
||||||
|
m_server->start(params);
|
||||||
|
});
|
||||||
|
}
|
54
QtScrcpy/device/device.h
Normal file
54
QtScrcpy/device/device.h
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#ifndef DEVICE_H
|
||||||
|
#define DEVICE_H
|
||||||
|
|
||||||
|
#include <QPointer>
|
||||||
|
#include <QTime>
|
||||||
|
|
||||||
|
#include "controller.h"
|
||||||
|
|
||||||
|
class Recorder;
|
||||||
|
class Server;
|
||||||
|
class VideoBuffer;
|
||||||
|
class Decoder;
|
||||||
|
class FileHandler;
|
||||||
|
class Stream;
|
||||||
|
class VideoForm;
|
||||||
|
class Device : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
struct DeviceParams {
|
||||||
|
QString recordFileName = "";
|
||||||
|
QString serial = "";
|
||||||
|
quint16 localPort = 27183;
|
||||||
|
quint16 maxSize = 0;
|
||||||
|
quint32 bitRate = 8000000;
|
||||||
|
bool closeScreen = false;
|
||||||
|
};
|
||||||
|
explicit Device(DeviceParams params, QObject *parent = nullptr);
|
||||||
|
virtual ~Device();
|
||||||
|
|
||||||
|
VideoForm *getVideoForm();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initSignals();
|
||||||
|
void startServer();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// server relevant
|
||||||
|
QPointer<Server> m_server;
|
||||||
|
QPointer<Decoder> m_decoder;
|
||||||
|
QPointer<Controller> m_controller;
|
||||||
|
QPointer<FileHandler> m_fileHandler;
|
||||||
|
QPointer<Stream> m_stream;
|
||||||
|
VideoBuffer* m_vb = Q_NULLPTR;
|
||||||
|
Recorder* m_recorder = Q_NULLPTR;
|
||||||
|
|
||||||
|
// ui
|
||||||
|
QPointer<VideoForm> m_videoForm;
|
||||||
|
|
||||||
|
QTime m_startTimeCount;
|
||||||
|
DeviceParams m_params;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DEVICE_H
|
5
QtScrcpy/device/device.pri
Normal file
5
QtScrcpy/device/device.pri
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
HEADERS += \
|
||||||
|
$$PWD/device.h
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/device.cpp
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
#include "dialog.h"
|
#include "dialog.h"
|
||||||
#include "ui_dialog.h"
|
#include "ui_dialog.h"
|
||||||
|
#include "device.h"
|
||||||
|
#include "videoform.h"
|
||||||
|
|
||||||
Dialog::Dialog(QWidget *parent) :
|
Dialog::Dialog(QWidget *parent) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
|
@ -90,7 +92,7 @@ void Dialog::on_updateDevice_clicked()
|
||||||
|
|
||||||
void Dialog::on_startServerBtn_clicked()
|
void Dialog::on_startServerBtn_clicked()
|
||||||
{
|
{
|
||||||
if (!m_videoForm) {
|
if (!m_device) {
|
||||||
QString absFilePath;
|
QString absFilePath;
|
||||||
QString fileDir(ui->recordPathEdt->text().trimmed());
|
QString fileDir(ui->recordPathEdt->text().trimmed());
|
||||||
if (!fileDir.isEmpty()) {
|
if (!fileDir.isEmpty()) {
|
||||||
|
@ -105,21 +107,25 @@ void Dialog::on_startServerBtn_clicked()
|
||||||
quint32 bitRate = ui->bitRateBox->currentText().trimmed().toUInt();
|
quint32 bitRate = ui->bitRateBox->currentText().trimmed().toUInt();
|
||||||
// this is ok that "native" toUshort is 0
|
// this is ok that "native" toUshort is 0
|
||||||
quint16 videoSize = ui->videoSizeBox->currentText().trimmed().toUShort();
|
quint16 videoSize = ui->videoSizeBox->currentText().trimmed().toUShort();
|
||||||
m_videoForm = new VideoForm(ui->serialBox->currentText().trimmed(), videoSize, bitRate,
|
Device::DeviceParams params;
|
||||||
absFilePath, ui->closeScreenCheck->isChecked());
|
params.serial = ui->serialBox->currentText().trimmed();
|
||||||
if (ui->alwaysTopCheck->isChecked()) {
|
params.maxSize = videoSize;
|
||||||
m_videoForm->staysOnTop();
|
params.bitRate = bitRate;
|
||||||
|
params.recordFileName = absFilePath;
|
||||||
|
params.closeScreen = ui->closeScreenCheck->isChecked();
|
||||||
|
m_device = new Device(params, this);
|
||||||
|
if (ui->alwaysTopCheck->isChecked() && m_device->getVideoForm()) {
|
||||||
|
m_device->getVideoForm()->staysOnTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
outLog("start server...", false);
|
outLog("start server...", false);
|
||||||
}
|
}
|
||||||
m_videoForm->show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dialog::on_stopServerBtn_clicked()
|
void Dialog::on_stopServerBtn_clicked()
|
||||||
{
|
{
|
||||||
if (m_videoForm) {
|
if (m_device) {
|
||||||
m_videoForm->close();
|
m_device->deleteLater();
|
||||||
outLog("stop server");
|
outLog("stop server");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,26 +235,26 @@ void Dialog::on_recordPathEdt_textChanged(const QString &arg1)
|
||||||
|
|
||||||
void Dialog::on_alwaysTopCheck_stateChanged(int arg1)
|
void Dialog::on_alwaysTopCheck_stateChanged(int arg1)
|
||||||
{
|
{
|
||||||
if (!m_videoForm) {
|
if (!m_device || m_device->getVideoForm()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Qt::Checked == arg1) {
|
if (Qt::Checked == arg1) {
|
||||||
m_videoForm->staysOnTop(true);
|
m_device->getVideoForm()->staysOnTop(true);
|
||||||
} else {
|
} else {
|
||||||
m_videoForm->staysOnTop(false);
|
m_device->getVideoForm()->staysOnTop(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dialog::on_closeScreenCheck_stateChanged(int arg1)
|
void Dialog::on_closeScreenCheck_stateChanged(int arg1)
|
||||||
{
|
{
|
||||||
Q_UNUSED(arg1);
|
Q_UNUSED(arg1);
|
||||||
if (!m_videoForm) {
|
if (!m_device || m_device->getVideoForm()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ui->closeScreenCheck->isChecked()) {
|
if (ui->closeScreenCheck->isChecked()) {
|
||||||
m_videoForm->getController()->setScreenPowerMode(ControlMsg::SPM_OFF);
|
m_device->getVideoForm()->getController()->setScreenPowerMode(ControlMsg::SPM_OFF);
|
||||||
} else {
|
} else {
|
||||||
m_videoForm->getController()->setScreenPowerMode(ControlMsg::SPM_NORMAL);
|
m_device->getVideoForm()->getController()->setScreenPowerMode(ControlMsg::SPM_NORMAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,13 @@
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
|
||||||
#include "videoform.h"
|
|
||||||
#include "adbprocess.h"
|
#include "adbprocess.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class Dialog;
|
class Dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Device;
|
||||||
class QYUVOpenGLWidget;
|
class QYUVOpenGLWidget;
|
||||||
class Dialog : public QDialog
|
class Dialog : public QDialog
|
||||||
{
|
{
|
||||||
|
@ -52,7 +52,7 @@ private:
|
||||||
private:
|
private:
|
||||||
Ui::Dialog *ui;
|
Ui::Dialog *ui;
|
||||||
AdbProcess m_adb;
|
AdbProcess m_adb;
|
||||||
QPointer<VideoForm> m_videoForm;
|
QPointer<Device> m_device;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DIALOG_H
|
#endif // DIALOG_H
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <QTcpSocket>
|
#include <QTcpSocket>
|
||||||
#include <QTcpServer>
|
#include <QTcpServer>
|
||||||
#include <QTranslator>
|
#include <QTranslator>
|
||||||
|
#include <QFile>
|
||||||
|
|
||||||
#include "dialog.h"
|
#include "dialog.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "ui_toolform.h"
|
#include "ui_toolform.h"
|
||||||
#include "iconhelper.h"
|
#include "iconhelper.h"
|
||||||
#include "videoform.h"
|
#include "videoform.h"
|
||||||
|
#include "controller.h"
|
||||||
|
|
||||||
ToolForm::ToolForm(QWidget* adsorbWidget, AdsorbPositions adsorbPos)
|
ToolForm::ToolForm(QWidget* adsorbWidget, AdsorbPositions adsorbPos)
|
||||||
: MagneticWidget(adsorbWidget, adsorbPos)
|
: MagneticWidget(adsorbWidget, adsorbPos)
|
||||||
|
@ -81,63 +82,63 @@ void ToolForm::on_fullScreenBtn_clicked()
|
||||||
|
|
||||||
void ToolForm::on_returnBtn_clicked()
|
void ToolForm::on_returnBtn_clicked()
|
||||||
{
|
{
|
||||||
if (m_videoForm) {
|
if (m_videoForm && m_videoForm->getController()) {
|
||||||
m_videoForm->getController()->postGoBack();
|
m_videoForm->getController()->postGoBack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToolForm::on_homeBtn_clicked()
|
void ToolForm::on_homeBtn_clicked()
|
||||||
{
|
{
|
||||||
if (m_videoForm) {
|
if (m_videoForm && m_videoForm->getController()) {
|
||||||
m_videoForm->getController()->postGoHome();
|
m_videoForm->getController()->postGoHome();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToolForm::on_menuBtn_clicked()
|
void ToolForm::on_menuBtn_clicked()
|
||||||
{
|
{
|
||||||
if (m_videoForm) {
|
if (m_videoForm && m_videoForm->getController()) {
|
||||||
m_videoForm->getController()->postGoMenu();
|
m_videoForm->getController()->postGoMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToolForm::on_appSwitchBtn_clicked()
|
void ToolForm::on_appSwitchBtn_clicked()
|
||||||
{
|
{
|
||||||
if (m_videoForm) {
|
if (m_videoForm && m_videoForm->getController()) {
|
||||||
m_videoForm->getController()->postAppSwitch();
|
m_videoForm->getController()->postAppSwitch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToolForm::on_powerBtn_clicked()
|
void ToolForm::on_powerBtn_clicked()
|
||||||
{
|
{
|
||||||
if (m_videoForm) {
|
if (m_videoForm && m_videoForm->getController()) {
|
||||||
m_videoForm->getController()->postPower();
|
m_videoForm->getController()->postPower();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToolForm::on_volumeUpBtn_clicked()
|
void ToolForm::on_volumeUpBtn_clicked()
|
||||||
{
|
{
|
||||||
if (m_videoForm) {
|
if (m_videoForm && m_videoForm->getController()) {
|
||||||
m_videoForm->getController()->postVolumeUp();
|
m_videoForm->getController()->postVolumeUp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToolForm::on_volumeDownBtn_clicked()
|
void ToolForm::on_volumeDownBtn_clicked()
|
||||||
{
|
{
|
||||||
if (m_videoForm) {
|
if (m_videoForm && m_videoForm->getController()) {
|
||||||
m_videoForm->getController()->postVolumeDown();
|
m_videoForm->getController()->postVolumeDown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToolForm::on_closeScreenBtn_clicked()
|
void ToolForm::on_closeScreenBtn_clicked()
|
||||||
{
|
{
|
||||||
if (m_videoForm) {
|
if (m_videoForm && m_videoForm->getController()) {
|
||||||
m_videoForm->getController()->setScreenPowerMode(ControlMsg::SPM_OFF);
|
m_videoForm->getController()->setScreenPowerMode(ControlMsg::SPM_OFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToolForm::on_expandNotifyBtn_clicked()
|
void ToolForm::on_expandNotifyBtn_clicked()
|
||||||
{
|
{
|
||||||
if (m_videoForm) {
|
if (m_videoForm && m_videoForm->getController()) {
|
||||||
m_videoForm->getController()->expandNotificationPanel();
|
m_videoForm->getController()->expandNotificationPanel();
|
||||||
}
|
}
|
||||||
}
|
}
|
11
QtScrcpy/ui/ui.pri
Normal file
11
QtScrcpy/ui/ui.pri
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/videoform.cpp \
|
||||||
|
$$PWD/toolform.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
$$PWD/videoform.h \
|
||||||
|
$$PWD/toolform.h
|
||||||
|
|
||||||
|
FORMS += \
|
||||||
|
$$PWD/videoform.ui \
|
||||||
|
$$PWD/toolform.ui
|
|
@ -13,85 +13,30 @@
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
#include "videoform.h"
|
#include "videoform.h"
|
||||||
#include "recorder.h"
|
#include "mousetap/mousetap.h"
|
||||||
#include "videobuffer.h"
|
|
||||||
#include "decoder.h"
|
|
||||||
#include "ui_videoform.h"
|
#include "ui_videoform.h"
|
||||||
#include "iconhelper.h"
|
#include "iconhelper.h"
|
||||||
#include "toolform.h"
|
#include "toolform.h"
|
||||||
|
#include "controller.h"
|
||||||
#include "filehandler.h"
|
#include "filehandler.h"
|
||||||
#include "stream.h"
|
extern "C"
|
||||||
#include "server.h"
|
{
|
||||||
#include "mousetap/mousetap.h"
|
#include "libavutil/frame.h"
|
||||||
|
}
|
||||||
|
|
||||||
VideoForm::VideoForm(const QString& serial, quint16 maxSize, quint32 bitRate, const QString& fileName, bool closeScreen, QWidget *parent) :
|
VideoForm::VideoForm(QWidget *parent) :
|
||||||
QWidget(parent),
|
QWidget(parent),
|
||||||
ui(new Ui::videoForm),
|
ui(new Ui::videoForm)
|
||||||
m_serial(serial),
|
|
||||||
m_maxSize(maxSize),
|
|
||||||
m_bitRate(bitRate)
|
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
initUI();
|
initUI();
|
||||||
|
|
||||||
m_closeScreen = closeScreen;
|
|
||||||
|
|
||||||
m_vb = new VideoBuffer();
|
|
||||||
m_vb->init();
|
|
||||||
|
|
||||||
m_server = new Server(this);
|
|
||||||
m_decoder = new Decoder(m_vb, this);
|
|
||||||
m_stream = new Stream(this);
|
|
||||||
m_stream->setDecoder(m_decoder);
|
|
||||||
m_controller = new Controller(this);
|
|
||||||
m_fileHandler = new FileHandler(this);
|
|
||||||
|
|
||||||
if (!fileName.trimmed().isEmpty()) {
|
|
||||||
m_recorder = new Recorder(fileName.trimmed());
|
|
||||||
m_stream->setRecoder(m_recorder);
|
|
||||||
}
|
|
||||||
|
|
||||||
initSignals();
|
|
||||||
|
|
||||||
// fix: macos cant recv finished signel, timer is ok
|
|
||||||
QTimer::singleShot(0, this, [this](){
|
|
||||||
bool sendFrameMeta = m_recorder ? true : false;
|
|
||||||
m_startTimeCount.start();
|
|
||||||
// max size support 480p 720p 1080p 设备原生分辨率
|
|
||||||
// support wireless connect, example:
|
|
||||||
//m_server->start("192.168.0.174:5555", 27183, m_maxSize, m_bitRate, "");
|
|
||||||
// only one devices, serial can be null
|
|
||||||
// mark: crop input format: "width:height:x:y" or - for no crop, for example: "100:200:0:0"
|
|
||||||
// sendFrameMeta for recorder mp4
|
|
||||||
Server::ServerParams params;
|
|
||||||
params.serial = m_serial;
|
|
||||||
params.localPort = 27183;
|
|
||||||
params.maxSize = m_maxSize;
|
|
||||||
params.bitRate = m_bitRate;
|
|
||||||
params.crop = "-";
|
|
||||||
params.sendFrameMeta = sendFrameMeta;
|
|
||||||
params.control = true;
|
|
||||||
m_server->start(params);
|
|
||||||
});
|
|
||||||
|
|
||||||
updateShowSize(size());
|
updateShowSize(size());
|
||||||
|
|
||||||
bool vertical = size().height() > size().width();
|
bool vertical = size().height() > size().width();
|
||||||
updateStyleSheet(vertical);
|
updateStyleSheet(vertical);
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoForm::~VideoForm()
|
VideoForm::~VideoForm()
|
||||||
{
|
{
|
||||||
m_server->stop();
|
|
||||||
// server must stop before decoder, because decoder block main thread
|
|
||||||
m_stream->stopDecode();
|
|
||||||
|
|
||||||
if (m_recorder) {
|
|
||||||
delete m_recorder;
|
|
||||||
}
|
|
||||||
m_vb->deInit();
|
|
||||||
delete m_vb;
|
|
||||||
|
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,90 +90,28 @@ void VideoForm::initUI()
|
||||||
ui->videoWidget->hide();
|
ui->videoWidget->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoForm::initSignals()
|
void VideoForm::onGrabCursor(bool grab)
|
||||||
{
|
{
|
||||||
connect(m_fileHandler, &FileHandler::fileHandlerResult, this, [this](FileHandler::FILE_HANDLER_RESULT processResult){
|
#if defined(Q_OS_WIN32) || defined(Q_OS_OSX)
|
||||||
if (FileHandler::FAR_IS_RUNNING == processResult) {
|
MouseTap::getInstance()->enableMouseEventTap(ui->videoWidget, grab);
|
||||||
QMessageBox::warning(this, "QtScrcpy", tr("wait current file transfer to complete"), QMessageBox::Ok);
|
#else
|
||||||
}
|
Q_UNUSED(grab);
|
||||||
if (FileHandler::FAR_SUCCESS_EXEC == processResult) {
|
|
||||||
QMessageBox::information(this, "QtScrcpy", tr("file transfer complete"), QMessageBox::Ok);
|
|
||||||
}
|
|
||||||
if (FileHandler::FAR_ERROR_EXEC == processResult) {
|
|
||||||
QMessageBox::information(this, "QtScrcpy", tr("file transfer failed"), QMessageBox::Ok);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(m_controller, &Controller::grabCursor, this, [this](bool grab){
|
|
||||||
|
|
||||||
#ifdef Q_OS_WIN32
|
|
||||||
MouseTap::getInstance()->enableMouseEventTap(ui->videoWidget, grab);
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef Q_OS_OSX
|
}
|
||||||
MouseTap::getInstance()->enableMouseEventTap(ui->videoWidget, grab);
|
|
||||||
#endif
|
void VideoForm::updateRender(const AVFrame *frame)
|
||||||
});
|
{
|
||||||
connect(m_server, &Server::serverStartResult, this, [this](bool success){
|
if (ui->videoWidget->isHidden()) {
|
||||||
if (success) {
|
if (m_loadingWidget) {
|
||||||
m_server->connectTo();
|
m_loadingWidget->close();
|
||||||
} else {
|
|
||||||
close();
|
|
||||||
}
|
}
|
||||||
});
|
ui->videoWidget->show();
|
||||||
|
}
|
||||||
|
|
||||||
connect(m_server, &Server::connectToResult, this, [this](bool success, const QString &deviceName, const QSize &size){
|
updateShowSize(QSize(frame->width, frame->height));
|
||||||
if (success) {
|
ui->videoWidget->setFrameSize(QSize(frame->width, frame->height));
|
||||||
float diff = m_startTimeCount.elapsed() / 1000.0f;
|
ui->videoWidget->updateTextures(frame->data[0], frame->data[1], frame->data[2],
|
||||||
qInfo(QString("server start finish in %1s").arg(diff).toStdString().c_str());
|
frame->linesize[0], frame->linesize[1], frame->linesize[2]);
|
||||||
|
|
||||||
// update ui
|
|
||||||
setWindowTitle(deviceName);
|
|
||||||
updateShowSize(size);
|
|
||||||
|
|
||||||
// init recorder
|
|
||||||
if (m_recorder) {
|
|
||||||
m_recorder->setFrameSize(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// init decoder
|
|
||||||
m_stream->setVideoSocket(m_server->getVideoSocket());
|
|
||||||
m_stream->startDecode();
|
|
||||||
|
|
||||||
// init controller
|
|
||||||
m_controller->setControlSocket(m_server->getControlSocket());
|
|
||||||
|
|
||||||
if (m_closeScreen) {
|
|
||||||
m_controller->setScreenPowerMode(ControlMsg::SPM_OFF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(m_server, &Server::onServerStop, this, [this](){
|
|
||||||
close();
|
|
||||||
qDebug() << "server process stop";
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(m_stream, &Stream::onStreamStop, this, [this](){
|
|
||||||
close();
|
|
||||||
qDebug() << "stream thread stop";
|
|
||||||
});
|
|
||||||
|
|
||||||
// must be Qt::QueuedConnection, ui update must be main thread
|
|
||||||
connect(m_decoder, &Decoder::onNewFrame, this, [this](){
|
|
||||||
if (ui->videoWidget->isHidden()) {
|
|
||||||
if (m_loadingWidget) {
|
|
||||||
m_loadingWidget->close();
|
|
||||||
}
|
|
||||||
ui->videoWidget->show();
|
|
||||||
}
|
|
||||||
m_vb->lock();
|
|
||||||
const AVFrame *frame = m_vb->consumeRenderedFrame();
|
|
||||||
//qDebug() << "widthxheight:" << frame->width << "x" << frame->height;
|
|
||||||
updateShowSize(QSize(frame->width, frame->height));
|
|
||||||
ui->videoWidget->setFrameSize(QSize(frame->width, frame->height));
|
|
||||||
ui->videoWidget->updateTextures(frame->data[0], frame->data[1], frame->data[2], frame->linesize[0], frame->linesize[1], frame->linesize[2]);
|
|
||||||
m_vb->unLock();
|
|
||||||
},Qt::QueuedConnection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoForm::showToolForm(bool show)
|
void VideoForm::showToolForm(bool show)
|
||||||
|
@ -332,8 +215,6 @@ void VideoForm::switchFullScreen()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void VideoForm::staysOnTop(bool top)
|
void VideoForm::staysOnTop(bool top)
|
||||||
{
|
{
|
||||||
bool needShow = false;
|
bool needShow = false;
|
||||||
|
@ -354,9 +235,27 @@ Controller *VideoForm::getController()
|
||||||
return m_controller;
|
return m_controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoForm::setFileHandler(FileHandler *fileHandler)
|
||||||
|
{
|
||||||
|
m_fileHandler = fileHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoForm::setSerial(const QString &serial)
|
||||||
|
{
|
||||||
|
m_serial = serial;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoForm::setController(Controller *controller)
|
||||||
|
{
|
||||||
|
m_controller = controller;
|
||||||
|
}
|
||||||
|
|
||||||
void VideoForm::mousePressEvent(QMouseEvent *event)
|
void VideoForm::mousePressEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
if (ui->videoWidget->geometry().contains(event->pos())) {
|
if (ui->videoWidget->geometry().contains(event->pos())) {
|
||||||
|
if (!m_controller) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
event->setLocalPos(ui->videoWidget->mapFrom(this, event->localPos().toPoint()));
|
event->setLocalPos(ui->videoWidget->mapFrom(this, event->localPos().toPoint()));
|
||||||
m_controller->mouseEvent(event, ui->videoWidget->frameSize(), ui->videoWidget->size());
|
m_controller->mouseEvent(event, ui->videoWidget->frameSize(), ui->videoWidget->size());
|
||||||
} else {
|
} else {
|
||||||
|
@ -370,6 +269,9 @@ void VideoForm::mousePressEvent(QMouseEvent *event)
|
||||||
void VideoForm::mouseReleaseEvent(QMouseEvent *event)
|
void VideoForm::mouseReleaseEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
if (ui->videoWidget->geometry().contains(event->pos())) {
|
if (ui->videoWidget->geometry().contains(event->pos())) {
|
||||||
|
if (!m_controller) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
event->setLocalPos(ui->videoWidget->mapFrom(this, event->localPos().toPoint()));
|
event->setLocalPos(ui->videoWidget->mapFrom(this, event->localPos().toPoint()));
|
||||||
m_controller->mouseEvent(event, ui->videoWidget->frameSize(), ui->videoWidget->size());
|
m_controller->mouseEvent(event, ui->videoWidget->frameSize(), ui->videoWidget->size());
|
||||||
}
|
}
|
||||||
|
@ -378,6 +280,9 @@ void VideoForm::mouseReleaseEvent(QMouseEvent *event)
|
||||||
void VideoForm::mouseMoveEvent(QMouseEvent *event)
|
void VideoForm::mouseMoveEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
if (ui->videoWidget->geometry().contains(event->pos())) {
|
if (ui->videoWidget->geometry().contains(event->pos())) {
|
||||||
|
if (!m_controller) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
event->setLocalPos(ui->videoWidget->mapFrom(this, event->localPos().toPoint()));
|
event->setLocalPos(ui->videoWidget->mapFrom(this, event->localPos().toPoint()));
|
||||||
m_controller->mouseEvent(event, ui->videoWidget->frameSize(), ui->videoWidget->size());
|
m_controller->mouseEvent(event, ui->videoWidget->frameSize(), ui->videoWidget->size());
|
||||||
} else {
|
} else {
|
||||||
|
@ -391,6 +296,9 @@ void VideoForm::mouseMoveEvent(QMouseEvent *event)
|
||||||
void VideoForm::wheelEvent(QWheelEvent *event)
|
void VideoForm::wheelEvent(QWheelEvent *event)
|
||||||
{
|
{
|
||||||
if (ui->videoWidget->geometry().contains(event->pos())) {
|
if (ui->videoWidget->geometry().contains(event->pos())) {
|
||||||
|
if (!m_controller) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
QPointF pos = ui->videoWidget->mapFrom(this, event->pos());
|
QPointF pos = ui->videoWidget->mapFrom(this, event->pos());
|
||||||
/*
|
/*
|
||||||
QWheelEvent(const QPointF &pos, const QPointF& globalPos, int delta,
|
QWheelEvent(const QPointF &pos, const QPointF& globalPos, int delta,
|
||||||
|
@ -410,6 +318,9 @@ void VideoForm::keyPressEvent(QKeyEvent *event)
|
||||||
&& isFullScreen()) {
|
&& isFullScreen()) {
|
||||||
switchFullScreen();
|
switchFullScreen();
|
||||||
}
|
}
|
||||||
|
if (!m_controller) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (event->key() == Qt::Key_C && (event->modifiers() & Qt::ControlModifier)) {
|
if (event->key() == Qt::Key_C && (event->modifiers() & Qt::ControlModifier)) {
|
||||||
m_controller->requestDeviceClipboard();
|
m_controller->requestDeviceClipboard();
|
||||||
}
|
}
|
||||||
|
@ -428,6 +339,9 @@ void VideoForm::keyPressEvent(QKeyEvent *event)
|
||||||
|
|
||||||
void VideoForm::keyReleaseEvent(QKeyEvent *event)
|
void VideoForm::keyReleaseEvent(QKeyEvent *event)
|
||||||
{
|
{
|
||||||
|
if (!m_controller) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
//qDebug() << "keyReleaseEvent" << event->isAutoRepeat();
|
//qDebug() << "keyReleaseEvent" << event->isAutoRepeat();
|
||||||
m_controller->keyEvent(event, ui->videoWidget->frameSize(), ui->videoWidget->size());
|
m_controller->keyEvent(event, ui->videoWidget->frameSize(), ui->videoWidget->size());
|
||||||
}
|
}
|
||||||
|
@ -466,6 +380,9 @@ void VideoForm::dragLeaveEvent(QDragLeaveEvent *event)
|
||||||
|
|
||||||
void VideoForm::dropEvent(QDropEvent *event)
|
void VideoForm::dropEvent(QDropEvent *event)
|
||||||
{
|
{
|
||||||
|
if (!m_fileHandler) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const QMimeData* qm = event->mimeData();
|
const QMimeData* qm = event->mimeData();
|
||||||
QString file = qm->urls()[0].toLocalFile();
|
QString file = qm->urls()[0].toLocalFile();
|
||||||
QFileInfo fileInfo(file);
|
QFileInfo fileInfo(file);
|
|
@ -3,37 +3,38 @@
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QTime>
|
|
||||||
|
|
||||||
#include "controller.h"
|
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class videoForm;
|
class videoForm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct AVFrame;
|
||||||
class ToolForm;
|
class ToolForm;
|
||||||
class Recorder;
|
class Controller;
|
||||||
class VideoBuffer;
|
|
||||||
class Decoder;
|
|
||||||
class FileHandler;
|
class FileHandler;
|
||||||
class Stream;
|
|
||||||
class Server;
|
|
||||||
class VideoForm : public QWidget
|
class VideoForm : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit VideoForm(const QString& serial, quint16 maxSize = 720, quint32 bitRate = 8000000, const QString& fileName = "", bool closeScreen = false, QWidget *parent = 0);
|
explicit VideoForm(QWidget *parent = 0);
|
||||||
~VideoForm();
|
~VideoForm();
|
||||||
|
|
||||||
void switchFullScreen();
|
void switchFullScreen();
|
||||||
void staysOnTop(bool top = true);
|
void staysOnTop(bool top = true);
|
||||||
Controller* getController();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void updateShowSize(const QSize &newSize);
|
void updateShowSize(const QSize &newSize);
|
||||||
|
void updateRender(const AVFrame *frame);
|
||||||
|
void setController(Controller *controller);
|
||||||
|
Controller* getController();
|
||||||
|
void setFileHandler(FileHandler *fileHandler);
|
||||||
|
void setSerial(const QString &serial);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void onGrabCursor(bool grab);
|
||||||
|
|
||||||
|
private:
|
||||||
void updateStyleSheet(bool vertical);
|
void updateStyleSheet(bool vertical);
|
||||||
void initUI();
|
void initUI();
|
||||||
void initSignals();
|
|
||||||
void showToolForm(bool show = true);
|
void showToolForm(bool show = true);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -58,27 +59,15 @@ private:
|
||||||
QPointer<ToolForm> m_toolForm;
|
QPointer<ToolForm> m_toolForm;
|
||||||
QPointer<QWidget> m_loadingWidget;
|
QPointer<QWidget> m_loadingWidget;
|
||||||
|
|
||||||
// server relevant
|
//inside member
|
||||||
QPointer<Server> m_server;
|
|
||||||
QPointer<Decoder> m_decoder;
|
|
||||||
QPointer<Controller> m_controller;
|
|
||||||
QPointer<FileHandler> m_fileHandler;
|
|
||||||
QPointer<Stream> m_stream;
|
|
||||||
|
|
||||||
VideoBuffer* m_vb = Q_NULLPTR;
|
|
||||||
Recorder* m_recorder = Q_NULLPTR;
|
|
||||||
|
|
||||||
// server params
|
|
||||||
QString m_serial = "";
|
|
||||||
quint16 m_maxSize = 720;
|
|
||||||
quint32 m_bitRate = 8000000;
|
|
||||||
|
|
||||||
// assist member
|
|
||||||
QSize frameSize;
|
QSize frameSize;
|
||||||
QPoint m_dragPosition;
|
QPoint m_dragPosition;
|
||||||
float m_widthHeightRatio = 0.5f;
|
float m_widthHeightRatio = 0.5f;
|
||||||
bool m_closeScreen = false;
|
|
||||||
QTime m_startTimeCount;
|
//outside member
|
||||||
|
QString m_serial = "";
|
||||||
|
QPointer<Controller> m_controller;
|
||||||
|
QPointer<FileHandler> m_fileHandler;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VIDEOFORM_H
|
#endif // VIDEOFORM_H
|
2
TODO.txt
2
TODO.txt
|
@ -12,8 +12,6 @@ b35733edb6df2a00b6af9b1c98627d344c377963
|
||||||
只录制不启动窗口(先重构,目前启动流程在videoform里)
|
只录制不启动窗口(先重构,目前启动流程在videoform里)
|
||||||
跳过帧改为动态配置,而不是静态编译 https://github.com/Genymobile/scrcpy/commit/ebccb9f6cc111e8acfbe10d656cac5c1f1b744a0
|
跳过帧改为动态配置,而不是静态编译 https://github.com/Genymobile/scrcpy/commit/ebccb9f6cc111e8acfbe10d656cac5c1f1b744a0
|
||||||
单独线程打印帧率 https://github.com/Genymobile/scrcpy/commit/e2a272bf99ecf48fcb050177113f903b3fb323c4
|
单独线程打印帧率 https://github.com/Genymobile/scrcpy/commit/e2a272bf99ecf48fcb050177113f903b3fb323c4
|
||||||
重构videoform
|
|
||||||
重构整个目录
|
|
||||||
群控
|
群控
|
||||||
|
|
||||||
mark:
|
mark:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue