串流中的帧率

引言

帧率很好理解,是一个游戏或者软件在单位时间内(一般取一秒)的画面数量。

上面这句话在一般交流的时候,并没有多大问题。如果是游戏,帧率一般指显卡中每秒渲染的画面数量,这与上面那句话基本对得上。但在串流中,这个说法就不再适用,或者说这个说法过于含糊不清。这句话提到的画面数量究竟指什么的画面数量?

串流中每个环节的帧率

要说清楚串流中的帧率,首先要理清串流有哪些环节。以Windows + DXGI抓屏为例:

被控端游戏渲染画面 -> 被控端系统输出画面 -> DXGI抓屏 -> 编码 -> 网络传输 -> 解码 -> 帧平滑 -> 渲染 -> 送显 -> 显示画面

上面几乎每个环节都可以有不同的帧率,并且以小于等于的方式往后传递。

首先,假设被控端运行的游戏有300fps,但是被控端的显示器只有120Hz刷新率,那么被控端系统输出画面最多只能有120的帧率DXGI抓屏同样最多只能有120的帧率,这里的表述是最多,因为有可能因为别的原因导致一秒内采集到小于120个画面。

然后是编码,如果被控端的编码性能不够、或是网络质量不允许、或是主控端解码性能不够,串流程序都必须主动丢弃一些采集到的画面。解码帧率编码帧率在一般情况下是一致的,这里不做其它方案的考虑。

接着解码结束后,帧平滑会根据其算法,选择丢弃一些帧,渲染一些帧。

最后,串流中的渲染与游戏的复杂度不一样,并不会花费太多时间。基本上送去渲染的帧都会送显。但是送显并不代表这帧一定会显示在显示器里。显示器有自己的刷新率,并且分配给每一帧的时间是固定的,这点很重要!被控编码每一帧的时间不固定、网络传输时间不固定、解码时间也不固定,也就是说,如果送显时机不对,比如在显示器的同一帧内,送显两帧,根据程序代码不同,显示器可能只显示了一帧,或是在送显第二帧的时候,将代码卡住。总之就是不能如愿完美地显示这两帧。又比如说,由于前面环节的各种延迟,导致原本相邻的两帧,相隔了一帧才送显,那么显示器可能就会显示一帧重复的画面。

串流软件标示的FPS

大部分串流软件和远控软件会在主控端显示一个FPS,这个FPS指上面所说的哪种帧率?很遗憾,除非能看到这个软件的源码,否则我们无从判断。

不过我们可以先排除掉一些选项。首先,这个FPS不可能是在被控端产生的帧率;其次,除非使用一些老旧接口,否则主控端显示画面帧率非常难统计,可以通过一些简易逆向手段,判断程序是否使用老旧接口,从而排除掉这个选项。

也就是说,串流软件中显示的FPS,可能是1.网络接收到的帧率2.渲染/送显的帧率3.真正的显示画面(小概率)