mirror of
https://github.com/barry-ran/QtScrcpy.git
synced 2025-04-22 04:24:59 +00:00
update:视频传输和控制指令改为两个不同的socket videosocket负责视频接收 controlsocket负责指令发送
This commit is contained in:
parent
7220d91ed3
commit
b44f78f19b
18 changed files with 181 additions and 125 deletions
|
@ -6,16 +6,16 @@ class QScrcpyEvent : public QEvent
|
|||
{
|
||||
public:
|
||||
enum Type {
|
||||
DeviceSocket = QEvent::User + 1,
|
||||
VideoSocket = QEvent::User + 1,
|
||||
Control,
|
||||
};
|
||||
QScrcpyEvent(Type type) : QEvent(QEvent::Type(type)){}
|
||||
};
|
||||
|
||||
// DeviceSocketEvent
|
||||
class DeviceSocketEvent : public QScrcpyEvent
|
||||
// VideoSocketEvent
|
||||
class VideoSocketEvent : public QScrcpyEvent
|
||||
{
|
||||
public:
|
||||
DeviceSocketEvent() : QScrcpyEvent(DeviceSocket){}
|
||||
VideoSocketEvent() : QScrcpyEvent(VideoSocket){}
|
||||
};
|
||||
#endif // QSCRCPYEVENT_H
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include <QCoreApplication>
|
||||
|
||||
#include "controller.h"
|
||||
#include "devicesocket.h"
|
||||
#include "videosocket.h"
|
||||
#include "controlevent.h"
|
||||
|
||||
Controller::Controller(QObject* parent) : QObject(parent)
|
||||
|
@ -14,9 +14,9 @@ Controller::~Controller()
|
|||
|
||||
}
|
||||
|
||||
void Controller::setDeviceSocket(DeviceSocket *deviceSocket)
|
||||
void Controller::setControlSocket(QTcpSocket* controlSocket)
|
||||
{
|
||||
m_deviceSocket = deviceSocket;
|
||||
m_controlSocket = controlSocket;
|
||||
}
|
||||
|
||||
void Controller::postControlEvent(ControlEvent *controlEvent)
|
||||
|
@ -51,8 +51,8 @@ bool Controller::sendControl(const QByteArray &buffer)
|
|||
return false;
|
||||
}
|
||||
qint32 len = 0;
|
||||
if (m_deviceSocket) {
|
||||
len = m_deviceSocket->write(buffer.data(), buffer.length());
|
||||
if (m_controlSocket) {
|
||||
len = m_controlSocket->write(buffer.data(), buffer.length());
|
||||
}
|
||||
return len == buffer.length() ? true : false;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <QObject>
|
||||
#include <QPointer>
|
||||
|
||||
class DeviceSocket;
|
||||
class QTcpSocket;
|
||||
class ControlEvent;
|
||||
class Controller : public QObject
|
||||
{
|
||||
|
@ -13,7 +13,7 @@ public:
|
|||
Controller(QObject* parent = Q_NULLPTR);
|
||||
virtual ~Controller();
|
||||
|
||||
void setDeviceSocket(DeviceSocket* deviceSocket);
|
||||
void setControlSocket(QTcpSocket* controlSocket);
|
||||
void postControlEvent(ControlEvent* controlEvent);
|
||||
void test(QRect rc);
|
||||
|
||||
|
@ -24,7 +24,7 @@ private:
|
|||
bool sendControl(const QByteArray& buffer);
|
||||
|
||||
private:
|
||||
QPointer<DeviceSocket> m_deviceSocket;
|
||||
QPointer<QTcpSocket> m_controlSocket;
|
||||
};
|
||||
|
||||
#endif // CONTROLLER_H
|
||||
|
|
|
@ -10,9 +10,9 @@ InputConvertBase::~InputConvertBase()
|
|||
|
||||
}
|
||||
|
||||
void InputConvertBase::setDeviceSocket(DeviceSocket *deviceSocket)
|
||||
void InputConvertBase::setControlSocket(QTcpSocket *controlSocket)
|
||||
{
|
||||
m_controller.setDeviceSocket(deviceSocket);
|
||||
m_controller.setControlSocket(controlSocket);
|
||||
}
|
||||
|
||||
void InputConvertBase::sendControlEvent(ControlEvent *event)
|
||||
|
|
|
@ -20,7 +20,7 @@ public:
|
|||
virtual void wheelEvent(const QWheelEvent* from, const QSize& frameSize, const QSize& showSize) = 0;
|
||||
virtual void keyEvent(const QKeyEvent* from, const QSize& frameSize, const QSize& showSize) = 0;
|
||||
|
||||
void setDeviceSocket(DeviceSocket* deviceSocket);
|
||||
void setControlSocket(QTcpSocket* controlSocket);
|
||||
void sendControlEvent(ControlEvent* event);
|
||||
|
||||
private:
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
#include <QThread>
|
||||
#include <QSize>
|
||||
#include <QTimerEvent>
|
||||
#include <QCoreApplication>
|
||||
#include <QFileInfo>
|
||||
|
@ -17,25 +16,30 @@ Server::Server(QObject *parent) : QObject(parent)
|
|||
connect(&m_workProcess, &AdbProcess::adbProcessResult, this, &Server::onWorkProcessResult);
|
||||
connect(&m_serverProcess, &AdbProcess::adbProcessResult, this, &Server::onWorkProcessResult);
|
||||
|
||||
connect(&m_serverSocket, &QTcpServer::newConnection, this, [this](){
|
||||
m_deviceSocket = dynamic_cast<DeviceSocket*>(m_serverSocket.nextPendingConnection());
|
||||
|
||||
QString deviceName;
|
||||
QSize deviceSize;
|
||||
|
||||
if (m_deviceSocket->isValid() && readInfo(deviceName, deviceSize)) {
|
||||
// we don't need the server socket anymore
|
||||
// just m_deviceSocket is ok
|
||||
m_serverSocket.close();
|
||||
// we don't need the adb tunnel anymore
|
||||
disableTunnelReverse();
|
||||
m_tunnelEnabled = false;
|
||||
emit connectToResult(true, deviceName, deviceSize);
|
||||
connect(&m_serverSocket, &QTcpServer::newConnection, this, [this](){
|
||||
QTcpSocket* tmp = m_serverSocket.nextPendingConnection();
|
||||
if (dynamic_cast<VideoSocket*>(tmp)) {
|
||||
m_videoSocket = dynamic_cast<VideoSocket*>(tmp);
|
||||
if (!m_videoSocket->isValid() || !readInfo(m_deviceName, m_deviceSize)) {
|
||||
stop();
|
||||
emit connectToResult(false);
|
||||
}
|
||||
} else {
|
||||
stop();
|
||||
emit connectToResult(false, deviceName, deviceSize);
|
||||
m_controlSocket = tmp;
|
||||
if (m_controlSocket && m_controlSocket->isValid()) {
|
||||
// we don't need the server socket anymore
|
||||
// just m_videoSocket is ok
|
||||
m_serverSocket.close();
|
||||
// we don't need the adb tunnel anymore
|
||||
disableTunnelReverse();
|
||||
m_tunnelEnabled = false;
|
||||
emit connectToResult(true, m_deviceName, m_deviceSize);
|
||||
} else {
|
||||
stop();
|
||||
emit connectToResult(false);
|
||||
}
|
||||
stopAcceptTimeoutTimer();
|
||||
}
|
||||
stopAcceptTimeoutTimer();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -159,7 +163,7 @@ bool Server::connectTo()
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!m_tunnelForward && !m_deviceSocket) {
|
||||
if (!m_tunnelForward && !m_videoSocket) {
|
||||
startAcceptTimeoutTimer();
|
||||
return true;
|
||||
}
|
||||
|
@ -167,39 +171,49 @@ bool Server::connectTo()
|
|||
// device server need time to start
|
||||
// TODO:电脑配置太低的话,这里有可能时间不够导致连接太早,安卓监听socket还没有建立
|
||||
// 后续研究其他办法
|
||||
// wait for devices server start
|
||||
QTimer::singleShot(1000, this, [this](){
|
||||
QString deviceName;
|
||||
QSize deviceSize;
|
||||
bool success = false;
|
||||
|
||||
m_deviceSocket = new DeviceSocket();
|
||||
|
||||
// wait for devices server start
|
||||
m_deviceSocket->connectToHost(QHostAddress::LocalHost, m_localPort);
|
||||
if (!m_deviceSocket->waitForConnected(1000)) {
|
||||
// video socket
|
||||
m_videoSocket = new VideoSocket();
|
||||
m_videoSocket->connectToHost(QHostAddress::LocalHost, m_localPort);
|
||||
if (!m_videoSocket->waitForConnected(1000)) {
|
||||
stop();
|
||||
qWarning("connect to server failed");
|
||||
qWarning("video socket connect to server failed");
|
||||
emit connectToResult(false, "", QSize());
|
||||
return false;
|
||||
}
|
||||
if (QTcpSocket::ConnectedState == m_deviceSocket->state()) {
|
||||
if (QTcpSocket::ConnectedState == m_videoSocket->state()) {
|
||||
// connect will success even if devices offline, recv data is real connect success
|
||||
// because connect is to pc adb server
|
||||
m_deviceSocket->waitForReadyRead(1000);
|
||||
m_videoSocket->waitForReadyRead(1000);
|
||||
// devices will send 1 byte first on tunnel forward mode
|
||||
QByteArray data = m_deviceSocket->read(1);
|
||||
QByteArray data = m_videoSocket->read(1);
|
||||
if (!data.isEmpty() && readInfo(deviceName, deviceSize)) {
|
||||
success = true;
|
||||
} else {
|
||||
qWarning("connect to server read device info failed");
|
||||
qWarning("video socket connect to server read device info failed");
|
||||
success = false;
|
||||
}
|
||||
} else {
|
||||
qWarning("connect to server failed");
|
||||
m_deviceSocket->deleteLater();
|
||||
m_videoSocket->deleteLater();
|
||||
success = false;
|
||||
}
|
||||
|
||||
// control socket
|
||||
m_controlSocket = new QTcpSocket();
|
||||
m_controlSocket->connectToHost(QHostAddress::LocalHost, m_localPort);
|
||||
if (!m_controlSocket->waitForConnected(1000)) {
|
||||
stop();
|
||||
qWarning("control socket connect to server failed");
|
||||
emit connectToResult(false, "", QSize());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (success) {
|
||||
// we don't need the adb tunnel anymore
|
||||
disableTunnelForward();
|
||||
|
@ -221,16 +235,25 @@ void Server::timerEvent(QTimerEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
DeviceSocket* Server::getDeviceSocket()
|
||||
VideoSocket* Server::getVideoSocket()
|
||||
{
|
||||
return m_deviceSocket;
|
||||
return m_videoSocket;
|
||||
}
|
||||
|
||||
QTcpSocket *Server::getControlSocket()
|
||||
{
|
||||
return m_controlSocket;
|
||||
}
|
||||
|
||||
void Server::stop()
|
||||
{
|
||||
if (m_deviceSocket) {
|
||||
m_deviceSocket->close();
|
||||
m_deviceSocket->deleteLater();
|
||||
if (m_videoSocket) {
|
||||
m_videoSocket->close();
|
||||
m_videoSocket->deleteLater();
|
||||
}
|
||||
if (m_controlSocket) {
|
||||
m_controlSocket->close();
|
||||
m_controlSocket->deleteLater();
|
||||
}
|
||||
// ignore failure
|
||||
m_serverProcess.kill();
|
||||
|
@ -270,7 +293,7 @@ bool Server::startServerByStep()
|
|||
// client listens and the server connects to the client. That way, the
|
||||
// client can listen before starting the server app, so there is no need to
|
||||
// try to connect until the server socket is listening on the device.
|
||||
m_serverSocket.setMaxPendingConnections(1);
|
||||
m_serverSocket.setMaxPendingConnections(2);
|
||||
if (!m_serverSocket.listen(QHostAddress::LocalHost, m_localPort)) {
|
||||
qCritical(QString("Could not listen on port %1").arg(m_localPort).toStdString().c_str());
|
||||
m_serverStartStep = SSS_NULL;
|
||||
|
@ -300,11 +323,11 @@ bool Server::startServerByStep()
|
|||
bool Server::readInfo(QString &deviceName, QSize &size)
|
||||
{
|
||||
unsigned char buf[DEVICE_NAME_FIELD_LENGTH + 4];
|
||||
if (m_deviceSocket->bytesAvailable() <= (DEVICE_NAME_FIELD_LENGTH + 4)) {
|
||||
m_deviceSocket->waitForReadyRead(300);
|
||||
if (m_videoSocket->bytesAvailable() <= (DEVICE_NAME_FIELD_LENGTH + 4)) {
|
||||
m_videoSocket->waitForReadyRead(300);
|
||||
}
|
||||
|
||||
qint64 len = m_deviceSocket->read((char*)buf, sizeof(buf));
|
||||
qint64 len = m_videoSocket->read((char*)buf, sizeof(buf));
|
||||
if (len < DEVICE_NAME_FIELD_LENGTH + 4) {
|
||||
qInfo("Could not retrieve device information");
|
||||
return false;
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
#include <QSize>
|
||||
|
||||
#include "tcpserver.h"
|
||||
#include "devicesocket.h"
|
||||
#include "videosocket.h"
|
||||
#include "adbprocess.h"
|
||||
|
||||
class Server : public QObject
|
||||
|
@ -27,13 +28,14 @@ public:
|
|||
bool start(const QString& serial, quint16 localPort, quint16 maxSize, quint32 bitRate, const QString& crop, bool sendFrameMeta = false);
|
||||
bool connectTo();
|
||||
|
||||
DeviceSocket* getDeviceSocket();
|
||||
VideoSocket* getVideoSocket();
|
||||
QTcpSocket* getControlSocket();
|
||||
|
||||
void stop();
|
||||
|
||||
signals:
|
||||
void serverStartResult(bool success);
|
||||
void connectToResult(bool success, const QString &deviceName, const QSize &size);
|
||||
void connectToResult(bool success, const QString &deviceName = "", const QSize &size = QSize());
|
||||
void onServerStop();
|
||||
|
||||
private slots:
|
||||
|
@ -62,7 +64,8 @@ private:
|
|||
QString m_serial = "";
|
||||
AdbProcess m_serverProcess;
|
||||
TcpServer m_serverSocket; // only used if !tunnel_forward
|
||||
QPointer<DeviceSocket> m_deviceSocket = Q_NULLPTR;
|
||||
QPointer<VideoSocket> m_videoSocket = Q_NULLPTR;
|
||||
QPointer<QTcpSocket> m_controlSocket = Q_NULLPTR;
|
||||
quint16 m_localPort = 0;
|
||||
bool m_tunnelEnabled = false;
|
||||
bool m_tunnelForward = false; // use "adb forward" instead of "adb reverse"
|
||||
|
@ -71,6 +74,8 @@ private:
|
|||
quint32 m_bitRate = 0;
|
||||
QString m_crop = "";
|
||||
quint32 m_acceptTimeoutTimer = 0;
|
||||
QString m_deviceName = "";
|
||||
QSize m_deviceSize = QSize();
|
||||
|
||||
SERVER_START_STEP m_serverStartStep = SSS_NULL;
|
||||
};
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
HEADERS += \
|
||||
$$PWD/devicesocket.h \
|
||||
$$PWD/server.h \
|
||||
$$PWD/tcpserver.h
|
||||
$$PWD/tcpserver.h \
|
||||
$$PWD/videosocket.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/devicesocket.cpp \
|
||||
$$PWD/server.cpp \
|
||||
$$PWD/tcpserver.cpp
|
||||
$$PWD/tcpserver.cpp \
|
||||
$$PWD/videosocket.cpp
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "tcpserver.h"
|
||||
#include "devicesocket.h"
|
||||
#include "videosocket.h"
|
||||
|
||||
TcpServer::TcpServer(QObject *parent) : QTcpServer(parent)
|
||||
{
|
||||
|
@ -13,7 +13,16 @@ TcpServer::~TcpServer()
|
|||
|
||||
void TcpServer::incomingConnection(qintptr handle)
|
||||
{
|
||||
DeviceSocket *socket = new DeviceSocket();
|
||||
socket->setSocketDescriptor(handle);
|
||||
addPendingConnection(socket);
|
||||
if (m_isVideoSocket) {
|
||||
VideoSocket *socket = new VideoSocket();
|
||||
socket->setSocketDescriptor(handle);
|
||||
addPendingConnection(socket);
|
||||
|
||||
// next is control socket
|
||||
m_isVideoSocket = false;
|
||||
} else {
|
||||
QTcpSocket *socket = new QTcpSocket();
|
||||
socket->setSocketDescriptor(handle);
|
||||
addPendingConnection(socket);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,9 @@ public:
|
|||
|
||||
protected:
|
||||
virtual void incomingConnection(qintptr handle);
|
||||
|
||||
private:
|
||||
bool m_isVideoSocket = true;
|
||||
};
|
||||
|
||||
#endif // TCPSERVER_H
|
||||
|
|
|
@ -3,21 +3,21 @@
|
|||
#include <QDebug>
|
||||
|
||||
#include "qscrcpyevent.h"
|
||||
#include "devicesocket.h"
|
||||
#include "videosocket.h"
|
||||
|
||||
DeviceSocket::DeviceSocket(QObject *parent) : QTcpSocket(parent)
|
||||
VideoSocket::VideoSocket(QObject *parent) : QTcpSocket(parent)
|
||||
{
|
||||
connect(this, &DeviceSocket::readyRead, this, &DeviceSocket::onReadyRead);
|
||||
connect(this, &DeviceSocket::aboutToClose, this, &DeviceSocket::quitNotify);
|
||||
connect(this, &DeviceSocket::disconnected, this, &DeviceSocket::quitNotify);
|
||||
connect(this, &VideoSocket::readyRead, this, &VideoSocket::onReadyRead);
|
||||
connect(this, &VideoSocket::aboutToClose, this, &VideoSocket::quitNotify);
|
||||
connect(this, &VideoSocket::disconnected, this, &VideoSocket::quitNotify);
|
||||
}
|
||||
|
||||
DeviceSocket::~DeviceSocket()
|
||||
VideoSocket::~VideoSocket()
|
||||
{
|
||||
quitNotify();
|
||||
}
|
||||
|
||||
qint32 DeviceSocket::subThreadRecvData(quint8 *buf, qint32 bufSize)
|
||||
qint32 VideoSocket::subThreadRecvData(quint8 *buf, qint32 bufSize)
|
||||
{
|
||||
// this function cant call in main thread
|
||||
Q_ASSERT(QCoreApplication::instance()->thread() != QThread::currentThread());
|
||||
|
@ -31,7 +31,7 @@ qint32 DeviceSocket::subThreadRecvData(quint8 *buf, qint32 bufSize)
|
|||
m_dataSize = 0;
|
||||
|
||||
// post event
|
||||
DeviceSocketEvent* getDataEvent = new DeviceSocketEvent();
|
||||
VideoSocketEvent* getDataEvent = new VideoSocketEvent();
|
||||
QCoreApplication::postEvent(this, getDataEvent);
|
||||
|
||||
// wait
|
||||
|
@ -43,16 +43,16 @@ qint32 DeviceSocket::subThreadRecvData(quint8 *buf, qint32 bufSize)
|
|||
return m_dataSize;
|
||||
}
|
||||
|
||||
bool DeviceSocket::event(QEvent *event)
|
||||
bool VideoSocket::event(QEvent *event)
|
||||
{
|
||||
if (event->type() == QScrcpyEvent::DeviceSocket) {
|
||||
if (event->type() == QScrcpyEvent::VideoSocket) {
|
||||
onReadyRead();
|
||||
return true;
|
||||
}
|
||||
return QTcpSocket::event(event);
|
||||
}
|
||||
|
||||
void DeviceSocket::onReadyRead()
|
||||
void VideoSocket::onReadyRead()
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
if (m_buffer && 0 < bytesAvailable()) {
|
||||
|
@ -67,7 +67,7 @@ void DeviceSocket::onReadyRead()
|
|||
}
|
||||
}
|
||||
|
||||
void DeviceSocket::quitNotify()
|
||||
void VideoSocket::quitNotify()
|
||||
{
|
||||
m_quit = true;
|
||||
QMutexLocker locker(&m_mutex);
|
|
@ -1,17 +1,17 @@
|
|||
#ifndef DEVICESOCKET_H
|
||||
#define DEVICESOCKET_H
|
||||
#ifndef VIDEOSOCKET_H
|
||||
#define VIDEOSOCKET_H
|
||||
|
||||
#include <QEvent>
|
||||
#include <QTcpSocket>
|
||||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
|
||||
class DeviceSocket : public QTcpSocket
|
||||
class VideoSocket : public QTcpSocket
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DeviceSocket(QObject *parent = nullptr);
|
||||
virtual ~DeviceSocket();
|
||||
explicit VideoSocket(QObject *parent = nullptr);
|
||||
virtual ~VideoSocket();
|
||||
|
||||
qint32 subThreadRecvData(quint8* buf, qint32 bufSize);
|
||||
|
||||
|
@ -32,4 +32,4 @@ private:
|
|||
bool m_quit = false;
|
||||
};
|
||||
|
||||
#endif // DEVICESOCKET_H
|
||||
#endif // VIDEOSOCKET_H
|
|
@ -4,7 +4,7 @@
|
|||
#include "compat.h"
|
||||
#include "stream.h"
|
||||
#include "decoder.h"
|
||||
#include "devicesocket.h"
|
||||
#include "videosocket.h"
|
||||
#include "recorder.h"
|
||||
|
||||
#define BUFSIZE 0x10000
|
||||
|
@ -199,9 +199,9 @@ static qint32 readRawPacket(void *opaque, quint8 *buf, qint32 bufSize) {
|
|||
return AVERROR_EOF;
|
||||
}
|
||||
|
||||
void Stream::setDeviceSocket(DeviceSocket* deviceSocket)
|
||||
void Stream::setVideoSocket(VideoSocket* videoSocket)
|
||||
{
|
||||
m_deviceSocket = deviceSocket;
|
||||
m_videoSocket = videoSocket;
|
||||
}
|
||||
|
||||
void Stream::setRecoder(Recorder *recorder)
|
||||
|
@ -214,8 +214,8 @@ qint32 Stream::recvData(quint8* buf, qint32 bufSize)
|
|||
if (!buf) {
|
||||
return 0;
|
||||
}
|
||||
if (m_deviceSocket) {
|
||||
qint32 len = m_deviceSocket->subThreadRecvData(buf, bufSize);
|
||||
if (m_videoSocket) {
|
||||
qint32 len = m_videoSocket->subThreadRecvData(buf, bufSize);
|
||||
return len;
|
||||
}
|
||||
return 0;
|
||||
|
@ -223,7 +223,7 @@ qint32 Stream::recvData(quint8* buf, qint32 bufSize)
|
|||
|
||||
bool Stream::startDecode()
|
||||
{
|
||||
if (!m_deviceSocket) {
|
||||
if (!m_videoSocket) {
|
||||
return false;
|
||||
}
|
||||
m_quit.store(0);
|
||||
|
|
|
@ -12,7 +12,7 @@ extern "C"
|
|||
#include "libavformat/avformat.h"
|
||||
}
|
||||
|
||||
class DeviceSocket;
|
||||
class VideoSocket;
|
||||
class Recorder;
|
||||
class Decoder;
|
||||
class Stream : public QThread
|
||||
|
@ -38,7 +38,7 @@ public:
|
|||
static void deInit();
|
||||
|
||||
void setDecoder(Decoder* vb);
|
||||
void setDeviceSocket(DeviceSocket* deviceSocket);
|
||||
void setVideoSocket(VideoSocket* deviceSocket);
|
||||
void setRecoder(Recorder* recorder);
|
||||
qint32 recvData(quint8* buf, qint32 bufSize);
|
||||
bool startDecode();
|
||||
|
@ -52,7 +52,7 @@ protected:
|
|||
void run();
|
||||
|
||||
private:
|
||||
QPointer<DeviceSocket> m_deviceSocket;
|
||||
QPointer<VideoSocket> m_videoSocket;
|
||||
QAtomicInteger<qint8> m_quit;
|
||||
|
||||
// for recorder
|
||||
|
|
|
@ -171,11 +171,11 @@ void VideoForm::initSignals()
|
|||
}
|
||||
|
||||
// init decoder
|
||||
m_stream.setDeviceSocket(m_server->getDeviceSocket());
|
||||
m_stream.setVideoSocket(m_server->getVideoSocket());
|
||||
m_stream.startDecode();
|
||||
|
||||
// init controller
|
||||
m_inputConvert.setDeviceSocket(m_server->getDeviceSocket());
|
||||
m_inputConvert.setControlSocket(m_server->getControlSocket());
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -16,16 +16,20 @@ public final class DesktopConnection implements Closeable {
|
|||
|
||||
private static final String SOCKET_NAME = "qtscrcpy";
|
||||
|
||||
private final LocalSocket socket;
|
||||
private final InputStream inputStream;
|
||||
private final FileDescriptor fd;
|
||||
private final LocalSocket videoSocket;
|
||||
private final FileDescriptor videoFd;
|
||||
|
||||
private final LocalSocket controlSocket;
|
||||
private final InputStream controlInputStream;
|
||||
|
||||
|
||||
private final ControlEventReader reader = new ControlEventReader();
|
||||
|
||||
private DesktopConnection(LocalSocket socket) throws IOException {
|
||||
this.socket = socket;
|
||||
inputStream = socket.getInputStream();
|
||||
fd = socket.getFileDescriptor();
|
||||
private DesktopConnection(LocalSocket videoSocket, LocalSocket controlSocket) throws IOException {
|
||||
this.videoSocket = videoSocket;
|
||||
this.controlSocket = controlSocket;
|
||||
controlInputStream = controlSocket.getInputStream();
|
||||
videoFd = videoSocket.getFileDescriptor();
|
||||
}
|
||||
|
||||
private static LocalSocket connect(String abstractName) throws IOException {
|
||||
|
@ -34,35 +38,47 @@ public final class DesktopConnection implements Closeable {
|
|||
return localSocket;
|
||||
}
|
||||
|
||||
private static LocalSocket listenAndAccept(String abstractName) throws IOException {
|
||||
LocalServerSocket localServerSocket = new LocalServerSocket(abstractName);
|
||||
try {
|
||||
return localServerSocket.accept();
|
||||
} finally {
|
||||
localServerSocket.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static DesktopConnection open(Device device, boolean tunnelForward) throws IOException {
|
||||
LocalSocket socket;
|
||||
LocalSocket videoSocket;
|
||||
LocalSocket controlSocket;
|
||||
if (tunnelForward) {
|
||||
socket = listenAndAccept(SOCKET_NAME);
|
||||
// send one byte so the client may read() to detect a connection error
|
||||
socket.getOutputStream().write(0);
|
||||
LocalServerSocket localServerSocket = new LocalServerSocket(SOCKET_NAME);
|
||||
try {
|
||||
videoSocket = localServerSocket.accept();
|
||||
// send one byte so the client may read() to detect a connection error
|
||||
videoSocket.getOutputStream().write(0);
|
||||
try {
|
||||
controlSocket = localServerSocket.accept();
|
||||
} catch (IOException | RuntimeException e) {
|
||||
videoSocket.close();
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
localServerSocket.close();
|
||||
}
|
||||
} else {
|
||||
socket = connect(SOCKET_NAME);
|
||||
videoSocket = connect(SOCKET_NAME);
|
||||
try {
|
||||
controlSocket = connect(SOCKET_NAME);
|
||||
} catch (IOException | RuntimeException e) {
|
||||
videoSocket.close();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
DesktopConnection connection = new DesktopConnection(socket);
|
||||
DesktopConnection connection = new DesktopConnection(videoSocket, controlSocket);
|
||||
Size videoSize = device.getScreenInfo().getVideoSize();
|
||||
connection.send(Device.getDeviceName(), videoSize.getWidth(), videoSize.getHeight());
|
||||
return connection;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
socket.shutdownInput();
|
||||
socket.shutdownOutput();
|
||||
socket.close();
|
||||
videoSocket.shutdownInput();
|
||||
videoSocket.shutdownOutput();
|
||||
videoSocket.close();
|
||||
controlSocket.shutdownInput();
|
||||
controlSocket.shutdownOutput();
|
||||
controlSocket.close();
|
||||
}
|
||||
|
||||
@SuppressWarnings("checkstyle:MagicNumber")
|
||||
|
@ -78,17 +94,17 @@ public final class DesktopConnection implements Closeable {
|
|||
buffer[DEVICE_NAME_FIELD_LENGTH + 1] = (byte) width;
|
||||
buffer[DEVICE_NAME_FIELD_LENGTH + 2] = (byte) (height >> 8);
|
||||
buffer[DEVICE_NAME_FIELD_LENGTH + 3] = (byte) height;
|
||||
IO.writeFully(fd, buffer, 0, buffer.length);
|
||||
IO.writeFully(videoFd, buffer, 0, buffer.length);
|
||||
}
|
||||
|
||||
public FileDescriptor getFd() {
|
||||
return fd;
|
||||
public FileDescriptor getVideoFd() {
|
||||
return videoFd;
|
||||
}
|
||||
|
||||
public ControlEvent receiveControlEvent() throws IOException {
|
||||
ControlEvent event = reader.next();
|
||||
while (event == null) {
|
||||
reader.readFrom(inputStream);
|
||||
reader.readFrom(controlInputStream);
|
||||
event = reader.next();
|
||||
}
|
||||
return event;
|
||||
|
|
|
@ -25,7 +25,7 @@ public final class Server {
|
|||
|
||||
try {
|
||||
// synchronous
|
||||
screenEncoder.streamScreen(device, connection.getFd());
|
||||
screenEncoder.streamScreen(device, connection.getVideoFd());
|
||||
} catch (IOException e) {
|
||||
// this is expected on close
|
||||
Ln.d("Screen streaming stopped");
|
||||
|
|
BIN
third_party/scrcpy-server.jar
vendored
BIN
third_party/scrcpy-server.jar
vendored
Binary file not shown.
Loading…
Add table
Reference in a new issue