在弱网环境下,为了保证推流的流畅性和低延时,我们需要弄一些策略使推流更流畅,一般有如下策略:
(1) 降帧率
网络发送层发现发送速度过慢,反馈给camera采集模块,通过抽帧的方式来降帧率,降低整体发送的码率
(2) 降编码码率
网络发送层发现发送速度过慢,反馈给视频编码模块,通过动态调整编码器码率,来减小视频编码的输出码率。Android上的MediaCodec在4.3+版本上都是支持动态调整码率的; x264以及ios上的VideoToolbox也是支持的
(3) 丢帧
上面两种方法,反射弧比较长一点,它们从pipeline上来看,操作的模块比较前面,生效比如慢一点,取决于各个模块间的缓冲的大小。丢帧策略的话直接作用于pipeline的末端,立即生效。
RTMP发送线程循环从一个缓冲队列里面读取帧,然后发送。为了方便作丢帧处理,encoder采用baseline的profile,这样,缓冲队列里面只存在I帧和P帧
如下 mVideoCount是这个缓冲队列里面视频帧的个数,
mVideoCapbility是这个缓冲队列总的大小
if(mVideoCount >= mVideoCapbility/2){
dropFrame(0.3f);
}
elseif(mVideoCount >= mVideoCapbility/3){
dropFrame(0.1f);
}
elseif(mVideoCount >= mVideoCapbility/4){
dropFrame(0.05f);
}
elseif(mVideoCount >= mVideoCapbility/5){
dropFrame(0.02f);
}
dropFrame的参数是丢帧的百分比,意思是相临两个gop之前丢掉的P帧的百分比。为了播放端不花屏,从一个GOP的最后面的P帧开始丢
比如dropFram(0.3f),如下序列,红色的P帧被丢弃
I P P P P P P P P P P I P P P P P P P P P PI P P …