mirror of
https://github.com/barry-ran/QtScrcpy.git
synced 2025-04-25 05:55:01 +00:00
feat: add config option to render expired frames
Replace the compilation flag SKIP_FRAMES by a config flag to force rendering of expired frames. By default, the expired frames are skipped.
This commit is contained in:
parent
eeeeae97fb
commit
e43b3bc0ad
10 changed files with 58 additions and 42 deletions
|
@ -9,6 +9,3 @@ SOURCES += \
|
|||
$$PWD/fpscounter.cpp \
|
||||
$$PWD/avframeconvert.cpp \
|
||||
$$PWD/videobuffer.cpp
|
||||
|
||||
#DEFINES += SKIP_FRAMES
|
||||
|
||||
|
|
|
@ -15,8 +15,9 @@ VideoBuffer::~VideoBuffer()
|
|||
|
||||
}
|
||||
|
||||
bool VideoBuffer::init()
|
||||
bool VideoBuffer::init(bool renderExpiredFrames)
|
||||
{
|
||||
m_renderExpiredFrames = renderExpiredFrames;
|
||||
m_decodingFrame = av_frame_alloc();
|
||||
if (!m_decodingFrame) {
|
||||
goto error;
|
||||
|
@ -71,17 +72,17 @@ void VideoBuffer::offerDecodedFrame(bool& previousFrameSkipped)
|
|||
{
|
||||
m_mutex.lock();
|
||||
|
||||
#ifndef SKIP_FRAMES
|
||||
// if SKIP_FRAMES is disabled, then the decoder must wait for the current
|
||||
// frame to be consumed
|
||||
while (!m_renderingFrameConsumed && !m_interrupted) {
|
||||
m_renderingFrameConsumedCond.wait(&m_mutex);
|
||||
}
|
||||
#else
|
||||
if (m_fpsCounter.isStarted() && !m_renderingFrameConsumed) {
|
||||
m_fpsCounter.addSkippedFrame();
|
||||
if (m_renderExpiredFrames) {
|
||||
// if m_renderExpiredFrames is enable, then the decoder must wait for the current
|
||||
// frame to be consumed
|
||||
while (!m_renderingFrameConsumed && !m_interrupted) {
|
||||
m_renderingFrameConsumedCond.wait(&m_mutex);
|
||||
}
|
||||
} else {
|
||||
if (m_fpsCounter.isStarted() && !m_renderingFrameConsumed) {
|
||||
m_fpsCounter.addSkippedFrame();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
swap();
|
||||
previousFrameSkipped = !m_renderingFrameConsumed;
|
||||
|
@ -96,23 +97,23 @@ const AVFrame *VideoBuffer::consumeRenderedFrame()
|
|||
if (m_fpsCounter.isStarted()) {
|
||||
m_fpsCounter.addRenderedFrame();
|
||||
}
|
||||
#ifndef SKIP_FRAMES
|
||||
// if SKIP_FRAMES is disabled, then notify the decoder the current frame is
|
||||
// consumed, so that it may push a new one
|
||||
m_renderingFrameConsumedCond.wakeOne();
|
||||
#endif
|
||||
if (m_renderExpiredFrames) {
|
||||
// if m_renderExpiredFrames is enable, then notify the decoder the current frame is
|
||||
// consumed, so that it may push a new one
|
||||
m_renderingFrameConsumedCond.wakeOne();
|
||||
}
|
||||
return m_renderingframe;
|
||||
}
|
||||
|
||||
void VideoBuffer::interrupt()
|
||||
{
|
||||
#ifndef SKIP_FRAMES
|
||||
m_mutex.lock();
|
||||
m_interrupted = true;
|
||||
m_mutex.unlock();
|
||||
// wake up blocking wait
|
||||
m_renderingFrameConsumedCond.wakeOne();
|
||||
#endif
|
||||
if (m_renderExpiredFrames) {
|
||||
m_mutex.lock();
|
||||
m_interrupted = true;
|
||||
m_mutex.unlock();
|
||||
// wake up blocking wait
|
||||
m_renderingFrameConsumedCond.wakeOne();
|
||||
}
|
||||
}
|
||||
|
||||
void VideoBuffer::swap()
|
||||
|
|
|
@ -15,7 +15,7 @@ public:
|
|||
VideoBuffer();
|
||||
virtual ~VideoBuffer();
|
||||
|
||||
bool init();
|
||||
bool init(bool renderExpiredFrames = false);
|
||||
void deInit();
|
||||
void lock();
|
||||
void unLock();
|
||||
|
@ -45,10 +45,12 @@ private:
|
|||
bool m_renderingFrameConsumed = true;
|
||||
FpsCounter m_fpsCounter;
|
||||
|
||||
#ifndef SKIP_FRAMES
|
||||
bool m_renderExpiredFrames = false;
|
||||
QWaitCondition m_renderingFrameConsumedCond;
|
||||
bool m_interrupted = true;
|
||||
#endif
|
||||
|
||||
// interrupted is not used if expired frames are not rendered
|
||||
// since offering a frame will never block
|
||||
bool m_interrupted = false;
|
||||
};
|
||||
|
||||
#endif // VIDEO_BUFFER_H
|
||||
|
|
|
@ -30,7 +30,7 @@ Device::Device(DeviceParams params, QObject *parent)
|
|||
|
||||
if (params.display) {
|
||||
m_vb = new VideoBuffer();
|
||||
m_vb->init();
|
||||
m_vb->init(params.renderExpiredFrames);
|
||||
m_decoder = new Decoder(m_vb, this);
|
||||
m_fileHandler = new FileHandler(this);
|
||||
m_controller = new Controller(params.gameScript, this);
|
||||
|
|
|
@ -18,16 +18,17 @@ class Device : public QObject
|
|||
Q_OBJECT
|
||||
public:
|
||||
struct DeviceParams {
|
||||
QString recordFileName = ""; // 视频录制文件名
|
||||
QString serial = ""; // 设备序列号
|
||||
quint16 localPort = 27183; // reverse时本地监听端口
|
||||
quint16 maxSize = 720; // 视频分辨率
|
||||
quint32 bitRate = 8000000; // 视频比特率
|
||||
quint32 maxFps = 60; // 视频最大帧率
|
||||
bool closeScreen = false; // 启动时自动息屏
|
||||
bool useReverse = true; // true:先使用adb reverse,失败后自动使用adb forward;false:直接使用adb forward
|
||||
bool display = true; // 是否显示画面(或者仅仅后台录制)
|
||||
QString gameScript = ""; // 游戏映射脚本
|
||||
QString recordFileName = ""; // 视频录制文件名
|
||||
QString serial = ""; // 设备序列号
|
||||
quint16 localPort = 27183; // reverse时本地监听端口
|
||||
quint16 maxSize = 720; // 视频分辨率
|
||||
quint32 bitRate = 8000000; // 视频比特率
|
||||
quint32 maxFps = 60; // 视频最大帧率
|
||||
bool closeScreen = false; // 启动时自动息屏
|
||||
bool useReverse = true; // true:先使用adb reverse,失败后自动使用adb forward;false:直接使用adb forward
|
||||
bool display = true; // 是否显示画面(或者仅仅后台录制)
|
||||
QString gameScript = ""; // 游戏映射脚本
|
||||
bool renderExpiredFrames = false; // 是否渲染延迟视频帧
|
||||
};
|
||||
explicit Device(DeviceParams params, QObject *parent = nullptr);
|
||||
virtual ~Device();
|
||||
|
|
|
@ -162,6 +162,7 @@ void Dialog::on_startServerBtn_clicked()
|
|||
params.closeScreen = ui->closeScreenCheck->isChecked();
|
||||
params.useReverse = ui->useReverseCheck->isChecked();
|
||||
params.display = !ui->notDisplayCheck->isChecked();
|
||||
params.renderExpiredFrames = Config::getInstance().getRenderExpiredFrames();
|
||||
|
||||
m_deviceManage.connectDevice(params);
|
||||
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
#define COMMON_SKIN_KEY "UseSkin"
|
||||
#define COMMON_SKIN_DEF 1
|
||||
|
||||
#define COMMON_RENDER_EXPIRED_FRAMES_KEY "RenderExpiredFrames"
|
||||
#define COMMON_RENDER_EXPIRED_FRAMES_DEF 0
|
||||
|
||||
QString Config::s_configPath = "";
|
||||
|
||||
Config::Config(QObject *parent) : QObject(parent)
|
||||
|
@ -108,6 +111,15 @@ int Config::getSkin()
|
|||
return skin;
|
||||
}
|
||||
|
||||
int Config::getRenderExpiredFrames()
|
||||
{
|
||||
int renderExpiredFrames = 1;
|
||||
m_settings->beginGroup(GROUP_COMMON);
|
||||
renderExpiredFrames = m_settings->value(COMMON_RENDER_EXPIRED_FRAMES_KEY, COMMON_RENDER_EXPIRED_FRAMES_DEF).toInt();
|
||||
m_settings->endGroup();
|
||||
return renderExpiredFrames;
|
||||
}
|
||||
|
||||
QString Config::getPushFilePath()
|
||||
{
|
||||
QString pushFile;
|
||||
|
|
|
@ -17,6 +17,7 @@ public:
|
|||
int getMaxFps();
|
||||
int getDesktopOpenGL();
|
||||
int getSkin();
|
||||
int getRenderExpiredFrames();
|
||||
QString getPushFilePath();
|
||||
QString getServerPath();
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ PushFilePath=/sdcard/
|
|||
MaxFps=60
|
||||
# 是否显示手机皮肤,0不显示
|
||||
UseSkin=1
|
||||
# 是否渲染过期视频帧(跳过过期视频帧意味着更低的延迟)
|
||||
RenderExpiredFrames=0
|
||||
# 视频解码方式:-1 自动,0 软解,1 dx硬解,2 opengl硬解
|
||||
UseDesktopOpenGL=-1
|
||||
# scrcpy-server的版本号(不要修改)
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
# TODO
|
||||
## 低优先级
|
||||
- 中文输入(server需要改为apk,作为一个输入法,暂不实现)(或者有其他方式案件注入方式,例如搜狗手机输入法可以监听当前注入?)
|
||||
- [跳过帧改为动态配置,而不是静态编译](https://github.com/Genymobile/scrcpy/commit/ebccb9f6cc111e8acfbe10d656cac5c1f1b744a0)
|
||||
- [单独线程统计帧率](https://github.com/Genymobile/scrcpy/commit/e2a272bf99ecf48fcb050177113f903b3fb323c4)
|
||||
- text转换 https://github.com/Genymobile/scrcpy/commit/c916af0984f72a60301d13fa8ef9a85112f54202?tdsourcetag=s_pctim_aiomsg
|
||||
- ui提供show touch设置
|
||||
|
|
Loading…
Add table
Reference in a new issue