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:
rankun 2020-02-01 10:50:26 +08:00
parent eeeeae97fb
commit e43b3bc0ad
10 changed files with 58 additions and 42 deletions

View file

@ -9,6 +9,3 @@ SOURCES += \
$$PWD/fpscounter.cpp \
$$PWD/avframeconvert.cpp \
$$PWD/videobuffer.cpp
#DEFINES += SKIP_FRAMES

View file

@ -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()

View file

@ -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

View file

@ -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);

View file

@ -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 forwardfalse:直接使用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 forwardfalse:直接使用adb forward
bool display = true; // 是否显示画面(或者仅仅后台录制)
QString gameScript = ""; // 游戏映射脚本
bool renderExpiredFrames = false; // 是否渲染延迟视频帧
};
explicit Device(DeviceParams params, QObject *parent = nullptr);
virtual ~Device();

View file

@ -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);

View file

@ -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;

View file

@ -17,6 +17,7 @@ public:
int getMaxFps();
int getDesktopOpenGL();
int getSkin();
int getRenderExpiredFrames();
QString getPushFilePath();
QString getServerPath();

View file

@ -9,6 +9,8 @@ PushFilePath=/sdcard/
MaxFps=60
# 是否显示手机皮肤0不显示
UseSkin=1
# 是否渲染过期视频帧(跳过过期视频帧意味着更低的延迟)
RenderExpiredFrames=0
# 视频解码方式:-1 自动0 软解1 dx硬解2 opengl硬解
UseDesktopOpenGL=-1
# scrcpy-server的版本号不要修改

View file

@ -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设置