根据上图所示,发送端有三个模块会对帧率进行调整:
1、当视频采集帧率大于编码器输出帧率,会直接掉帧。在VideoStreamEncoder::EncodeTask类中的Run函数里实现。
2、编码器输出码率是否超过目标码率,超过时会在编码前进行掉帧。在MediaOptimization->DropFrame漏桶算法里实现。
3、webrtc的VPX、openh264编码器,码控模块有接口配置是否掉帧调节码率功能。参见VideoCodecVPX/VideoCodecH264的frameDroppingOn定义。
详细实现流程,请参考《webrtc QOS方法五.2(发送端帧率调整原理及实现流程)》
如上框架图,webrtc的帧率从左到右,帧率是持递减状态的。摄像头的采集帧率是发送端帧率的极限值。
视频采集卡帧率能力集,可以通过potplay工具查看。打开->设备设置->摄像头
摄像头能采集的帧率与摄像头的型号、视频分辨率有关。他能提供的帧率,决定发送端视频帧率的最大值。
但是摄像头实际采集帧率,可能受实际环境光强影响,具体请参见:《webrtc QOS方法七(摄像头采集帧率调整)》
理论上编码器的输入帧率小于等于视频采集的帧率。编码器编码的性能+视频采集帧率决定编码器的输入帧率。
若摄像头的640*480的采集帧率是30fps,若编码器的640*480的编码性能是60fps,那么编码器的输入帧率为640*480 30fps。
若编码器性能比较差,640*480的编码性能是25fps,那么编码器的输入帧率为640*480 25fps。
当采集帧率大于编码帧率,会在VideoStreamEncoder::EncodeTask::Run函数进行掉帧处理。没有使用平滑算法,仅仅判断当前编码器是否空闲,空闲可以正常编码,不会丢帧,否则就会丢弃当前帧。
输入到编码器的视频帧,不一定全部被编码。如前面Send Side BWE介绍,当网络出现延时或者丢包的情况下,码率会持续下调。但是帧率不变的情况下,码率持续下调必然会导致视频质量快速下降。MediaOptimization大概思路就是在编码前通过降帧率的方法,降低码率。这样单帧的视频质量不会下降的特别明显。
详细实现参见:VideoSender->VideoSender::AddVideoFrame->_mediaOpt.DropFrame()
另外VP8、VP9、openH264都有一个EnableFrameSkip选项,开启该功能后,当视频编码输出的码率无法压缩到指定的目标码率,编码器的码控模块,也会通过掉帧的方式调节。导致实际输出编码器的帧数小于等于输入编码器的帧数。
同一帧视频的不同RTP的报文时间戳是相同的,一帧视频结束的最后一包的RTP报文头的MARK位为1。所以在网络测,判断一帧视频是否接收完全,同一个时间戳的报文的序列号是否连续,改时间戳的RTP报文是否收到MARK为1的包。
由于网络丢包延时等影响,网络接收到的数据帧若不完全,是不需要传递给解码器的,否则解码器也会解出花屏的数据。或者网络接收模块没有判断出数据有缺失,但是解码器判断异常,出现无法正常解码的情况。这样就会出现网络接收帧率大于等于解码器输出帧率的现象。
如第四小节描述,这里仅统计完整正确能解码出视频帧的帧率。
这是最终将第一小节的视频采集卡视频显示给用户的界面。可能出现个别终端的渲染器性能比较差,解码出来的全部数据不一定能及时渲染出来。目前webrtc在这里没有增加特殊处理,要是渲染不及时就会累积,出现视频延时的现象。
可以看出webrtc只有在发送端会有主动丢帧降帧率。其余的地方是由于网络丢包延时、编码性能、渲染性能导致被丢帧。
https://blog.csdn.net/chinabinlang/article/details/79654852
http://www.enkichen.com/2017/07/29/webrtc-drop-frame/