背景:
项目中遇到一个问题,前方不断传过来数据(一帧一帧的传过来),我这边需要对传过来的数据进行帧率控制,然后发给后面。
简单实现:
一种简单的控制帧率的方式就是丢弃一部分帧,不过为了平滑,丢弃的帧不能过于集中,需要均匀的丢弃,一种实现思路是列出需要控制的帧率对应的时间点,比如fps设定为20,则1000/20=50ms
,也就是每一帧大约持续50ms,那么50ms内只能有一帧允许输出出去,如果50ms内有多余的帧,那就要丢弃那些多余的帧:
class Test {
public:
// ......
private:
bool IsActiveByEnableFpsControl() {
// 首先计算出需要控制的fps对应的时间间隔
static int interval_times = 1 * 1000 / ctrl_fps_; // 毫秒
// 获取当前的系统时间戳,GetTimeStamp()自己去实现
int64_t curr_times = GetTimeStamp();
// 如果fps_ctrl_timestamp_为0,表示刚开始第一帧,要初始化一下
if (fps_ctrl_timestamp_ == 0) {
// 初始化为当前时间加上时间间隔,如果后面来的一帧超过这个fps_ctrl_timestamp_,
// 表示后面来的这一帧不用丢弃
fps_ctrl_timestamp_ = curr_times + interval_times;
// 这里是第一帧,那肯定不用激活,激活就意味着丢弃这一帧
return false;
}
if (curr_times <= fps_ctrl_timestamp_) {
// 如果当前时间小于等于fps_ctrl_timestamp_,说明一帧的时间间隔内有超过一帧了,
// 那就要把这些帧给丢弃掉,所以要激活
return true;
}
else {
// 如果当前时间大于fps_ctrl_timestamp_,则表示当前的帧超过了设置的帧率对应的时间间隔,
// 表示当前帧与上一帧不在同一个时间间隔内,那么当前帧就不需要丢弃,并且需要更新一下
// fps_ctrl_timestamp_,注意,这里更新是直接加上时间间隔即可,不是加上当前时间
fps_ctrl_timestamp_ += interval_times;
return false;
}
}
private:
int64_t fps_ctrl_timestamp_{0};
int ctrl_fps_{25};
};
上述的函数IsActiveByEnableFpsControl()
就可以用来控制帧率,通过设置ctrl_fps_
,调用函数,当函数返回false
的时候,就不用丢掉当前帧,函数返回true
的时候就丢掉当前的帧。